@operato/scene-scichart 7.3.10 → 7.3.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. package/dist/charts/ox-scichart-multiple.d.ts +1 -1
  2. package/dist/charts/ox-scichart-multiple.js +1 -2
  3. package/dist/charts/ox-scichart-multiple.js.map +1 -1
  4. package/dist/charts/ox-scichart.d.ts +1 -1
  5. package/dist/charts/ox-scichart.js +1 -2
  6. package/dist/charts/ox-scichart.js.map +1 -1
  7. package/dist/scichart-multiple-timeseries.d.ts +1 -0
  8. package/dist/scichart-multiple-timeseries.js +5 -0
  9. package/dist/scichart-multiple-timeseries.js.map +1 -1
  10. package/dist/scichart-timeseries.d.ts +1 -0
  11. package/dist/scichart-timeseries.js +5 -0
  12. package/dist/scichart-timeseries.js.map +1 -1
  13. package/package.json +2 -2
  14. package/CHANGELOG.md +0 -250
  15. package/db.sqlite +0 -0
  16. package/logs/.08636eb59927f12972f6774f5947c8507b3564c2-audit.json +0 -15
  17. package/logs/.5e5d741d8b7784a2fbad65eedc0fd46946aaf6f2-audit.json +0 -15
  18. package/logs/application-2024-09-10-23.log +0 -105
  19. package/logs/connections-2024-09-10-23.log +0 -50
  20. package/schema.graphql +0 -4455
  21. package/src/charts/axis-synchronizer.ts +0 -37
  22. package/src/charts/ox-scichart-multiple.ts +0 -581
  23. package/src/charts/ox-scichart.ts +0 -157
  24. package/src/charts/scichart-builder.ts +0 -630
  25. package/src/editors/index.ts +0 -8
  26. package/src/groups/index.ts +0 -0
  27. package/src/index.ts +0 -2
  28. package/src/scichart-multiple-timeseries.ts +0 -64
  29. package/src/scichart-timeseries.ts +0 -46
  30. package/src/templates/index.ts +0 -4
  31. package/src/templates/scichart-multiple-timeseries.ts +0 -87
  32. package/src/templates/scichart-timeseries.ts +0 -73
  33. package/tsconfig.json +0 -23
  34. package/tsconfig.tsbuildinfo +0 -1
