@operato/scene-scichart 7.0.7 → 7.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/cache/translations/system/en.json +1 -1
  3. package/cache/translations/system/ko.json +1 -1
  4. package/db.sqlite +0 -0
  5. package/dist/charts/axis-synchronizer.d.ts +10 -0
  6. package/dist/charts/axis-synchronizer.js +32 -0
  7. package/dist/charts/axis-synchronizer.js.map +1 -0
  8. package/dist/charts/ox-scichart-multiple.d.ts +43 -0
  9. package/dist/charts/ox-scichart-multiple.js +298 -0
  10. package/dist/charts/ox-scichart-multiple.js.map +1 -0
  11. package/dist/charts/ox-scichart.d.ts +4 -1
  12. package/dist/charts/ox-scichart.js +1 -0
  13. package/dist/charts/ox-scichart.js.map +1 -1
  14. package/dist/charts/scichart-builder.d.ts +10 -1
  15. package/dist/charts/scichart-builder.js +98 -15
  16. package/dist/charts/scichart-builder.js.map +1 -1
  17. package/dist/index.d.ts +1 -0
  18. package/dist/index.js +1 -0
  19. package/dist/index.js.map +1 -1
  20. package/dist/scichart-multiple-timeseries.d.ts +14 -0
  21. package/dist/scichart-multiple-timeseries.js +60 -0
  22. package/dist/scichart-multiple-timeseries.js.map +1 -0
  23. package/dist/scichart-timeseries.d.ts +2 -11
  24. package/dist/scichart-timeseries.js +2 -42
  25. package/dist/scichart-timeseries.js.map +1 -1
  26. package/dist/templates/index.js +2 -1
  27. package/dist/templates/index.js.map +1 -1
  28. package/dist/templates/scichart-multiple-timeseries.d.ts +53 -0
  29. package/dist/templates/scichart-multiple-timeseries.js +81 -0
  30. package/dist/templates/scichart-multiple-timeseries.js.map +1 -0
  31. package/helps/scene/component/scichart-multiple-timeseries.md +23 -0
  32. package/helps/scene/component/scichart-timeseries.md +18 -0
  33. package/icons/scichart-multiple-timeseries.png +0 -0
  34. package/logs/.08636eb59927f12972f6774f5947c8507b3564c2-audit.json +26 -6
  35. package/logs/.5e5d741d8b7784a2fbad65eedc0fd46946aaf6f2-audit.json +31 -21
  36. package/logs/{application-2024-07-13-21.log → application-2024-07-28-03.log} +8 -8
  37. package/logs/{application-2024-07-13-20.log → application-2024-07-28-17.log} +32 -36
  38. package/logs/application-2024-07-28-18.log +210 -0
  39. package/logs/application-2024-07-29-01.log +105 -0
  40. package/logs/application-2024-07-29-14.log +105 -0
  41. package/logs/application-2024-07-29-16.log +105 -0
  42. package/logs/connections-2024-07-23-14.log +50 -0
  43. package/logs/connections-2024-07-25-23.log +50 -0
  44. package/logs/connections-2024-07-26-18.log +50 -0
  45. package/logs/connections-2024-07-28-03.log +50 -0
  46. package/logs/connections-2024-07-28-17.log +200 -0
  47. package/logs/connections-2024-07-28-18.log +100 -0
  48. package/logs/connections-2024-07-29-01.log +50 -0
  49. package/logs/connections-2024-07-29-14.log +50 -0
  50. package/logs/connections-2024-07-29-16.log +50 -0
  51. package/package.json +2 -2
  52. package/schema.graphql +112 -0
  53. package/src/charts/axis-synchronizer.ts +37 -0
  54. package/src/charts/ox-scichart-multiple.ts +362 -0
  55. package/src/charts/ox-scichart.ts +3 -1
  56. package/src/charts/scichart-builder.ts +136 -24
  57. package/src/index.ts +1 -0
  58. package/src/scichart-multiple-timeseries.ts +74 -0
  59. package/src/scichart-timeseries.ts +3 -54
  60. package/src/templates/index.ts +2 -1
  61. package/src/templates/scichart-multiple-timeseries.ts +87 -0
  62. package/things-scene.config.js +0 -2
  63. package/translations/en.json +3 -1
  64. package/translations/ja.json +3 -1
  65. package/translations/ko.json +3 -1
  66. package/translations/ms.json +3 -1
  67. package/translations/zh.json +3 -1
  68. package/tsconfig.tsbuildinfo +1 -1
  69. package/logs/connections-2024-07-08-22.log +0 -50
  70. package/logs/connections-2024-07-08-23.log +0 -100
  71. package/logs/connections-2024-07-09-15.log +0 -100
  72. package/logs/connections-2024-07-10-00.log +0 -50
  73. package/logs/connections-2024-07-10-10.log +0 -50
  74. package/logs/connections-2024-07-13-20.log +0 -200
  75. package/logs/connections-2024-07-13-21.log +0 -50
