mdt-charts 1.13.2 → 1.14.0

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 (82) hide show
  1. package/README.md +1 -189
  2. package/lib/config/config.d.ts +28 -6
  3. package/lib/designer/designerConfig.d.ts +20 -2
  4. package/lib/engine/block/blockSvg.d.ts +3 -1
  5. package/lib/engine/block/blockSvg.js +8 -3
  6. package/lib/engine/block/defs.d.ts +7 -0
  7. package/lib/engine/block/defs.js +18 -0
  8. package/lib/engine/cardsNotation/card/cardService.js +2 -2
  9. package/lib/engine/elementHighlighter/elementHighlighter.js +2 -1
  10. package/lib/engine/features/axis/axis.js +6 -3
  11. package/lib/engine/features/axis/axisHelper.d.ts +2 -2
  12. package/lib/engine/features/axis/axisHelper.js +6 -11
  13. package/lib/engine/features/axis/axisLabelDomHelper.js +9 -11
  14. package/lib/engine/features/legend/legend.d.ts +17 -12
  15. package/lib/engine/features/legend/legend.js +38 -22
  16. package/lib/engine/features/legend/legendDomHelper.d.ts +8 -4
  17. package/lib/engine/features/legend/legendDomHelper.js +20 -8
  18. package/lib/engine/features/legend/legendEventsManager.d.ts +2 -2
  19. package/lib/engine/features/legend/legendEventsManager.js +5 -5
  20. package/lib/engine/features/legend/legendHelper.d.ts +6 -3
  21. package/lib/engine/features/legend/legendHelper.js +5 -7
  22. package/lib/engine/features/legend/legendMarkerCreator.d.ts +21 -0
  23. package/lib/engine/features/legend/legendMarkerCreator.js +88 -0
  24. package/lib/engine/features/legend/legendWidthCalculator.d.ts +16 -0
  25. package/lib/engine/features/legend/legendWidthCalculator.js +119 -0
  26. package/lib/engine/features/tolltip/tooltip.js +2 -5
  27. package/lib/engine/features/tolltip/tooltipDomHelper.d.ts +4 -4
  28. package/lib/engine/features/tolltip/tooltipDomHelper.js +13 -26
  29. package/lib/engine/helpers/domHelper.js +1 -1
  30. package/lib/engine/helpers/pipeline/Pipeline.d.ts +9 -0
  31. package/lib/engine/helpers/pipeline/Pipeline.js +37 -0
  32. package/lib/engine/intervalNotation/intervalManager.js +0 -2
  33. package/lib/engine/polarNotation/polarManager.js +3 -3
  34. package/lib/engine/twoDimensionalNotation/bar/bar.d.ts +16 -13
  35. package/lib/engine/twoDimensionalNotation/bar/bar.js +30 -18
  36. package/lib/engine/twoDimensionalNotation/bar/barHelper.d.ts +3 -0
  37. package/lib/engine/twoDimensionalNotation/bar/barHelper.js +9 -0
  38. package/lib/engine/twoDimensionalNotation/line/line.d.ts +22 -11
  39. package/lib/engine/twoDimensionalNotation/line/line.js +33 -17
  40. package/lib/engine/twoDimensionalNotation/line/lineGenerator.d.ts +15 -0
  41. package/lib/engine/twoDimensionalNotation/line/lineGenerator.js +27 -0
  42. package/lib/engine/twoDimensionalNotation/line/lineHelper.d.ts +18 -4
  43. package/lib/engine/twoDimensionalNotation/line/lineHelper.js +26 -16
  44. package/lib/engine/twoDimensionalNotation/twoDimensionalManager.js +13 -12
  45. package/lib/model/featuresModel/axisModel.d.ts +2 -1
  46. package/lib/model/featuresModel/axisModel.js +11 -1
  47. package/lib/model/featuresModel/legendModel/legendModel.d.ts +2 -1
  48. package/lib/model/featuresModel/legendModel/legendModel.js +5 -1
  49. package/lib/model/featuresModel/otherComponents.d.ts +2 -1
  50. package/lib/model/featuresModel/otherComponents.js +1 -1
  51. package/lib/model/featuresModel/scaleModel/scaleModel.d.ts +2 -1
  52. package/lib/model/featuresModel/scaleModel/scaleModel.js +4 -2
  53. package/lib/model/margin/marginModel.d.ts +6 -3
  54. package/lib/model/margin/marginModel.js +12 -8
  55. package/lib/model/margin/twoDim/twoDimMarginModel.d.ts +6 -3
  56. package/lib/model/margin/twoDim/twoDimMarginModel.js +30 -29
  57. package/lib/model/model.d.ts +56 -4
  58. package/lib/model/model.js +7 -1
  59. package/lib/model/modelBuilder.js +11 -6
  60. package/lib/model/modelInstance/configReader.d.ts +19 -0
  61. package/lib/model/modelInstance/configReader.js +35 -0
  62. package/lib/model/modelInstance/dataModel/dataModel.d.ts +2 -2
  63. package/lib/model/modelInstance/dataModel/dataModel.js +0 -1
  64. package/lib/model/modelInstance/dataModel/dataRepository.d.ts +6 -2
  65. package/lib/model/modelInstance/dataModel/dataRepository.js +15 -2
  66. package/lib/model/modelInstance/modelInstance.d.ts +2 -1
  67. package/lib/model/modelInstance/modelInstance.js +6 -4
  68. package/lib/model/notations/cards/cardsChangeService.js +2 -2
  69. package/lib/model/notations/cards/cardsModelService.js +1 -1
  70. package/lib/model/notations/intervalModel.js +4 -3
  71. package/lib/model/notations/polar/polarModel.js +6 -1
  72. package/lib/model/notations/twoDimensional/styles.d.ts +6 -0
  73. package/lib/model/notations/twoDimensional/styles.js +41 -0
  74. package/lib/model/notations/twoDimensionalModel.d.ts +5 -5
  75. package/lib/model/notations/twoDimensionalModel.js +13 -8
  76. package/lib/style/charts-main.css +3 -0
  77. package/lib/style/charts-main.less +3 -0
  78. package/package.json +5 -5
  79. package/lib/engine/contentManager.d.ts +0 -9
  80. package/lib/engine/contentManager.js +0 -29
  81. package/lib/model/modelInstance/canvasModel/marginModelService.d.ts +0 -11
  82. package/lib/model/modelInstance/canvasModel/marginModelService.js +0 -26
