mdt-charts 1.18.2 → 1.18.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/lib/config/config.d.ts +30 -3
  2. package/lib/engine/contentManager/contentManagerFactory.js +0 -2
  3. package/lib/engine/features/axis/axis.d.ts +1 -0
  4. package/lib/engine/features/axis/axis.js +19 -2
  5. package/lib/engine/features/axis/axisHelper.js +3 -1
  6. package/lib/engine/features/legend/legend.d.ts +2 -2
  7. package/lib/engine/features/legend/legendHelper.d.ts +2 -2
  8. package/lib/engine/features/legend/legendHelper.js +0 -3
  9. package/lib/engine/features/scale/scale.d.ts +4 -0
  10. package/lib/engine/features/scale/scale.js +4 -0
  11. package/lib/engine/features/title/title.d.ts +1 -1
  12. package/lib/engine/features/title/title.js +2 -3
  13. package/lib/engine/features/tolltip/tooltip.d.ts +0 -1
  14. package/lib/engine/features/tolltip/tooltip.js +2 -21
  15. package/lib/engine/features/tolltip/tooltipDomHelper.d.ts +6 -3
  16. package/lib/engine/features/tolltip/tooltipDomHelper.js +64 -27
  17. package/lib/engine/filterManager/filterEventManager.d.ts +6 -0
  18. package/lib/engine/filterManager/filterEventManager.js +8 -0
  19. package/lib/engine/polarNotation/polarManager.js +1 -1
  20. package/lib/engine/twoDimensionalNotation/line/line.d.ts +6 -0
  21. package/lib/engine/twoDimensionalNotation/line/line.js +7 -8
  22. package/lib/engine/twoDimensionalNotation/line/lineHelper.d.ts +4 -1
  23. package/lib/engine/twoDimensionalNotation/line/lineHelper.js +18 -6
  24. package/lib/engine/twoDimensionalNotation/twoDimensionalManager.js +11 -9
  25. package/lib/model/EventEmitter.d.ts +10 -0
  26. package/lib/model/EventEmitter.js +26 -0
  27. package/lib/model/dataManagerModel/dataManagerModel.d.ts +0 -1
  28. package/lib/model/dataManagerModel/dataManagerModel.js +0 -13
  29. package/lib/model/featuresModel/axisModel.d.ts +1 -0
  30. package/lib/model/featuresModel/axisModel.js +13 -2
  31. package/lib/model/featuresModel/scaleModel/scaleDomainService.d.ts +3 -2
  32. package/lib/model/featuresModel/scaleModel/scaleDomainService.js +16 -6
  33. package/lib/model/featuresModel/scaleModel/scaleModel.d.ts +1 -0
  34. package/lib/model/featuresModel/scaleModel/scaleModel.js +12 -0
  35. package/lib/model/helpers/modelHelper.d.ts +2 -2
  36. package/lib/model/helpers/modelHelper.js +11 -22
  37. package/lib/model/margin/twoDim/twoDimMarginModel.d.ts +1 -1
  38. package/lib/model/margin/twoDim/twoDimMarginModel.js +3 -3
  39. package/lib/model/model.d.ts +6 -2
  40. package/lib/model/modelBuilder.js +0 -13
  41. package/lib/model/modelInstance/configReader.d.ts +2 -0
  42. package/lib/model/modelInstance/configReader.js +11 -1
  43. package/lib/model/notations/twoDimensionalModel.js +9 -2
  44. package/lib/style/charts-main.css +9 -7
  45. package/lib/style/charts-main.less +9 -7
  46. package/lib/style/css-vars.css +3 -0
  47. package/package.json +3 -3
@@ -1,15 +1,17 @@
1
1
  import { Line as ILine } from 'd3-shape';
2
2
  import { MdtChartsDataRow } from '../../../config/config';
3
- import { Orient, BlockMargin, LineCurveType, TwoDimensionalChartModel } from "../../../model/model";
3
+ import { Orient, BlockMargin, LineCurveType, TwoDimensionalChartModel, LineLikeChartRenderOptions } from "../../../model/model";
4
4
  import { Scales } from "../../features/scale/scale";
5
5
  import { Pipeline } from '../../helpers/pipeline/Pipeline';
6
6
  import { BaseType, Selection } from 'd3-selection';
7
+ import { Segment } from './line';
7
8
  interface LineGeneratorFactoryOptions {
8
9
  keyAxisOrient: Orient;
9
10
  scales: Scales;
10
11
  keyFieldName: string;
11
12
  margin: BlockMargin;
12
13
  curve: LineCurveType;
14
+ shouldRenderLine: LineLikeChartRenderOptions;
13
15
  }
