mdt-charts 1.12.7 → 1.12.11
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.
- package/lib/designer/designerConfig.d.ts +1 -1
- package/lib/engine/twoDimensionalNotation/area/area.js +3 -3
- package/lib/engine/twoDimensionalNotation/bar/bar.js +3 -3
- package/lib/engine/twoDimensionalNotation/bar/barHelper.js +8 -8
- package/lib/engine/twoDimensionalNotation/bar/stackedData/dataStacker.d.ts +13 -0
- package/lib/engine/twoDimensionalNotation/bar/stackedData/dataStacker.js +32 -0
- package/lib/engine/twoDimensionalNotation/bar/stackedData/dataStacker.test.d.ts +1 -0
- package/lib/engine/twoDimensionalNotation/bar/stackedData/dataStacker.test.js +199 -0
- package/lib/engine/twoDimensionalNotation/bar/stackedData/dataStackerService.d.ts +5 -0
- package/lib/engine/twoDimensionalNotation/bar/stackedData/dataStackerService.js +19 -0
- package/lib/model/chartStyleModel/TwoDimensionalChartStyleModel.js +1 -1
- package/lib/model/dataManagerModel/dataManagerModel.d.ts +1 -0
- package/lib/model/dataManagerModel/dataManagerModel.js +5 -5
- package/lib/model/featuresModel/axisModel.js +7 -3
- package/lib/model/featuresModel/legendModel/legendCanvasModel.d.ts +0 -1
- package/lib/model/featuresModel/legendModel/legendCanvasModel.js +0 -25
- package/lib/model/featuresModel/legendModel/legendModel.d.ts +2 -6
- package/lib/model/featuresModel/legendModel/legendModel.js +2 -45
- package/lib/model/featuresModel/legendModel/polarMarginCalculator.d.ts +2 -5
- package/lib/model/featuresModel/legendModel/polarMarginCalculator.js +11 -28
- package/lib/model/featuresModel/legendModel/twoDimLegendModel.d.ts +7 -0
- package/lib/model/featuresModel/legendModel/twoDimLegendModel.js +24 -0
- package/lib/model/featuresModel/otherComponents.d.ts +0 -2
- package/lib/model/featuresModel/otherComponents.js +1 -1
- package/lib/model/featuresModel/scaleModel/scaleModel.js +6 -3
- package/lib/model/helpers/modelHelper.d.ts +7 -0
- package/lib/model/helpers/modelHelper.js +41 -0
- package/lib/model/helpers/unitsFromConfigReader.d.ts +2 -0
- package/lib/model/helpers/unitsFromConfigReader.js +7 -0
- package/lib/model/helpers/unitsReader.d.ts +5 -0
- package/lib/model/helpers/unitsReader.js +15 -0
- package/lib/model/marginModel.d.ts +2 -3
- package/lib/model/marginModel.js +11 -41
- package/lib/model/model.d.ts +2 -2
- package/lib/model/modelBuilder.js +1 -1
- package/lib/model/notations/polar/donut/donutThicknessService.d.ts +0 -2
- package/lib/model/notations/polar/donut/donutThicknessService.js +4 -16
- package/lib/style/charts-main.css +5 -4
- package/lib/style/charts-main.less +5 -4
- package/package.json +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { stack } from 'd3-shape';
|
|
2
1
|
import { select } from 'd3-selection';
|
|
3
2
|
import { MarkDot } from "../../features/markDots/markDot";
|
|
4
3
|
import { AreaHelper } from './areaHelper';
|
|
5
4
|
import { DomHelper } from '../../helpers/domHelper';
|
|
6
5
|
import { Helper } from '../../helpers/helper';
|
|
6
|
+
import { getStackedDataWithOwn } from '../bar/stackedData/dataStacker';
|
|
7
7
|
export class Area {
|
|
8
8
|
static render(block, scales, data, keyField, margin, keyAxisOrient, chart, blockSize) {
|
|
9
9
|
if (chart.isSegmented)
|
|
@@ -44,7 +44,7 @@ export class Area {
|
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
46
|
static renderSegmented(block, scales, data, keyField, margin, keyAxisOrient, chart) {
|
|
47
|
-
const stackedData =
|
|
47
|
+
const stackedData = getStackedDataWithOwn(data, chart.data.valueFields.map(field => field.name));
|
|
48
48
|
const areaGenerator = AreaHelper.getSegmentedAreaGenerator(keyAxisOrient, scales, margin, keyField.name);
|
|
49
49
|
const areas = block.getChartGroup(chart.index)
|
|
50
50
|
.selectAll(`.${this.areaChartClass}${Helper.getCssClassesLine(chart.cssClasses)}`)
|
|
@@ -76,7 +76,7 @@ export class Area {
|
|
|
76
76
|
return promises;
|
|
77
77
|
}
|
|
78
78
|
static updateSegmented(block, scales, newData, keyField, margin, chart, keyAxisOrient) {
|
|
79
|
-
const stackedData =
|
|
79
|
+
const stackedData = getStackedDataWithOwn(newData, chart.data.valueFields.map(field => field.name));
|
|
80
80
|
const areaGenerator = AreaHelper.getSegmentedAreaGenerator(keyAxisOrient, scales, margin, keyField.name);
|
|
81
81
|
const areas = block.getChartGroup(chart.index)
|
|
82
82
|
.selectAll(`path.${this.areaChartClass}${Helper.getCssClassesLine(chart.cssClasses)}`)
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { stack } from 'd3-shape';
|
|
2
1
|
import { select } from 'd3-selection';
|
|
3
2
|
import { EmbeddedLabels } from "../../features/embeddedLabels/embeddedLabels";
|
|
4
3
|
import { EmbeddedLabelsHelper } from "../../features/embeddedLabels/embeddedLabelsHelper";
|
|
@@ -6,6 +5,7 @@ import { BarHelper } from "./barHelper";
|
|
|
6
5
|
import { sum } from "d3-array";
|
|
7
6
|
import { DomHelper } from "../../helpers/domHelper";
|
|
8
7
|
import { Helper } from "../../helpers/helper";
|
|
8
|
+
import { getStackedDataWithOwn } from './stackedData/dataStacker';
|
|
9
9
|
export class Bar {
|
|
10
10
|
static render(block, scales, data, keyField, margin, keyAxisOrient, chart, blockSize, barSettings, barsAmounts, isSegmented, firstBarIndex) {
|
|
11
11
|
if (isSegmented)
|
|
@@ -52,7 +52,7 @@ export class Bar {
|
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
static renderSegmented(block, scales, data, keyField, margin, keyAxisOrient, chart, barsAmounts, blockSize, firstBarIndex, barSettings) {
|
|
55
|
-
const stackedData =
|
|
55
|
+
const stackedData = getStackedDataWithOwn(data, chart.data.valueFields.map(field => field.name));
|
|
56
56
|
let groups = block.getChartGroup(chart.index)
|
|
57
57
|
.selectAll(`g.${this.barSegmentGroupClass}${Helper.getCssClassesLine(chart.cssClasses)}`)
|
|
58
58
|
.data(stackedData);
|
|
@@ -129,7 +129,7 @@ export class Bar {
|
|
|
129
129
|
return promises;
|
|
130
130
|
}
|
|
131
131
|
static updateSegmented(block, newData, scales, margin, keyAxisOrient, chart, blockSize, barsAmounts, keyField, firstBarIndex, barSettings) {
|
|
132
|
-
const stackedData =
|
|
132
|
+
const stackedData = getStackedDataWithOwn(newData, chart.data.valueFields.map(field => field.name));
|
|
133
133
|
block.getChartGroup(chart.index)
|
|
134
134
|
.selectAll(`.${this.barItemClass}${Helper.getCssClassesLine(chart.cssClasses)}`)
|
|
135
135
|
.filter(d => newData.findIndex(row => row[keyField.name] === d.data[keyField.name]) === -1)
|
|
@@ -84,20 +84,20 @@ export class BarHelper {
|
|
|
84
84
|
}
|
|
85
85
|
static setSegmentedBarAttrsByValue(attrs, keyAxisOrient, scaleValue, margin, blockSize) {
|
|
86
86
|
if (keyAxisOrient === 'top') {
|
|
87
|
-
attrs.y = d =>
|
|
88
|
-
attrs.height = d =>
|
|
87
|
+
attrs.y = d => scaleValue(Math.min(d[1], d[0])) + margin.top;
|
|
88
|
+
attrs.height = d => Math.abs(scaleValue(d[1]) - scaleValue(d[0]));
|
|
89
89
|
}
|
|
90
90
|
if (keyAxisOrient === 'bottom') {
|
|
91
|
-
attrs.y = d => scaleValue(d[1]) + margin.top;
|
|
92
|
-
attrs.height = d =>
|
|
91
|
+
attrs.y = d => scaleValue(Math.max(d[1], d[0])) + margin.top;
|
|
92
|
+
attrs.height = d => Math.abs(scaleValue(d[1]) - scaleValue(d[0]));
|
|
93
93
|
}
|
|
94
94
|
if (keyAxisOrient === 'left') {
|
|
95
|
-
attrs.x = d =>
|
|
96
|
-
attrs.width = d =>
|
|
95
|
+
attrs.x = d => scaleValue(Math.min(d[1], d[0])) + margin.left;
|
|
96
|
+
attrs.width = d => Math.abs(scaleValue(d[1]) - scaleValue(d[0]));
|
|
97
97
|
}
|
|
98
98
|
if (keyAxisOrient === 'right') {
|
|
99
|
-
attrs.x = d => scaleValue(d[1]) + margin.left;
|
|
100
|
-
attrs.width = d =>
|
|
99
|
+
attrs.x = d => scaleValue(Math.max(d[1], d[0])) + margin.left;
|
|
100
|
+
attrs.width = d => Math.abs(scaleValue(d[1]) - scaleValue(d[0]));
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { MdtChartsDataRow } from "../../../../config/config";
|
|
2
|
+
export interface StackedDataRow {
|
|
3
|
+
0: number;
|
|
4
|
+
1: number;
|
|
5
|
+
data: MdtChartsDataRow;
|
|
6
|
+
}
|
|
7
|
+
export declare type StackedDataFull = StackedDataRow[][];
|
|
8
|
+
export declare class DataStacker {
|
|
9
|
+
private service;
|
|
10
|
+
getStackedData(rawData: MdtChartsDataRow[], valueFields: string[]): StackedDataFull;
|
|
11
|
+
}
|
|
12
|
+
export declare function getStackedDataWithOwn(rawData: MdtChartsDataRow[], valueFields: string[]): StackedDataFull;
|
|
13
|
+
export declare function getStackedDataWithD3(rawData: MdtChartsDataRow[], valueFields: string[]): StackedDataFull;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { stack } from "d3-shape";
|
|
2
|
+
import { DataStackerService } from "./dataStackerService";
|
|
3
|
+
export class DataStacker {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.service = new DataStackerService();
|
|
6
|
+
}
|
|
7
|
+
getStackedData(rawData, valueFields) {
|
|
8
|
+
const stackedData = [];
|
|
9
|
+
valueFields.forEach((vField, vfIndex) => {
|
|
10
|
+
const fieldStack = [];
|
|
11
|
+
rawData.forEach((dataRow, drIndex) => {
|
|
12
|
+
const valueFromData = dataRow[vField];
|
|
13
|
+
const value0 = this.service.getValue0(stackedData, vfIndex, drIndex, valueFromData);
|
|
14
|
+
const value1 = this.service.getValue1(value0, valueFromData);
|
|
15
|
+
fieldStack.push({
|
|
16
|
+
"0": value0,
|
|
17
|
+
"1": value1,
|
|
18
|
+
data: dataRow
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
stackedData.push(fieldStack);
|
|
22
|
+
});
|
|
23
|
+
return stackedData;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function getStackedDataWithOwn(rawData, valueFields) {
|
|
27
|
+
const stacker = new DataStacker();
|
|
28
|
+
return stacker.getStackedData(rawData, valueFields);
|
|
29
|
+
}
|
|
30
|
+
export function getStackedDataWithD3(rawData, valueFields) {
|
|
31
|
+
return stack().keys(valueFields)(rawData);
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { DataStacker } from "./dataStacker";
|
|
2
|
+
import { DataStackerService } from "./dataStackerService";
|
|
3
|
+
describe('DataStacker', () => {
|
|
4
|
+
const stacker = new DataStacker();
|
|
5
|
+
describe('getStackedData', () => {
|
|
6
|
+
describe('for positive values', () => {
|
|
7
|
+
let dataRows = [
|
|
8
|
+
{ price: 12, count: 30 },
|
|
9
|
+
{ price: 30, count: 12 },
|
|
10
|
+
{ price: 0, count: 100 },
|
|
11
|
+
{ price: 10, count: 0 }
|
|
12
|
+
];
|
|
13
|
+
const valueFields = ["price", "count"];
|
|
14
|
+
test('should return right stack', () => {
|
|
15
|
+
const res = stacker.getStackedData(dataRows, valueFields);
|
|
16
|
+
expect(res).toEqual([
|
|
17
|
+
[
|
|
18
|
+
{ "0": 0, "1": 12, data: dataRows[0] },
|
|
19
|
+
{ "0": 0, "1": 30, data: dataRows[1] },
|
|
20
|
+
{ "0": 0, "1": 0, data: dataRows[2] },
|
|
21
|
+
{ "0": 0, "1": 10, data: dataRows[3] },
|
|
22
|
+
],
|
|
23
|
+
[
|
|
24
|
+
{ "0": 12, "1": 42, data: dataRows[0] },
|
|
25
|
+
{ "0": 30, "1": 42, data: dataRows[1] },
|
|
26
|
+
{ "0": 0, "1": 100, data: dataRows[2] },
|
|
27
|
+
{ "0": 10, "1": 10, data: dataRows[3] },
|
|
28
|
+
]
|
|
29
|
+
]);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe('for negative values', () => {
|
|
33
|
+
let dataRows = [
|
|
34
|
+
{ price: -12, count: -30 },
|
|
35
|
+
{ price: -30, count: -12 },
|
|
36
|
+
{ price: 0, count: -100 },
|
|
37
|
+
{ price: -10, count: 0 }
|
|
38
|
+
];
|
|
39
|
+
const valueFields = ["price", "count"];
|
|
40
|
+
test('should return right stack', () => {
|
|
41
|
+
const res = stacker.getStackedData(dataRows, valueFields);
|
|
42
|
+
expect(res).toEqual([
|
|
43
|
+
[
|
|
44
|
+
{ "0": 0, "1": -12, data: dataRows[0] },
|
|
45
|
+
{ "0": 0, "1": -30, data: dataRows[1] },
|
|
46
|
+
{ "0": 0, "1": 0, data: dataRows[2] },
|
|
47
|
+
{ "0": 0, "1": -10, data: dataRows[3] },
|
|
48
|
+
],
|
|
49
|
+
[
|
|
50
|
+
{ "0": -12, "1": -42, data: dataRows[0] },
|
|
51
|
+
{ "0": -30, "1": -42, data: dataRows[1] },
|
|
52
|
+
{ "0": 0, "1": -100, data: dataRows[2] },
|
|
53
|
+
{ "0": -10, "1": -10, data: dataRows[3] },
|
|
54
|
+
]
|
|
55
|
+
]);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe('DataStackerService', () => {
|
|
61
|
+
const service = new DataStackerService();
|
|
62
|
+
let data = [
|
|
63
|
+
[
|
|
64
|
+
{ "0": 0, "1": 42, data: {} },
|
|
65
|
+
{ "0": 0, "1": -123, data: {} }
|
|
66
|
+
]
|
|
67
|
+
];
|
|
68
|
+
describe('getLastValue', () => {
|
|
69
|
+
test('should return 0 if vfIndex is 0', () => {
|
|
70
|
+
const res = service.getValue0(data, 0, 0, 0);
|
|
71
|
+
expect(res).toBe(0);
|
|
72
|
+
});
|
|
73
|
+
test('should return last positive values if positive value exists and need positive', () => {
|
|
74
|
+
const res = service.getValue0(data, 1, 0, 12);
|
|
75
|
+
expect(res).toBe(42);
|
|
76
|
+
});
|
|
77
|
+
test('should return 0 if positive value not exists and need positive', () => {
|
|
78
|
+
const res = service.getValue0(data, 1, 1, 12);
|
|
79
|
+
expect(res).toBe(0);
|
|
80
|
+
});
|
|
81
|
+
test('should return last negative value if negative value exists and need negative', () => {
|
|
82
|
+
const res = service.getValue0(data, 1, 1, -12);
|
|
83
|
+
expect(res).toBe(-123);
|
|
84
|
+
});
|
|
85
|
+
test('should return 0 if negative value not exists and need negative', () => {
|
|
86
|
+
const res = service.getValue0(data, 1, 0, -12);
|
|
87
|
+
expect(res).toBe(0);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
describe('getValue1', () => {
|
|
91
|
+
test('should return sum of value0 + value from data', () => {
|
|
92
|
+
let res = service.getValue1(0, 12);
|
|
93
|
+
expect(res).toBe(12);
|
|
94
|
+
res = service.getValue1(-12, -30);
|
|
95
|
+
expect(res).toBe(-42);
|
|
96
|
+
res = service.getValue1(0, 30);
|
|
97
|
+
expect(res).toBe(30);
|
|
98
|
+
res = service.getValue1(0, -30);
|
|
99
|
+
expect(res).toBe(-30);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
describe('real example (positive only)', () => {
|
|
104
|
+
const stacker = new DataStacker();
|
|
105
|
+
const data = [
|
|
106
|
+
{
|
|
107
|
+
$id: 1,
|
|
108
|
+
brand: "BMW BMW",
|
|
109
|
+
price: 100000,
|
|
110
|
+
count: 12000,
|
|
111
|
+
color: "red"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
$id: 2,
|
|
115
|
+
brand: "LADA",
|
|
116
|
+
price: 0,
|
|
117
|
+
count: 1000,
|
|
118
|
+
color: "green"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
$id: 3,
|
|
122
|
+
brand: "MERCEDES",
|
|
123
|
+
price: 15000,
|
|
124
|
+
count: 1200,
|
|
125
|
+
color: "blue"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
$id: 4,
|
|
129
|
+
brand: "AUDI",
|
|
130
|
+
price: 20000,
|
|
131
|
+
count: 500,
|
|
132
|
+
color: "yellow"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
$id: 5,
|
|
136
|
+
brand: "VOLKSWAGEN",
|
|
137
|
+
price: 115000,
|
|
138
|
+
count: 6000,
|
|
139
|
+
color: "cyan"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
$id: 6,
|
|
143
|
+
brand: "DODGE",
|
|
144
|
+
price: 115000,
|
|
145
|
+
count: 4000,
|
|
146
|
+
color: "red"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
$id: 7,
|
|
150
|
+
brand: "SAAB",
|
|
151
|
+
price: 50000,
|
|
152
|
+
count: 11000,
|
|
153
|
+
color: "orange"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
$id: 8,
|
|
157
|
+
brand: "HONDA",
|
|
158
|
+
price: 20000,
|
|
159
|
+
count: 2000,
|
|
160
|
+
color: "brown"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
$id: 9,
|
|
164
|
+
brand: "TOYOTA",
|
|
165
|
+
price: 40000,
|
|
166
|
+
count: 15000,
|
|
167
|
+
color: "pink"
|
|
168
|
+
}
|
|
169
|
+
];
|
|
170
|
+
const valueFields = ["price", "count"];
|
|
171
|
+
const stackedData = [
|
|
172
|
+
[
|
|
173
|
+
{ "0": 0, "1": 100000, data: data[0] },
|
|
174
|
+
{ "0": 0, "1": 0, data: data[1] },
|
|
175
|
+
{ "0": 0, "1": 15000, data: data[2] },
|
|
176
|
+
{ "0": 0, "1": 20000, data: data[3] },
|
|
177
|
+
{ "0": 0, "1": 115000, data: data[4] },
|
|
178
|
+
{ "0": 0, "1": 115000, data: data[5] },
|
|
179
|
+
{ "0": 0, "1": 50000, data: data[6] },
|
|
180
|
+
{ "0": 0, "1": 20000, data: data[7] },
|
|
181
|
+
{ "0": 0, "1": 40000, data: data[8] }
|
|
182
|
+
],
|
|
183
|
+
[
|
|
184
|
+
{ "0": 100000, "1": 112000, data: data[0] },
|
|
185
|
+
{ "0": 0, "1": 1000, data: data[1] },
|
|
186
|
+
{ "0": 15000, "1": 16200, data: data[2] },
|
|
187
|
+
{ "0": 20000, "1": 20500, data: data[3] },
|
|
188
|
+
{ "0": 115000, "1": 121000, data: data[4] },
|
|
189
|
+
{ "0": 115000, "1": 119000, data: data[5] },
|
|
190
|
+
{ "0": 50000, "1": 61000, data: data[6] },
|
|
191
|
+
{ "0": 20000, "1": 22000, data: data[7] },
|
|
192
|
+
{ "0": 40000, "1": 55000, data: data[8] }
|
|
193
|
+
]
|
|
194
|
+
];
|
|
195
|
+
test('check on real example', () => {
|
|
196
|
+
const res = stacker.getStackedData(data, valueFields);
|
|
197
|
+
expect(res).toEqual(stackedData);
|
|
198
|
+
});
|
|
199
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export class DataStackerService {
|
|
2
|
+
getValue0(stackedData, vfIndex, drIndex, valueFromData) {
|
|
3
|
+
if (vfIndex === 0)
|
|
4
|
+
return 0;
|
|
5
|
+
for (let i = vfIndex - 1; i >= 0; i--) {
|
|
6
|
+
if (valueFromData === 0) {
|
|
7
|
+
return stackedData[i][drIndex][1];
|
|
8
|
+
}
|
|
9
|
+
const needed = stackedData[i][drIndex][1] >= 0 === valueFromData >= 0;
|
|
10
|
+
if (needed) {
|
|
11
|
+
return stackedData[i][drIndex][1];
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return 0;
|
|
15
|
+
}
|
|
16
|
+
getValue1(value0, valueFromData) {
|
|
17
|
+
return value0 + valueFromData;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as chroma from "chroma-js";
|
|
2
|
-
import { ModelHelper } from "../modelHelper";
|
|
2
|
+
import { ModelHelper } from "../helpers/modelHelper";
|
|
3
3
|
import { ChartStyleModelService } from "./chartStyleModel";
|
|
4
4
|
export class TwoDimensionalChartStyleModel {
|
|
5
5
|
constructor(charts, chartStyleConfig) {
|
|
@@ -11,6 +11,7 @@ export interface DataLegendParams {
|
|
|
11
11
|
}
|
|
12
12
|
export declare class DataManagerModel {
|
|
13
13
|
private static service;
|
|
14
|
+
private static polarMarginCalculator;
|
|
14
15
|
static getPreparedData(data: MdtChartsDataSource, allowableKeys: string[], config: MdtChartsConfig): MdtChartsDataSource;
|
|
15
16
|
static initDataScope(config: MdtChartsConfig, data: MdtChartsDataSource, designerConfig: DesignerConfig, legendBlock: LegendBlockModel, modelInstance: ModelInstance): void;
|
|
16
17
|
static getDataValuesByKeyField(data: MdtChartsDataSource, dataSourceName: string, keyFieldName: string): string[];
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { AxisModel } from "../featuresModel/axisModel";
|
|
2
2
|
import { LegendCanvasModel } from "../featuresModel/legendModel/legendCanvasModel";
|
|
3
|
-
import {
|
|
4
|
-
import { ModelHelper } from "../modelHelper";
|
|
3
|
+
import { ModelHelper } from "../helpers/modelHelper";
|
|
5
4
|
import { MIN_DONUT_BLOCK_SIZE, PolarModel } from "../notations/polar/polarModel";
|
|
6
5
|
import { DataManagerModelService } from "./dataManagerModelService";
|
|
6
|
+
import { LegendPolarMarginCalculator } from "../featuresModel/legendModel/polarMarginCalculator";
|
|
7
7
|
export class DataManagerModel {
|
|
8
8
|
static getPreparedData(data, allowableKeys, config) {
|
|
9
9
|
const scopedData = this.getScopedData(data, allowableKeys, config);
|
|
@@ -66,14 +66,13 @@ export class DataManagerModel {
|
|
|
66
66
|
//TODO: global refactor of method
|
|
67
67
|
const allowableKeys = keys.slice(0, maxItemsNumber);
|
|
68
68
|
const hidedRecordsAmount = keys.length - maxItemsNumber;
|
|
69
|
-
|
|
70
|
-
marginCalculator.updateMargin(position, canvasModel, legendBlock, position === "bottom" ? size.height : size.width);
|
|
69
|
+
this.polarMarginCalculator.updateMargin(position, canvasModel, legendBlock, position === "bottom" ? size.height : size.width);
|
|
71
70
|
modelInstance.dataModel.initScope(this.limitAllowableKeys(allowableKeys, hidedRecordsAmount, modelInstance.dataModel));
|
|
72
71
|
}
|
|
73
72
|
//TODO: position type
|
|
74
73
|
static getLegendDataParams(position, keys, legendCanvas, canvasModel, legendBlock) {
|
|
75
74
|
if (position === 'right') {
|
|
76
|
-
return LegendCanvasModel.findElementsAmountByLegendSize(keys, position, legendCanvas.
|
|
75
|
+
return LegendCanvasModel.findElementsAmountByLegendSize(keys, position, this.polarMarginCalculator.getMaxLegendWidth(legendCanvas, canvasModel.getBlockSize().width), canvasModel.getChartBlockHeight() - legendBlock.coordinate.bottom.margin.bottom);
|
|
77
76
|
}
|
|
78
77
|
else {
|
|
79
78
|
return LegendCanvasModel.findElementsAmountByLegendSize(keys, position, canvasModel.getChartBlockWidth() - legendBlock.coordinate.bottom.margin.left - legendBlock.coordinate.bottom.margin.right, canvasModel.getChartBlockHeight() - legendBlock.coordinate.bottom.margin.bottom - legendBlock.coordinate.bottom.margin.top - MIN_DONUT_BLOCK_SIZE);
|
|
@@ -143,3 +142,4 @@ export class DataManagerModel {
|
|
|
143
142
|
}
|
|
144
143
|
}
|
|
145
144
|
DataManagerModel.service = new DataManagerModelService();
|
|
145
|
+
DataManagerModel.polarMarginCalculator = new LegendPolarMarginCalculator();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ModelHelper } from "../modelHelper";
|
|
1
|
+
import { ModelHelper } from "../helpers/modelHelper";
|
|
2
2
|
import { AxisType, CLASSES } from "../modelBuilder";
|
|
3
3
|
import { DataManagerModel } from "../dataManagerModel/dataManagerModel";
|
|
4
4
|
import { TwoDimensionalModel } from "../notations/twoDimensionalModel";
|
|
@@ -111,11 +111,15 @@ export class AxisModel {
|
|
|
111
111
|
let translateY;
|
|
112
112
|
let translateX;
|
|
113
113
|
if (chartOrientation === "vertical") {
|
|
114
|
-
translateY = getZeroCoordinate
|
|
114
|
+
translateY = getZeroCoordinate
|
|
115
|
+
? getZeroCoordinate() + canvasModel.getMarginSide("top")
|
|
116
|
+
: AxisModel.getAxisTranslateY(AxisType.Key, chartOrientation, axisPosition, canvasModel);
|
|
115
117
|
translateX = AxisModel.getAxisTranslateX(AxisType.Key, chartOrientation, axisPosition, canvasModel);
|
|
116
118
|
}
|
|
117
119
|
else {
|
|
118
|
-
translateX = getZeroCoordinate
|
|
120
|
+
translateX = getZeroCoordinate
|
|
121
|
+
? getZeroCoordinate() + canvasModel.getMarginSide("left")
|
|
122
|
+
: AxisModel.getAxisTranslateX(AxisType.Key, chartOrientation, axisPosition, canvasModel);
|
|
119
123
|
translateY = AxisModel.getAxisTranslateY(AxisType.Key, chartOrientation, axisPosition, canvasModel);
|
|
120
124
|
}
|
|
121
125
|
return {
|
|
@@ -2,7 +2,6 @@ import { DataLegendParams } from "../../dataManagerModel/dataManagerModel";
|
|
|
2
2
|
import { LegendPosition } from "../../model";
|
|
3
3
|
export declare type LegendItemsDirection = 'row' | 'column';
|
|
4
4
|
export declare class LegendCanvasModel {
|
|
5
|
-
static getLegendHeight(texts: string[], chartBlockWidth: number, itemsDirection: LegendItemsDirection, legendPosition: LegendPosition): number;
|
|
6
5
|
static getLegendItemWidth(text: string): number;
|
|
7
6
|
static findElementsAmountByLegendSize(texts: string[], position: LegendPosition, legendBlockWidth: number, legendBlockHeight: number): DataLegendParams;
|
|
8
7
|
private static getLegendWrapperEl;
|
|
@@ -1,30 +1,5 @@
|
|
|
1
1
|
import { CLASSES } from "../../modelBuilder";
|
|
2
2
|
export class LegendCanvasModel {
|
|
3
|
-
static getLegendHeight(texts, chartBlockWidth, itemsDirection, legendPosition) {
|
|
4
|
-
const legendWrapper = this.getLegendWrapperEl(chartBlockWidth, itemsDirection);
|
|
5
|
-
texts.forEach(text => {
|
|
6
|
-
const itemWrapper = document.createElement('div');
|
|
7
|
-
const colorBlock = document.createElement('span');
|
|
8
|
-
const textBlock = document.createElement('span');
|
|
9
|
-
itemWrapper.classList.add("legend-item");
|
|
10
|
-
if (legendPosition === 'bottom') {
|
|
11
|
-
itemWrapper.classList.add('legend-item-inline');
|
|
12
|
-
textBlock.classList.add('legend-label-nowrap');
|
|
13
|
-
}
|
|
14
|
-
else {
|
|
15
|
-
itemWrapper.classList.add('legend-item-row');
|
|
16
|
-
}
|
|
17
|
-
colorBlock.classList.add(CLASSES.legendColor);
|
|
18
|
-
textBlock.classList.add(CLASSES.legendLabel);
|
|
19
|
-
textBlock.textContent = text;
|
|
20
|
-
itemWrapper.append(colorBlock, textBlock);
|
|
21
|
-
legendWrapper.append(itemWrapper);
|
|
22
|
-
});
|
|
23
|
-
document.body.append(legendWrapper);
|
|
24
|
-
const height = legendWrapper.offsetHeight;
|
|
25
|
-
legendWrapper.remove();
|
|
26
|
-
return height + 1;
|
|
27
|
-
}
|
|
28
3
|
static getLegendItemWidth(text) {
|
|
29
4
|
const itemWrapper = document.createElement('div');
|
|
30
5
|
itemWrapper.style.opacity = '0';
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ILegendModel, LegendBlockModel, Orient } from "../../model";
|
|
1
|
+
import { LegendBlockModel } from "../../model";
|
|
3
2
|
import { CanvasModel } from "../../modelInstance/canvasModel/canvasModel";
|
|
4
3
|
import { LegendItemsDirection } from "./legendCanvasModel";
|
|
5
4
|
export declare class LegendModel {
|
|
6
|
-
static
|
|
7
|
-
static getBaseLegendBlockModel(notation: ChartNotation, canvasModel: CanvasModel): LegendBlockModel;
|
|
8
|
-
static getLegendModel(chartNotation: ChartNotation, legendShow: boolean, canvasModel: CanvasModel): ILegendModel;
|
|
5
|
+
static getBaseLegendBlockModel(canvasModel: CanvasModel): LegendBlockModel;
|
|
9
6
|
static getLegendItemClass(itemsPosition: LegendItemsDirection): string;
|
|
10
|
-
private static getLegendWidth;
|
|
11
7
|
}
|
|
@@ -1,20 +1,5 @@
|
|
|
1
|
-
import { ModelHelper } from "../../modelHelper";
|
|
2
|
-
import { PolarModel } from "../../notations/polar/polarModel";
|
|
3
|
-
import { LegendCanvasModel } from "./legendCanvasModel";
|
|
4
1
|
export class LegendModel {
|
|
5
|
-
static
|
|
6
|
-
if (position === 'left' || position === 'right')
|
|
7
|
-
return this.getLegendWidth(texts, legendMaxWidth);
|
|
8
|
-
//TODO: rm duplicate
|
|
9
|
-
if (chartNotation === '2d' || chartNotation === 'interval') {
|
|
10
|
-
return LegendCanvasModel.getLegendHeight(texts, blockSize.width - legendBlockModel.coordinate[position].margin.left - legendBlockModel.coordinate[position].margin.right, 'row', position);
|
|
11
|
-
}
|
|
12
|
-
else if (chartNotation === 'polar') {
|
|
13
|
-
const size = LegendCanvasModel.getLegendHeight(texts, blockSize.width - legendBlockModel.coordinate[position].margin.left - legendBlockModel.coordinate[position].margin.right, 'row', position);
|
|
14
|
-
return size;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
static getBaseLegendBlockModel(notation, canvasModel) {
|
|
2
|
+
static getBaseLegendBlockModel(canvasModel) {
|
|
18
3
|
const mt = 20, mb = 20, ml = 20, mr = 20;
|
|
19
4
|
return {
|
|
20
5
|
coordinate: {
|
|
@@ -38,38 +23,10 @@ export class LegendModel {
|
|
|
38
23
|
margin: { top: 5, bottom: 10, left: 0, right: 0 },
|
|
39
24
|
pad: canvasModel.titleCanvas.getAllNeededSpace()
|
|
40
25
|
}
|
|
41
|
-
}
|
|
42
|
-
standartTooltip: notation === 'polar' ? false : true
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
static getLegendModel(chartNotation, legendShow, canvasModel) {
|
|
46
|
-
if (!legendShow)
|
|
47
|
-
return {
|
|
48
|
-
position: 'off'
|
|
49
|
-
};
|
|
50
|
-
let legendPosition = 'off';
|
|
51
|
-
if (chartNotation === '2d' || chartNotation === 'interval')
|
|
52
|
-
legendPosition = 'top';
|
|
53
|
-
else if (chartNotation === 'polar') {
|
|
54
|
-
legendPosition = PolarModel.getLegendPositionByBlockSize(canvasModel);
|
|
55
|
-
}
|
|
56
|
-
return {
|
|
57
|
-
position: legendPosition
|
|
26
|
+
}
|
|
58
27
|
};
|
|
59
28
|
}
|
|
60
29
|
static getLegendItemClass(itemsPosition) {
|
|
61
30
|
return itemsPosition === 'column' ? 'legend-item-row' : 'legend-item-inline';
|
|
62
31
|
}
|
|
63
|
-
static getLegendWidth(texts, legendMaxWidth) {
|
|
64
|
-
let longestText = '';
|
|
65
|
-
let biggestScore = 0;
|
|
66
|
-
texts.forEach(text => {
|
|
67
|
-
if (ModelHelper.getStringScore(text) > biggestScore) {
|
|
68
|
-
longestText = text;
|
|
69
|
-
biggestScore = ModelHelper.getStringScore(text);
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
const maxWidth = LegendCanvasModel.getLegendItemWidth(longestText + '?'); // One letter reserve
|
|
73
|
-
return maxWidth > legendMaxWidth ? legendMaxWidth : maxWidth;
|
|
74
|
-
}
|
|
75
32
|
}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LegendBlockCanvas } from "../../../designer/designerConfig";
|
|
2
2
|
import { LegendBlockModel } from "../../model";
|
|
3
3
|
import { CanvasModel } from "../../modelInstance/canvasModel/canvasModel";
|
|
4
|
-
import { ModelInstance } from "../../modelInstance/modelInstance";
|
|
5
4
|
export declare class LegendPolarMarginCalculator {
|
|
6
|
-
recalcMargin(modelInstance: ModelInstance, options: MdtChartsPolarOptions, legendMaxWidth: number, legendBlockModel: LegendBlockModel, data: MdtChartsDataSource): void;
|
|
7
5
|
updateMargin(legendPosition: "right" | "bottom", canvasModel: CanvasModel, legendBlockModel: LegendBlockModel, size: number): void;
|
|
6
|
+
getMaxLegendWidth(legendCanvas: LegendBlockCanvas, blockWidth: number): number;
|
|
8
7
|
private updateMarginObj;
|
|
9
|
-
private getLegendSize;
|
|
10
|
-
private getLegendItemsContent;
|
|
11
8
|
}
|
|
@@ -1,30 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getPxPercentUnitByValue } from "../../helpers/unitsFromConfigReader";
|
|
2
2
|
import { MarginModel } from "../../marginModel";
|
|
3
|
-
import { MIN_DONUT_BLOCK_SIZE } from "../../notations/polar/polarModel";
|
|
4
|
-
import { LegendModel } from "./legendModel";
|
|
5
3
|
export class LegendPolarMarginCalculator {
|
|
6
|
-
recalcMargin(modelInstance, options, legendMaxWidth, legendBlockModel, data) {
|
|
7
|
-
const canvasModel = modelInstance.canvasModel;
|
|
8
|
-
let legendPosition = LegendModel.getLegendModel(options.type, options.legend.show, modelInstance.canvasModel).position;
|
|
9
|
-
modelInstance.canvasModel.legendCanvas.setPosition(legendPosition);
|
|
10
|
-
if (legendPosition === "off")
|
|
11
|
-
return;
|
|
12
|
-
let legendSize = this.getLegendSize(options, legendMaxWidth, legendBlockModel, data, canvasModel, legendPosition);
|
|
13
|
-
if (legendPosition === "right" && canvasModel.getChartBlockWidth() - legendSize < MIN_DONUT_BLOCK_SIZE) {
|
|
14
|
-
legendSize = this.getLegendSize(options, legendMaxWidth, legendBlockModel, data, canvasModel, "bottom");
|
|
15
|
-
legendPosition = "bottom";
|
|
16
|
-
modelInstance.canvasModel.legendCanvas.setPosition(legendPosition);
|
|
17
|
-
}
|
|
18
|
-
if (legendSize !== 0) {
|
|
19
|
-
canvasModel.increaseMarginSide(legendPosition, legendSize);
|
|
20
|
-
MarginModel.appendToGlobalMarginValuesLegendMargin(canvasModel, legendPosition, legendBlockModel);
|
|
21
|
-
}
|
|
22
|
-
legendBlockModel.coordinate[legendPosition].size = legendSize;
|
|
23
|
-
}
|
|
24
4
|
updateMargin(legendPosition, canvasModel, legendBlockModel, size) {
|
|
25
5
|
canvasModel.legendCanvas.setPosition(legendPosition);
|
|
26
6
|
this.updateMarginObj(legendBlockModel, legendPosition, size, canvasModel);
|
|
27
7
|
}
|
|
8
|
+
getMaxLegendWidth(legendCanvas, blockWidth) {
|
|
9
|
+
const maxWidth = legendCanvas.maxWidth;
|
|
10
|
+
if (typeof maxWidth === "number")
|
|
11
|
+
return maxWidth;
|
|
12
|
+
const unit = getPxPercentUnitByValue(maxWidth);
|
|
13
|
+
const maxWidthNumber = parseInt(maxWidth);
|
|
14
|
+
if (unit === "px")
|
|
15
|
+
return maxWidthNumber;
|
|
16
|
+
return maxWidthNumber / 100 * blockWidth;
|
|
17
|
+
}
|
|
28
18
|
updateMarginObj(legendBlockModel, legendPosition, legendSize, canvasModel) {
|
|
29
19
|
if (legendSize !== 0) {
|
|
30
20
|
canvasModel.increaseMarginSide(legendPosition, legendSize);
|
|
@@ -32,11 +22,4 @@ export class LegendPolarMarginCalculator {
|
|
|
32
22
|
}
|
|
33
23
|
legendBlockModel.coordinate[legendPosition].size = legendSize;
|
|
34
24
|
}
|
|
35
|
-
getLegendSize(options, legendMaxWidth, legendBlockModel, data, canvasModel, legendPosition) {
|
|
36
|
-
const legendItemsContent = this.getLegendItemsContent(options, data);
|
|
37
|
-
return LegendModel.getLegendSize(options.type, legendPosition, legendItemsContent, legendMaxWidth, canvasModel.getBlockSize(), legendBlockModel);
|
|
38
|
-
}
|
|
39
|
-
getLegendItemsContent(options, data) {
|
|
40
|
-
return DataManagerModel.getDataValuesByKeyField(data, options.data.dataSource, options.data.keyField.name);
|
|
41
|
-
}
|
|
42
25
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { LegendBlockModel } from "../../model";
|
|
2
|
+
import { ModelInstance } from "../../modelInstance/modelInstance";
|
|
3
|
+
export declare class TwoDimLegendModel {
|
|
4
|
+
recalcMarginWith2DLegend(modelInstance: ModelInstance, legendBlockModel: LegendBlockModel): void;
|
|
5
|
+
private getLegendSize;
|
|
6
|
+
private getLegendModel;
|
|
7
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { MarginModel } from "../../marginModel";
|
|
2
|
+
export class TwoDimLegendModel {
|
|
3
|
+
recalcMarginWith2DLegend(modelInstance, legendBlockModel) {
|
|
4
|
+
const canvasModel = modelInstance.canvasModel;
|
|
5
|
+
const legendPosition = this.getLegendModel().position;
|
|
6
|
+
modelInstance.canvasModel.legendCanvas.setPosition(legendPosition);
|
|
7
|
+
if (legendPosition !== 'off') {
|
|
8
|
+
const legendSize = this.getLegendSize();
|
|
9
|
+
canvasModel.increaseMarginSide(legendPosition, legendSize);
|
|
10
|
+
if (legendSize !== 0)
|
|
11
|
+
MarginModel.appendToGlobalMarginValuesLegendMargin(canvasModel, legendPosition, legendBlockModel);
|
|
12
|
+
legendBlockModel.coordinate[legendPosition].size = legendSize;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
getLegendSize() {
|
|
16
|
+
const heightOfLegendItemWithoutWordWrapping = 20;
|
|
17
|
+
return heightOfLegendItemWithoutWordWrapping;
|
|
18
|
+
}
|
|
19
|
+
getLegendModel() {
|
|
20
|
+
return {
|
|
21
|
+
position: "top"
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { OtherCommonComponents } from "../model";
|
|
2
2
|
import { ElementsOptions } from "../../designer/designerConfig";
|
|
3
|
-
import { ChartNotation } from "../../config/config";
|
|
4
3
|
import { ModelInstance } from "../modelInstance/modelInstance";
|
|
5
4
|
interface OtherComponentsModelDependencies {
|
|
6
5
|
elementsOptions: ElementsOptions;
|
|
7
6
|
title: string;
|
|
8
|
-
notation: ChartNotation;
|
|
9
7
|
}
|
|
10
8
|
export declare class OtherComponentsModel {
|
|
11
9
|
static getOtherComponentsModel(dependencies: OtherComponentsModelDependencies, modelInstance: ModelInstance): OtherCommonComponents;
|
|
@@ -6,7 +6,7 @@ export class OtherComponentsModel {
|
|
|
6
6
|
const canvasModel = modelInstance.canvasModel;
|
|
7
7
|
canvasModel.titleCanvas.init(TitleModel.getTitleModel(dependencies.title));
|
|
8
8
|
return {
|
|
9
|
-
legendBlock: LegendModel.getBaseLegendBlockModel(
|
|
9
|
+
legendBlock: LegendModel.getBaseLegendBlockModel(canvasModel),
|
|
10
10
|
titleBlock: canvasModel.titleCanvas.getModel(),
|
|
11
11
|
tooltipBlock: TooltipModel.getTooltipModel(dependencies.elementsOptions.tooltip)
|
|
12
12
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ModelHelper } from "../../modelHelper";
|
|
1
|
+
import { ModelHelper } from "../../helpers/modelHelper";
|
|
2
2
|
export var ScaleType;
|
|
3
3
|
(function (ScaleType) {
|
|
4
4
|
ScaleType[ScaleType["Key"] = 0] = "Key";
|
|
@@ -86,7 +86,7 @@ export class ScaleModel {
|
|
|
86
86
|
dataRows.forEach(dataRow => {
|
|
87
87
|
let sumInRow = 0;
|
|
88
88
|
chart.data.valueFields.forEach(field => {
|
|
89
|
-
if (chart.isSegmented)
|
|
89
|
+
if (chart.isSegmented && dataRow[field.name] > 0)
|
|
90
90
|
sumInRow += dataRow[field.name];
|
|
91
91
|
else if (dataRow[field.name] > sumInRow)
|
|
92
92
|
sumInRow = dataRow[field.name];
|
|
@@ -103,7 +103,10 @@ export class ScaleModel {
|
|
|
103
103
|
dataRows.forEach(dataRow => {
|
|
104
104
|
let sumInRow = 0;
|
|
105
105
|
chart.data.valueFields.forEach(field => {
|
|
106
|
-
if (dataRow[field.name] <
|
|
106
|
+
if (chart.isSegmented && dataRow[field.name] < 0) {
|
|
107
|
+
sumInRow += dataRow[field.name];
|
|
108
|
+
}
|
|
109
|
+
else if (dataRow[field.name] < sumInRow)
|
|
107
110
|
sumInRow = dataRow[field.name];
|
|
108
111
|
});
|
|
109
112
|
if (min > sumInRow)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { MdtChartsDataSource, IntervalChart } from "../../config/config";
|
|
2
|
+
export declare class ModelHelper {
|
|
3
|
+
static getSum(items: number[]): number;
|
|
4
|
+
static getMinAndMaxOfIntervalData(data: MdtChartsDataSource, dataSource: string, chart: IntervalChart): [Date, Date];
|
|
5
|
+
static getUniqueValues(values: string[]): string[];
|
|
6
|
+
static getStringScore(word: string): number;
|
|
7
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export class ModelHelper {
|
|
2
|
+
static getSum(items) {
|
|
3
|
+
return items.reduce((acc, item) => acc + item, 0);
|
|
4
|
+
}
|
|
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
|
+
static getUniqueValues(values) {
|
|
24
|
+
const uniqueValues = values.filter((keyValue, index, self) => self.indexOf(keyValue) === index);
|
|
25
|
+
return uniqueValues;
|
|
26
|
+
}
|
|
27
|
+
static getStringScore(word) {
|
|
28
|
+
// lower case letter width ~ 0.74 from upper case width.
|
|
29
|
+
// Number width == lower case letter width
|
|
30
|
+
let score = 0;
|
|
31
|
+
const upperLetterScore = 1;
|
|
32
|
+
const lowerLetterScore = 0.74;
|
|
33
|
+
for (let i = 0; i < word.length; i++) {
|
|
34
|
+
if (word[i].toUpperCase() === word[i] && parseFloat(word[i]).toString() !== word[i])
|
|
35
|
+
score += upperLetterScore;
|
|
36
|
+
else
|
|
37
|
+
score += lowerLetterScore;
|
|
38
|
+
}
|
|
39
|
+
return score;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export class UnitsReader {
|
|
2
|
+
getUnitByValue(value, defaultUnit, units) {
|
|
3
|
+
if (typeof value !== "string")
|
|
4
|
+
return defaultUnit;
|
|
5
|
+
return this.getLastUnitFromString(value, units) || defaultUnit;
|
|
6
|
+
}
|
|
7
|
+
getLastUnitFromString(value, units) {
|
|
8
|
+
let resultUnit = null;
|
|
9
|
+
units.forEach(unit => {
|
|
10
|
+
if (value.endsWith(unit))
|
|
11
|
+
resultUnit = unit;
|
|
12
|
+
});
|
|
13
|
+
return resultUnit;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -6,13 +6,12 @@ import { CanvasModel } from "./modelInstance/canvasModel/canvasModel";
|
|
|
6
6
|
export declare const AXIS_HORIZONTAL_LABEL_PADDING = 15;
|
|
7
7
|
export declare const AXIS_VERTICAL_LABEL_PADDING = 10;
|
|
8
8
|
export declare class MarginModel {
|
|
9
|
+
private static twoDimLegendModel;
|
|
9
10
|
static initMargin(designerConfig: DesignerConfig, config: MdtChartsConfig, otherComponents: OtherCommonComponents, data: MdtChartsDataSource, modelInstance: ModelInstance): void;
|
|
10
11
|
static recalcMarginByVerticalAxisLabel(modelInstance: ModelInstance, config: MdtChartsConfig, designerConfig: DesignerConfig, dataScope: DataScope): void;
|
|
12
|
+
static appendToGlobalMarginValuesLegendMargin(canvasModel: CanvasModel, position: Orient, legendBlockModel: LegendBlockModel): void;
|
|
11
13
|
private static getHorizontalMarginByAxisLabels;
|
|
12
14
|
private static recalcVerticalMarginByAxisLabelHeight;
|
|
13
15
|
private static recalcHorizontalMarginByAxisLabelWidth;
|
|
14
|
-
private static recalcMarginWithLegend;
|
|
15
|
-
private static getLegendItemsContent;
|
|
16
|
-
static appendToGlobalMarginValuesLegendMargin(canvasModel: CanvasModel, position: Orient, legendBlockModel: LegendBlockModel): void;
|
|
17
16
|
private static recalcMarginByTitle;
|
|
18
17
|
}
|
package/lib/model/marginModel.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { AxisModel } from "./featuresModel/axisModel";
|
|
2
2
|
import { DataManagerModel } from "./dataManagerModel/dataManagerModel";
|
|
3
|
-
import { LegendModel } from "./featuresModel/legendModel/legendModel";
|
|
4
3
|
import { AxisType } from "./modelBuilder";
|
|
5
4
|
import { TwoDimensionalModel } from "./notations/twoDimensionalModel";
|
|
6
5
|
import { keyAxisLabelHorizontalLog, keyAxisLabelVerticalLog } from "./featuresModel/scaleModel/scaleAxisRecalcer";
|
|
6
|
+
import { TwoDimLegendModel } from "./featuresModel/legendModel/twoDimLegendModel";
|
|
7
7
|
export const AXIS_HORIZONTAL_LABEL_PADDING = 15;
|
|
8
8
|
export const AXIS_VERTICAL_LABEL_PADDING = 10;
|
|
9
9
|
export class MarginModel {
|
|
10
10
|
static initMargin(designerConfig, config, otherComponents, data, modelInstance) {
|
|
11
11
|
const canvasModel = modelInstance.canvasModel;
|
|
12
12
|
canvasModel.initMargin(Object.assign({}, designerConfig.canvas.chartBlockMargin));
|
|
13
|
-
this.recalcMarginWithLegend(modelInstance, config, designerConfig.canvas.legendBlock.maxWidth, otherComponents.legendBlock, data);
|
|
14
13
|
this.recalcMarginByTitle(canvasModel, otherComponents.titleBlock);
|
|
15
|
-
if (config.options.type === '2d'
|
|
14
|
+
if (config.options.type === '2d') {
|
|
15
|
+
this.twoDimLegendModel.recalcMarginWith2DLegend(modelInstance, otherComponents.legendBlock);
|
|
16
16
|
const labelSize = this.getHorizontalMarginByAxisLabels(designerConfig.canvas.axisLabel.maxSize.main, config.options.axis, data, config.options);
|
|
17
17
|
this.recalcVerticalMarginByAxisLabelHeight(labelSize, canvasModel, config.options.orientation, config.options.axis);
|
|
18
18
|
// Если встроенный лейбл показывает ключи, то лейблы оси ключей не показываются
|
|
@@ -35,6 +35,13 @@ export class MarginModel {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
+
static appendToGlobalMarginValuesLegendMargin(canvasModel, position, legendBlockModel) {
|
|
39
|
+
const legendCoordinate = legendBlockModel.coordinate;
|
|
40
|
+
if (position === 'left' || position === 'right')
|
|
41
|
+
canvasModel.increaseMarginSide(position, legendCoordinate[position].margin.left + legendCoordinate[position].margin.right);
|
|
42
|
+
else
|
|
43
|
+
canvasModel.increaseMarginSide(position, legendCoordinate[position].margin.top + legendCoordinate[position].margin.bottom);
|
|
44
|
+
}
|
|
38
45
|
static getHorizontalMarginByAxisLabels(labelsMaxWidth, axis, data, options) {
|
|
39
46
|
const keyAxisOrient = AxisModel.getAxisOrient(AxisType.Key, options.orientation, axis.key.position);
|
|
40
47
|
let labelsTexts;
|
|
@@ -66,45 +73,8 @@ export class MarginModel {
|
|
|
66
73
|
canvasModel.increaseMarginSide(valueAxisOrient, labelSize.width + AXIS_VERTICAL_LABEL_PADDING);
|
|
67
74
|
}
|
|
68
75
|
}
|
|
69
|
-
static recalcMarginWithLegend(modelInstance, config, legendMaxWidth, legendBlockModel, data) {
|
|
70
|
-
if (config.options.type === "polar") {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
const canvasModel = modelInstance.canvasModel;
|
|
74
|
-
const legendPosition = LegendModel.getLegendModel(config.options.type, config.options.legend.show, modelInstance.canvasModel).position;
|
|
75
|
-
modelInstance.canvasModel.legendCanvas.setPosition(legendPosition);
|
|
76
|
-
if (legendPosition !== 'off') {
|
|
77
|
-
const legendItemsContent = this.getLegendItemsContent(config.options, data);
|
|
78
|
-
const legendSize = LegendModel.getLegendSize(config.options.type, legendPosition, legendItemsContent, legendMaxWidth, canvasModel.getBlockSize(), legendBlockModel);
|
|
79
|
-
canvasModel.increaseMarginSide(legendPosition, legendSize);
|
|
80
|
-
if (legendSize !== 0)
|
|
81
|
-
this.appendToGlobalMarginValuesLegendMargin(canvasModel, legendPosition, legendBlockModel);
|
|
82
|
-
legendBlockModel.coordinate[legendPosition].size = legendSize;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
static getLegendItemsContent(options, data) {
|
|
86
|
-
if (options.type === '2d') {
|
|
87
|
-
let texts = [];
|
|
88
|
-
options.charts.forEach(chart => {
|
|
89
|
-
texts = texts.concat(chart.data.valueFields.map(field => field.title));
|
|
90
|
-
});
|
|
91
|
-
return texts;
|
|
92
|
-
}
|
|
93
|
-
else if (options.type === 'polar') {
|
|
94
|
-
return DataManagerModel.getDataValuesByKeyField(data, options.data.dataSource, options.data.keyField.name);
|
|
95
|
-
}
|
|
96
|
-
else if (options.type === 'interval') {
|
|
97
|
-
return [options.chart.data.valueField1.name];
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
static appendToGlobalMarginValuesLegendMargin(canvasModel, position, legendBlockModel) {
|
|
101
|
-
const legendCoordinate = legendBlockModel.coordinate;
|
|
102
|
-
if (position === 'left' || position === 'right')
|
|
103
|
-
canvasModel.increaseMarginSide(position, legendCoordinate[position].margin.left + legendCoordinate[position].margin.right);
|
|
104
|
-
else
|
|
105
|
-
canvasModel.increaseMarginSide(position, legendCoordinate[position].margin.top + legendCoordinate[position].margin.bottom);
|
|
106
|
-
}
|
|
107
76
|
static recalcMarginByTitle(canvasModel, titleBlockModel) {
|
|
108
77
|
canvasModel.increaseMarginSide("top", titleBlockModel.margin.top + titleBlockModel.size + titleBlockModel.margin.bottom);
|
|
109
78
|
}
|
|
110
79
|
}
|
|
80
|
+
MarginModel.twoDimLegendModel = new TwoDimLegendModel();
|
package/lib/model/model.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export declare type EmbeddedLabelTypeModel = "none" | "key" | "value";
|
|
|
9
9
|
export declare type DataOptions = {
|
|
10
10
|
[option: string]: any;
|
|
11
11
|
};
|
|
12
|
+
export declare type UnitsFromConfig = "%" | "px";
|
|
12
13
|
export interface Model<O = TwoDimensionalOptionsModel | PolarOptionsModel | IntervalOptionsModel> {
|
|
13
14
|
blockCanvas: BlockCanvas;
|
|
14
15
|
chartBlock: ChartBlockModel;
|
|
@@ -148,7 +149,7 @@ export interface DonutAggregatorContent {
|
|
|
148
149
|
value: string | number;
|
|
149
150
|
title: string;
|
|
150
151
|
}
|
|
151
|
-
export declare type DonutThicknessUnit =
|
|
152
|
+
export declare type DonutThicknessUnit = UnitsFromConfig;
|
|
152
153
|
export interface DonutThicknessOptions {
|
|
153
154
|
min: number;
|
|
154
155
|
max: number;
|
|
@@ -223,7 +224,6 @@ interface ComponentBlockModel {
|
|
|
223
224
|
}
|
|
224
225
|
export interface LegendBlockModel {
|
|
225
226
|
coordinate: LegendCoordinate;
|
|
226
|
-
standartTooltip: boolean;
|
|
227
227
|
}
|
|
228
228
|
export interface LegendCoordinate {
|
|
229
229
|
top: LegendCanvasCoordinate;
|
|
@@ -67,7 +67,7 @@ export function assembleModel(config, data, designerConfig) {
|
|
|
67
67
|
dataSettings: null
|
|
68
68
|
};
|
|
69
69
|
resetFalsyValues(data, config.options.data.keyField.name);
|
|
70
|
-
const otherComponents = OtherComponentsModel.getOtherComponentsModel({ elementsOptions: designerConfig.elementsOptions,
|
|
70
|
+
const otherComponents = OtherComponentsModel.getOtherComponentsModel({ elementsOptions: designerConfig.elementsOptions, title: config.options.title }, modelInstance);
|
|
71
71
|
MarginModel.initMargin(designerConfig, config, otherComponents, data, modelInstance);
|
|
72
72
|
DataManagerModel.initDataScope(config, data, designerConfig, otherComponents.legendBlock, modelInstance);
|
|
73
73
|
const preparedData = DataManagerModel.getPreparedData(data, modelInstance.dataModel.getAllowableKeys(), config);
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
import { getPxPercentUnitByValue } from "../../../helpers/unitsFromConfigReader";
|
|
1
2
|
export class DonutThicknessService {
|
|
2
3
|
constructor() {
|
|
3
4
|
this.defaultUnit = "px";
|
|
4
5
|
}
|
|
5
6
|
getUnit(settingsFromConfig) {
|
|
6
7
|
if (settingsFromConfig.value)
|
|
7
|
-
return
|
|
8
|
-
const minUnit =
|
|
9
|
-
const maxUnit =
|
|
8
|
+
return getPxPercentUnitByValue(settingsFromConfig.value);
|
|
9
|
+
const minUnit = getPxPercentUnitByValue(settingsFromConfig.min);
|
|
10
|
+
const maxUnit = getPxPercentUnitByValue(settingsFromConfig.max);
|
|
10
11
|
return minUnit === maxUnit ? minUnit : this.defaultUnit;
|
|
11
12
|
}
|
|
12
13
|
valueToNumber(value) {
|
|
@@ -14,17 +15,4 @@ export class DonutThicknessService {
|
|
|
14
15
|
return value;
|
|
15
16
|
return parseInt(value);
|
|
16
17
|
}
|
|
17
|
-
getUnitByValue(value) {
|
|
18
|
-
if (typeof value !== "string")
|
|
19
|
-
return this.defaultUnit;
|
|
20
|
-
return this.getLastUnitFromString(value);
|
|
21
|
-
}
|
|
22
|
-
getLastUnitFromString(value) {
|
|
23
|
-
let resultUnit = this.defaultUnit;
|
|
24
|
-
["%", "px"].forEach(unit => {
|
|
25
|
-
if (value.endsWith(unit))
|
|
26
|
-
resultUnit = unit;
|
|
27
|
-
});
|
|
28
|
-
return resultUnit;
|
|
29
|
-
}
|
|
30
18
|
}
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
/* will-change: opacity; */
|
|
63
63
|
}
|
|
64
64
|
.legend-block-column .legend-item:not(:first-of-type) {
|
|
65
|
-
margin-top:
|
|
65
|
+
margin-top: 10px;
|
|
66
66
|
}
|
|
67
67
|
.legend-item-inline {
|
|
68
68
|
white-space: nowrap;
|
|
@@ -73,13 +73,15 @@
|
|
|
73
73
|
margin-left: 20px;
|
|
74
74
|
}
|
|
75
75
|
.legend-wrapper-with-wrap .legend-item-inline {
|
|
76
|
-
margin:
|
|
76
|
+
margin: 2px;
|
|
77
77
|
}
|
|
78
78
|
.legend-item-row {
|
|
79
79
|
display: flex;
|
|
80
80
|
}
|
|
81
81
|
.legend-item-row > span {
|
|
82
82
|
display: block;
|
|
83
|
+
overflow: hidden;
|
|
84
|
+
text-overflow: ellipsis;
|
|
83
85
|
}
|
|
84
86
|
|
|
85
87
|
.legend-label {
|
|
@@ -201,7 +203,6 @@
|
|
|
201
203
|
line-height: 1;
|
|
202
204
|
}
|
|
203
205
|
.aggregator-value {
|
|
204
|
-
margin-top: 0.5em;
|
|
205
206
|
pointer-events: auto;
|
|
206
207
|
}
|
|
207
208
|
.aggregator-name {
|
|
@@ -221,7 +222,7 @@
|
|
|
221
222
|
/* Record overflow */
|
|
222
223
|
.record-overflow-alert {
|
|
223
224
|
background-color: #FFFFFF;;
|
|
224
|
-
padding:
|
|
225
|
+
padding: 2px 8px;
|
|
225
226
|
border: 1px solid #0F6698;
|
|
226
227
|
box-sizing: border-box;
|
|
227
228
|
border-radius: 100px;
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
/* will-change: opacity; */
|
|
63
63
|
}
|
|
64
64
|
.legend-block-column .legend-item:not(:first-of-type) {
|
|
65
|
-
margin-top:
|
|
65
|
+
margin-top: 10px;
|
|
66
66
|
}
|
|
67
67
|
.legend-item-inline {
|
|
68
68
|
white-space: nowrap;
|
|
@@ -73,13 +73,15 @@
|
|
|
73
73
|
margin-left: 20px;
|
|
74
74
|
}
|
|
75
75
|
.legend-wrapper-with-wrap .legend-item-inline {
|
|
76
|
-
margin:
|
|
76
|
+
margin: 2px;
|
|
77
77
|
}
|
|
78
78
|
.legend-item-row {
|
|
79
79
|
display: flex;
|
|
80
80
|
}
|
|
81
81
|
.legend-item-row > span {
|
|
82
82
|
display: block;
|
|
83
|
+
overflow: hidden;
|
|
84
|
+
text-overflow: ellipsis;
|
|
83
85
|
}
|
|
84
86
|
|
|
85
87
|
.legend-label {
|
|
@@ -201,7 +203,6 @@
|
|
|
201
203
|
line-height: 1;
|
|
202
204
|
}
|
|
203
205
|
.aggregator-value {
|
|
204
|
-
margin-top: 0.5em;
|
|
205
206
|
pointer-events: auto;
|
|
206
207
|
}
|
|
207
208
|
.aggregator-name {
|
|
@@ -221,7 +222,7 @@
|
|
|
221
222
|
/* Record overflow */
|
|
222
223
|
.record-overflow-alert {
|
|
223
224
|
background-color: #FFFFFF;;
|
|
224
|
-
padding:
|
|
225
|
+
padding: 2px 8px;
|
|
225
226
|
border: 1px solid #0F6698;
|
|
226
227
|
box-sizing: border-box;
|
|
227
228
|
border-radius: 100px;
|