package/schema.graphql CHANGED
@@ -1598,6 +1598,9 @@ type Mutation {
1598
1598
  """To create new ApprovalLine for current user"""
1599
1599
  createMyApprovalLine(approvalLine: NewApprovalLine!): ApprovalLine!
1600
1600
 
1601
+ """To create my new PagePreference"""
1602
+ createMyPagePreference(pagePreference: NewPagePreference!): PagePreference!
1603
+
1601
1604
  """To create new Notification"""
1602
1605
  createNotification(notification: NewNotification!): Notification!
1603
1606
 
@@ -1639,6 +1642,9 @@ type Mutation {
1639
1642
 
1640
1643
  """To create new user"""
1641
1644
  createUser(user: NewUser!): User!
1645
+
1646
+ """To create new UserPreference"""
1647
+ createUserPreference(preference: NewUserPreference!): UserPreference!
1642
1648
  deleteAppBinding(id: String!): Boolean!
1643
1649
 
1644
1650
  """To delete appliance"""
@@ -1779,6 +1785,12 @@ type Mutation {
1779
1785
  """To delete multiple ApprovalLines for current user"""
1780
1786
  deleteMyApprovalLines(ids: [String!]!): Boolean!
1781
1787
 
1788
+ """To delete my PagePreference"""
1789
+ deleteMyPagePreference(element: String!, page: String!): Boolean!
1790
+
1791
+ """To delete my preference"""
1792
+ deleteMyUserPreference(element: String!, key: String!): Boolean!
1793
+
1782
1794
  """To delete Notification"""
1783
1795
  deleteNotification(id: String!): Boolean!
1784
1796
 
@@ -1797,6 +1809,12 @@ type Mutation {
1797
1809
  """To delete multiple Oauth2Clients"""
1798
1810
  deleteOauth2Clients(ids: [String!]!): Boolean!
1799
1811
 
1812
+ """To delete PagePreference"""
1813
+ deletePagePreference(id: String!): Boolean!
1814
+
1815
+ """To delete multiple PagePreferences"""
1816
+ deletePagePreferences(ids: [String!]!): Boolean!
1817
+
1800
1818
  """To delete multiple partnerSettings"""
1801
1819
  deletePartnerSettings(ids: [String!]!): Boolean!
1802
1820
 
@@ -1860,6 +1878,12 @@ type Mutation {
1860
1878
  """To delete a user"""
1861
1879
  deleteUser(email: EmailAddress!): Boolean!
1862
1880
 
1881
+ """To delete UserPreference"""
1882
+ deleteUserPreference(id: String!): Boolean!
1883
+
1884
+ """To delete multiple UserPreferences"""
1885
+ deleteUserPreferences(ids: [String!]!): Boolean!
1886
+
1863
1887
  """To delete some users"""
1864
1888
  deleteUsers(emails: [String!]!): Boolean!
1865
1889
 
@@ -2177,6 +2201,12 @@ type Mutation {
2177
2201
  """To modify ApprovalLine information for current user"""
2178
2202
  updateMyApprovalLine(id: String!, patch: ApprovalLinePatch!): ApprovalLine!
2179
2203
 
2204
+ """To create or update my PagePreference"""
2205
+ updateMyPagePreference(element: String!, page: String!, preference: Object!): PagePreference!
2206
+
2207
+ """To create or update my preference"""
2208
+ updateMyUserPreference(key: String!, preference: Object!): UserPreference!
2209
+
2180
2210
  """To modify Notification information"""
2181
2211
  updateNotification(id: String!, patch: NotificationPatch!): Notification!
2182
2212
 
@@ -2231,6 +2261,9 @@ type Mutation {
2231
2261
  """To modify user information"""
2232
2262
  updateUser(email: EmailAddress!, patch: UserPatch!): User!
2233
2263
 
2264
+ """To modify UserPreference information"""
2265
+ updateUserPreference(id: String!, patch: UserPreferencePatch!): UserPreference!
2266
+
2234
2267
  """To update roles for a user"""
2235
2268
  updateUserRoles(availableRoles: [ObjectRef!]!, selectedRoles: [ObjectRef!]!, userId: String!): User!
2236
2269
  }
@@ -2630,6 +2663,13 @@ input NewOauth2Client {
2630
2663
  webhook: String
2631
2664
  }
2632
2665
 
2666
+ input NewPagePreference {
2667
+ element: String
2668
+ page: String
2669
+ preference: Object!
2670
+ user: ObjectRef!
2671
+ }
2672
+
2633
2673
  input NewPayloadLog {
2634
2674
  description: String
2635
2675
  name: String!
@@ -2755,6 +2795,12 @@ input NewUserByDomainWizardInput {
2755
2795
  roles: [NewRole!]!
2756
2796
  }
2757
2797
 
2798
+ input NewUserPreference {
2799
+ key: String!
2800
+ preference: Object!
2801
+ user: ObjectRef!
2802
+ }
2803
+
2758
2804
  """Entity for Notification"""
2759
2805
  type Notification {
2760
2806
  body: String
@@ -2978,6 +3024,25 @@ enum OrgMemberTargetType {
2978
3024
  Role
2979
3025
  }
2980
3026
 
3027
+ """Entity for PagePreference"""
3028
+ type PagePreference {
3029
+ createdAt: DateTimeISO
3030
+ creator: User
3031
+ domain: Domain!
3032
+ element: String
3033
+ id: ID!
3034
+ page: String
3035
+ preference: Object
3036
+ updatedAt: DateTimeISO
3037
+ updater: User
3038
+ user: User!
3039
+ }
3040
+
3041
+ type PagePreferenceList {
3042
+ items: [PagePreference!]!
3043
+ total: Int!
3044
+ }
3045
+
2981
3046
  input Pagination {
2982
3047
  limit: Int
2983
3048
  page: Int
@@ -3461,9 +3526,24 @@ type Query {
3461
3526
  """To fetch my notifications"""
3462
3527
  myNotifications(filters: [Filter!], inherited: InheritedValueType, pagination: Pagination, sortings: [Sorting!]): NotificationList!
3463
3528
 
3529
+ """To fetch a User's own PagePreference"""
3530
+ myPageAllPreferences(page: String!): [PagePreference!]
3531
+
3532
+ """To fetch a User's own PagePreference"""
3533
+ myPagePreference(element: String!, page: String!): PagePreference
3534
+
3535
+ """To fetch multiple PagePreferences"""
3536
+ myPagePreferences(filters: [Filter!], inherited: InheritedValueType, pagination: Pagination, sortings: [Sorting!]): PagePreferenceList!
3537
+
3464
3538
  """To fetch roles of current user"""
3465
3539
  myRoles: [Role!]!
3466
3540
 
3541
+ """To fetch a User's own UserPreference"""
3542
+ myUserPreference(element: String!, key: String!): UserPreference
3543
+
3544
+ """To fetch multiple UserPreferences"""
3545
+ myUserPreferences(filters: [Filter!], inherited: InheritedValueType, pagination: Pagination, sortings: [Sorting!]): UserPreferenceList!
3546
+
3467
3547
  """To fetch a Notification"""
3468
3548
  notification(id: String!): Notification
3469
3549
 
@@ -3482,6 +3562,9 @@ type Query {
3482
3562
  """To fetch multiple Oauth2Clients"""
3483
3563
  oauth2Clients(filters: [Filter!], inherited: InheritedValueType, pagination: Pagination, sortings: [Sorting!]): Oauth2ClientList!
3484
3564
 
3565
+ """To fetch a PagePreference"""
3566
+ pagePreference(id: String!): PagePreference
3567
+
3485
3568
  """To fetch specific domain's CommonCodes by given name"""
3486
3569
  partnerCommonCode(name: String!, partnerDomainId: String!): CommonCode!
3487
3570
 
@@ -3507,6 +3590,9 @@ type Query {
3507
3590
  """To fetch multiple PlayGroups"""
3508
3591
  playGroups(filters: [Filter!], inherited: InheritedValueType, pagination: Pagination, sortings: [Sorting!]): PlayGroupList!
3509
3592
 
3593
+ """To fetch a UserPreference"""
3594
+ preference(id: String!): UserPreference
3595
+
3510
3596
  """To fetch a PrinterDevice"""
3511
3597
  printerDevice(id: String!): PrinterDevice!
3512
3598
 
@@ -4074,6 +4160,32 @@ input UserPatch {
4074
4160
  userType: String
4075
4161
  }
4076
4162
 
4163
+ """Entity for UserPreference"""
4164
+ type UserPreference {
4165
+ createdAt: DateTimeISO
4166
+ creator: User
4167
+ domain: Domain
4168
+ id: ID!
4169
+ key: String
4170
+ preference: Object
4171
+ updatedAt: DateTimeISO
4172
+ updater: User
4173
+ user: User!
4174
+ }
4175
+
4176
+ type UserPreferenceList {
4177
+ items: [UserPreference!]!
4178
+ total: Int!
4179
+ }
4180
+
4181
+ input UserPreferencePatch {
4182
+ cuFlag: String
4183
+ id: ID
4184
+ key: String!
4185
+ preference: Object!
4186
+ user: ObjectRef!
4187
+ }
4188
+
4077
4189
  type UserRole {
4078
4190
  assigned: Boolean
4079
4191
  description: String
@@ -0,0 +1,37 @@
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
+ }
@@ -0,0 +1,362 @@
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 { buildSciChart, buildSciChartOverview } from './scichart-builder'
6
+ import { AxisSynchroniser } from './axis-synchronizer'
7
+ import { NumberRange, scaleAxes, SciChartVerticalGroup } from 'scichart'
8
+
9
+ import { ScrollbarStyles } from '@operato/styles'
10
+
11
+ @customElement('ox-scichart-multiple')
12
+ export class OxSciChartMultiple extends LitElement {
13
+ @property({ type: Object }) config: OperatoChart.ChartConfig | null = null
14
+ @property({ type: Array }) data: { [attr: string]: any }[] = []
15
+ @property({ type: Array }) visibleSeries: string[] = []
16
+ @property({ type: Boolean, attribute: 'show-overview' }) showOverview: boolean = true
17
+
18
+ private synchronizer: AxisSynchroniser = new AxisSynchroniser(new NumberRange(200, 500))
19
+ private verticalGroup: SciChartVerticalGroup = new SciChartVerticalGroup()
20
+
21
+ private isInitializing: boolean = false
22
+ private overviewChart: any = null
23
+ private overviewDataSeries: any[] = []
24
+ private groupCharts: {
25
+ dataKey: string
26
+ sciChartSurface: any
27
+ dataSeries: any[]
28
+ }[] = []
29
+
30
+ /*
31
+ [주의]
32
+ ox-scichart container의 id를 글로벌 유니크하게 해야한다.
33
+ SciChart가 특별히 container의 id를 기반으로 하위 컴포넌트를 구성하고 있기 때문이다.
34
+ shadowDom 안에 있는 container 이더라도, 글로벌 유니크한 id를 제공해야 한다.
35
+ 그렇지 않으면, 단 하나의 차트만 제대로 렌더링된다.
36
+ */
37
+ private containerId: string = 'ox-scichart-multiple' + ++OxSciChartMultiple.idx
38
+
39
+ @query('.overview') overviewContainer!: HTMLDivElement
40
+
41
+ static idx: number = 0
42
+
43
+ static styles = [
44
+ ScrollbarStyles,
45
+ css`
46
+ :host {
47
+ display: flex;
48
+ flex-direction: column;
49
+
50
+ width: 100%;
51
+ height: 100%;
52
+ }
53
+
54
+ .overview {
55
+ height: 80px;
56
+ }
57
+
58
+ #chart-group {
59
+ flex: 1;
60
+
61
+ display: flex;
62
+ flex-direction: column;
63
+ overflow-y: auto;
64
+ }
65
+
66
+ .grouped-chart {
67
+ flex: 1;
68
+
69
+ min-height: 25%;
70
+ }
71
+
72
+ [hidden] {
73
+ display: none;
74
+ }
75
+ `
76
+ ]
77
+
78
+ async initializeSciChart() {
79
+ this.cleanup()
80
+
81
+ const { chart, dataSeries } =
82
+ (await buildSciChartOverview(this.config, this.overviewContainer, {}, this.synchronizer)) || {}
83
+
84
+ this.verticalGroup.addSurfaceToGroup(chart.sciChartSurface)
85
+
86
+ this.overviewChart = chart
87
+ this.overviewDataSeries = dataSeries!
88
+ }
89
+
90
+ async updated(changedProperties: Map<string | number | symbol, unknown>) {
91
+ var needDataUpdate = false
92
+
93
+ if (changedProperties.has('config') && this.config) {
94
+ this.isInitializing = true
95
+ await this.initializeSciChart()
96
+ this.isInitializing = false
97
+ needDataUpdate = true
98
+ }
99
+
100
+ if (changedProperties.has('visibleSeries')) {
101
+ if (this.isInitializing) {
102
+ await this.ensureInitialization()
103
+ }
104
+ await this.updateSeries(this.visibleSeries, changedProperties.get('visibleSeries') as string[])
105
+ needDataUpdate = true
106
+ }
107
+
108
+ if (changedProperties.has('data')) {
109
+ needDataUpdate = true
110
+ }
111
+
112
+ if (needDataUpdate) {
113
+ await this.updateDataSeries()
114
+ }
115
+ }
116
+
117
+ private async ensureInitialization() {
118
+ while (this.isInitializing) {
119
+ await new Promise(resolve => setTimeout(resolve, 100)) // Check every 100ms
120
+ }
121
+ }
122
+
123
+ cleanup() {
124
+ this.cleanupGroup()
125
+
126
+ if (this.overviewChart) {
127
+ this.overviewChart.sciChartSurface?.delete()
128
+ this.overviewChart = null
129
+ }
130
+ }
131
+
132
+ cleanupGroup() {
133
+ this.groupCharts.forEach(chart => {
134
+ if (chart.sciChartSurface) {
135
+ this.synchronizer.removeAxis(chart.sciChartSurface.xAxes.get(0))
136
+ this.verticalGroup.removeSurface(chart.sciChartSurface)
137
+ chart.sciChartSurface.delete()
138
+ }
139
+ })
140
+
141
+ this.groupCharts.length = 0
142
+ }
143
+
144
+ async updateDataSeries() {
145
+ const { config, data } = this
146
+ const { datasets = [], labelDataKey: attrX } = config?.data || {}
147
+
148
+ if (!(data instanceof Array) || !attrX) {
149
+ return []
150
+ }
151
+
152
+ const newData = this.dataSet
153
+
154
+ ;(this.groupCharts || []).forEach(({ dataKey, sciChartSurface, dataSeries }) => {
155
+ try {
156
+ dataSeries.forEach(ds => ds.clear())
157
+ const dataSet = newData.filter((data, index) => dataKey == datasets[index].dataKey!)
158
+
159
+ dataSet.forEach((data, index) => {
160
+ dataSeries[index].appendRange(
161
+ data.map(d => d.xValue),
162
+ data.map(d => d.yValue)
163
+ )
164
+ })
165
+ } catch (error) {
166
+ console.log(error)
167
+ }
168
+
169
+ sciChartSurface.zoomExtents()
170
+ sciChartSurface.invalidateElement()
171
+ })
172
+
173
+ try {
174
+ this.overviewDataSeries.forEach(ds => ds.clear())
175
+
176
+ newData.forEach((data, index) => {
177
+ if (this.visibleSeries.includes(datasets[index].dataKey!)) {
178
+ this.overviewDataSeries[index].appendRange(
179
+ data.map(d => d.xValue),
180
+ data.map(d => d.yValue)
181
+ )
182
+ }
183
+ })
184
+
185
+ this.overviewChart?.sciChartSurface.zoomExtents()
186
+ this.overviewChart?.sciChartSurface.invalidateElement()
187
+ } catch (error) {
188
+ console.log(error)
189
+ }
190
+ }
191
+
192
+ get dataSet(): { xValue: number; yValue: number }[][] {
193
+ const { config, data } = this
194
+ const { datasets = [], labelDataKey: attrX } = config?.data || {}
195
+
196
+ if (!(data instanceof Array) || !attrX) {
197
+ return []
198
+ }
199
+
200
+ return datasets.map(dataset => {
201
+ return data
202
+ .map(item => {
203
+ if (!item || typeof item !== 'object') {
204
+ return
205
+ }
206
+
207
+ const xValue = new Date(item[attrX])
208
+ if (isNaN(xValue.getTime())) {
209
+ console.error('Invalid date:', item[attrX])
210
+ return
211
+ }
212
+
213
+ return {
214
+ xValue: xValue.getTime() / 1000,
215
+ yValue: item[dataset.dataKey!]
216
+ }
217
+ })
218
+ .filter(Boolean) as { xValue: number; yValue: number }[]
219
+ })
220
+ }
221
+
222
+ render() {
223
+ const { datasets = [] } = this.config?.data || {}
224
+
225
+ return html`
226
+ <div id=${this.containerId + '-overview'} class="overview" ?hidden=${!this.showOverview}></div>
227
+ <div id="chart-group">
228
+ ${datasets.map(({ dataKey }) =>
229
+ keyed(
230
+ dataKey,
231
+ html`
232
+ <div
233
+ id=${this.containerId + '-' + dataKey}
234
+ class="grouped-chart"
235
+ ?hidden=${!this.visibleSeries.includes(dataKey!)}
236
+ ></div>
237
+ `
238
+ )
239
+ )}
240
+ </div>
241
+ `
242
+ }
243
+
244
+ async buildChartGroup() {
245
+ this.cleanupGroup()
246
+
247
+ const { config } = this
248
+ const { datasets = [] } = config?.data || {}
249
+
250
+ await Promise.all(
251
+ datasets
252
+ .filter(dataset => this.visibleSeries.includes(dataset.dataKey!))
253
+ .map(async dataset => {
254
+ await this.addChart(dataset.dataKey!)
255
+ })
256
+ )
257
+ }
258
+
259
+ async updateSeries(after: string[], before: string[]) {
260
+ /* 기존 시리즈와 새로운 시리즈의 차이를 비교해서, before에는 있는데, after에는 없으면 await removeChart(string)를 호출하고, after에는 있는데, before에는 없으면, addChart(string) 한다. */
261
+ // before에는 있는데 after에는 없는 시리즈를 제거합니다.
262
+ for (const series of before || []) {
263
+ if (!after.includes(series)) {
264
+ await this.removeChart(series)
265
+ }
266
+ }
267
+
268
+ // after에는 있는데 before에는 없는 시리즈를 추가합니다.
269
+ for (const series of after || []) {
270
+ if (!before || !before.includes(series)) {
271
+ await this.addChart(series)
272
+ }
273
+ }
274
+ }
275
+
276
+ async addChart(dataKey: string) {
277
+ const groupedChart = {
278
+ dataKey: '',
279
+ sciChartSurface: undefined,
280
+ dataSeries: [] as any[]
281
+ }
282
+
283
+ const { data = {}, options = {} } = this.config || {}
284
+ const { datasets = [] } = data as OperatoChart.ChartData
285
+ const dataset = datasets.find(dataset => dataset.dataKey == dataKey)
286
+
287
+ if (!dataset) {
288
+ return
289
+ }
290
+
291
+ const { scales } = options
292
+ const { yAxes = [] } = scales || {}
293
+ const yAxis = {
294
+ ...yAxes[0],
295
+ axisTitle: dataset?.label
296
+ }
297
+
298
+ const config = {
299
+ ...this.config,
300
+ data: {
301
+ datasets: [dataset]
302
+ },
303
+ options: {
304
+ ...options,
305
+ scales: {
306
+ ...scales,
307
+ yAxes: [yAxis]
308
+ }
309
+ }
310
+ }
311
+
312
+ const container = this.renderRoot.querySelector(`#${this.containerId + '-' + dataKey}`)
313
+ var { chart, dataSeries } = (await buildSciChart(
314
+ config,
315
+ container,
316
+ { fontSize: 14, fontFamily: 'Roboto', fontColor: undefined },
317
+ this.containerId
318
+ ))!
319
+
320
+ this.verticalGroup.addSurfaceToGroup(chart.sciChartSurface)
321
+ this.synchronizer.addAxis(chart.sciChartSurface.xAxes.get(0))
322
+
323
+ groupedChart.dataKey = config.data.datasets[0]!.dataKey!
324
+ groupedChart.sciChartSurface = chart.sciChartSurface
325
+ groupedChart.dataSeries = dataSeries
326
+
327
+ this.groupCharts = this.groupSorter([...this.groupCharts, groupedChart])
328
+ }
329
+
330
+ removeChart(dataKey: string) {
331
+ const index = this.groupCharts.findIndex((chart: any) => chart.dataKey == dataKey)
332
+ const [groupedChart] = this.groupCharts.splice(index, 1)
333
+
334
+ if (!groupedChart) {
335
+ return
336
+ }
337
+
338
+ this.verticalGroup.removeSurface(groupedChart.sciChartSurface)
339
+ this.synchronizer.removeAxis(groupedChart.sciChartSurface.xAxes.get(0))
340
+
341
+ groupedChart.sciChartSurface.delete()
342
+ groupedChart.sciChartSurface = undefined
343
+
344
+ this.groupCharts = this.groupSorter(this.groupCharts)
345
+ }
346
+
347
+ groupSorter(group: any[]) {
348
+ return group.sort(
349
+ (a, b) =>
350
+ this.visibleSeries.findIndex((s: any) => s.dataKey == a.dataKey) -
351
+ this.visibleSeries.findIndex((s: any) => s.dataKey == b.dataKey)
352
+ )
353
+ }
354
+
355
+ async appendData(appendum: { [attr: string]: any }[]) {}
356
+ }
357
+
358
+ declare global {
359
+ interface HTMLElementTagNameMap {
360
+ 'ox-scichart-multiple': OxSciChartMultiple
361
+ }
362
+ }
@@ -7,7 +7,7 @@ export class OxSciChart extends LitElement {
7
7
  @property({ type: Object }) config: OperatoChart.ChartConfig | null = null
8
8
  @property({ type: Array }) data: { [attr: string]: any }[] = []
9
9
 
10
- private chart: any = null
10
+ public chart: any = null
11
11
  private dataSeries: any[] = []
12
12
  /*
13
13
  [주의]
@@ -117,6 +117,8 @@ export class OxSciChart extends LitElement {
117
117
  })
118
118
  }
119
119
 
120
+ async appendData(appendum: { [attr: string]: any }[]) {}
121
+
120
122
  render() {
121
123
  return html` <div id=${this.containerId} class="chart-container"></div> `
122
124
  }