14
16
  export declare class LineGeneratorFactory {
15
17
  private options;
@@ -19,4 +21,5 @@ export declare class LineGeneratorFactory {
19
21
  }
20
22
  export declare function onLineChartInit(creatingPipeline: Pipeline<Selection<SVGElement, any, BaseType, any>, TwoDimensionalChartModel>): void;
21
23
  export declare function applyLineDash(lineSelection: Selection<SVGElement, any, BaseType, any>, dashSize: number, gapSize: number): Selection<SVGElement, any, BaseType, any>;
24
+ export declare function getStackedData(data: MdtChartsDataRow[], chart: TwoDimensionalChartModel): Segment[][];
22
25
  export {};
@@ -1,3 +1,4 @@
1
+ import { stack } from 'd3-shape';
1
2
  import { Scale } from "../../features/scale/scale";
2
3
  import { LineGenerator } from './lineGenerator';
3
4
  export class LineGeneratorFactory {
@@ -5,23 +6,23 @@ export class LineGeneratorFactory {
5
6
  this.options = options;
6
7
  }
7
8
  getLineGenerator(valueFieldName) {
8
- const { keyAxisOrient, scales, keyFieldName, margin } = this.options;
9
+ const { keyAxisOrient, scales, keyFieldName, margin, shouldRenderLine } = this.options;
9
10
  const generator = new LineGenerator({ curve: this.options.curve });
10
11
  if (keyAxisOrient === 'bottom' || keyAxisOrient === 'top') {
11
- return generator.get(d => Scale.getScaledValue(scales.key, d[keyFieldName]) + margin.left, d => scales.value(d[valueFieldName]) + margin.top);
12
+ return generator.get(d => Scale.getScaledValue(scales.key, d[keyFieldName]) + margin.left, d => scales.value(d[valueFieldName]) + margin.top).defined(d => shouldRenderLine(d, valueFieldName));
12
13
  }
13
14
  if (keyAxisOrient === 'left' || keyAxisOrient === 'right') {
14
- return generator.get(d => scales.value(d[valueFieldName]) + margin.left, d => Scale.getScaledValue(scales.key, d[keyFieldName]) + margin.top);
15
+ return generator.get(d => scales.value(d[valueFieldName]) + margin.left, d => Scale.getScaledValue(scales.key, d[keyFieldName]) + margin.top).defined(d => shouldRenderLine(d, valueFieldName));
15
16
  }
16
17
  }
17
18
  getSegmentedLineGenerator() {
18
- const { keyAxisOrient, scales, keyFieldName, margin } = this.options;
19
+ const { keyAxisOrient, scales, keyFieldName, margin, shouldRenderLine } = this.options;
19
20
  const generator = new LineGenerator({ curve: this.options.curve });
20
21
  if (keyAxisOrient === 'bottom' || keyAxisOrient === 'top') {
21
- return generator.get(d => Scale.getScaledValue(scales.key, d.data[keyFieldName]) + margin.left, d => scales.value(d[1]) + margin.top);
22
+ return generator.get(d => Scale.getScaledValue(scales.key, d.data[keyFieldName]) + margin.left, d => scales.value(d[1]) + margin.top).defined(d => shouldRenderLine(d.data, d.fieldName));
22
23
  }
23
24
  if (keyAxisOrient === 'left' || keyAxisOrient === 'right') {
24
- return generator.get(d => scales.value(d[1]) + margin.left, d => Scale.getScaledValue(scales.key, d.data[keyFieldName]) + margin.top);
25
+ return generator.get(d => scales.value(d[1]) + margin.left, d => Scale.getScaledValue(scales.key, d.data[keyFieldName]) + margin.top).defined(d => shouldRenderLine(d.data, d.fieldName));
25
26
  }
26
27
  }
27
28
  }
@@ -36,3 +37,14 @@ export function onLineChartInit(creatingPipeline) {
36
37
  export function applyLineDash(lineSelection, dashSize, gapSize) {
37
38
  return lineSelection.style('stroke-dasharray', `${dashSize} ${gapSize}`);
38
39
  }
40
+ export function getStackedData(data, chart) {
41
+ let stackedData = stack().keys(chart.data.valueFields.map(field => field.name))(data)
42
+ .map((layer, index) => {
43
+ const fieldName = chart.data.valueFields[index].name;
44
+ return layer.map((segment) => {
45
+ segment.fieldName = fieldName;
46
+ return segment;
47
+ });
48
+ });
49
+ return stackedData;
50
+ }
@@ -16,7 +16,7 @@ import { Line } from "./line/line";
16
16
  export class TwoDimensionalManager {
17
17
  render(engine, model) {
18
18
  const options = model.options;
19
- const scales = Scale.getScales(options.scale.key, options.scale.value, options.chartSettings.bar);
19
+ const scales = Scale.getScalesWithSecondary(options.scale.key, options.scale.value, options.scale.valueSecondary, options.chartSettings.bar);
20
20
  engine.block.scales = scales;
21
21
  engine.block.svg.render(model.blockCanvas.size);
22
22
  Axis.render(engine.block, scales, options.scale, options.axis, model.blockCanvas.size);
@@ -42,12 +42,12 @@ export class TwoDimensionalManager {
42
42
  updateData(block, model, data) {
43
43
  block.transitionManager.interruptTransitions();
44
44
  block.filterEventManager.updateData(data[model.options.data.dataSource]);
45
- Title.updateData(model.options.title);
45
+ Title.updateData(block, model.options.title);
46
46
  TipBox.clearEvents(block);
47
47
  Tooltip.hide(block);
48
48
  const options = model.options;
49
49
  ElementHighlighter.remove2DChartsFullHighlighting(block, options.charts);
50
- const scales = Scale.getScales(options.scale.key, options.scale.value, options.chartSettings.bar);
50
+ const scales = Scale.getScalesWithSecondary(options.scale.key, options.scale.value, options.scale.valueSecondary, options.chartSettings.bar);
51
51
  const keyDomainEquality = Helper.checkDomainsEquality(block.scales.key.domain(), scales.key.domain());
52
52
  block.scales = scales;
53
53
  Axis.update(block, scales, options.scale, options.axis, model.blockCanvas.size, keyDomainEquality);
@@ -80,12 +80,13 @@ export class TwoDimensionalManager {
80
80
  block.svg.renderBarHatchPattern();
81
81
  block.svg.renderChartsBlock();
82
82
  charts.forEach((chart) => {
83
+ const chartScales = { key: scales.key, value: chart.data.valueGroup === "secondary" ? scales.valueSecondary : scales.value };
83
84
  if (chart.type === 'bar')
84
- Bar.get().render(block, scales, data[dataOptions.dataSource], dataOptions.keyField, margin, keyAxisOrient, chart, blockSize, chartSettings.bar, BarHelper.getBarsInGroupAmount(charts), chart.isSegmented, charts.findIndex(ch => ch.type === 'bar'));
85
+ Bar.get().render(block, chartScales, data[dataOptions.dataSource], dataOptions.keyField, margin, keyAxisOrient, chart, blockSize, chartSettings.bar, BarHelper.getBarsInGroupAmount(charts), chart.isSegmented, charts.findIndex(ch => ch.type === 'bar'));
85
86
  else if (chart.type === 'line')
86
- Line.get({ staticSettings: chartSettings.lineLike }).render(block, scales, data[dataOptions.dataSource], dataOptions.keyField, margin, keyAxisOrient, chart);
87
+ Line.get({ staticSettings: chartSettings.lineLike }).render(block, chartScales, data[dataOptions.dataSource], dataOptions.keyField, margin, keyAxisOrient, chart);
87
88
  else if (chart.type === 'area')
88
- Area.render(block, scales, data[dataOptions.dataSource], dataOptions.keyField, margin, keyAxisOrient, chart, blockSize);
89
+ Area.render(block, chartScales, data[dataOptions.dataSource], dataOptions.keyField, margin, keyAxisOrient, chart, blockSize);
89
90
  });
90
91
  EmbeddedLabels.raiseGroups(block);
91
92
  }
@@ -93,15 +94,16 @@ export class TwoDimensionalManager {
93
94
  block.svg.updateChartClipPath(margin, blockSize);
94
95
  let promises = [];
95
96
  charts.forEach((chart) => {
97
+ const chartScales = { key: scales.key, value: chart.data.valueGroup === "secondary" ? scales.valueSecondary : scales.value };
96
98
  let proms;
97
99
  if (chart.type === 'bar') {
98
- proms = Bar.get().update(block, data[dataOptions.dataSource], scales, margin, keyAxisOrient, chart, blockSize, BarHelper.getBarsInGroupAmount(charts), dataOptions.keyField, charts.findIndex(ch => ch.type === 'bar'), chartSettings.bar, chart.isSegmented);
100
+ proms = Bar.get().update(block, data[dataOptions.dataSource], chartScales, margin, keyAxisOrient, chart, blockSize, BarHelper.getBarsInGroupAmount(charts), dataOptions.keyField, charts.findIndex(ch => ch.type === 'bar'), chartSettings.bar, chart.isSegmented);
99
101
  }
100
102
  else if (chart.type === 'line') {
101
- proms = Line.get({ staticSettings: chartSettings.lineLike }).update(block, scales, data[dataOptions.dataSource], dataOptions.keyField, margin, keyAxisOrient, chart);
103
+ proms = Line.get({ staticSettings: chartSettings.lineLike }).update(block, chartScales, data[dataOptions.dataSource], dataOptions.keyField, margin, keyAxisOrient, chart);
102
104
  }
103
105
  else if (chart.type === 'area') {
104
- proms = Area.update(block, scales, data[dataOptions.dataSource], dataOptions.keyField, margin, chart, keyAxisOrient, blockSize);
106
+ proms = Area.update(block, chartScales, data[dataOptions.dataSource], dataOptions.keyField, margin, chart, keyAxisOrient, blockSize);
105
107
  }
106
108
  promises.push(...proms);
107
109
  });
@@ -0,0 +1,10 @@
1
+ export declare class EventEmitter<E = Record<string, Record<string, any>>> {
2
+ private events;
3
+ subscribe<T extends keyof E>(code: T, listener: (args: E[T]) => void): () => void;
4
+ unsubscribe<T extends keyof E>(code: T, listener: (args: E[T]) => void): void;
5
+ emit<T extends keyof E>(code: T, args?: E[T]): void;
6
+ getSubscribeController(): {
7
+ subscribe: <T extends keyof E>(code: T, listener: (args: E[T]) => void) => () => void;
8
+ unsubscribe: <T_1 extends keyof E>(code: T_1, listener: (args: E[T_1]) => void) => void;
9
+ };
10
+ }
@@ -0,0 +1,26 @@
1
+ export class EventEmitter {
2
+ constructor() {
3
+ this.events = {};
4
+ }
5
+ subscribe(code, listener) {
6
+ if (!this.events[code])
7
+ this.events[code] = [];
8
+ this.events[code].push(listener);
9
+ return () => this.unsubscribe(code, listener);
10
+ }
11
+ unsubscribe(code, listener) {
12
+ var _a;
13
+ this.events[code] = (_a = this.events[code]) === null || _a === void 0 ? void 0 : _a.filter((cur) => cur != listener);
14
+ }
15
+ emit(code, args) {
16
+ (this.events[code] || []).forEach((callback) => {
17
+ callback(args);
18
+ });
19
+ }
20
+ getSubscribeController() {
21
+ return {
22
+ subscribe: (code, listener) => this.subscribe(code, listener),
23
+ unsubscribe: (code, listener) => this.unsubscribe(code, listener)
24
+ };
25
+ }
26
+ }
@@ -30,7 +30,6 @@ export declare class DataManagerModel {
30
30
  private static getBarChartsInGroupAmount;
31
31
  private static getScopedData;
32
32
  private static getScopedChartData;
33
- private static setDataType;
34
33
  private static getTypedData;
35
34
  private static getDataLimitByItemSize;
36
35
  }
@@ -8,7 +8,6 @@ import { styledElementValues } from "../modelBuilder";
8
8
  export class DataManagerModel {
9
9
  static getPreparedData(data, allowableKeys, config) {
10
10
  const scopedData = this.getScopedData(data, allowableKeys, config.options.data);
11
- this.setDataType(scopedData, config);
12
11
  return scopedData;
13
12
  }
14
13
  static initDataScope(config, data, designerConfig, legendBlock, modelInstance) {
@@ -28,7 +27,6 @@ export class DataManagerModel {
28
27
  return data[dataSourceName].map(dataRow => dataRow[keyFieldName]);
29
28
  }
30
29
  static initDataScopeFor2D(configOptions, modelInstance, data, designerConfig) {
31
- // Для interval всегда один элемент, так как там может быть только один столбик
32
30
  modelInstance.dataModel.initMaxRecordsAmount(configOptions.data.maxRecordsAmount);
33
31
  let itemsLength = 1;
34
32
  itemsLength = (configOptions.charts)
@@ -125,17 +123,6 @@ export class DataManagerModel {
125
123
  static getScopedChartData(data, allowableKeys, keyFieldName) {
126
124
  return data.filter(d => allowableKeys.findIndex(key => key === d[keyFieldName]) !== -1);
127
125
  }
128
- static setDataType(data, config) {
129
- if (config.options.type === 'interval') {
130
- const chart = config.options.chart;
131
- if (chart.data.valueField1.format === 'date') {
132
- data[config.options.data.dataSource] = this.getTypedData(data[config.options.data.dataSource], chart.data.valueField1);
133
- }
134
- if (chart.data.valueField2.format === 'date') {
135
- data[config.options.data.dataSource] = this.getTypedData(data[config.options.data.dataSource], chart.data.valueField2);
136
- }
137
- }
138
- }
139
126
  static getTypedData(data, field) {
140
127
  if (field.format === 'date')
141
128
  data.forEach(d => {
@@ -20,5 +20,6 @@ export declare class AxisModel {
20
20
  static getKeyAxisLabelPosition(canvasModel: CanvasModel, scopedDataLength: number, axisConfig?: DiscreteAxisOptions): AxisLabelPosition;
21
21
  static getLabelSize(labelMaxWidth: number, labelTexts: string[]): LabelSize;
22
22
  static getLabelSizeLegacy(labelMaxWidth: number, labelTexts: string[]): LabelSize;
23
+ static getRoundValue(value: number): number;
23
24
  private static getKeyAxisTranslateModel;
24
25
  }
@@ -92,7 +92,7 @@ export class AxisModel {
92
92
  static getLabelSize(labelMaxWidth, labelTexts) {
93
93
  const LABEL_ELEMENT_HEIGHT_PX = 17;
94
94
  const ONE_UPPER_SYMBOL_WIDTH_PX = 8;
95
- const longestLabelLength = Math.max(...labelTexts.map(t => ModelHelper.getStringScore(t)));
95
+ const longestLabelLength = labelTexts.length ? Math.max(...labelTexts.map(t => ModelHelper.getStringScore(t))) : 0;
96
96
  const longestLabelWidth = ONE_UPPER_SYMBOL_WIDTH_PX * longestLabelLength;
97
97
  return {
98
98
  height: LABEL_ELEMENT_HEIGHT_PX,
@@ -118,7 +118,7 @@ export class AxisModel {
118
118
  biggestScore = ModelHelper.getStringScore(text);
119
119
  }
120
120
  });
121
- textBlock.textContent = maxLabel === '0000' ? maxLabel : maxLabel + 'D';
121
+ textBlock.textContent = maxLabel === '0000' ? maxLabel : maxLabel;
122
122
  document.body.append(textBlock);
123
123
  maxWidth = Math.ceil(textBlock.getBoundingClientRect().width);
124
124
  labelSize.height = textBlock.getBoundingClientRect().height;
@@ -126,6 +126,17 @@ export class AxisModel {
126
126
  textBlock.remove();
127
127
  return labelSize;
128
128
  }
129
+ static getRoundValue(value) {
130
+ const absValue = Math.abs(value);
131
+ const sign = Math.sign(value);
132
+ if (absValue < 10)
133
+ return value;
134
+ const valueStr = absValue.toString();
135
+ const firstTwoDigits = Math.floor(absValue / Math.pow(10, valueStr.length - 2));
136
+ const roundedFirstTwoDigits = firstTwoDigits < 10 ? firstTwoDigits : Math.floor(firstTwoDigits / 5) * 5;
137
+ const roundedNumber = roundedFirstTwoDigits * Math.pow(10, valueStr.length - 2);
138
+ return sign * roundedNumber;
139
+ }
129
140
  static getKeyAxisTranslateModel(chartOrientation, axisPosition, canvasModel, getZeroCoordinate) {
130
141
  let translateY;
131
142
  let translateX;
@@ -1,5 +1,6 @@
1
- import { MdtChartsDataRow, MdtChartsTwoDimensionalChart, MdtChartsTwoDimensionalOptions, NumberDomain } from "../../../config/config";
2
- export declare function getScaleLinearDomain(configDomain: NumberDomain, dataRows: MdtChartsDataRow[], configOptions: MdtChartsTwoDimensionalOptions): number[];
1
+ import { AxisNumberDomain, MdtChartsDataRow, MdtChartsTwoDimensionalChart, MdtChartsTwoDimensionalOptions, TwoDimensionalValueGroup } from "../../../config/config";
2
+ export declare function getResolvedDomain(domain: AxisNumberDomain, dataRows: MdtChartsDataRow[]): import("../../../config/config").NumberDomain;
3
+ export declare function getScaleLinearDomain(configDomain: AxisNumberDomain, dataRows: MdtChartsDataRow[], configOptions: MdtChartsTwoDimensionalOptions, valueGroup?: TwoDimensionalValueGroup): number[];
3
4
  export declare class ScaleDomainCalculator {
4
5
  getScaleMinValue(charts: MdtChartsTwoDimensionalChart[], dataRows: MdtChartsDataRow[]): number;
5
6
  getScaleMaxValue(charts: MdtChartsTwoDimensionalChart[], dataRows: MdtChartsDataRow[]): number;
@@ -1,15 +1,25 @@
1
- export function getScaleLinearDomain(configDomain, dataRows, configOptions) {
1
+ export function getResolvedDomain(domain, dataRows) {
2
+ return typeof domain === 'function'
3
+ ? domain({ data: dataRows })
4
+ : domain;
5
+ }
6
+ export function getScaleLinearDomain(configDomain, dataRows, configOptions, valueGroup = 'main') {
2
7
  const calculator = new ScaleDomainCalculator();
3
8
  let domainPeekMin;
4
9
  let domainPeekMax;
5
- if (configDomain.start === -1)
10
+ const resolvedConfigDomain = getResolvedDomain(configDomain, dataRows);
11
+ const charts = configOptions.charts.filter(chart => {
12
+ var _a;
13
+ return ((_a = chart.data.valueGroup) !== null && _a !== void 0 ? _a : "main") === valueGroup;
14
+ });
15
+ if (resolvedConfigDomain.start === -1)
6
16
  domainPeekMin = calculator.getScaleMinValue(configOptions.charts, dataRows);
7
17
  else
8
- domainPeekMin = configDomain.start;
9
- if (configDomain.end === -1)
10
- domainPeekMax = calculator.getScaleMaxValue(configOptions.charts, dataRows);
18
+ domainPeekMin = resolvedConfigDomain.start;
19
+ if (resolvedConfigDomain.end === -1)
20
+ domainPeekMax = calculator.getScaleMaxValue(charts, dataRows);
11
21
  else
12
- domainPeekMax = configDomain.end;
22
+ domainPeekMax = resolvedConfigDomain.end;
13
23
  if (configOptions.axis.key.position === 'start')
14
24
  return [domainPeekMin, domainPeekMax];
15
25
  return [domainPeekMax, domainPeekMin];
@@ -9,5 +9,6 @@ export declare enum ScaleType {
9
9
  export declare class ScaleModel {
10
10
  getScaleKey(allowableKeys: string[], orient: ChartOrientation, canvasModel: CanvasModel, charts: MdtChartsTwoDimensionalChart[], barCharts: MdtChartsTwoDimensionalChart[]): ScaleKeyModel;
11
11
  getScaleLinear(options: MdtChartsTwoDimensionalOptions, dataRows: MdtChartsDataRow[], canvasModel: CanvasModel, configReader?: TwoDimConfigReader): ScaleValueModel;
12
+ getScaleSecondaryLinear(options: MdtChartsTwoDimensionalOptions, dataRows: MdtChartsDataRow[], canvasModel: CanvasModel, configReader?: TwoDimConfigReader): ScaleValueModel;
12
13
  private getScaleKeyType;
13
14
  }
@@ -29,6 +29,18 @@ export class ScaleModel {
29
29
  formatter: (_a = configReader === null || configReader === void 0 ? void 0 : configReader.getAxisLabelFormatter()) !== null && _a !== void 0 ? _a : null
30
30
  };
31
31
  }
32
+ getScaleSecondaryLinear(options, dataRows, canvasModel, configReader) {
33
+ var _a;
34
+ return {
35
+ domain: getScaleLinearDomain(options.axis.value.domain, dataRows, options, 'secondary'),
36
+ range: {
37
+ start: 0,
38
+ end: getScaleValueRangePeek(options.orientation, canvasModel)
39
+ },
40
+ type: "linear",
41
+ formatter: (_a = configReader === null || configReader === void 0 ? void 0 : configReader.getAxisLabelFormatter()) !== null && _a !== void 0 ? _a : null
42
+ };
43
+ }
32
44
  getScaleKeyType(charts) {
33
45
  if (charts.findIndex((chart) => chart.type === 'bar') === -1)
34
46
  return 'point';
@@ -1,7 +1,7 @@
1
- import { MdtChartsDataSource, IntervalChart } from "../../config/config";
2
1
  export declare class ModelHelper {
2
+ private static baseFontSize;
3
+ private static getBaseFontSize;
3
4
  static getSum(items: number[]): number;
4
- static getMinAndMaxOfIntervalData(data: MdtChartsDataSource, dataSource: string, chart: IntervalChart): [Date, Date];
5
5
  static getUniqueValues(values: string[]): string[];
6
6
  static getStringScore(word: string): number;
7
7
  }
@@ -1,25 +1,13 @@
1
+ import { DomHelper } from "../../engine/helpers/domHelper";
1
2
  export class ModelHelper {
3
+ static getBaseFontSize() {
4
+ if (!this.baseFontSize)
5
+ this.baseFontSize = parseInt(DomHelper.getCssPropertyValue(document.documentElement, '--chart-base-font-size'));
6
+ return this.baseFontSize;
7
+ }
2
8
  static getSum(items) {
3
9
  return items.reduce((acc, item) => acc + item, 0);
4
10
  }
5
- static getMinAndMaxOfIntervalData(data, dataSource, chart) {
6
- let min = data[dataSource][0][chart.data.valueField1.name];
7
- let max = data[dataSource][0][chart.data.valueField1.name];
8
- const chartData = data[dataSource];
9
- const valueField1 = chart.data.valueField1.name;
10
- const valueField2 = chart.data.valueField2.name;
11
- chartData.forEach(dataRow => {
12
- if (dataRow[valueField1] > max)
13
- max = dataRow[valueField1];
14
- if (dataRow[valueField1] < min)
15
- min = dataRow[valueField1];
16
- if (dataRow[valueField2] > max)
17
- max = dataRow[valueField2];
18
- if (dataRow[valueField2] < min)
19
- min = dataRow[valueField2];
20
- });
21
- return [min, max];
22
- }
23
11
  static getUniqueValues(values) {
24
12
  const uniqueValues = values.filter((keyValue, index, self) => self.indexOf(keyValue) === index);
25
13
  return uniqueValues;
@@ -27,11 +15,12 @@ export class ModelHelper {
27
15
  static getStringScore(word) {
28
16
  // lower case letter width ~ 0.8 from upper case width.
29
17
  // Number width == lower case letter width
18
+ const fontSize = this.getBaseFontSize();
30
19
  let score = 0;
31
- const upperLetterScore = 1;
32
- const lowerLetterScore = 0.8;
33
- const digitScore = 0.75;
34
- const otherSymbolScore = 0.52;
20
+ const upperLetterScore = fontSize / 13;
21
+ const lowerLetterScore = fontSize / 15;
22
+ const digitScore = fontSize / 15;
23
+ const otherSymbolScore = fontSize / 23;
35
24
  const specialSmallSymbols = [",", ".", " "];
36
25
  for (let i = 0; i < word.length; i++) {
37
26
  if (parseFloat(word[i]).toString() !== word[i] && !specialSmallSymbols.includes(word[i]) && word[i].trim().length > 0) {
@@ -11,7 +11,7 @@ export declare class TwoDimMarginModel {
11
11
  constructor(designerConfig: DesignerConfig, configReader: TwoDimConfigReader);
12
12
  recalcMargin(otherComponents: OtherCommonComponents, modelInstance: ModelInstance): void;
13
13
  recalcMarginByVerticalAxisLabel(modelInstance: ModelInstance): void;
14
- private getHorizontalMarginByAxisLabels;
14
+ private getMaxLabelSize;
15
15
  private recalcVerticalMarginByAxisLabelHeight;
16
16
  private recalcHorizontalMarginByAxisLabelWidth;
17
17
  }
@@ -14,7 +14,7 @@ export class TwoDimMarginModel {
14
14
  recalcMargin(otherComponents, modelInstance) {
15
15
  const canvasModel = modelInstance.canvasModel;
16
16
  this.twoDimLegendModel.recalcMarginWith2DLegend(modelInstance, otherComponents.legendBlock, this.configReader.options.legend);
17
- const labelSize = this.getHorizontalMarginByAxisLabels(modelInstance);
17
+ const labelSize = this.getMaxLabelSize(modelInstance);
18
18
  this.recalcVerticalMarginByAxisLabelHeight(labelSize, canvasModel);
19
19
  // Если встроенный лейбл показывает ключи, то лейблы оси ключей не показываются
20
20
  // При этом все графики должны иметь: embeddedLabels = 'key'
@@ -36,14 +36,14 @@ export class TwoDimMarginModel {
36
36
  }
37
37
  }
38
38
  }
39
- getHorizontalMarginByAxisLabels(modelInstance) {
39
+ getMaxLabelSize(modelInstance) {
40
40
  const keyAxisOrient = AxisModel.getAxisOrient(AxisType.Key, this.configReader.options.orientation, this.configReader.options.axis.key.position);
41
41
  let labelsTexts;
42
42
  if (keyAxisOrient === 'left' || keyAxisOrient === 'right') {
43
43
  labelsTexts = modelInstance.dataModel.repository.getValuesByKeyField();
44
44
  }
45
45
  else {
46
- labelsTexts = modelInstance.dataModel.repository.getBiggestValueAndDecremented(this.configReader.getFieldsBySegments())
46
+ labelsTexts = this.configReader.calculateBiggestValueAndDecremented(modelInstance.dataModel.repository)
47
47
  .map(v => this.configReader.getAxisLabelFormatter()(v).toString());
48
48
  }
49
49
  return AxisModel.getLabelSize(this.designerConfig.canvas.axisLabel.maxSize.main, labelsTexts);
@@ -1,4 +1,4 @@
1
- import { ChartOrientation, MdtChartsColorField, IntervalChartType, PolarChartType, Size, TooltipOptions, TwoDimensionalChartType, AxisLabelPosition, ShowTickFn } from "../config/config";
1
+ import { ChartOrientation, MdtChartsColorField, IntervalChartType, PolarChartType, Size, TooltipOptions, TwoDimensionalChartType, AxisLabelPosition, ShowTickFn, MdtChartsDataRow, TwoDimensionalValueGroup } from "../config/config";
2
2
  import { DataType, DonutOptionsCanvas, Formatter, StaticLegendBlockCanvas, TooltipSettings, Transitions } from "../designer/designerConfig";
3
3
  declare type AxisType = "key" | "value";
4
4
  export declare type Orient = "top" | "bottom" | "left" | "right";
@@ -80,6 +80,7 @@ export interface Field {
80
80
  export interface IScaleModel {
81
81
  key: ScaleKeyModel;
82
82
  value: ScaleValueModel;
83
+ valueSecondary?: ScaleValueModel;
83
84
  }
84
85
  export interface ScaleKeyModel {
85
86
  domain: any[];
@@ -209,7 +210,7 @@ export declare type LegendMarkerShape = "default" | "bar" | "line";
209
210
  export interface TwoDimensionalChartLegendBarModel extends TwoDimensionalBarLikeChartViewModel {
210
211
  width: number;
211
212
  }
212
- export interface TwoDimensionalChartLegendLineModel extends TwoDimensionalLineLikeChartViewModel {
213
+ export interface TwoDimensionalChartLegendLineModel extends Omit<TwoDimensionalLineLikeChartViewModel, 'renderForKey'> {
213
214
  width: number;
214
215
  }
215
216
  interface TwoDimensionalLineLikeChartModel {
@@ -218,7 +219,9 @@ interface TwoDimensionalLineLikeChartModel {
218
219
  }
219
220
  interface TwoDimensionalLineLikeChartViewModel {
220
221
  dashedStyles: LineLikeChartDashOptions;
222
+ renderForKey: LineLikeChartRenderOptions;
221
223
  }
224
+ export declare type LineLikeChartRenderOptions = (dataRow: MdtChartsDataRow, valueFieldName: string) => boolean;
222
225
  interface TwoDimensionalBarLikeChartModel {
223
226
  barViewOptions: TwoDimensionalBarLikeChartViewModel;
224
227
  }
@@ -244,6 +247,7 @@ export interface PolarChartModel extends ChartModel {
244
247
  }
245
248
  export interface TwoDimensionalChartDataModel {
246
249
  valueFields: ValueField[];
250
+ valueGroup?: TwoDimensionalValueGroup;
247
251
  }
248
252
  export interface ValueField extends Field {
249
253
  title: string;
@@ -76,7 +76,6 @@ export function assembleModel(config, data, designerConfig) {
76
76
  options: null,
77
77
  dataSettings: null
78
78
  };
79
- resetFalsyValues(data);
80
79
  const dataRows = modelInstance.dataModel.repository.getRawRows();
81
80
  const resolvedTitle = getResolvedTitle(config.options.title, dataRows);
82
81
  const otherComponents = OtherComponentsModel.getOtherComponentsModel({
@@ -104,19 +103,7 @@ export function assembleModel(config, data, designerConfig) {
104
103
  transitions
105
104
  };
106
105
  }
107
- function resetFalsyValues(data) {
108
- for (let setName in data) {
109
- data[setName].forEach(dataRow => {
110
- for (let fieldName in dataRow) {
111
- if (dataRow[fieldName] == null) {
112
- dataRow[fieldName] = 0;
113
- }
114
- }
115
- });
116
- }
117
- }
118
106
  export function getPreparedData(model, data, config) {
119
- resetFalsyValues(data);
120
107
  const isModelOrDataEmpty = !model || Object.keys(model).length === 0 || !data || Object.keys(data).length === 0;
121
108
  if (isModelOrDataEmpty)
122
109
  return null;
@@ -1,5 +1,6 @@
1
1
  import { AxisLabelFormatter, MdtChartsConfig, MdtChartsField, MdtChartsFieldName, MdtChartsTwoDimensionalOptions, TwoDimensionalChartType } from "../../config/config";
2
2
  import { DesignerConfig } from "../../designer/designerConfig";
3
+ import { DataRepositoryModel } from "../../model/modelInstance/dataModel/dataRepository";
3
4
  interface BaseConfigReader {
4
5
  getValueFields(): MdtChartsField[];
5
6
  }
@@ -9,6 +10,7 @@ export declare class TwoDimConfigReader implements BaseConfigReader {
9
10
  readonly options: MdtChartsTwoDimensionalOptions;
10
11
  constructor(config: MdtChartsConfig, designerConfig: DesignerConfig);
11
12
  getValueFields(): MdtChartsField[];
13
+ calculateBiggestValueAndDecremented(repository: DataRepositoryModel): number[];
12
14
  getFieldsBySegments(): MdtChartsFieldName[][];
13
15
  getAxisLabelFormatter(): AxisLabelFormatter;
14
16
  getLegendItemInfo(): {
@@ -1,3 +1,4 @@
1
+ import { getResolvedDomain } from "../../model/featuresModel/scaleModel/scaleDomainService";
1
2
  export function getConfigReader(config, designerConfig) {
2
3
  if (config.options.type === "2d")
3
4
  return new TwoDimConfigReader(config, designerConfig);
@@ -17,9 +18,18 @@ export class TwoDimConfigReader {
17
18
  });
18
19
  return fields;
19
20
  }
21
+ calculateBiggestValueAndDecremented(repository) {
22
+ const domain = this.options.axis.value.domain;
23
+ const resolvedDomain = getResolvedDomain(domain, repository.getRawRows());
24
+ if (resolvedDomain && resolvedDomain.end !== -1) {
25
+ return [resolvedDomain.end, resolvedDomain.end - 1];
26
+ }
27
+ return repository.getBiggestValueAndDecremented(this.getFieldsBySegments());
28
+ }
20
29
  getFieldsBySegments() {
21
30
  const segments = [];
22
- this.options.charts.forEach(chart => {
31
+ const mainCharts = this.options.charts.filter(chart => chart.data.valueGroup !== 'secondary');
32
+ mainCharts.forEach(chart => {
23
33
  if (!chart.isSegmented)
24
34
  segments.push(...chart.data.valueFields.map(vf => [vf.name]));
25
35
  else
@@ -14,6 +14,9 @@ export class TwoDimensionalModel {
14
14
  const scaleMarginRecalcer = new ScaleAxisRecalcer(() => scaleModel.getScaleLinear(options, modelInstance.dataModel.repository.getScopedRows(), canvasModel, configReader));
15
15
  scaleMarginRecalcer.recalculateMargin(canvasModel, options.orientation, options.axis.key);
16
16
  const scaleValueInfo = scaleMarginRecalcer.getScaleValue();
17
+ const secondaryScaleMarginRecalcer = new ScaleAxisRecalcer(() => scaleModel.getScaleSecondaryLinear(options, modelInstance.dataModel.repository.getScopedRows(), canvasModel, configReader));
18
+ secondaryScaleMarginRecalcer.recalculateMargin(canvasModel, options.orientation, options.axis.key);
19
+ const secondaryScaleValueInfo = secondaryScaleMarginRecalcer.getScaleValue();
17
20
  return {
18
21
  legend: canvasModel.legendCanvas.getModel(),
19
22
  title: resolvedTitle,
@@ -21,7 +24,8 @@ export class TwoDimensionalModel {
21
24
  orient: options.orientation,
22
25
  scale: {
23
26
  key: scaleModel.getScaleKey(modelInstance.dataModel.getAllowableKeys(), options.orientation, canvasModel, options.charts, this.getChartsByType(options.charts, 'bar')),
24
- value: scaleValueInfo.scale
27
+ value: scaleValueInfo.scale,
28
+ valueSecondary: secondaryScaleValueInfo.scale,
25
29
  },
26
30
  axis: {
27
31
  key: AxisModel.getKeyAxis(options, modelInstance.dataModel.repository.getScopedFullSource(), designerConfig.canvas.axisLabel, canvasModel, designerConfig.elementsOptions.tooltip, () => scaleValueInfo.scaleFn(0)),
@@ -85,7 +89,10 @@ export class TwoDimensionalModel {
85
89
  }
86
90
  }
87
91
  },
88
- lineViewOptions: { dashedStyles: parseDashStyles((_k = chart.lineStyles) === null || _k === void 0 ? void 0 : _k.dash) },
92
+ lineViewOptions: {
93
+ dashedStyles: parseDashStyles((_k = chart.lineStyles) === null || _k === void 0 ? void 0 : _k.dash),
94
+ renderForKey: (dataRow, valueFieldName) => dataRow[valueFieldName] !== null && dataRow[valueFieldName] !== undefined
95
+ },
89
96
  barViewOptions: { hatch: { on: (_o = (_m = (_l = chart.barStyles) === null || _l === void 0 ? void 0 : _l.hatch) === null || _m === void 0 ? void 0 : _m.on) !== null && _o !== void 0 ? _o : false } },
90
97
  legend: getLegendMarkerOptions(chart),
91
98
  index
@@ -1,3 +1,5 @@
1
+ @import './css-vars.css';
2
+
1
3
  .wrapper {
2
4
  margin: 0 auto;
3
5
  position: relative;
@@ -18,8 +20,8 @@
18
20
  .data-label {
19
21
  font-family: "Roboto";
20
22
  font-style: normal;
21
- font-weight: 300;
22
- font-size: 12px;
23
+ font-weight: 400;
24
+ font-size: var(--chart-base-font-size);
23
25
  line-height: 140.62%;
24
26
  color: #444444;
25
27
  cursor: default;
@@ -85,9 +87,9 @@
85
87
  }
86
88
 
87
89
  .legend-label {
88
- font-size: 12px;
90
+ font-size: var(--chart-base-font-size);
89
91
  font-family: "Roboto", sans-serif;
90
- font-weight: 300;
92
+ font-weight: 400;
91
93
  color: #444444;
92
94
  width: calc(100% - 19px);
93
95
  overflow: hidden;
@@ -130,7 +132,7 @@
130
132
  z-index: 102;
131
133
  max-width: 500px;
132
134
  background: rgba(0, 0, 0, 0.82);
133
- font-size: 11px;
135
+ font-size: var(--chart-base-font-size);
134
136
  }
135
137
  .mdt-charts-tooltip-arrow {
136
138
  width: 0;
@@ -169,7 +171,7 @@
169
171
  stroke-linecap: round;
170
172
  }
171
173
  .mdt-charts-tooltip-content .tooltip-head {
172
- font-size: 12px;
174
+ font-size: var(--chart-base-font-size);
173
175
  margin-bottom: 10px;
174
176
  }
175
177
  .mdt-charts-tooltip-content .tooltip-texts {
@@ -250,7 +252,7 @@
250
252
  font-family: "Roboto", sans-serif;
251
253
  font-style: normal;
252
254
  font-weight: 500;
253
- font-size: 12px;
255
+ font-size: var(--chart-base-font-size);
254
256
  line-height: 140.62%;
255
257
  }
256
258