@@ -1,19 +1,20 @@
1
1
  import { ValueFormatter, } from "../../valueFormatter";
2
2
  import { TooltipHelper } from './tooltipHelper';
3
3
  import { Helper } from '../../helpers/helper';
4
+ import { getMarkerCreator } from '../legend/legendMarkerCreator';
4
5
  export const ARROW_SIZE = 20;
5
6
  export const ARROW_DEFAULT_POSITION = 9;
6
7
  export const TOOLTIP_ARROW_PADDING_X = ARROW_DEFAULT_POSITION - (ARROW_SIZE * Math.sqrt(2) - ARROW_SIZE) / 2 + 14;
7
8
  export const TOOLTIP_ARROW_PADDING_Y = 13;
8
9
  export class TooltipDomHelper {
9
- static fillForMulty2DCharts(contentBlock, charts, data, dataOptions, keyValue, htmlHandler) {
10
+ static fillForMulti2DCharts(contentBlock, charts, data, dataOptions, keyValue, htmlHandler) {
10
11
  contentBlock.html('');
11
12
  if (!htmlHandler) {
12
13
  this.renderHead(contentBlock, keyValue);
13
14
  charts.forEach(chart => {
14
15
  chart.data.valueFields.forEach((field, index) => {
15
16
  const html = this.getTooltipItemHtml(data, dataOptions, keyValue, field);
16
- this.fillValuesContent(contentBlock, chart.style.elementColors[index % chart.style.elementColors.length], html);
17
+ this.fillValuesContent(contentBlock, chart.style.elementColors[index % chart.style.elementColors.length], html, this.getMarkerCreator(chart.legend));
17
18
  });
18
19
  });
19
20
  }
@@ -26,22 +27,7 @@ export class TooltipDomHelper {
26
27
  if (!htmlHandler) {
27
28
  this.renderHead(contentBlock, keyValue);
28
29
  const html = this.getTooltipItemHtml(data, dataOptions, keyValue, chart.data.valueField);
29
- this.fillValuesContent(contentBlock, markColor, html);
30
- }
31
- else {
32
- this.fillContentByFunction(contentBlock, data, dataOptions, keyValue, htmlHandler);
33
- }
34
- }
35
- static fillForIntervalChart(contentBlock, charts, data, dataOptions, keyValue, htmlHandler) {
36
- contentBlock.html('');
37
- if (!htmlHandler) {
38
- this.renderHead(contentBlock, keyValue);
39
- charts.forEach(chart => {
40
- let html = this.getTooltipItemHtml(data, dataOptions, keyValue, chart.data.valueField1);
41
- this.fillValuesContent(contentBlock, chart.style.elementColors[0 % chart.style.elementColors.length], html);
42
- html = this.getTooltipItemHtml(data, dataOptions, keyValue, chart.data.valueField2);
43
- this.fillValuesContent(contentBlock, chart.style.elementColors[0 % chart.style.elementColors.length], html);
44
- });
30
+ this.fillValuesContent(contentBlock, markColor, html, this.getMarkerCreator(chart.legend));
45
31
  }
46
32
  else {
47
33
  this.fillContentByFunction(contentBlock, data, dataOptions, keyValue, htmlHandler);
@@ -60,15 +46,13 @@ export class TooltipDomHelper {
60
46
  .attr('class', `${this.groupClass} ${this.headClass}`)
61
47
  .text(keyValue);
62
48
  }
63
- static fillValuesContent(contentBlock, markColor, tooltipHtml) {
49
+ static fillValuesContent(contentBlock, markColor, tooltipHtml, markerCreator) {
64
50
  const group = contentBlock.append('div')
65
51
  .attr('class', this.groupClass);
66
- if (markColor)
67
- group.append('div')
68
- .attr('class', 'tooltip-color')
69
- .append('span')
70
- .attr('class', 'tooltip-circle')
71
- .style('background-color', markColor);
52
+ if (markColor) {
53
+ const colorBlock = group.append('div').attr('class', 'tooltip-color');
54
+ markerCreator === null || markerCreator === void 0 ? void 0 : markerCreator.renderMarker(colorBlock, markColor);
55
+ }
72
56
  group.append('div')
73
57
  .attr('class', 'tooltip-texts')
74
58
  .append('div')
@@ -96,8 +80,11 @@ export class TooltipDomHelper {
96
80
  static setWhiteSpaceForTextBlocks(contentBlock) {
97
81
  contentBlock.selectAll(`.${this.textItemClass}`).style('white-space', 'pre-wrap');
98
82
  }
83
+ static getMarkerCreator(options) {
84
+ return getMarkerCreator(options, { default: { cssClass: TooltipDomHelper.tooltipLegendDefaultMarker } });
85
+ }
99
86
  }
100
87
  TooltipDomHelper.groupClass = 'tooltip-group';
101
88
  TooltipDomHelper.headClass = 'tooltip-head';
102
89
  TooltipDomHelper.textItemClass = 'tooltip-text-item';
103
- TooltipDomHelper.maxContentWidth = 500;
90
+ TooltipDomHelper.tooltipLegendDefaultMarker = 'tooltip-circle';
@@ -15,7 +15,7 @@ export class DomHelper {
15
15
  if (chart.type === 'line' || chart.type === 'area')
16
16
  return MarkDot.getMarkDotForChart(block, chart.cssClasses);
17
17
  else
18
- return Bar.getAllBarsForChart(block, chart.cssClasses);
18
+ return Bar.get().getAllBarsForChart(block, chart.cssClasses);
19
19
  }
20
20
  static getCssPropertyValue(node, propertyName) {
21
21
  return window.getComputedStyle(node).getPropertyValue(propertyName);
@@ -0,0 +1,9 @@
1
+ declare type Middleware<D, M> = (args: D, meta?: M) => D | undefined;
2
+ export declare class Pipeline<D = any, M = any> {
3
+ private middlewaresStorage;
4
+ constructor(middlewares?: Middleware<D, M>[]);
5
+ push(middleware: Middleware<D, M>): () => void;
6
+ remove(middleware: Middleware<D, M>): void;
7
+ execute<CurrentArgs extends D = D>(args: CurrentArgs, meta?: M): CurrentArgs;
8
+ }
9
+ export {};
@@ -0,0 +1,37 @@
1
+ export class Pipeline {
2
+ constructor(middlewares) {
3
+ this.middlewaresStorage = new PipelineMiddlewaresStorage(middlewares);
4
+ }
5
+ push(middleware) {
6
+ return this.middlewaresStorage.push(middleware);
7
+ }
8
+ remove(middleware) {
9
+ this.middlewaresStorage.remove(middleware);
10
+ }
11
+ execute(args, meta) {
12
+ const process = (args, middlewares) => {
13
+ const current = middlewares[0];
14
+ if (!current) {
15
+ return args;
16
+ }
17
+ const replaceArgs = current(args, meta);
18
+ return process(replaceArgs === undefined ? args : replaceArgs, middlewares.slice(1));
19
+ };
20
+ return process(args, this.middlewaresStorage.getList());
21
+ }
22
+ }
23
+ class PipelineMiddlewaresStorage {
24
+ constructor(middlewares) {
25
+ this.middlewares = middlewares || [];
26
+ }
27
+ push(middleware) {
28
+ this.middlewares.push(middleware);
29
+ return () => this.remove(middleware);
30
+ }
31
+ remove(middleware) {
32
+ this.middlewares = this.middlewares.filter((cur) => cur != middleware);
33
+ }
34
+ getList() {
35
+ return this.middlewares;
36
+ }
37
+ }
@@ -1,6 +1,5 @@
1
1
  import { Axis } from "../features/axis/axis";
2
2
  import { GridLine } from "../features/gridLine/gridLine";
3
- import { Legend } from "../features/legend/legend";
4
3
  import { Scale } from "../features/scale/scale";
5
4
  import { Title } from "../features/title/title";
6
5
  import { Gantt } from "./gantt";
@@ -13,7 +12,6 @@ export class IntervalManager {
13
12
  GridLine.render(block, options.additionalElements.gridLine.flag, options.axis, model.blockCanvas.size, model.chartBlock.margin, scales);
14
13
  this.renderCharts(block, options.charts, scales, data, options.data, model.chartBlock.margin, options.axis.key.orient, options.chartSettings);
15
14
  Title.render(block, options.title, model.otherComponents.titleBlock, model.blockCanvas.size);
16
- Legend.render(block, data, options, model);
17
15
  }
18
16
  static renderCharts(block, charts, scales, data, dataOptions, margin, keyAxisOrient, chartSettings) {
19
17
  block.svg.renderChartsBlock();
@@ -11,7 +11,7 @@ export class PolarManager {
11
11
  engine.block.svg.render(model.blockCanvas.size);
12
12
  this.renderCharts(engine.block, options.charts, engine.data, options.data.dataSource, model.chartBlock.margin, model.blockCanvas.size, options.chartCanvas);
13
13
  Title.render(engine.block, options.title, model.otherComponents.titleBlock, model.blockCanvas.size);
14
- Legend.render(engine.block, engine.data, options, model);
14
+ Legend.get().render(engine.block, engine.data, options, model);
15
15
  Tooltip.render(engine.block, model, engine.data, model.otherComponents.tooltipBlock);
16
16
  engine.block.filterEventManager.setListenerPolar(model.chartBlock.margin, model.blockCanvas.size, options);
17
17
  if (model.dataSettings.scope.hidedRecordsAmount !== 0)
@@ -40,14 +40,14 @@ export class PolarManager {
40
40
  block.filterEventManager.setListenerPolar(model.chartBlock.margin, model.blockCanvas.size, options);
41
41
  });
42
42
  Aggregator.update(block, options.charts[0].data.valueField, options.chartCanvas.aggregator);
43
- Legend.update(block, data, model);
43
+ Legend.get().update(block, data, model);
44
44
  PolarRecordOverflowAlert.update(block, {
45
45
  hidedRecordsAmount: model.dataSettings.scope.hidedRecordsAmount,
46
46
  legendPosition: model.options.legend.position
47
47
  });
48
48
  }
49
49
  updateColors(block, model) {
50
- Legend.updateColors(block, model.options);
50
+ Legend.get().updateColors(block, model.options);
51
51
  Donut.updateColors(block, model.options.charts[0]);
52
52
  }
53
53
  renderCharts(block, charts, data, dataSource, margin, blockSize, donutSettings) {
@@ -15,20 +15,23 @@ export interface RectElemWithAttrs extends SVGElement {
15
15
  }
16
16
  export declare class Bar {
17
17
  static readonly barItemClass = "bar-item";
18
- static readonly barItemCloneClass = "bar-item-clone";
19
- private static readonly barSegmentGroupClass;
20
- static render(block: Block, scales: Scales, data: MdtChartsDataRow[], keyField: Field, margin: BlockMargin, keyAxisOrient: Orient, chart: TwoDimensionalChartModel, blockSize: Size, barSettings: BarChartSettings, barsAmounts: number[], isSegmented: boolean, firstBarIndex: number): void;
21
- static update(block: Block, newData: MdtChartsDataRow[], scales: Scales, margin: BlockMargin, keyAxisOrient: Orient, chart: TwoDimensionalChartModel, blockSize: Size, barsAmounts: number[], keyField: Field, firstBarIndex: number, barSettings: BarChartSettings, isSegmented: boolean): Promise<any>[];
22
- static updateColors(block: Block, chart: TwoDimensionalChartModel): void;
23
- static getAllBarsForChart(block: Block, chartCssClasses: string[]): Selection<BaseType, MdtChartsDataRow, BaseType, unknown>;
24
- private static renderGrouped;
25
- private static renderSegmented;
26
- private static updateGrouped;
27
- private static updateSegmented;
28
- private static fillBarAttrs;
29
- private static setSegmentColor;
18
+ static get(): Bar;
19
+ private readonly barItemClass;
20
+ private readonly barSegmentGroupClass;
21
+ private createBarPipeline;
22
+ constructor();
23
+ render(block: Block, scales: Scales, data: MdtChartsDataRow[], keyField: Field, margin: BlockMargin, keyAxisOrient: Orient, chart: TwoDimensionalChartModel, blockSize: Size, barSettings: BarChartSettings, barsAmounts: number[], isSegmented: boolean, firstBarIndex: number): void;
24
+ update(block: Block, newData: MdtChartsDataRow[], scales: Scales, margin: BlockMargin, keyAxisOrient: Orient, chart: TwoDimensionalChartModel, blockSize: Size, barsAmounts: number[], keyField: Field, firstBarIndex: number, barSettings: BarChartSettings, isSegmented: boolean): Promise<any>[];
25
+ updateColors(block: Block, chart: TwoDimensionalChartModel): void;
26
+ getAllBarsForChart(block: Block, chartCssClasses: string[]): Selection<BaseType, MdtChartsDataRow, BaseType, unknown>;
27
+ private renderGrouped;
28
+ private renderSegmented;
29
+ private updateGrouped;
30
+ private updateSegmented;
31
+ private fillBarAttrs;
32
+ private setSegmentColor;
30
33
  /**
31
34
  * Устнановка координат для удобного обновления.
32
35
  */
33
- private static setInitialAttrsInfo;
36
+ private setInitialAttrsInfo;
34
37
  }
@@ -1,19 +1,29 @@
1
1
  import { select } from 'd3-selection';
2
2
  import { EmbeddedLabels } from "../../features/embeddedLabels/embeddedLabels";
3
3
  import { EmbeddedLabelsHelper } from "../../features/embeddedLabels/embeddedLabelsHelper";
4
- import { BarHelper } from "./barHelper";
4
+ import { BarHelper, onBarChartInit } from "./barHelper";
5
5
  import { sum } from "d3-array";
6
6
  import { DomHelper } from "../../helpers/domHelper";
7
7
  import { Helper } from "../../helpers/helper";
8
8
  import { getStackedDataWithOwn } from './stackedData/dataStacker';
9
+ import { Pipeline } from '../../helpers/pipeline/Pipeline';
9
10
  export class Bar {
10
- static render(block, scales, data, keyField, margin, keyAxisOrient, chart, blockSize, barSettings, barsAmounts, isSegmented, firstBarIndex) {
11
+ constructor() {
12
+ this.barItemClass = Bar.barItemClass;
13
+ this.barSegmentGroupClass = 'bar-segment-group';
14
+ this.createBarPipeline = new Pipeline();
15
+ onBarChartInit(this.createBarPipeline);
16
+ }
17
+ static get() {
18
+ return new Bar();
19
+ }
20
+ render(block, scales, data, keyField, margin, keyAxisOrient, chart, blockSize, barSettings, barsAmounts, isSegmented, firstBarIndex) {
11
21
  if (isSegmented)
12
22
  this.renderSegmented(block, scales, data, keyField, margin, keyAxisOrient, chart, barsAmounts, blockSize, firstBarIndex, barSettings);
13
23
  else
14
24
  this.renderGrouped(block, scales, data, keyField, margin, keyAxisOrient, chart, barsAmounts, blockSize, firstBarIndex, barSettings);
15
25
  }
16
- static update(block, newData, scales, margin, keyAxisOrient, chart, blockSize, barsAmounts, keyField, firstBarIndex, barSettings, isSegmented) {
26
+ update(block, newData, scales, margin, keyAxisOrient, chart, blockSize, barsAmounts, keyField, firstBarIndex, barSettings, isSegmented) {
17
27
  let promises;
18
28
  if (isSegmented) {
19
29
  promises = this.updateSegmented(block, newData, scales, margin, keyAxisOrient, chart, blockSize, barsAmounts, keyField, firstBarIndex, barSettings);
@@ -23,25 +33,26 @@ export class Bar {
23
33
  }
24
34
  return promises;
25
35
  }
26
- static updateColors(block, chart) {
36
+ updateColors(block, chart) {
27
37
  chart.data.valueFields.forEach((_vf, index) => {
28
38
  const bars = block.svg.getChartGroup(chart.index)
29
39
  .selectAll(`.${this.barItemClass}${Helper.getCssClassesLine(chart.cssClasses)}${Helper.getCssClassesLine(Helper.getCssClassesWithElementIndex(chart.cssClasses, index))}`);
30
40
  DomHelper.setChartStyle(bars, chart.style, index, 'fill');
31
41
  });
32
42
  }
33
- static getAllBarsForChart(block, chartCssClasses) {
43
+ getAllBarsForChart(block, chartCssClasses) {
34
44
  return block.getSvg().selectAll(`rect.${this.barItemClass}${Helper.getCssClassesLine(chartCssClasses)}`);
35
45
  }
36
- static renderGrouped(block, scales, data, keyField, margin, keyAxisOrient, chart, barsAmounts, blockSize, firstBarIndex, barSettings) {
46
+ renderGrouped(block, scales, data, keyField, margin, keyAxisOrient, chart, barsAmounts, blockSize, firstBarIndex, barSettings) {
37
47
  chart.data.valueFields.forEach((field, index) => {
38
- const bars = block.svg.getChartGroup(chart.index)
48
+ let bars = block.svg.getChartGroup(chart.index)
39
49
  .selectAll(`.${this.barItemClass}${Helper.getCssClassesLine(chart.cssClasses)}${Helper.getCssClassesLine(Helper.getCssClassesWithElementIndex(chart.cssClasses, index))}`)
40
50
  .data(data)
41
51
  .enter()
42
52
  .append('rect')
43
53
  .attr('class', this.barItemClass)
44
54
  .style('clip-path', `url(#${block.svg.getClipPathId()})`);
55
+ bars = this.createBarPipeline.execute(bars, chart);
45
56
  const barAttrs = BarHelper.getGroupedBarAttrs(keyAxisOrient, scales, margin, keyField.name, field.name, blockSize, BarHelper.getBarIndex(barsAmounts, chart.index - firstBarIndex) + index, sum(barsAmounts), barSettings);
46
57
  this.fillBarAttrs(bars, barAttrs);
47
58
  DomHelper.setCssClasses(bars, Helper.getCssClassesWithElementIndex(chart.cssClasses, index));
@@ -51,7 +62,7 @@ export class Bar {
51
62
  EmbeddedLabels.render(block, bars, barAttrs, EmbeddedLabelsHelper.getLabelField(chart.embeddedLabels, chart.data.valueFields, keyField, index), chart.embeddedLabels, keyAxisOrient, blockSize, margin, index, chart.cssClasses);
52
63
  });
53
64
  }
54
- static renderSegmented(block, scales, data, keyField, margin, keyAxisOrient, chart, barsAmounts, blockSize, firstBarIndex, barSettings) {
65
+ renderSegmented(block, scales, data, keyField, margin, keyAxisOrient, chart, barsAmounts, blockSize, firstBarIndex, barSettings) {
55
66
  const stackedData = getStackedDataWithOwn(data, chart.data.valueFields.map(field => field.name));
56
67
  let groups = block.svg.getChartGroup(chart.index)
57
68
  .selectAll(`g.${this.barSegmentGroupClass}${Helper.getCssClassesLine(chart.cssClasses)}`)
@@ -62,13 +73,14 @@ export class Bar {
62
73
  .enter()
63
74
  .append('g')
64
75
  .attr('class', this.barSegmentGroupClass);
65
- const bars = groups
76
+ let bars = groups
66
77
  .selectAll(`rect${Helper.getCssClassesLine(chart.cssClasses)}`)
67
78
  .data(d => d)
68
79
  .enter()
69
80
  .append('rect')
70
81
  .attr('class', this.barItemClass)
71
82
  .style('clip-path', `url(#${block.svg.getClipPathId()})`);
83
+ bars = this.createBarPipeline.execute(bars, chart);
72
84
  const barAttrs = BarHelper.getStackedBarAttr(keyAxisOrient, scales, margin, keyField.name, blockSize, BarHelper.getBarIndex(barsAmounts, chart.index) - firstBarIndex, sum(barsAmounts), barSettings);
73
85
  this.fillBarAttrs(bars, barAttrs);
74
86
  this.setInitialAttrsInfo(bars, keyAxisOrient, barSettings);
@@ -80,7 +92,7 @@ export class Bar {
80
92
  thisClass.setSegmentColor(select(this).selectAll(Helper.getCssClassesLine(chart.cssClasses)), chart.style.elementColors, i);
81
93
  });
82
94
  }
83
- static updateGrouped(block, newData, scales, margin, keyAxisOrient, chart, blockSize, barsAmounts, keyField, firstBarIndex, barSettings) {
95
+ updateGrouped(block, newData, scales, margin, keyAxisOrient, chart, blockSize, barsAmounts, keyField, firstBarIndex, barSettings) {
84
96
  const promises = [];
85
97
  chart.data.valueFields.forEach((valueField, index) => {
86
98
  const indexesOfRemoved = [];
@@ -102,11 +114,12 @@ export class Bar {
102
114
  .filter(d => newData.findIndex(row => row[keyField.name] === d[keyField.name]) !== -1)
103
115
  .style('opacity', 1)
104
116
  .data(newData);
105
- const newBars = bars
117
+ let newBars = bars
106
118
  .enter()
107
119
  .append('rect')
108
120
  .attr('class', this.barItemClass)
109
121
  .style('clip-path', `url(#${block.svg.getClipPathId()})`);
122
+ newBars = this.createBarPipeline.execute(newBars, chart);
110
123
  const barAttrs = BarHelper.getGroupedBarAttrs(keyAxisOrient, scales, margin, keyField.name, valueField.name, blockSize, BarHelper.getBarIndex(barsAmounts, chart.index) + index - firstBarIndex, sum(barsAmounts), barSettings);
111
124
  const prom = this.fillBarAttrs(bars, barAttrs, block.transitionManager.durations.chartUpdate)
112
125
  .then(() => {
@@ -128,7 +141,7 @@ export class Bar {
128
141
  });
129
142
  return promises;
130
143
  }
131
- static updateSegmented(block, newData, scales, margin, keyAxisOrient, chart, blockSize, barsAmounts, keyField, firstBarIndex, barSettings) {
144
+ updateSegmented(block, newData, scales, margin, keyAxisOrient, chart, blockSize, barsAmounts, keyField, firstBarIndex, barSettings) {
132
145
  const stackedData = getStackedDataWithOwn(newData, chart.data.valueFields.map(field => field.name));
133
146
  block.svg.getChartGroup(chart.index)
134
147
  .selectAll(`.${this.barItemClass}${Helper.getCssClassesLine(chart.cssClasses)}`)
@@ -145,10 +158,11 @@ export class Bar {
145
158
  .filter(d => newData.findIndex(row => row[keyField.name] === d.data[keyField.name]) !== -1)
146
159
  .style('opacity', 1)
147
160
  .data(d => d);
148
- const newBars = bars.enter()
161
+ let newBars = bars.enter()
149
162
  .append('rect')
150
163
  .attr('class', this.barItemClass)
151
164
  .style('clip-path', `url(#${block.svg.getClipPathId()})`);
165
+ newBars = this.createBarPipeline.execute(newBars, chart);
152
166
  const barAttrs = BarHelper.getStackedBarAttr(keyAxisOrient, scales, margin, keyField.name, blockSize, BarHelper.getBarIndex(barsAmounts, chart.index) - firstBarIndex, sum(barsAmounts), barSettings);
153
167
  const prom = this.fillBarAttrs(bars, barAttrs, block.transitionManager.durations.chartUpdate)
154
168
  .then(() => {
@@ -165,7 +179,7 @@ export class Bar {
165
179
  });
166
180
  return [prom];
167
181
  }
168
- static fillBarAttrs(bars, barAttrs, transitionDuration = 0) {
182
+ fillBarAttrs(bars, barAttrs, transitionDuration = 0) {
169
183
  return new Promise((resolve) => {
170
184
  if (bars.size() === 0) {
171
185
  resolve('');
@@ -187,13 +201,13 @@ export class Bar {
187
201
  resolve('');
188
202
  });
189
203
  }
190
- static setSegmentColor(segments, colorPalette, segmentedIndex) {
204
+ setSegmentColor(segments, colorPalette, segmentedIndex) {
191
205
  segments.style('fill', colorPalette[segmentedIndex % colorPalette.length]);
192
206
  }
193
207
  /**
194
208
  * Устнановка координат для удобного обновления.
195
209
  */
196
- static setInitialAttrsInfo(bars, keyAxisOrient, barSettings) {
210
+ setInitialAttrsInfo(bars, keyAxisOrient, barSettings) {
197
211
  bars.each(function () {
198
212
  const width = DomHelper.getSelectionNumericAttr(select(this), 'width');
199
213
  const height = DomHelper.getSelectionNumericAttr(select(this), 'height');
@@ -212,5 +226,3 @@ export class Bar {
212
226
  }
213
227
  }
214
228
  Bar.barItemClass = 'bar-item';
215
- Bar.barItemCloneClass = 'bar-item-clone';
216
- Bar.barSegmentGroupClass = 'bar-segment-group';
@@ -1,6 +1,8 @@
1
1
  import { BarChartSettings, BlockMargin, Orient, TwoDimensionalChartModel } from "../../../model/model";
2
2
  import { Scales } from "../../features/scale/scale";
3
3
  import { MdtChartsDataRow, Size } from "../../../config/config";
4
+ import { Pipeline } from "../../helpers/pipeline/Pipeline";
5
+ import { BaseType, Selection } from "d3-selection";
4
6
  export interface BarAttrsHelper {
5
7
  x: (dataRow: MdtChartsDataRow) => number;
6
8
  y: (dataRow: MdtChartsDataRow) => number;
@@ -22,3 +24,4 @@ export declare class BarHelper {
22
24
  private static setGroupedBarAttrsByValue;
23
25
  private static setSegmentedBarAttrsByValue;
24
26
  }
27
+ export declare function onBarChartInit(createBarPipeline: Pipeline<Selection<SVGRectElement, any, BaseType, any>, TwoDimensionalChartModel>): void;
@@ -1,5 +1,6 @@
1
1
  import { Scale } from "../../features/scale/scale";
2
2
  import { Helper } from "../../helpers/helper";
3
+ import { HatchPatternDef } from "../../block/defs";
3
4
  export class BarHelper {
4
5
  static getGroupedBarAttrs(keyAxisOrient, scales, margin, keyField, valueFieldName, blockSize, barIndex, barsAmount, barSettings) {
5
6
  const attrs = {
@@ -101,3 +102,11 @@ export class BarHelper {
101
102
  }
102
103
  }
103
104
  }
105
+ export function onBarChartInit(createBarPipeline) {
106
+ createBarPipeline.push(hatchBar);
107
+ }
108
+ function hatchBar(bars, chart) {
109
+ if (chart.barViewOptions.hatch.on)
110
+ bars.style("mask", HatchPatternDef.getMaskValue());
111
+ return bars;
112
+ }
@@ -1,17 +1,28 @@
1
- import { BlockMargin, Field, Orient, TwoDimensionalChartModel } from "../../../model/model";
1
+ import { BaseType, Selection } from 'd3-selection';
2
+ import { BlockMargin, Field, LineLikeChartSettings, Orient, TwoDimensionalChartModel } from "../../../model/model";
2
3
  import { Scales } from "../../features/scale/scale";
3
4
  import { Block } from "../../block/block";
4
5
  import { MdtChartsDataRow } from '../../../config/config';
6
+ import { Pipeline } from '../../helpers/pipeline/Pipeline';
7
+ interface LineChartOptions {
8
+ staticSettings: LineLikeChartSettings;
9
+ }
5
10
  export declare class Line {
11
+ private options;
6
12
  static readonly lineChartClass = "line";
7
- static render(block: Block, scales: Scales, data: MdtChartsDataRow[], keyField: Field, margin: BlockMargin, keyAxisOrient: Orient, chart: TwoDimensionalChartModel): void;
8
- static update(block: Block, scales: Scales, newData: MdtChartsDataRow[], keyField: Field, margin: BlockMargin, keyAxisOrient: Orient, chart: TwoDimensionalChartModel): Promise<any>[];
9
- static updateColors(block: Block, chart: TwoDimensionalChartModel): void;
10
- private static renderGrouped;
11
- private static renderSegmented;
12
- private static updateGrouped;
13
- private static updateSegmented;
14
- private static updateGroupedPath;
15
- private static updateSegmentedPath;
16
- private static setSegmentColor;
13
+ readonly creatingPipeline: Pipeline<Selection<SVGPathElement, any, BaseType, any>, TwoDimensionalChartModel>;
14
+ private readonly lineChartClass;
15
+ static get(options: LineChartOptions): Line;
16
+ constructor(options: LineChartOptions);
17
+ render(block: Block, scales: Scales, data: MdtChartsDataRow[], keyField: Field, margin: BlockMargin, keyAxisOrient: Orient, chart: TwoDimensionalChartModel): void;
18
+ update(block: Block, scales: Scales, newData: MdtChartsDataRow[], keyField: Field, margin: BlockMargin, keyAxisOrient: Orient, chart: TwoDimensionalChartModel): Promise<any>[];
19
+ updateColors(block: Block, chart: TwoDimensionalChartModel): void;
20
+ private renderGrouped;
21
+ private renderSegmented;
22
+ private updateGrouped;
23
+ private updateSegmented;
24
+ private updateGroupedPath;
25
+ private updateSegmentedPath;
26
+ private setSegmentColor;
17
27
  }
28
+ export {};
@@ -1,17 +1,27 @@
1
1
  import { stack } from 'd3-shape';
2
2
  import { select } from 'd3-selection';
3
3
  import { MarkDot } from "../../features/markDots/markDot";
4
- import { LineHelper } from './lineHelper';
4
+ import { LineGeneratorFactory, onLineChartInit } from './lineHelper';
5
5
  import { DomHelper } from '../../helpers/domHelper';
6
6
  import { Helper } from '../../helpers/helper';
7
+ import { Pipeline } from '../../helpers/pipeline/Pipeline';
7
8
  export class Line {
8
- static render(block, scales, data, keyField, margin, keyAxisOrient, chart) {
9
+ constructor(options) {
10
+ this.options = options;
11
+ this.creatingPipeline = new Pipeline();
12
+ this.lineChartClass = Line.lineChartClass; //TODO: remove after refactor
13
+ onLineChartInit(this.creatingPipeline);
14
+ }
15
+ static get(options) {
16
+ return new Line(options);
17
+ }
18
+ render(block, scales, data, keyField, margin, keyAxisOrient, chart) {
9
19
  if (chart.isSegmented)
10
20
  this.renderSegmented(block, scales, data, keyField, margin, keyAxisOrient, chart);
11
21
  else
12
22
  this.renderGrouped(block, scales, data, keyField, margin, keyAxisOrient, chart);
13
23
  }
14
- static update(block, scales, newData, keyField, margin, keyAxisOrient, chart) {
24
+ update(block, scales, newData, keyField, margin, keyAxisOrient, chart) {
15
25
  let promises;
16
26
  if (chart.isSegmented) {
17
27
  promises = this.updateSegmented(block, scales, newData, keyField, margin, keyAxisOrient, chart);
@@ -21,7 +31,7 @@ export class Line {
21
31
  }
22
32
  return promises;
23
33
  }
24
- static updateColors(block, chart) {
34
+ updateColors(block, chart) {
25
35
  chart.data.valueFields.forEach((_vf, valueIndex) => {
26
36
  const path = block.svg.getChartGroup(chart.index)
27
37
  .select(`.${this.lineChartClass}${Helper.getCssClassesLine(chart.cssClasses)}.chart-element-${valueIndex}`);
@@ -29,25 +39,28 @@ export class Line {
29
39
  MarkDot.updateColors(block, chart, valueIndex);
30
40
  });
31
41
  }
32
- static renderGrouped(block, scales, data, keyField, margin, keyAxisOrient, chart) {
42
+ renderGrouped(block, scales, data, keyField, margin, keyAxisOrient, chart) {
43
+ const generatorFactory = new LineGeneratorFactory({ keyAxisOrient, scales, keyFieldName: keyField.name, margin, curve: this.options.staticSettings.shape.curve.type });
33
44
  chart.data.valueFields.forEach((valueField, valueIndex) => {
34
- const lineGenerator = LineHelper.getLineGenerator(keyAxisOrient, scales, keyField.name, valueField.name, margin);
35
- const path = block.svg.getChartGroup(chart.index)
45
+ const lineGenerator = generatorFactory.getLineGenerator(valueField.name);
46
+ let path = block.svg.getChartGroup(chart.index)
36
47
  .append('path')
37
48
  .attr('d', lineGenerator(data))
38
49
  .attr('class', this.lineChartClass)
39
50
  .style('fill', 'none')
40
51
  .style('clip-path', `url(#${block.svg.getClipPathId()})`)
41
52
  .style('pointer-events', 'none');
53
+ path = this.creatingPipeline.execute(path, chart);
42
54
  DomHelper.setCssClasses(path, Helper.getCssClassesWithElementIndex(chart.cssClasses, valueIndex));
43
55
  DomHelper.setChartStyle(path, chart.style, valueIndex, 'stroke');
44
56
  MarkDot.render(block, data, keyAxisOrient, scales, margin, keyField.name, valueIndex, valueField.name, chart);
45
57
  });
46
58
  }
47
- static renderSegmented(block, scales, data, keyField, margin, keyAxisOrient, chart) {
59
+ renderSegmented(block, scales, data, keyField, margin, keyAxisOrient, chart) {
48
60
  const stackedData = stack().keys(chart.data.valueFields.map(field => field.name))(data);
49
- const lineGenerator = LineHelper.getSegmentedLineGenerator(keyAxisOrient, scales, keyField.name, margin);
50
- const lines = block.svg.getChartGroup(chart.index)
61
+ const generatorFactory = new LineGeneratorFactory({ keyAxisOrient, scales, keyFieldName: keyField.name, margin, curve: this.options.staticSettings.shape.curve.type });
62
+ const lineGenerator = generatorFactory.getSegmentedLineGenerator();
63
+ let lines = block.svg.getChartGroup(chart.index)
51
64
  .selectAll(`.${this.lineChartClass}${Helper.getCssClassesLine(chart.cssClasses)}`)
52
65
  .data(stackedData)
53
66
  .enter()
@@ -57,6 +70,7 @@ export class Line {
57
70
  .style('fill', 'none')
58
71
  .style('clip-path', `url(#${block.svg.getClipPathId()})`)
59
72
  .style('pointer-events', 'none');
73
+ lines = this.creatingPipeline.execute(lines, chart);
60
74
  lines.each(function (d, i) {
61
75
  DomHelper.setCssClasses(select(this), Helper.getCssClassesWithElementIndex(chart.cssClasses, i));
62
76
  });
@@ -65,10 +79,11 @@ export class Line {
65
79
  MarkDot.render(block, dataset, keyAxisOrient, scales, margin, keyField.name, stackIndex, '1', chart);
66
80
  });
67
81
  }
68
- static updateGrouped(block, scales, newData, keyField, margin, keyAxisOrient, chart) {
82
+ updateGrouped(block, scales, newData, keyField, margin, keyAxisOrient, chart) {
69
83
  const promises = [];
84
+ const generatorFactory = new LineGeneratorFactory({ keyAxisOrient, scales, keyFieldName: keyField.name, margin, curve: this.options.staticSettings.shape.curve.type });
70
85
  chart.data.valueFields.forEach((valueField, valueFieldIndex) => {
71
- const lineGenerator = LineHelper.getLineGenerator(keyAxisOrient, scales, keyField.name, valueField.name, margin);
86
+ const lineGenerator = generatorFactory.getLineGenerator(valueField.name);
72
87
  const lineObject = block.svg.getChartGroup(chart.index)
73
88
  .select(`.${this.lineChartClass}${Helper.getCssClassesLine(chart.cssClasses)}.chart-element-${valueFieldIndex}`);
74
89
  const prom = this.updateGroupedPath(block, lineObject, lineGenerator, newData);
@@ -77,9 +92,10 @@ export class Line {
77
92
  });
78
93
  return promises;
79
94
  }
80
- static updateSegmented(block, scales, newData, keyField, margin, keyAxisOrient, chart) {
95
+ updateSegmented(block, scales, newData, keyField, margin, keyAxisOrient, chart) {
81
96
  const stackedData = stack().keys(chart.data.valueFields.map(field => field.name))(newData);
82
- const lineGenerator = LineHelper.getSegmentedLineGenerator(keyAxisOrient, scales, keyField.name, margin);
97
+ const generatorFactory = new LineGeneratorFactory({ keyAxisOrient, scales, keyFieldName: keyField.name, margin, curve: this.options.staticSettings.shape.curve.type });
98
+ const lineGenerator = generatorFactory.getSegmentedLineGenerator();
83
99
  const lines = block.svg.getChartGroup(chart.index)
84
100
  .selectAll(`path.${this.lineChartClass}${Helper.getCssClassesLine(chart.cssClasses)}`)
85
101
  .data(stackedData);
@@ -89,7 +105,7 @@ export class Line {
89
105
  });
90
106
  return [prom];
91
107
  }
92
- static updateGroupedPath(block, lineObject, lineGenerator, newData) {
108
+ updateGroupedPath(block, lineObject, lineGenerator, newData) {
93
109
  return new Promise(resolve => {
94
110
  if (lineObject.size() === 0) {
95
111
  resolve('');
@@ -107,7 +123,7 @@ export class Line {
107
123
  resolve('');
108
124
  });
109
125
  }
110
- static updateSegmentedPath(block, linesObjects, lineGenerator) {
126
+ updateSegmentedPath(block, linesObjects, lineGenerator) {
111
127
  return new Promise(resolve => {
112
128
  if (linesObjects.size() === 0) {
113
129
  resolve('');
@@ -125,7 +141,7 @@ export class Line {
125
141
  resolve('');
126
142
  });
127
143
  }
128
- static setSegmentColor(segments, colorPalette) {
144
+ setSegmentColor(segments, colorPalette) {
129
145
  segments.style('stroke', (d, i) => colorPalette[i % colorPalette.length]);
130
146
  }
131
147
  }
@@ -0,0 +1,15 @@
1
+ import { Line as ILine } from "d3-shape";
2
+ import { MdtChartsDataRow } from "../../../config/config";
3
+ import { LineCurveType } from "../../../model/model";
4
+ interface LineGeneratorOptions {
5
+ curve?: LineCurveType;
6
+ }
7
+ declare type CoordinateGetter = (dataRow: MdtChartsDataRow) => number;
8
+ export declare class LineGenerator {
9
+ private options;
10
+ private readonly curvies;
11
+ constructor(options: LineGeneratorOptions);
12
+ get(xValue: CoordinateGetter, yValue: CoordinateGetter): ILine<MdtChartsDataRow>;
13
+ private setCurve;
14
+ }
15
+ export {};
@@ -0,0 +1,27 @@
1
+ import { curveBasis, curveMonotoneX, line, curveMonotoneY } from "d3-shape";
2
+ import { LineCurveType } from "../../../model/model";
3
+ export class LineGenerator {
4
+ constructor(options) {
5
+ this.options = options;
6
+ this.curvies = {
7
+ [LineCurveType.monotoneX]: curveMonotoneX,
8
+ [LineCurveType.monotoneY]: curveMonotoneY,
9
+ [LineCurveType.basis]: curveBasis,
10
+ [LineCurveType.none]: undefined
11
+ };
12
+ }
13
+ get(xValue, yValue) {
14
+ const generator = line()
15
+ .x(xValue)
16
+ .y(yValue);
17
+ this.setCurve(generator);
18
+ return generator;
19
+ }
20
+ setCurve(generator) {
21
+ if (this.options.curve != null) {
22
+ const curve = this.curvies[this.options.curve];
23
+ if (curve)
24
+ generator.curve(curve);
25
+ }
26
+ }
27
+ }