devexpress-reporting
Version:
DevExpress Reporting provides the capability to develop a reporting application to create and customize reports.
238 lines (237 loc) • 15.8 kB
JavaScript
/**
* DevExpress HTML/JS Reporting (chart\components\series\_template.js)
* Version: 24.2.7
* Build date: Apr 29, 2025
* Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
* License: https://www.devexpress.com/Support/EULAs/universal.xml
*/
import { SerializableModel } from '@devexpress/analytics-core/analytics-elements';
import { extend, formatDate, formatUnicorn } from '@devexpress/analytics-core/analytics-internal';
import { getLocalization, ModelSerializer } from '@devexpress/analytics-core/analytics-utils';
import { editorTemplates, FilterStringOptions } from '@devexpress/analytics-core/analytics-widgets';
import * as ko from 'knockout';
import { CommonValueDataMembers } from '../../internal/data/_commonValue';
import { legendName } from '../../internal/meta/_axis';
import { bubbleSeriesPointsSortingKeys, colorDataMember, commonSeriesPointsSortingKeys, dateTimeSumaryOptions, numericSummaryOptions, qualitativeSummaryOptions, rangeSeriesPointsSortingKeys, stockSeriesPointsSortingKeys, topNOptions, viewBindableSerializationInfo } from '../../internal/meta/_chart';
import { defaultBooleanValues, filterString, filterStringEditable, scaleTypeValues, showInLegend, visible } from '../../internal/meta/_common';
import { chartDataSource, editorTemplates as chartEditorTemplates } from '../../internal/_editorTemplates';
import { _getUnconvertiblePoint } from '../../internal/_utils';
import { seriesLabel } from './_label';
import { mapTypes, onlyNumericArgumentSupportedSeriesViewTypes, viewTypesDataMembers } from './_templateOptions';
import { SeriesViewViewModel, view } from './_view';
const _isBubble = (viewType) => viewType === 'BubbleSeriesView';
const _isRange = (viewType) => viewType === 'PolarRangeAreaSeriesView' ||
viewType === 'RadarRangeAreaSeriesView' ||
viewType === 'RangeArea3DSeriesView' ||
viewType === 'RangeAreaSeriesView' ||
viewType === 'OverlappedGanttSeriesView' ||
viewType === 'SideBySideGanttSeriesView' ||
viewType === 'OverlappedRangeBarSeriesView' ||
viewType === 'SideBySideRangeBarSeriesView';
const _isStock = (viewType) => viewType === 'StockSeriesView' ||
viewType === 'CandleStickSeriesView';
export var ScaleType;
(function (ScaleType) {
ScaleType[ScaleType["Qualitative"] = 0] = "Qualitative";
ScaleType[ScaleType["Numerical"] = 1] = "Numerical";
ScaleType[ScaleType["DateTime"] = 2] = "DateTime";
ScaleType[ScaleType["Auto"] = 3] = "Auto";
})(ScaleType || (ScaleType = {}));
export const ScaleTypeMap = {
'Qualitative': ScaleType.Qualitative,
'Numerical': ScaleType.Numerical,
'DateTime': ScaleType.DateTime,
'Auto': ScaleType.Auto
};
function _fixSeriesTemplateModel(model) {
delete model['@SeriesDataMember'];
return model;
}
export class SeriesTemplateViewModel extends SerializableModel {
static from(model, serializer) {
return new SeriesTemplateViewModel(model || {}, serializer, seriesTemplateSerializationsInfo);
}
static toJson(value, serializer, refs) {
return serializer.serialize(value, seriesTemplateSerializationsInfo, refs);
}
updateByView(view) {
if (this.label && this.label.typeNameSerializable) {
this.label.typeNameSerializable(mapTypes[view.typeName]);
}
this.valueDataMembers.peek().dispose();
this.valueDataMembers(new (viewTypesDataMembers[view.typeName] || CommonValueDataMembers)(this.valueDataMembers.peek().toString(), this.valueScaleType));
}
preInitProperties(model) {
delete model['DataFilters'];
}
getChildComponents() {
return [
{ component: ko.unwrap(this.view), path: 'View' },
{ component: ko.unwrap(this.label), path: 'Label' },
];
}
getExpressionProperties() {
return ['LegendTextPattern'];
}
_isOnlyNumericArgumentScaleTypeSupported() {
return onlyNumericArgumentSupportedSeriesViewTypes.indexOf(this.viewType()) > -1;
}
_getCurrentSeriesPointsSortingKeys(viewType) {
if (_isBubble(viewType))
return bubbleSeriesPointsSortingKeys;
if (_isRange(viewType))
return rangeSeriesPointsSortingKeys;
if (_isStock(viewType))
return stockSeriesPointsSortingKeys;
return commonSeriesPointsSortingKeys;
}
_adjustArgumentScaleType() {
if (this._isOnlyNumericArgumentScaleTypeSupported())
this.argumentScaleType('Numerical');
}
_updateSeriesPointsSortingKey(seriesPointsSortingKeyMeta) {
const value = this[seriesPointsSortingKeyMeta.propertyName];
if (!!value() && !seriesPointsSortingKeyMeta.valuesArray.some(x => x.value === value())) {
value(seriesPointsSortingKeyMeta.valuesArray[0].value);
}
}
_isDataMemberPropertyDisabled(name) {
if (SeriesTemplateViewModel.dataMemberProperies.concat(['valueScaleType', 'argumentScaleType']).some(x => x === name)) {
return !ko.unwrap(this.dataSource);
}
return false;
}
_isPropertyDisabled(name) {
if (name === 'argumentScaleType') {
return this._isOnlyNumericArgumentScaleTypeSupported();
}
return false;
}
getPath(propertyName) {
const dataSourceInfo = ko.unwrap(this.dataSource);
if (dataSourceInfo) {
const helper = dataSourceInfo.dsHelperProvider && dataSourceInfo.dsHelperProvider();
return helper && helper.getDataSourcePath(dataSourceInfo);
}
}
constructor(model, serializer, info) {
super(_fixSeriesTemplateModel(model), serializer, info);
this._actualArgumentScaleType = ko.observable(ScaleType.Numerical);
if (this.valueDataMembers) {
ko.unwrap(this.valueDataMembers).dispose();
}
this.viewType = ko.observable(this.view().typeName);
this._adjustArgumentScaleType();
const newInfo = extend(true, [], info);
const seriesPointsSortingKeyMeta = newInfo.filter(x => x.propertyName === seriesPointsSortingKey.propertyName)[0];
Object.defineProperty(seriesPointsSortingKeyMeta, 'valuesArray', {
get: () => this._getCurrentSeriesPointsSortingKeys(this.viewType()),
configurable: true
});
this.viewType.subscribe((newType) => {
const newSerializer = serializer || new ModelSerializer();
this.view(SeriesViewViewModel.from({ '@TypeNameSerializable': newType }, newSerializer)());
this._adjustArgumentScaleType();
this._updateSeriesPointsSortingKey(seriesPointsSortingKeyMeta);
});
this.getInfo = () => newInfo;
this._disposables.push(this.view.subscribe((newView) => {
if (this.viewType() !== newView.typeName) {
this.viewType(newView.typeName);
}
this.updateByView(newView);
}));
this.valueDataMembers = ko.observable(new (viewTypesDataMembers[this.view().typeName] || CommonValueDataMembers)(model['@ValueDataMembersSerializable'] || '', this.valueScaleType));
this._disposables.push(this['indicators'] = ko.computed(() => {
return this.view() && this.view()['indicators'] && this.view()['indicators']();
}));
this._disposables.push(this['titles'] = ko.computed(() => {
return this.view() && this.view()['titles'] && this.view()['titles']();
}));
this._disposables.push(this._actualArgumentScaleType.subscribe((newVal) => {
switch (newVal) {
case ScaleType.DateTime:
this.qualitativeSummaryOptions.resetAllProperties();
this.numericSummaryOptions.resetAllProperties();
break;
case ScaleType.Numerical:
this.qualitativeSummaryOptions.resetAllProperties();
this.dateTimeSummaryOptions.resetAllProperties();
break;
case ScaleType.Qualitative:
this.numericSummaryOptions.resetAllProperties();
this.dateTimeSummaryOptions.resetAllProperties();
break;
}
}));
this.updateByView(this.view());
[this.qualitativeSummaryOptions, this.numericSummaryOptions, this.dateTimeSummaryOptions].forEach(options => {
options['getPath'] = (propertyName) => {
return this['getPath'] && this['getPath']('summaryFunction') || '';
};
});
this.viewBindable = {
model: this.view,
type: this.viewType
};
this.filterString = new FilterStringOptions(this._filterString, ko.pureComputed(() => { return this['getPath'] && this['getPath']('argumentDataMember') || ''; }));
}
isPropertyVisible(propertyName) {
switch (propertyName) {
case 'qualitativeSummaryOptions':
return this._actualArgumentScaleType() === ScaleType.Qualitative;
case 'numericSummaryOptions':
return this._actualArgumentScaleType() === ScaleType.Numerical;
case 'dateTimeSummaryOptions':
return this._actualArgumentScaleType() === ScaleType.DateTime;
default:
return true;
}
}
}
SeriesTemplateViewModel.dataMemberProperies = ['argumentDataMember', 'valueDataMembers'];
export const seriesPointsSorting = {
propertyName: 'seriesPointsSorting', modelName: '@SeriesPointsSorting', displayName: 'Series Points Sorting', editor: editorTemplates.getEditor('combobox'), valuesArray: [{ value: 'None', displayValue: 'None', localizationId: 'DevExpress.XtraReports.UI.MultiColumnMode.None' }, { value: 'Ascending', displayValue: 'Ascending', localizationId: 'DevExpress.XtraReports.UI.XRColumnSortOrder.Ascending' }, { value: 'Descending', displayValue: 'Descending', localizationId: 'DevExpress.XtraReports.UI.XRColumnSortOrder.Descending' }],
localizationId: 'DevExpress.XtraCharts.SeriesBase.SeriesPointsSorting', defaultVal: 'None'
}, seriesPointsSortingKey = {
propertyName: 'seriesPointsSortingKey', modelName: '@SeriesPointsSortingKey', displayName: 'Series Points Sorting Key', editor: editorTemplates.getEditor('combobox'), valuesArray: commonSeriesPointsSortingKeys, localizationId: 'DevExpress.XtraCharts.SeriesBase.SeriesPointsSortingKey', defaultVal: 'Argument'
}, legendTextPattern = { propertyName: 'legendTextPattern', modelName: '@LegendTextPattern', displayName: 'Legend Text Pattern', localizable: true, editor: editorTemplates.getEditor('text'), localizationId: 'DevExpress.XtraCharts.SeriesBase.LegendTextPattern' }, _argumentScaleTypeValidatorOptions = {
_seriesViewModel: null,
onInitialized: ({ model }) => { _argumentScaleTypeValidatorOptions._seriesViewModel = model._model; },
validationRules: [{
type: 'custom',
reevaluate: true,
validationCallback: (params) => {
let model = _argumentScaleTypeValidatorOptions._seriesViewModel.peek();
if ('points' in model && model instanceof SeriesTemplateViewModel) {
model = model;
const unconvertiblePoint = _getUnconvertiblePoint('argumentSerializable', model.argumentScaleType.peek(), params.value, model.points.peek());
const stringFormat = getLocalization("The type of the '{0}' point isn't compatible with the {1} scale.", 'ChartStringId.MsgIncompatiblePointType');
let argumentValue = unconvertiblePoint && unconvertiblePoint.argumentSerializable();
if (argumentValue && (argumentValue instanceof Date))
argumentValue = formatDate(argumentValue);
params.rule.message = formatUnicorn(stringFormat, (argumentValue !== null || argumentValue !== void 0) ? argumentValue : '', params.value);
return !unconvertiblePoint;
}
return true;
}
}]
}, checkedInLegend = { propertyName: 'checkedInLegend', modelName: '@CheckedInLegend', displayName: 'Checked in Legend', localizationId: 'DevExpress.XtraCharts.SeriesBase.CheckedInLegend', editor: editorTemplates.getEditor('bool'), defaultVal: true }, checkableInLegend = { propertyName: 'checkableInLegend', modelName: '@CheckableInLegend', displayName: 'Checkable in Legend', localizationId: 'DevExpress.XtraCharts.SeriesBase.CheckableInLegend', editor: editorTemplates.getEditor('bool'), defaultVal: true }, allowResample = { propertyName: 'allowResample', modelName: '@AllowResample', displayName: 'Allow Resample', localizationId: 'DevExpress.XtraCharts.Series.AllowResample', editor: editorTemplates.getEditor('bool'), defaultVal: false }, argumentScaleType = {
propertyName: 'argumentScaleType', modelName: '@ArgumentScaleType', displayName: 'Argument Scale Type', defaultVal: 'Auto', editor: editorTemplates.getEditor('combobox'), valuesArray: scaleTypeValues, localizationId: 'DevExpress.XtraCharts.SeriesBase.ArgumentScaleType', validatorOptions: _argumentScaleTypeValidatorOptions
}, valueScaleType = {
propertyName: 'valueScaleType', modelName: '@ValueScaleType', displayName: 'Value Scale Type', defaultVal: 'Numerical', editor: editorTemplates.getEditor('combobox'), valuesArray: [
{ value: 'Numerical', displayValue: 'Numerical', localizationId: 'DevExpress.XtraCharts.ScaleType.Numerical' },
{ value: 'DateTime', displayValue: 'DateTime', localizationId: 'DevExpress.XtraTreeList.Data.UnboundColumnType.DateTime' }
],
localizationId: 'DevExpress.XtraCharts.SeriesBase.ValueScaleType'
}, labelsVisibility = { propertyName: 'labelsVisibility', modelName: '@LabelsVisibility', displayName: 'Labels Visibility', defaultVal: 'Default', editor: editorTemplates.getEditor('combobox'), valuesArray: defaultBooleanValues, localizationId: 'DevExpress.XtraCharts.SeriesBase.LabelsVisibility' }, argumentDataMember = { propertyName: 'argumentDataMember', modelName: '@ArgumentDataMember', displayName: 'Argument Data Member', defaultVal: '', editor: chartEditorTemplates.getEditor('valueDataMember'), localizationId: 'DevExpress.XtraCharts.SeriesBase.ArgumentDataMember' }, valueDataMembersSerializable = { propertyName: 'valueDataMembers', modelName: '@ValueDataMembersSerializable', displayName: 'Value Data Members', defaultVal: '', editor: editorTemplates.getEditor('objecteditor'), from: CommonValueDataMembers.from, toJsonObject: CommonValueDataMembers.toJson, localizationId: 'DevExpress.XtraCharts.SeriesBase.ValueDataMembers' };
export const seriesTemplateSerializationsInfo = [
viewBindableSerializationInfo,
{ propertyName: 'titles', displayName: 'Titles', localizationId: 'DevExpress.XtraReports.UI.XRChart.Titles' },
{ propertyName: 'indicators', displayName: 'Indicators', localizationId: 'DevExpress.XtraReports.UI.XRChart.Indicators' },
view, allowResample, argumentDataMember, valueDataMembersSerializable, colorDataMember, argumentScaleType, valueScaleType, filterString,
filterStringEditable, seriesPointsSorting, seriesPointsSortingKey, showInLegend, legendName, checkableInLegend, checkedInLegend, legendTextPattern, labelsVisibility,
qualitativeSummaryOptions, numericSummaryOptions, dateTimeSumaryOptions,
seriesLabel, topNOptions, visible, chartDataSource
];
export const seriesTemplate = { propertyName: 'seriesTemplate', modelName: 'SeriesTemplate', displayName: 'Series Template', localizationId: 'DevExpress.XtraReports.UI.XRChart.SeriesTemplate', info: seriesTemplateSerializationsInfo, from: SeriesTemplateViewModel.from, toJsonObject: SeriesTemplateViewModel.toJson, editor: editorTemplates.getEditor('objecteditor') };