@operato/scene-chartjs 0.0.5
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/CHANGELOG.md +17 -0
- package/LICENSE +21 -0
- package/README.md +21 -0
- package/assets/bar-chart.png +0 -0
- package/assets/doughnut-chart.png +0 -0
- package/assets/horizontal-bar-chart.png +0 -0
- package/assets/line-chart.png +0 -0
- package/assets/mixed-chart.png +0 -0
- package/assets/pie-chart.png +0 -0
- package/assets/polar-area-chart.png +0 -0
- package/assets/radar-chart.png +0 -0
- package/demo/bar.html +266 -0
- package/demo/chartjs.html +73 -0
- package/demo/index.html +547 -0
- package/demo/legend.html +267 -0
- package/demo/things-scene-chartjs.html +7 -0
- package/dist/chartjs.d.ts +27 -0
- package/dist/chartjs.js +109 -0
- package/dist/chartjs.js.map +1 -0
- package/dist/config-converter.d.ts +1 -0
- package/dist/config-converter.js +343 -0
- package/dist/config-converter.js.map +1 -0
- package/dist/editors/index.d.ts +5 -0
- package/dist/editors/index.js +11 -0
- package/dist/editors/index.js.map +1 -0
- package/dist/editors/property-editor-chartjs-abstract.d.ts +44 -0
- package/dist/editors/property-editor-chartjs-abstract.js +250 -0
- package/dist/editors/property-editor-chartjs-abstract.js.map +1 -0
- package/dist/editors/property-editor-chartjs-hbar.d.ts +9 -0
- package/dist/editors/property-editor-chartjs-hbar.js +160 -0
- package/dist/editors/property-editor-chartjs-hbar.js.map +1 -0
- package/dist/editors/property-editor-chartjs-mixed.d.ts +20 -0
- package/dist/editors/property-editor-chartjs-mixed.js +193 -0
- package/dist/editors/property-editor-chartjs-mixed.js.map +1 -0
- package/dist/editors/property-editor-chartjs-multi-series-abstract.d.ts +31 -0
- package/dist/editors/property-editor-chartjs-multi-series-abstract.js +373 -0
- package/dist/editors/property-editor-chartjs-multi-series-abstract.js.map +1 -0
- package/dist/editors/property-editor-chartjs-pie.d.ts +14 -0
- package/dist/editors/property-editor-chartjs-pie.js +70 -0
- package/dist/editors/property-editor-chartjs-pie.js.map +1 -0
- package/dist/editors/property-editor-chartjs-radar.d.ts +10 -0
- package/dist/editors/property-editor-chartjs-radar.js +42 -0
- package/dist/editors/property-editor-chartjs-radar.js.map +1 -0
- package/dist/editors/property-editor-chartjs-styles.d.ts +1 -0
- package/dist/editors/property-editor-chartjs-styles.js +165 -0
- package/dist/editors/property-editor-chartjs-styles.js.map +1 -0
- package/dist/editors/property-editor-chartjs.d.ts +14 -0
- package/dist/editors/property-editor-chartjs.js +83 -0
- package/dist/editors/property-editor-chartjs.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/ox-chart.d.ts +20 -0
- package/dist/ox-chart.js +137 -0
- package/dist/ox-chart.js.map +1 -0
- package/dist/plugins/chart-series-highlight.d.ts +5 -0
- package/dist/plugins/chart-series-highlight.js +37 -0
- package/dist/plugins/chart-series-highlight.js.map +1 -0
- package/dist/plugins/chartjs-plugin-data-binder.d.ts +5 -0
- package/dist/plugins/chartjs-plugin-data-binder.js +111 -0
- package/dist/plugins/chartjs-plugin-data-binder.js.map +1 -0
- package/helps/scene/component/chartjs.ko.md +332 -0
- package/helps/scene/component/chartjs.md +333 -0
- package/helps/scene/component/chartjs.zh.md +331 -0
- package/helps/scene/images/chart-bar-01.png +0 -0
- package/helps/scene/images/chart-bar-02.png +0 -0
- package/helps/scene/images/chart-bar-03.png +0 -0
- package/helps/scene/images/chart-bar-08.png +0 -0
- package/helps/scene/images/chart-bar-12.png +0 -0
- package/helps/scene/images/chart-data-01.png +0 -0
- package/helps/scene/images/chart-data-04.png +0 -0
- package/helps/scene/images/chart-doughnut-01.png +0 -0
- package/helps/scene/images/chart-horizontal-bar-01.png +0 -0
- package/helps/scene/images/chart-line-01.png +0 -0
- package/helps/scene/images/chart-mix-01.png +0 -0
- package/helps/scene/images/chart-mix-02.png +0 -0
- package/helps/scene/images/chart-pie-01.png +0 -0
- package/helps/scene/images/chart-polar-01.png +0 -0
- package/helps/scene/images/chart-radar-01.png +0 -0
- package/package.json +78 -0
- package/src/chartjs.ts +134 -0
- package/src/config-converter.ts +401 -0
- package/src/editors/index.ts +11 -0
- package/src/editors/property-editor-chartjs-abstract.ts +301 -0
- package/src/editors/property-editor-chartjs-hbar.ts +163 -0
- package/src/editors/property-editor-chartjs-mixed.ts +204 -0
- package/src/editors/property-editor-chartjs-multi-series-abstract.ts +393 -0
- package/src/editors/property-editor-chartjs-pie.ts +79 -0
- package/src/editors/property-editor-chartjs-radar.ts +43 -0
- package/src/editors/property-editor-chartjs-styles.ts +165 -0
- package/src/editors/property-editor-chartjs.ts +88 -0
- package/src/index.ts +7 -0
- package/src/ox-chart.ts +150 -0
- package/src/plugins/chart-series-highlight.ts +43 -0
- package/src/plugins/chartjs-plugin-data-binder.ts +138 -0
- package/src/scene-chart.d.ts +152 -0
- package/templates/bar-chart.js +124 -0
- package/templates/doughnut-chart.js +58 -0
- package/templates/horizontal-bar-chart.js +121 -0
- package/templates/index.js +22 -0
- package/templates/line-chart.js +155 -0
- package/templates/mixed-chart.js +152 -0
- package/templates/pie-chart.js +58 -0
- package/templates/polar-area-chart.js +92 -0
- package/templates/radar-chart.js +98 -0
- package/test/basic-test.html +61 -0
- package/test/index.html +20 -0
- package/things-scene.config.js +7 -0
- package/translations/en.json +5 -0
- package/translations/ko.json +5 -0
- package/translations/ms.json +5 -0
- package/translations/zh.json +5 -0
- package/tsconfig.json +22 -0
- package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,401 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright © HatioLab Inc. All rights reserved.
|
3
|
+
*/
|
4
|
+
|
5
|
+
import { TinyColor } from '@ctrl/tinycolor'
|
6
|
+
|
7
|
+
export function convertConfigure(chart: SceneChart.ChartConfig) {
|
8
|
+
if (!chart) return
|
9
|
+
|
10
|
+
var data = chart.data || {}
|
11
|
+
var datasets = data.datasets || []
|
12
|
+
var options = chart.options || {}
|
13
|
+
var scales = options.scales || {}
|
14
|
+
var xAxes: Array<SceneChart.ChartXAxe>
|
15
|
+
var yAxes: Array<SceneChart.ChartYAxe>
|
16
|
+
var scale
|
17
|
+
var legend = options.legend || {}
|
18
|
+
var tooltips = (options.tooltips = options.tooltips || {})
|
19
|
+
|
20
|
+
var multiAxis = options.multiAxis
|
21
|
+
var stacked = false
|
22
|
+
var yStacked = [false, false]
|
23
|
+
var fontSize = Number(options.defaultFontSize)
|
24
|
+
var fontFamily = options.defaultFontFamily
|
25
|
+
var fontColor = options.defaultFontColor
|
26
|
+
var theme = options.theme
|
27
|
+
|
28
|
+
// backward compatible
|
29
|
+
_configureBackwardsCompatible(chart.type, options)
|
30
|
+
|
31
|
+
// setup series configure
|
32
|
+
for (let i in datasets) {
|
33
|
+
let series = datasets[i]
|
34
|
+
|
35
|
+
if (options.stacked && !series.stack) {
|
36
|
+
series.stack = 'A'
|
37
|
+
}
|
38
|
+
|
39
|
+
/*
|
40
|
+
* TODO from chartjs 2.9, categoryPercentage, barPercentage properties move to dataset.
|
41
|
+
* so need to move related properties - categorySpacing, barSpacing should be moved to series.
|
42
|
+
*/
|
43
|
+
if (chart.type == 'bar') {
|
44
|
+
let categorySpacing = (scales.xAxes && scales.xAxes[0].categorySpacing) || 0
|
45
|
+
let barSpacing = (scales.xAxes && scales.xAxes[0].barSpacing) || 0
|
46
|
+
|
47
|
+
series.categoryPercentage = 1 - categorySpacing || 1
|
48
|
+
series.barPercentage = 1 - barSpacing || 0.8
|
49
|
+
} else if (chart.type == 'horizontalBar') {
|
50
|
+
let categorySpacing = (scales.yAxes && scales.yAxes[0].categorySpacing) || 0
|
51
|
+
let barSpacing = (scales.yAxes && scales.yAxes[0].barSpacing) || 0
|
52
|
+
|
53
|
+
series.categoryPercentage = 1 - categorySpacing || 1
|
54
|
+
series.barPercentage = 1 - barSpacing || 0.8
|
55
|
+
}
|
56
|
+
|
57
|
+
_setSeriesConfigures(series, chart)
|
58
|
+
|
59
|
+
if (!multiAxis) {
|
60
|
+
if (series.yAxisID == 'right') series.yAxisID = 'left'
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
delete options.stacked
|
65
|
+
|
66
|
+
var leftSeries = datasets.filter(d => d.yAxisID == 'left')
|
67
|
+
var rightSeries = datasets.filter(d => d.yAxisID == 'right')
|
68
|
+
|
69
|
+
leftSeries.forEach(s => {
|
70
|
+
var filtered = leftSeries.filter(ss => s.stack == ss.stack)
|
71
|
+
if (filtered.length > 1) {
|
72
|
+
yStacked[0] = true
|
73
|
+
return
|
74
|
+
}
|
75
|
+
})
|
76
|
+
|
77
|
+
rightSeries.forEach(s => {
|
78
|
+
var filtered = rightSeries.filter(ss => s.stack == ss.stack)
|
79
|
+
if (filtered.length > 1) {
|
80
|
+
yStacked[1] = true
|
81
|
+
return
|
82
|
+
}
|
83
|
+
})
|
84
|
+
|
85
|
+
stacked = yStacked[0] || yStacked[1]
|
86
|
+
|
87
|
+
// setup options
|
88
|
+
// 1. setup scales
|
89
|
+
switch (chart.type) {
|
90
|
+
case 'line':
|
91
|
+
case 'bar':
|
92
|
+
case 'horizontalBar':
|
93
|
+
xAxes = scales.xAxes || []
|
94
|
+
yAxes = scales.yAxes || []
|
95
|
+
|
96
|
+
if (chart.type == 'horizontalBar') {
|
97
|
+
xAxes = scales.yAxes || []
|
98
|
+
yAxes = scales.xAxes || []
|
99
|
+
}
|
100
|
+
|
101
|
+
// 1-1. setup xAxes
|
102
|
+
for (let i in xAxes) {
|
103
|
+
let axis = xAxes[i]
|
104
|
+
_setStacked(axis, stacked)
|
105
|
+
_setScalesFont(axis, {
|
106
|
+
fontSize,
|
107
|
+
fontFamily
|
108
|
+
})
|
109
|
+
_setScalesAutoMinMax(axis)
|
110
|
+
_setScalesTickRotation(axis)
|
111
|
+
_setAxisTitle(axis)
|
112
|
+
_setScalesTheme(axis, theme, fontColor)
|
113
|
+
_appendTickCallback(axis.ticks)
|
114
|
+
|
115
|
+
axis.gridLines!.display = options.xGridLine
|
116
|
+
}
|
117
|
+
|
118
|
+
// 1-2. setup yAxes
|
119
|
+
for (let i in yAxes) {
|
120
|
+
let axis = yAxes[i]
|
121
|
+
|
122
|
+
//@ts-ignore
|
123
|
+
if (i == 1) {
|
124
|
+
_setMultiAxis(axis, multiAxis)
|
125
|
+
}
|
126
|
+
_setStacked(axis, yStacked[i])
|
127
|
+
_setScalesFont(axis, {
|
128
|
+
fontSize,
|
129
|
+
fontFamily
|
130
|
+
})
|
131
|
+
_setScalesAutoMinMax(axis)
|
132
|
+
_setAxisTitle(axis)
|
133
|
+
_setScalesTheme(axis, theme, fontColor)
|
134
|
+
_appendTickCallback(axis.ticks)
|
135
|
+
|
136
|
+
//@ts-ignore
|
137
|
+
if (i == 0) axis.gridLines.display = options.yGridLine
|
138
|
+
|
139
|
+
//@ts-ignore
|
140
|
+
if (i == 1) axis.gridLines.display = options.y2ndGridLine
|
141
|
+
}
|
142
|
+
|
143
|
+
break
|
144
|
+
case 'pie':
|
145
|
+
case 'doughnut':
|
146
|
+
break
|
147
|
+
default:
|
148
|
+
scale = options.scale || {}
|
149
|
+
_setScalesFont(scale, {
|
150
|
+
fontSize,
|
151
|
+
fontFamily
|
152
|
+
})
|
153
|
+
break
|
154
|
+
}
|
155
|
+
|
156
|
+
// 2. setup legend
|
157
|
+
_setLegendFont(legend, {
|
158
|
+
fontSize,
|
159
|
+
fontFamily
|
160
|
+
})
|
161
|
+
legend.labels && (legend.labels.boxWidth = 15)
|
162
|
+
_setLegendTheme(legend, theme, fontColor)
|
163
|
+
|
164
|
+
// 3. setup tooltips
|
165
|
+
_setTooltipFont(tooltips, {
|
166
|
+
fontSize,
|
167
|
+
fontFamily
|
168
|
+
})
|
169
|
+
_setTooltipCallback(tooltips)
|
170
|
+
}
|
171
|
+
|
172
|
+
function _configureBackwardsCompatible(type: string, options: SceneChart.ChartOptions) {
|
173
|
+
switch (type) {
|
174
|
+
case 'horizontalBar':
|
175
|
+
if (!options.scales) options.scales = {}
|
176
|
+
break
|
177
|
+
case 'radar':
|
178
|
+
case 'polarArea':
|
179
|
+
if (options.defaultFontColor) {
|
180
|
+
options.scale!.ticks!.fontColor = options.defaultFontColor
|
181
|
+
if (options.scale.pointLabels) {
|
182
|
+
options.scale.pointLabels.fontColor = options.defaultFontColor
|
183
|
+
} else {
|
184
|
+
options.scale.pointLabels = { fontColor: options.defaultFontColor }
|
185
|
+
}
|
186
|
+
}
|
187
|
+
options.scale!.ticks!.backdropColor = options.fillStyle ? options.fillStyle : '#00ff0000'
|
188
|
+
break
|
189
|
+
case 'line':
|
190
|
+
case 'bar':
|
191
|
+
if (!options.scales) options.scales = {}
|
192
|
+
if (!options.scales.yAxes) options.scales.yAxes = []
|
193
|
+
|
194
|
+
if (options.scales.yAxes.length === 1) {
|
195
|
+
let yAxes = options.scales.yAxes
|
196
|
+
yAxes.push({
|
197
|
+
position: 'right',
|
198
|
+
id: 'right',
|
199
|
+
display: options.multiAxis || false,
|
200
|
+
gridLines: {
|
201
|
+
display: (yAxes[0] && yAxes[0].gridLines && yAxes[0].gridLines.display) || false
|
202
|
+
},
|
203
|
+
ticks: {
|
204
|
+
beginAtZero: false,
|
205
|
+
callback: function (value: any, index: number, values: any[]) {
|
206
|
+
var returnValue = value
|
207
|
+
if (typeof returnValue == 'number') {
|
208
|
+
returnValue = returnValue.toLocaleString()
|
209
|
+
}
|
210
|
+
|
211
|
+
return returnValue
|
212
|
+
}
|
213
|
+
}
|
214
|
+
})
|
215
|
+
}
|
216
|
+
break
|
217
|
+
case 'pie':
|
218
|
+
case 'doughnut':
|
219
|
+
break
|
220
|
+
default:
|
221
|
+
if (!options.scale) options.scale = {}
|
222
|
+
|
223
|
+
break
|
224
|
+
}
|
225
|
+
}
|
226
|
+
|
227
|
+
function _setStacked(axis: SceneChart.ChartXAxe, stacked: boolean) {
|
228
|
+
axis.stacked = stacked
|
229
|
+
}
|
230
|
+
|
231
|
+
function _setMultiAxis(axis: SceneChart.ChartXAxe, multiAxis: boolean) {
|
232
|
+
axis.display = multiAxis
|
233
|
+
}
|
234
|
+
|
235
|
+
function _setAxisTitle(axis: SceneChart.ChartXAxe) {
|
236
|
+
if (!axis.scaleLabel) axis.scaleLabel = {}
|
237
|
+
axis.scaleLabel.labelString = axis.axisTitle
|
238
|
+
axis.scaleLabel.display = axis.axisTitle ? true : false
|
239
|
+
}
|
240
|
+
|
241
|
+
function _setScalesFont(
|
242
|
+
axis: SceneChart.ChartXAxe | SceneChart.RadialLinearScale,
|
243
|
+
{ fontSize, fontFamily }: { fontSize: number; fontFamily: string }
|
244
|
+
) {
|
245
|
+
axis.ticks = axis.ticks ? axis.ticks : {}
|
246
|
+
axis.ticks.fontSize = fontSize
|
247
|
+
|
248
|
+
if (fontFamily) {
|
249
|
+
axis.ticks.fontFamily = fontFamily
|
250
|
+
}
|
251
|
+
|
252
|
+
;(axis as SceneChart.RadialLinearScale).pointLabels = {
|
253
|
+
fontSize,
|
254
|
+
fontFamily
|
255
|
+
}
|
256
|
+
}
|
257
|
+
|
258
|
+
function _setScalesAutoMinMax(axis: SceneChart.ChartXAxe) {
|
259
|
+
axis.ticks = axis.ticks ? axis.ticks : {}
|
260
|
+
|
261
|
+
let autoMin = axis.ticks.autoMin
|
262
|
+
let autoMax = axis.ticks.autoMax
|
263
|
+
|
264
|
+
if (autoMin === true) {
|
265
|
+
delete axis.ticks.min
|
266
|
+
}
|
267
|
+
if (autoMax === true) {
|
268
|
+
delete axis.ticks.max
|
269
|
+
}
|
270
|
+
}
|
271
|
+
|
272
|
+
function _setScalesTickRotation(axis: SceneChart.ChartXAxe) {
|
273
|
+
axis.ticks = axis.ticks ? axis.ticks : {}
|
274
|
+
// axis.ticks.maxRotation = 0
|
275
|
+
}
|
276
|
+
|
277
|
+
function _setScalesTheme(axis: SceneChart.ChartXAxe, theme: SceneChart.Theme, fontColor: string) {
|
278
|
+
var baseColor = _getBaseColorFromTheme(theme)
|
279
|
+
|
280
|
+
axis.gridLines = axis.gridLines ? axis.gridLines : {}
|
281
|
+
if (axis.gridLines) {
|
282
|
+
axis.gridLines.zeroLineColor = baseColor.clone().setAlpha(0.5).toString()
|
283
|
+
axis.gridLines.color = baseColor.clone().setAlpha(0.1).toString()
|
284
|
+
}
|
285
|
+
|
286
|
+
axis.ticks = axis.ticks ? axis.ticks : {}
|
287
|
+
axis.ticks.fontColor = fontColor ? fontColor : baseColor.clone().setAlpha(0.5).toString()
|
288
|
+
}
|
289
|
+
|
290
|
+
function _setLegendFont(
|
291
|
+
legend: SceneChart.ChartLegendOptions,
|
292
|
+
{ fontFamily, fontSize }: { fontFamily: string; fontSize: number }
|
293
|
+
) {
|
294
|
+
legend.labels = legend.labels ? legend.labels : {}
|
295
|
+
legend.labels.fontSize = fontSize
|
296
|
+
if (fontFamily) legend.labels.fontFamily = fontFamily
|
297
|
+
}
|
298
|
+
|
299
|
+
function _setLegendTheme(legend: SceneChart.ChartLegendOptions, theme: SceneChart.Theme, fontColor: string) {
|
300
|
+
var baseColor = _getBaseColorFromTheme(theme)
|
301
|
+
|
302
|
+
legend.labels = legend.labels ? legend.labels : {}
|
303
|
+
legend.labels.fontColor = fontColor ? fontColor : baseColor.clone().setAlpha(0.5).toString()
|
304
|
+
}
|
305
|
+
|
306
|
+
function _getBaseColorFromTheme(theme: SceneChart.Theme) {
|
307
|
+
let darkColor = '#000'
|
308
|
+
let lightColor = '#fff'
|
309
|
+
|
310
|
+
var baseColor
|
311
|
+
|
312
|
+
switch (theme) {
|
313
|
+
case 'light':
|
314
|
+
baseColor = lightColor
|
315
|
+
break
|
316
|
+
case 'dark':
|
317
|
+
default:
|
318
|
+
baseColor = darkColor
|
319
|
+
break
|
320
|
+
}
|
321
|
+
|
322
|
+
baseColor = new TinyColor(baseColor)
|
323
|
+
|
324
|
+
return baseColor
|
325
|
+
}
|
326
|
+
|
327
|
+
function _setSeriesConfigures(series: SceneChart.ChartDataSets, chart: SceneChart.ChartConfig) {
|
328
|
+
var type = series.type || chart.type
|
329
|
+
var stackGroup = `${type} ${series.yAxisID} ${series.stack || series.dataKey}`
|
330
|
+
var color = series.color ? series.color : series.backgroundColor
|
331
|
+
|
332
|
+
switch (type) {
|
333
|
+
case 'bar':
|
334
|
+
case 'horizontalBar':
|
335
|
+
series.borderColor = series.backgroundColor = color
|
336
|
+
break
|
337
|
+
|
338
|
+
case 'line':
|
339
|
+
case 'radar':
|
340
|
+
color = series.color ? series.color : series.borderColor
|
341
|
+
series.pointBackgroundColor = series.pointBorderColor = series.borderColor = series.backgroundColor = color
|
342
|
+
series.pointBorderWidth = (series.borderWidth as number) * 0.5
|
343
|
+
series.pointHoverRadius = series.pointRadius
|
344
|
+
if (series.fill == undefined) series.fill = false
|
345
|
+
break
|
346
|
+
|
347
|
+
default:
|
348
|
+
series.borderColor = series.backgroundColor = color
|
349
|
+
break
|
350
|
+
}
|
351
|
+
|
352
|
+
series.stack = stackGroup
|
353
|
+
}
|
354
|
+
|
355
|
+
function _appendTickCallback(ticks: SceneChart.TickOptions | undefined) {
|
356
|
+
if (!ticks) {
|
357
|
+
return
|
358
|
+
}
|
359
|
+
|
360
|
+
ticks.callback = function (value, index, values) {
|
361
|
+
var returnValue
|
362
|
+
if (!Number.isNaN(Number(value))) {
|
363
|
+
returnValue = Number(value).toLocaleString()
|
364
|
+
} else {
|
365
|
+
returnValue = value
|
366
|
+
}
|
367
|
+
|
368
|
+
if (returnValue) return returnValue
|
369
|
+
}
|
370
|
+
}
|
371
|
+
|
372
|
+
function _setTooltipFont(
|
373
|
+
tooltips: SceneChart.ChartTooltipOptions,
|
374
|
+
{ fontSize, fontFamily }: { fontSize: number; fontFamily: string }
|
375
|
+
) {
|
376
|
+
tooltips.titleFontSize = tooltips.bodyFontSize = tooltips.footerFontSize = fontSize
|
377
|
+
if (fontFamily) tooltips.titleFontFamily = tooltips.bodyFontFamily = tooltips.footerFontFamily = fontFamily
|
378
|
+
}
|
379
|
+
|
380
|
+
function _setTooltipCallback(tooltips: SceneChart.ChartTooltipOptions) {
|
381
|
+
tooltips.callbacks = tooltips.callbacks || {}
|
382
|
+
|
383
|
+
tooltips.intersect = false
|
384
|
+
tooltips.mode = 'index'
|
385
|
+
|
386
|
+
tooltips.callbacks.label = function (tooltipItem: SceneChart.ChartTooltipItem, data: SceneChart.ChartData) {
|
387
|
+
var value = data.datasets?.[tooltipItem.datasetIndex || 0].data?.[tooltipItem.index || 0]
|
388
|
+
var datasetLabel = data.datasets?.[tooltipItem.datasetIndex || 0].label
|
389
|
+
var label = datasetLabel || data.labels?.[tooltipItem.index || 0]
|
390
|
+
var toNumValue = Number(value)
|
391
|
+
|
392
|
+
if (!isNaN(toNumValue)) {
|
393
|
+
value = toNumValue
|
394
|
+
}
|
395
|
+
|
396
|
+
var prefix = data.datasets?.[tooltipItem.datasetIndex || 0].valuePrefix || ''
|
397
|
+
var suffix = data.datasets?.[tooltipItem.datasetIndex || 0].valueSuffix || ''
|
398
|
+
|
399
|
+
return `${label}: ${prefix + value?.toLocaleString() + suffix}`
|
400
|
+
}
|
401
|
+
}
|
@@ -0,0 +1,301 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright © HatioLab Inc. All rights reserved.
|
3
|
+
*/
|
4
|
+
|
5
|
+
import { html, LitElement } from 'lit'
|
6
|
+
import { property } from 'lit/decorators.js'
|
7
|
+
|
8
|
+
import { random as randomColor, TinyColor } from '@ctrl/tinycolor'
|
9
|
+
|
10
|
+
import { PropertyEditorChartJSStyles } from './property-editor-chartjs-styles'
|
11
|
+
|
12
|
+
export default class PropertyEditorChartJSAbstract extends LitElement {
|
13
|
+
static styles = [PropertyEditorChartJSStyles]
|
14
|
+
|
15
|
+
@property({ type: Object }) value: any = {}
|
16
|
+
@property({ type: Number }) currentSeriesIndex: number = 0
|
17
|
+
|
18
|
+
render() {
|
19
|
+
return html`
|
20
|
+
<legend><i18n-msg msgid="label.chart">Chart</i18n-msg></legend>
|
21
|
+
|
22
|
+
<label> <i18n-msg msgid="label.theme">theme</i18n-msg> </label>
|
23
|
+
<select value-key="theme" class="select-content" .value=${this.theme}>
|
24
|
+
<option value="dark">dark</option>
|
25
|
+
<option value="light">light</option>
|
26
|
+
</select>
|
27
|
+
|
28
|
+
<input type="checkbox" value-key="display" .checked=${this.display} />
|
29
|
+
<label> <i18n-msg msgid="label.legend">Legend</i18n-msg> </label>
|
30
|
+
|
31
|
+
${this.display
|
32
|
+
? html`
|
33
|
+
<label> <i18n-msg msgid="label.position">Position</i18n-msg> </label>
|
34
|
+
<select value-key="position" class="select-content" .value=${this.position}>
|
35
|
+
<option value="top">top</option>
|
36
|
+
<option value="right">right</option>
|
37
|
+
<option value="bottom">bottom</option>
|
38
|
+
<option value="left">left</option>
|
39
|
+
</select>
|
40
|
+
`
|
41
|
+
: html``}
|
42
|
+
${this.editorTemplate(this)}
|
43
|
+
`
|
44
|
+
}
|
45
|
+
|
46
|
+
firstUpdated() {
|
47
|
+
this.renderRoot.addEventListener('change', this.onValuesChanged.bind(this))
|
48
|
+
}
|
49
|
+
|
50
|
+
displayValueTemplate() {
|
51
|
+
return html`
|
52
|
+
<label> <i18n-msg msgid="label.value-prefix">Value Prefix</i18n-msg> </label>
|
53
|
+
<input type="text" value-key="series.valuePrefix" .value=${this.series.valuePrefix || ''} />
|
54
|
+
|
55
|
+
<label> <i18n-msg msgid="label.value-suffix">Value suffix</i18n-msg> </label>
|
56
|
+
<input type="text" value-key="series.valueSuffix" .value=${this.series.valueSuffix || ''} />
|
57
|
+
|
58
|
+
<input type="checkbox" value-key="series.displayValue" .checked=${this.series.displayValue || false} />
|
59
|
+
<label> <i18n-msg msgid="label.value-display">Value Display</i18n-msg> </label>
|
60
|
+
|
61
|
+
${this.series.displayValue
|
62
|
+
? html`
|
63
|
+
<label> <i18n-msg msgid="label.font-color">Font Color</i18n-msg> </label>
|
64
|
+
<things-editor-color
|
65
|
+
value-key="series.defaultFontColor"
|
66
|
+
.value=${this.series.defaultFontColor || '#000'}
|
67
|
+
></things-editor-color>
|
68
|
+
<label> <i18n-msg msgid="label.font-size">Font Size</i18n-msg> </label>
|
69
|
+
<input type="number" value-key="series.defaultFontSize" .value=${this.series.defaultFontSize || 10} />
|
70
|
+
<label> <i18n-msg msgid="label.position">Position</i18n-msg> </label>
|
71
|
+
<select value-key="series.dataLabelAnchor" .value=${this.series.dataLabelAnchor || 'center'}>
|
72
|
+
<option value="start">Start</option>
|
73
|
+
<option value="center" selected>Center</option>
|
74
|
+
<option value="end">End</option>
|
75
|
+
</select>
|
76
|
+
`
|
77
|
+
: html``}
|
78
|
+
`
|
79
|
+
}
|
80
|
+
|
81
|
+
editorTemplate(props: any) {
|
82
|
+
return html``
|
83
|
+
}
|
84
|
+
|
85
|
+
get data() {
|
86
|
+
return this.value.data
|
87
|
+
}
|
88
|
+
|
89
|
+
set data(data) {
|
90
|
+
this.value.data = data
|
91
|
+
}
|
92
|
+
|
93
|
+
get datasets() {
|
94
|
+
if (!this.data.datasets) this.data.datasets = []
|
95
|
+
|
96
|
+
return this.data.datasets
|
97
|
+
}
|
98
|
+
|
99
|
+
set datasets(datasets) {
|
100
|
+
this.datasets = datasets
|
101
|
+
}
|
102
|
+
|
103
|
+
get series() {
|
104
|
+
if (!this.datasets[this.currentSeriesIndex]) this.datasets[this.currentSeriesIndex] = {}
|
105
|
+
return this.datasets[this.currentSeriesIndex]
|
106
|
+
}
|
107
|
+
|
108
|
+
set series(series) {
|
109
|
+
!this.data ? (this.data = { dataset: [series] }) : (this.datasets[this.currentSeriesIndex] = series)
|
110
|
+
}
|
111
|
+
|
112
|
+
set dataKey(key) {
|
113
|
+
this.series.dataKey = key
|
114
|
+
}
|
115
|
+
|
116
|
+
get dataKey() {
|
117
|
+
return this.series.dataKey
|
118
|
+
}
|
119
|
+
|
120
|
+
get legend() {
|
121
|
+
!this.value.options && (this.value.options = {})
|
122
|
+
return this.value.options.legend
|
123
|
+
}
|
124
|
+
|
125
|
+
set legend(legend) {
|
126
|
+
this.value.options.legend = legend
|
127
|
+
}
|
128
|
+
|
129
|
+
get theme() {
|
130
|
+
return this.value.options && this.value.options.theme
|
131
|
+
}
|
132
|
+
|
133
|
+
set theme(theme) {
|
134
|
+
!this.value.options && (this.value.options = {})
|
135
|
+
this.value.options.theme = theme
|
136
|
+
}
|
137
|
+
|
138
|
+
get scales() {
|
139
|
+
return this.value.options.scales
|
140
|
+
}
|
141
|
+
|
142
|
+
set scales(scales) {
|
143
|
+
!this.value.options && (this.value.options = {})
|
144
|
+
this.value.options.scales = scales
|
145
|
+
}
|
146
|
+
|
147
|
+
get display() {
|
148
|
+
return this.legend && this.legend.display
|
149
|
+
}
|
150
|
+
|
151
|
+
set display(display) {
|
152
|
+
this.legend.display = display
|
153
|
+
}
|
154
|
+
|
155
|
+
get position() {
|
156
|
+
return this.legend.position
|
157
|
+
}
|
158
|
+
|
159
|
+
set position(position) {
|
160
|
+
this.legend.position = position
|
161
|
+
}
|
162
|
+
|
163
|
+
get stacked() {
|
164
|
+
return this.value.options.stacked
|
165
|
+
}
|
166
|
+
|
167
|
+
set stacked(stacked) {
|
168
|
+
this.value.options.stacked = stacked
|
169
|
+
}
|
170
|
+
|
171
|
+
get labelDataKey() {
|
172
|
+
return this.data && this.data.labelDataKey
|
173
|
+
}
|
174
|
+
|
175
|
+
set labelDataKey(labelDataKey) {
|
176
|
+
this.data.labelDataKey = labelDataKey
|
177
|
+
}
|
178
|
+
|
179
|
+
set options(options) {
|
180
|
+
this.value.options = options
|
181
|
+
}
|
182
|
+
|
183
|
+
get options() {
|
184
|
+
return this.value.options
|
185
|
+
}
|
186
|
+
|
187
|
+
onValuesChanged(e: Event) {
|
188
|
+
var element = e.target as HTMLInputElement
|
189
|
+
var key = element.getAttribute('value-key')
|
190
|
+
var value = element.value
|
191
|
+
|
192
|
+
if (!key) {
|
193
|
+
return
|
194
|
+
}
|
195
|
+
|
196
|
+
value = this._getElementValue(element)
|
197
|
+
|
198
|
+
var attrs = key.split('.')
|
199
|
+
var attr = attrs.shift() || ''
|
200
|
+
var variable = this
|
201
|
+
|
202
|
+
while (attrs.length > 0) {
|
203
|
+
//@ts-ignore
|
204
|
+
variable = variable[attr]
|
205
|
+
attr = attrs.shift() || ''
|
206
|
+
}
|
207
|
+
|
208
|
+
//@ts-ignore
|
209
|
+
variable[attr] = value
|
210
|
+
|
211
|
+
this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
|
212
|
+
this.requestUpdate()
|
213
|
+
}
|
214
|
+
|
215
|
+
onTapAddTab(e: Event) {
|
216
|
+
if (!this.value.data.datasets) return
|
217
|
+
|
218
|
+
var lastSeriesIndex = this.value.data.datasets.length
|
219
|
+
var chartType = this.series.type || this.value.type
|
220
|
+
var lastSeriesColor = new TinyColor(this.datasets[lastSeriesIndex - 1].backgroundColor)
|
221
|
+
|
222
|
+
var seriesModel = this._getSeriesModel({
|
223
|
+
chartType,
|
224
|
+
datasetsLength: lastSeriesIndex,
|
225
|
+
lastSeriesColor
|
226
|
+
})
|
227
|
+
|
228
|
+
this.value.data.datasets.push(seriesModel)
|
229
|
+
this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
|
230
|
+
this.currentSeriesIndex = lastSeriesIndex
|
231
|
+
}
|
232
|
+
|
233
|
+
onTapRemoveCurrentTab(e: Event) {
|
234
|
+
if (!this.value.data.datasets) return
|
235
|
+
|
236
|
+
var currIndex = this.currentSeriesIndex
|
237
|
+
this.value.data.datasets.splice(currIndex, 1)
|
238
|
+
|
239
|
+
currIndex--
|
240
|
+
|
241
|
+
if (currIndex < 0) currIndex = 0
|
242
|
+
|
243
|
+
this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
|
244
|
+
this.currentSeriesIndex = currIndex
|
245
|
+
|
246
|
+
this.requestUpdate()
|
247
|
+
}
|
248
|
+
|
249
|
+
_getSeriesModel({
|
250
|
+
chartType,
|
251
|
+
datasetsLength,
|
252
|
+
lastSeriesColor
|
253
|
+
}: {
|
254
|
+
chartType: any
|
255
|
+
datasetsLength: number
|
256
|
+
lastSeriesColor: TinyColor
|
257
|
+
}) {
|
258
|
+
var addSeriesOption: any = {
|
259
|
+
label: `series ${datasetsLength + 1}`,
|
260
|
+
data: [],
|
261
|
+
borderWidth: 1,
|
262
|
+
dataKey: '',
|
263
|
+
yAxisID: 'left',
|
264
|
+
color: randomColor({
|
265
|
+
hue: lastSeriesColor as any
|
266
|
+
}).toRgbString()
|
267
|
+
}
|
268
|
+
|
269
|
+
addSeriesOption.type = addSeriesOption.chartType = chartType
|
270
|
+
return addSeriesOption
|
271
|
+
}
|
272
|
+
|
273
|
+
_getElementValue(element: HTMLElement) {
|
274
|
+
switch (element.tagName) {
|
275
|
+
case 'INPUT':
|
276
|
+
switch ((element as HTMLInputElement).type) {
|
277
|
+
case 'checkbox':
|
278
|
+
return (element as HTMLInputElement).checked
|
279
|
+
case 'number':
|
280
|
+
return Number((element as HTMLInputElement).value) || 0
|
281
|
+
case 'text':
|
282
|
+
return String((element as HTMLInputElement).value)
|
283
|
+
}
|
284
|
+
|
285
|
+
case 'PAPER-BUTTON':
|
286
|
+
return (element as any).active
|
287
|
+
|
288
|
+
case 'PAPER-LISTBOX':
|
289
|
+
return (element as any).selected
|
290
|
+
|
291
|
+
case 'THINGS-EDITOR-MULTIPLE-COLOR':
|
292
|
+
return (element as any).values
|
293
|
+
|
294
|
+
case 'THINGS-EDITOR-ANGLE-INPUT':
|
295
|
+
return Number((element as any).radian) || 0
|
296
|
+
|
297
|
+
default:
|
298
|
+
return (element as any).value
|
299
|
+
}
|
300
|
+
}
|
301
|
+
}
|