@@ -1,37 +0,0 @@
1
- import { AxisBase2D, EventHandler, NumberRange, VisibleRangeChangedArgs } from 'scichart'
2
-
3
- export class AxisSynchroniser {
4
- public visibleRange: NumberRange
5
- private axes: AxisBase2D[] = []
6
- public visibleRangeChanged: EventHandler<VisibleRangeChangedArgs> = new EventHandler<VisibleRangeChangedArgs>()
7
-
8
- public constructor(initialRange: NumberRange, axes?: AxisBase2D[]) {
9
- this.visibleRange = initialRange
10
- this.publishChange = this.publishChange.bind(this)
11
- if (axes) {
12
- axes.forEach(a => this.addAxis(a))
13
- }
14
- }
15
-
16
- public publishChange(data?: VisibleRangeChangedArgs) {
17
- this.visibleRange = data!.visibleRange
18
- this.axes.forEach(a => (a.visibleRange = this.visibleRange))
19
- this.visibleRangeChanged.raiseEvent(data)
20
- }
21
-
22
- public addAxis(axis: AxisBase2D) {
23
- if (!this.axes.includes(axis)) {
24
- this.axes.push(axis)
25
- axis.visibleRange = this.visibleRange
26
- axis.visibleRangeChanged.subscribe(this.publishChange)
27
- }
28
- }
29
-
30
- public removeAxis(axis: AxisBase2D) {
31
- const index = this.axes.findIndex(a => a === axis)
32
- if (index >= 0) {
33
- this.axes.splice(index, 1)
34
- axis.visibleRangeChanged.unsubscribe(this.publishChange)
35
- }
36
- }
37
- }
@@ -1,581 +0,0 @@
1
- import { LitElement, html, css } from 'lit'
2
- import { property, query, customElement } from 'lit/decorators.js'
3
- import { keyed } from 'lit/directives/keyed.js'
4
-
5
- import {
6
- calculatePrecision,
7
- buildSciChart,
8
- buildSciChartOverview,
9
- convertColor,
10
- DEFAULT_COLOR
11
- } from './scichart-builder'
12
- import { AxisSynchroniser } from './axis-synchronizer'
13
- import {
14
- EAutoRange,
15
- FastLineRenderableSeries,
16
- NumberRange,
17
- NumericAxis,
18
- scaleAxes,
19
- SciChartVerticalGroup,
20
- XyDataSeries
21
- } from 'scichart'
22
-
23
- import { ScrollbarStyles } from '@operato/styles'
24
-
25
- @customElement('ox-scichart-multiple')
26
- export class OxSciChartMultiple extends LitElement {
27
- @property({ type: Object }) config: OperatoChart.ChartConfig | null = null
28
- @property({ type: Array }) data: { [attr: string]: any }[] = []
29
- @property({ type: Array }) visibleSeries: string[] = []
30
- @property({ type: Boolean, attribute: 'show-overview' }) showOverview: boolean = true
31
-
32
- private synchronizer: AxisSynchroniser = new AxisSynchroniser(new NumberRange(200, 500))
33
- private verticalGroup: SciChartVerticalGroup = new SciChartVerticalGroup()
34
-
35
- private overviewChart: any = null
36
- private overviewDataSeries: any[] = []
37
- private groupCharts: {
38
- dataKey: string
39
- sciChartSurface: any
40
- dataSeries: any[]
41
- }[] = []
42
-
43
- private initializationQueue: Promise<void> = Promise.resolve()
44
-
45
- /*
46
- [주의]
47
- ox-scichart container의 id를 글로벌 유니크하게 해야한다.
48
- SciChart가 특별히 container의 id를 기반으로 하위 컴포넌트를 구성하고 있기 때문이다.
49
- shadowDom 안에 있는 container 이더라도, 글로벌 유니크한 id를 제공해야 한다.
50
- 그렇지 않으면, 단 하나의 차트만 제대로 렌더링된다.
51
- */
52
- private containerId: string = 'ox-scichart-multiple' + ++OxSciChartMultiple.idx
53
-
54
- @query('.overview') overviewContainer!: HTMLDivElement
55
-
56
- static idx: number = 0
57
-
58
- static styles = [
59
- ScrollbarStyles,
60
- css`
61
- :host {
62
- display: flex;
63
- flex-direction: column;
64
-
65
- width: 100%;
66
- height: 100%;
67
- }
68
-
69
- .overview {
70
- height: 80px;
71
- }
72
-
73
- #chart-group {
74
- flex: 1;
75
-
76
- display: flex;
77
- flex-direction: column;
78
- overflow-y: auto;
79
- }
80
-
81
- .grouped-chart {
82
- flex: 1;
83
-
84
- min-height: 25%;
85
- }
86
-
87
- [hidden] {
88
- display: none;
89
- }
90
- `
91
- ]
92
-
93
- async initializeSciChart() {
94
- this.cleanup()
95
- await this.createOverviewChart()
96
- }
97
-
98
- disconnectedCallback(): void {
99
- super.disconnectedCallback()
100
-
101
- // 그룹 차트 자원 해제
102
- this.groupCharts.forEach(chart => {
103
- if (chart.sciChartSurface) {
104
- this.synchronizer.removeAxis(chart.sciChartSurface.xAxes.get(0))
105
- this.verticalGroup.removeSurface(chart.sciChartSurface)
106
-
107
- // 각 데이터 시리즈 명시적으로 해제
108
- chart.dataSeries.forEach(ds => ds.delete())
109
-
110
- // 차트 삭제
111
- chart.sciChartSurface.delete()
112
- }
113
- })
114
-
115
- // 오버뷰 차트 자원 해제
116
- if (this.overviewChart) {
117
- this.overviewChart.sciChartSurface.renderableSeries.clear()
118
- this.overviewDataSeries.forEach(ds => ds.delete())
119
- this.overviewChart.sciChartSurface.delete()
120
- this.overviewDataSeries.length = 0
121
- }
122
-
123
- // 사용된 그룹, 오버뷰 데이터 초기화
124
- this.groupCharts.length = 0
125
- this.overviewChart = null
126
- }
127
-
128
- async createOverviewChart() {
129
- const { chart, dataSeries } =
130
- (await buildSciChartOverview(
131
- {
132
- ...this.config,
133
- data: { datasets: [] }
134
- },
135
- this.overviewContainer,
136
- {},
137
- this.synchronizer
138
- )) || {}
139
-
140
- this.verticalGroup.addSurfaceToGroup(chart.sciChartSurface)
141
-
142
- this.overviewChart = chart
143
- this.overviewDataSeries = dataSeries!
144
- }
145
-
146
- async updated(changedProperties: Map<string | number | symbol, unknown>) {
147
- this.initializationQueue = this.initializationQueue
148
- .then(async () => {
149
- let needUpdateDataSeries = false
150
- let needBuildChartGroup = false
151
-
152
- if (changedProperties.has('config') && this.config) {
153
- await this.initializeSciChart()
154
- needBuildChartGroup = true
155
- needUpdateDataSeries = true
156
- }
157
-
158
- if (changedProperties.has('visibleSeries')) {
159
- await this.updateSeries(this.visibleSeries, changedProperties.get('visibleSeries') as string[])
160
- /* [중요] buildChartGroup 을 visibleSeries 수정때마다 하는 이유는, render() 의 캐시 컨트롤이 안되기 때문이다. 가급적 시도하지 말라. */
161
- needBuildChartGroup = true
162
- needUpdateDataSeries = true
163
- }
164
-
165
- if (changedProperties.has('data')) {
166
- needUpdateDataSeries = true
167
- }
168
-
169
- if (needBuildChartGroup) {
170
- await this.buildChartGroup()
171
- }
172
-
173
- if (needUpdateDataSeries) {
174
- await this.updateDataSeries()
175
- }
176
- })
177
- .catch((error: any) => {
178
- console.error('Error in updated queue:', error)
179
- })
180
- }
181
-
182
- cleanup() {
183
- this.cleanupGroup()
184
- this.cleanupOverview()
185
- }
186
-
187
- cleanupGroup() {
188
- this.groupCharts.forEach(chart => {
189
- if (chart.sciChartSurface) {
190
- this.synchronizer.removeAxis(chart.sciChartSurface.xAxes.get(0))
191
- this.verticalGroup.removeSurface(chart.sciChartSurface)
192
- chart.sciChartSurface.delete()
193
- }
194
- })
195
-
196
- this.groupCharts.length = 0
197
- }
198
-
199
- cleanupOverview() {
200
- if (this.overviewChart) {
201
- this.overviewChart.sciChartSurface.renderableSeries.clear()
202
- this.overviewDataSeries.forEach(ds => ds.delete())
203
- this.overviewDataSeries.length = 0
204
- }
205
-
206
- this.overviewChart = null
207
- }
208
-
209
- async updateDataSeries() {
210
- const { config, data } = this
211
- const { datasets = [], labelDataKey: attrX } = config?.data || {}
212
-
213
- if (!(data instanceof Array) || !attrX) {
214
- return []
215
- }
216
-
217
- const newData = this.dataSet
218
-
219
- this.groupCharts.forEach(({ dataKey, sciChartSurface, dataSeries }) => {
220
- try {
221
- // dataKey로 시작하는 모든 시리즈를 업데이트
222
- const relatedDatasets = datasets.filter(dataset => dataset.dataKey?.startsWith(dataKey))
223
-
224
- // 각 relatedDatasets에 대해 해당하는 dataSeries를 업데이트
225
- dataSeries.forEach((ds, index) => {
226
- ds.clear()
227
-
228
- const relatedDataset = relatedDatasets[index]
229
- if (relatedDataset) {
230
- const filteredData = newData[datasets.findIndex(ds => ds.dataKey === relatedDataset.dataKey)].filter(
231
- d => typeof d.yValue === 'number'
232
- )
233
-
234
- if (filteredData.length > 0) {
235
- ds.appendRange(
236
- filteredData.map(d => d.xValue),
237
- filteredData.map(d => d.yValue)
238
- )
239
- }
240
- }
241
- })
242
-
243
- sciChartSurface.zoomExtents()
244
- sciChartSurface.invalidateElement()
245
- } catch (error) {
246
- console.error('Error updating data series:', error)
247
- }
248
- })
249
-
250
- try {
251
- // Overview 차트 데이터 업데이트
252
- this.overviewDataSeries.forEach((ds, index) => {
253
- const visibleKey = this.visibleSeries[index]
254
- const dataset = datasets.find(dataset => dataset.dataKey === visibleKey)
255
- if (!dataset) {
256
- return
257
- }
258
-
259
- const dataIndex = datasets.findIndex(ds => ds.dataKey === dataset.dataKey)
260
- const filteredData = newData[dataIndex]?.filter(d => typeof d.yValue === 'number') || []
261
-
262
- ds.clear()
263
- if (filteredData.length > 0) {
264
- ds.appendRange(
265
- filteredData.map(d => d.xValue),
266
- filteredData.map(d => d.yValue)
267
- )
268
- }
269
- })
270
-
271
- // this.overviewDataSeries.forEach(ds => ds.clear())
272
-
273
- // newData.forEach((data, index) => {
274
- // if (this.visibleSeries.includes(datasets[index].dataKey!)) {
275
- // const filteredData = data.filter(d => typeof d.yValue === 'number')
276
- // if (filteredData.length > 0) {
277
- // this.overviewDataSeries[index].appendRange(
278
- // filteredData.map(d => d.xValue),
279
- // filteredData.map(d => d.yValue)
280
- // )
281
- // }
282
- // }
283
- // })
284
- } catch (error) {
285
- console.error('Error updating overview data series:', error)
286
- }
287
- }
288
-
289
- get dataSet(): { xValue: number; yValue: number }[][] {
290
- const { config, data } = this
291
- const { datasets = [], labelDataKey: attrX } = config?.data || {}
292
-
293
- if (!(data instanceof Array) || !attrX) {
294
- return []
295
- }
296
-
297
- return datasets.map(dataset => {
298
- return data
299
- .map(item => {
300
- if (!item || typeof item !== 'object') {
301
- return
302
- }
303
-
304
- const xValue = new Date(item[attrX])
305
- if (isNaN(xValue.getTime())) {
306
- console.error('Invalid date:', item[attrX])
307
- return
308
- }
309
-
310
- return {
311
- xValue: xValue.getTime() / 1000,
312
- yValue: item[dataset.dataKey!]
313
- }
314
- })
315
- .filter(Boolean) as { xValue: number; yValue: number }[]
316
- })
317
- }
318
-
319
- render() {
320
- const { datasets = [] } = this.config?.data || {}
321
-
322
- return html`
323
- <div id=${this.containerId + '-overview'} class="overview" ?hidden=${!this.showOverview}></div>
324
- <div id="chart-group">
325
- ${this.visibleSeries.map(dataKey =>
326
- keyed(
327
- dataKey,
328
- html`
329
- <div
330
- id=${this.containerId + '-' + dataKey}
331
- class="grouped-chart"
332
- ?hidden=${!this.visibleSeries.includes(dataKey!)}
333
- ></div>
334
- `
335
- )
336
- )}
337
- </div>
338
- `
339
- }
340
-
341
- async buildChartGroup() {
342
- this.cleanupGroup()
343
-
344
- const { config } = this
345
- const { datasets = [] } = config?.data || {}
346
-
347
- await Promise.all(
348
- datasets
349
- .filter(dataset => this.visibleSeries.includes(dataset.dataKey!))
350
- .map(async dataset => {
351
- await this.addChart(dataset.dataKey!)
352
- })
353
- )
354
- }
355
-
356
- async updateSeries(after: string[], before: string[]) {
357
- const addSeries = after?.filter(series => !before?.includes(series)) || []
358
- const removeSeries = before?.filter(series => !after?.includes(series)) || []
359
-
360
- for (const series of removeSeries) {
361
- await this.removeChart(series)
362
- }
363
-
364
- for (const series of addSeries) {
365
- await this.addChart(series)
366
- }
367
- }
368
-
369
- async addChart(dataKey: string) {
370
- const chartData = await this.createChart(dataKey)
371
-
372
- if (chartData) {
373
- const { chart, dataSeries, dataKey } = chartData
374
- this.verticalGroup.addSurfaceToGroup(chart.sciChartSurface)
375
-
376
- this.groupCharts = this.groupSorter([
377
- ...this.groupCharts,
378
- { dataKey, sciChartSurface: chart.sciChartSurface, dataSeries }
379
- ])
380
-
381
- await this.addSeriesToOverviewChart(dataKey)
382
- }
383
- }
384
-
385
- async removeChart(dataKey: string) {
386
- const index = this.groupCharts.findIndex(chart => chart.dataKey == dataKey)
387
- if (index === -1) return
388
-
389
- const [groupedChart] = this.groupCharts.splice(index, 1)
390
- this.destroyChart(groupedChart)
391
-
392
- this.groupCharts = this.groupSorter(this.groupCharts)
393
-
394
- await this.removeSeriesFromOverviewChart(dataKey)
395
- }
396
-
397
- groupSorter(group: any[]) {
398
- return group.sort(
399
- (a, b) =>
400
- this.visibleSeries.findIndex((s: any) => s.dataKey == a.dataKey) -
401
- this.visibleSeries.findIndex((s: any) => s.dataKey == b.dataKey)
402
- )
403
- }
404
-
405
- async appendData(appendum: { [attr: string]: any }[]) {}
406
-
407
- private async createChart(dataKey: string) {
408
- const { data = {}, options = {} } = this.config || {}
409
- const { datasets = [] } = data as OperatoChart.ChartData
410
- const primaryDataset = datasets.find(dataset => dataset.dataKey == dataKey)
411
-
412
- if (!primaryDataset) {
413
- return null
414
- }
415
-
416
- const relatedDatasets = datasets.filter(dataset => dataset.dataKey?.startsWith(dataKey))
417
-
418
- const yAxis = {
419
- ...options.scales?.yAxes?.[0],
420
- axisTitle: primaryDataset?.label
421
- }
422
-
423
- const config = {
424
- ...this.config,
425
- data: {
426
- datasets: relatedDatasets
427
- },
428
- options: {
429
- ...options,
430
- scales: {
431
- ...options.scales,
432
- yAxes: [yAxis]
433
- }
434
- }
435
- }
436
-
437
- const container = this.renderRoot.querySelector(`#${this.containerId + '-' + dataKey}`)
438
- const { chart, dataSeries } = (await buildSciChart(
439
- config,
440
- container,
441
- { fontSize: 14, fontFamily: 'Roboto', fontColor: undefined },
442
- {
443
- precision: primaryDataset.valueFormat ? calculatePrecision(primaryDataset.valueFormat) : undefined,
444
- grouped: this.containerId
445
- }
446
- ))!
447
-
448
- this.synchronizer.addAxis(chart.sciChartSurface.xAxes.get(0))
449
-
450
- // 각 시리즈에 대해 올바른 데이터를 추가
451
- const newData = this.dataSet
452
- dataSeries.forEach((ds, seriesIndex) => {
453
- const dataset = relatedDatasets[seriesIndex]
454
- const filteredData = newData[seriesIndex]?.filter(d => typeof d.yValue === 'number') || []
455
- if (filteredData.length > 0) {
456
- ds.appendRange(
457
- filteredData.map(d => d.xValue),
458
- filteredData.map(d => d.yValue)
459
- )
460
- }
461
- })
462
-
463
- return { chart, dataSeries, dataKey }
464
- }
465
-
466
- private destroyChart(groupedChart: { dataKey: string; sciChartSurface: any; dataSeries: any[] }) {
467
- this.verticalGroup.removeSurface(groupedChart.sciChartSurface)
468
- this.synchronizer.removeAxis(groupedChart.sciChartSurface.xAxes.get(0))
469
- groupedChart.sciChartSurface.delete()
470
- }
471
-
472
- private async addSeriesToOverviewChart(dataKey: string) {
473
- if (!this.overviewChart || !this.overviewDataSeries) {
474
- console.error('Overview chart is not initialized.')
475
- return
476
- }
477
-
478
- // Check if the series already exists in the overview chart
479
- const existingSeries = this.overviewChart.sciChartSurface.renderableSeries.asArray().find((series: any) => {
480
- return series.dataSeries.dataSeriesName === dataKey
481
- })
482
-
483
- if (existingSeries) {
484
- console.warn(`Series for dataKey ${dataKey} already exists in the overview chart.`)
485
- return // Exit the function without adding the series again
486
- }
487
-
488
- const dataset = this.config?.data.datasets.find(dataset => dataset.dataKey === dataKey)
489
- if (!dataset) {
490
- console.error('Dataset not found for dataKey:', dataKey)
491
- return
492
- }
493
-
494
- const newSeries = await this.createSeriesForOverview(dataset)
495
-
496
- if (newSeries) {
497
- this.overviewChart.sciChartSurface.renderableSeries.add(newSeries.series)
498
- this.overviewDataSeries.push(newSeries.dataSeries)
499
- }
500
- }
501
-
502
- private async removeSeriesFromOverviewChart(dataKey: string) {
503
- if (!this.overviewChart || !this.overviewDataSeries) {
504
- console.error('Overview chart is not initialized.')
505
- return
506
- }
507
-
508
- const { sciChartSurface } = this.overviewChart
509
-
510
- // 오버뷰 차트의 renderableSeries에서 해당 시리즈 제거
511
- const seriesIndex = sciChartSurface.renderableSeries.asArray().findIndex((series: any) => {
512
- return series.dataSeries.dataSeriesName === dataKey
513
- })
514
-
515
- if (seriesIndex !== -1) {
516
- const series = sciChartSurface.renderableSeries.get(seriesIndex)
517
- const yAxisId = series.yAxisId
518
-
519
- // 시리즈 제거
520
- sciChartSurface.renderableSeries.removeAt(seriesIndex)
521
- this.overviewDataSeries.splice(seriesIndex, 1) // 데이터 시리즈도 제거
522
-
523
- // 고유 Y축 제거
524
- if (yAxisId) {
525
- const yAxisIndex = sciChartSurface.yAxes.asArray().findIndex((axis: any) => axis.id === yAxisId)
526
- if (yAxisIndex !== -1) {
527
- sciChartSurface.yAxes.removeAt(yAxisIndex)
528
- }
529
- }
530
- } else {
531
- console.error('Series not found in overview chart for dataKey:', dataKey)
532
- }
533
- }
534
-
535
- private async createSeriesForOverview(dataset: any) {
536
- if (!this.overviewChart) return null
537
-
538
- const { sciChartSurface, wasmContext } = this.overviewChart
539
- const dataSeries = new XyDataSeries(wasmContext, {
540
- dataSeriesName: dataset.dataKey,
541
- containsNaN: false
542
- })
543
-
544
- // 새로운 Y축을 추가하여 노멀라이즈 효과를 제공
545
- const yAxisId = `yAxis_${dataset.dataKey}`
546
- const yAxis = new NumericAxis(wasmContext, {
547
- id: yAxisId,
548
- autoRange: EAutoRange.Always,
549
- drawLabels: false,
550
- drawMajorTickLines: false,
551
- drawMinorTickLines: false,
552
- drawMajorGridLines: false,
553
- drawMinorGridLines: false
554
- })
555
-
556
- sciChartSurface.yAxes.add(yAxis)
557
-
558
- const series = new FastLineRenderableSeries(wasmContext, {
559
- dataSeries,
560
- strokeThickness: 1,
561
- stroke: convertColor(dataset.color, DEFAULT_COLOR),
562
- yAxisId
563
- })
564
-
565
- // 초기 데이터 추가
566
- const newData = this.dataSet.find((data, index) => this.config?.data.datasets[index].dataKey === dataset.dataKey)
567
- if (newData && newData.length > 0) {
568
- const filteredData = newData.filter(d => typeof d.yValue === 'number')
569
- if (filteredData.length > 0) {
570
- dataSeries.appendRange(
571
- filteredData.map(d => d.xValue),
572
- filteredData.map(d => d.yValue)
573
- )
574
- } else {
575
- console.warn('No valid yValues found for dataset:', dataset.dataKey)
576
- }
577
- }
578
-
579
- return { series, dataSeries }
580
- }
581
- }