@finos/legend-data-cube 0.0.36 → 0.0.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/README.md +1 -1
  2. package/lib/__lib__/DataCubeEvent.d.ts +21 -0
  3. package/lib/__lib__/DataCubeEvent.d.ts.map +1 -0
  4. package/lib/__lib__/DataCubeEvent.js +22 -0
  5. package/lib/__lib__/DataCubeEvent.js.map +1 -0
  6. package/lib/components/DataCube.d.ts +3 -1
  7. package/lib/components/DataCube.d.ts.map +1 -1
  8. package/lib/components/DataCube.js +10 -9
  9. package/lib/components/DataCube.js.map +1 -1
  10. package/lib/components/DataCubeProvider.js +1 -1
  11. package/lib/components/DataCubeProvider.js.map +1 -1
  12. package/lib/components/core/DataCubeAlert.d.ts +3 -2
  13. package/lib/components/core/DataCubeAlert.d.ts.map +1 -1
  14. package/lib/components/core/DataCubeAlert.js +4 -2
  15. package/lib/components/core/DataCubeAlert.js.map +1 -1
  16. package/lib/components/core/DataCubeFormUtils.d.ts +26 -0
  17. package/lib/components/core/DataCubeFormUtils.d.ts.map +1 -1
  18. package/lib/components/core/DataCubeFormUtils.js +127 -4
  19. package/lib/components/core/DataCubeFormUtils.js.map +1 -1
  20. package/lib/components/core/DataCubeLayoutManager.js +1 -1
  21. package/lib/components/core/DataCubeLayoutManager.js.map +1 -1
  22. package/lib/components/core/DataCubeSettingsPanel.d.ts.map +1 -1
  23. package/lib/components/core/DataCubeSettingsPanel.js +53 -27
  24. package/lib/components/core/DataCubeSettingsPanel.js.map +1 -1
  25. package/lib/components/view/editor/DataCubeEditor.d.ts.map +1 -1
  26. package/lib/components/view/editor/DataCubeEditor.js +6 -5
  27. package/lib/components/view/editor/DataCubeEditor.js.map +1 -1
  28. package/lib/components/view/editor/DataCubeEditorColumnPropertiesPanel.d.ts.map +1 -1
  29. package/lib/components/view/editor/DataCubeEditorColumnPropertiesPanel.js +4 -4
  30. package/lib/components/view/editor/DataCubeEditorColumnPropertiesPanel.js.map +1 -1
  31. package/lib/components/view/editor/DataCubeEditorGeneralPropertiesPanel.d.ts.map +1 -1
  32. package/lib/components/view/editor/DataCubeEditorGeneralPropertiesPanel.js +2 -2
  33. package/lib/components/view/editor/DataCubeEditorGeneralPropertiesPanel.js.map +1 -1
  34. package/lib/components/view/extend/DataCubeColumnEditor.d.ts.map +1 -1
  35. package/lib/components/view/extend/DataCubeColumnEditor.js +12 -12
  36. package/lib/components/view/extend/DataCubeColumnEditor.js.map +1 -1
  37. package/lib/components/view/filter/DataCubeFilterEditor.d.ts.map +1 -1
  38. package/lib/components/view/filter/DataCubeFilterEditor.js +4 -4
  39. package/lib/components/view/filter/DataCubeFilterEditor.js.map +1 -1
  40. package/lib/components/view/grid/DataCubeGrid.d.ts.map +1 -1
  41. package/lib/components/view/grid/DataCubeGrid.js +7 -7
  42. package/lib/components/view/grid/DataCubeGrid.js.map +1 -1
  43. package/lib/index.css +1 -1
  44. package/lib/index.d.ts +7 -2
  45. package/lib/index.d.ts.map +1 -1
  46. package/lib/index.js +7 -2
  47. package/lib/index.js.map +1 -1
  48. package/lib/package.json +2 -2
  49. package/lib/stores/DataCubeOptions.d.ts +6 -5
  50. package/lib/stores/DataCubeOptions.d.ts.map +1 -1
  51. package/lib/stores/DataCubeSettings.d.ts +25 -22
  52. package/lib/stores/DataCubeSettings.d.ts.map +1 -1
  53. package/lib/stores/DataCubeSettings.js +250 -62
  54. package/lib/stores/DataCubeSettings.js.map +1 -1
  55. package/lib/stores/DataCubeState.d.ts +8 -5
  56. package/lib/stores/DataCubeState.d.ts.map +1 -1
  57. package/lib/stores/DataCubeState.js +27 -42
  58. package/lib/stores/DataCubeState.js.map +1 -1
  59. package/lib/stores/core/DataCubeEngine.d.ts +15 -18
  60. package/lib/stores/core/DataCubeEngine.d.ts.map +1 -1
  61. package/lib/stores/core/DataCubeEngine.js +5 -16
  62. package/lib/stores/core/DataCubeEngine.js.map +1 -1
  63. package/lib/stores/core/DataCubeQueryBuilder.d.ts +1 -0
  64. package/lib/stores/core/DataCubeQueryBuilder.d.ts.map +1 -1
  65. package/lib/stores/core/DataCubeQueryBuilder.js.map +1 -1
  66. package/lib/stores/core/DataCubeQueryBuilderUtils.d.ts +3 -0
  67. package/lib/stores/core/DataCubeQueryBuilderUtils.d.ts.map +1 -1
  68. package/lib/stores/core/DataCubeQueryBuilderUtils.js +12 -1
  69. package/lib/stores/core/DataCubeQueryBuilderUtils.js.map +1 -1
  70. package/lib/stores/core/DataCubeQuerySnapshotBuilder.d.ts.map +1 -1
  71. package/lib/stores/core/DataCubeQuerySnapshotBuilder.js +46 -30
  72. package/lib/stores/core/DataCubeQuerySnapshotBuilder.js.map +1 -1
  73. package/lib/stores/core/DataCubeSetting.d.ts +51 -0
  74. package/lib/stores/core/DataCubeSetting.d.ts.map +1 -0
  75. package/lib/stores/core/DataCubeSetting.js +36 -0
  76. package/lib/stores/core/DataCubeSetting.js.map +1 -0
  77. package/lib/stores/core/models/AdhocQueryDataCubeSource.d.ts +29 -0
  78. package/lib/stores/core/models/AdhocQueryDataCubeSource.d.ts.map +1 -0
  79. package/lib/stores/core/models/AdhocQueryDataCubeSource.js +35 -0
  80. package/lib/stores/core/models/AdhocQueryDataCubeSource.js.map +1 -0
  81. package/lib/stores/core/models/DataCubeSource.d.ts +1 -1
  82. package/lib/stores/core/models/DataCubeSource.d.ts.map +1 -1
  83. package/lib/stores/core/models/DataCubeSource.js +1 -1
  84. package/lib/stores/core/models/DataCubeSource.js.map +1 -1
  85. package/lib/stores/view/DataCubeQuerySnapshotManager.d.ts.map +1 -1
  86. package/lib/stores/view/DataCubeQuerySnapshotManager.js +9 -2
  87. package/lib/stores/view/DataCubeQuerySnapshotManager.js.map +1 -1
  88. package/lib/stores/view/DataCubeViewState.d.ts +1 -1
  89. package/lib/stores/view/DataCubeViewState.d.ts.map +1 -1
  90. package/lib/stores/view/DataCubeViewState.js +5 -14
  91. package/lib/stores/view/DataCubeViewState.js.map +1 -1
  92. package/lib/stores/view/extend/DataCubeColumnEditorState.d.ts.map +1 -1
  93. package/lib/stores/view/extend/DataCubeColumnEditorState.js +5 -5
  94. package/lib/stores/view/extend/DataCubeColumnEditorState.js.map +1 -1
  95. package/lib/stores/view/grid/DataCubeGridClientEngine.d.ts +1 -1
  96. package/lib/stores/view/grid/DataCubeGridClientEngine.d.ts.map +1 -1
  97. package/lib/stores/view/grid/DataCubeGridClientEngine.js +11 -7
  98. package/lib/stores/view/grid/DataCubeGridClientEngine.js.map +1 -1
  99. package/lib/stores/view/grid/DataCubeGridQueryBuilder.d.ts.map +1 -1
  100. package/lib/stores/view/grid/DataCubeGridQueryBuilder.js +2 -2
  101. package/lib/stores/view/grid/DataCubeGridQueryBuilder.js.map +1 -1
  102. package/lib/stores/view/grid/DataCubeGridState.d.ts +1 -0
  103. package/lib/stores/view/grid/DataCubeGridState.d.ts.map +1 -1
  104. package/lib/stores/view/grid/DataCubeGridState.js +8 -3
  105. package/lib/stores/view/grid/DataCubeGridState.js.map +1 -1
  106. package/package.json +6 -6
  107. package/src/__lib__/DataCubeEvent.ts +21 -0
  108. package/src/components/DataCube.tsx +14 -8
  109. package/src/components/DataCubeProvider.tsx +1 -1
  110. package/src/components/core/DataCubeAlert.tsx +12 -7
  111. package/src/components/core/DataCubeFormUtils.tsx +245 -16
  112. package/src/components/core/DataCubeLayoutManager.tsx +1 -1
  113. package/src/components/core/DataCubeSettingsPanel.tsx +166 -134
  114. package/src/components/view/editor/DataCubeEditor.tsx +12 -16
  115. package/src/components/view/editor/DataCubeEditorColumnPropertiesPanel.tsx +6 -5
  116. package/src/components/view/editor/DataCubeEditorGeneralPropertiesPanel.tsx +4 -3
  117. package/src/components/view/extend/DataCubeColumnEditor.tsx +24 -28
  118. package/src/components/view/filter/DataCubeFilterEditor.tsx +10 -18
  119. package/src/components/view/grid/DataCubeGrid.tsx +8 -7
  120. package/src/index.tsx +13 -2
  121. package/src/stores/DataCubeOptions.ts +14 -10
  122. package/src/stores/DataCubeSettings.tsx +421 -0
  123. package/src/stores/DataCubeState.tsx +38 -51
  124. package/src/stores/core/DataCubeEngine.tsx +45 -62
  125. package/src/stores/core/DataCubeQueryBuilder.ts +1 -0
  126. package/src/stores/core/DataCubeQueryBuilderUtils.ts +17 -0
  127. package/src/stores/core/DataCubeQuerySnapshotBuilder.ts +59 -30
  128. package/src/stores/core/DataCubeSetting.ts +63 -0
  129. package/src/stores/core/models/AdhocQueryDataCubeSource.ts +45 -0
  130. package/src/stores/core/models/DataCubeSource.ts +1 -1
  131. package/src/stores/view/DataCubeQuerySnapshotManager.ts +16 -4
  132. package/src/stores/view/DataCubeViewState.ts +8 -17
  133. package/src/stores/view/extend/DataCubeColumnEditorState.tsx +8 -6
  134. package/src/stores/view/grid/DataCubeGridClientEngine.ts +22 -11
  135. package/src/stores/view/grid/DataCubeGridQueryBuilder.ts +7 -1
  136. package/src/stores/view/grid/DataCubeGridState.ts +17 -3
  137. package/tsconfig.json +4 -1
  138. package/src/stores/DataCubeSettings.ts +0 -107
package/src/index.tsx CHANGED
@@ -16,16 +16,27 @@
16
16
 
17
17
  export * from './stores/core/models/DataCubeQuery.js';
18
18
  export * from './stores/core/models/DataCubeSource.js';
19
+ export { type DataCubeColumn } from './stores/core/models/DataCubeColumn.js';
19
20
  export * from './stores/core/models/DataCubeConfiguration.js';
21
+ export * from './stores/core/models/AdhocQueryDataCubeSource.js';
20
22
 
21
23
  export * from './stores/core/DataCubeEngine.js';
22
24
  export * from './stores/core/DataCubeQueryEngine.js';
23
25
  export * from './stores/core/DataCubeLayoutManagerState.js';
24
26
  export * from './stores/core/DataCubeQueryBuilderUtils.js';
27
+
28
+ export {
29
+ type DataCubeSetting,
30
+ DataCubeSettingGroup,
31
+ DataCubeSettingType,
32
+ type DataCubeSettingValues,
33
+ } from './stores/core/DataCubeSetting.js';
25
34
  export { DataCubeState } from './stores/DataCubeState.js';
35
+ export { useDataCube } from './components/DataCubeProvider.js';
26
36
  export * from './stores/DataCubeAPI.js';
27
37
  export * from './stores/DataCubeOptions.js';
28
- export { DataCubeSettingKey } from './stores/DataCubeSettings.js';
29
38
 
30
- export * from './components/core/DataCubeAlert.js';
31
39
  export * from './components/DataCube.js';
40
+ export * from './components/core/DataCubeAlert.js';
41
+ export * from './components/core/DataCubeFormUtils.js';
42
+ export * from './components/core/DataCubeLayoutManager.js';
@@ -14,23 +14,27 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
+ import type {
18
+ DataCubeSetting,
19
+ DataCubeSettingValues,
20
+ } from './core/DataCubeSetting.js';
17
21
  import type { DataCubeSource } from './core/models/DataCubeSource.js';
18
22
  import type { DataCubeState } from './DataCubeState.js';
19
23
 
20
24
  export type DataCubeOptions = {
21
- enableDebugMode?: boolean | undefined;
22
- gridClientRowBuffer?: number | undefined;
23
- gridClientPurgeClosedRowNodes?: boolean | undefined;
24
- gridClientSuppressLargeDatasetWarning?: boolean | undefined;
25
+ gridClientLicense?: string | undefined;
26
+
27
+ onInitialized?: ((dataCube: DataCubeState) => void) | undefined;
25
28
 
26
29
  onNameChanged?: ((name: string, source: DataCubeSource) => void) | undefined;
27
- onSettingChanged?:
28
- | ((
29
- key: string,
30
- value: string | number | boolean | object | undefined,
31
- ) => void)
32
- | undefined;
30
+
33
31
  innerHeaderComponent?:
34
32
  | ((dataCube: DataCubeState) => React.ReactNode)
35
33
  | undefined;
34
+
35
+ getSettingItems?: (() => DataCubeSetting[]) | undefined;
36
+ getSettingValues?: (() => DataCubeSettingValues | undefined) | undefined;
37
+ onSettingValuesChanged?:
38
+ | ((values: DataCubeSettingValues) => void)
39
+ | undefined;
36
40
  };
@@ -0,0 +1,421 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import type { DataCubeState } from './DataCubeState.js';
18
+ import {
19
+ DataCubeSettingGroup,
20
+ DataCubeSettingKey,
21
+ DataCubeSettingType,
22
+ type DataCubeSetting,
23
+ type DataCubeSettingValue,
24
+ type DataCubeSettingValues,
25
+ } from './core/DataCubeSetting.js';
26
+ import {
27
+ hashArray,
28
+ IllegalStateError,
29
+ isBoolean,
30
+ isNumber,
31
+ isString,
32
+ LogEvent,
33
+ UnsupportedOperationError,
34
+ } from '@finos/legend-shared';
35
+ import { DataCubeEvent } from '../__lib__/DataCubeEvent.js';
36
+ import type { DataCubeOptions } from './DataCubeOptions.js';
37
+ import {
38
+ action,
39
+ computed,
40
+ makeObservable,
41
+ observable,
42
+ runInAction,
43
+ } from 'mobx';
44
+ import type { DisplayState } from './core/DataCubeLayoutManagerState.js';
45
+ import { DataCubeSettingsPanel } from '../components/core/DataCubeSettingsPanel.js';
46
+
47
+ export class DataCubeSettings {
48
+ readonly dataCube: DataCubeState;
49
+ readonly display: DisplayState;
50
+ readonly configurations = new Map<string, DataCubeSetting>();
51
+ readonly defaultValues = new Map<string, DataCubeSettingValue>();
52
+ readonly defaultValuesHashCode!: string;
53
+ readonly values = new Map<string, DataCubeSettingValue>();
54
+ readonly currentValues = new Map<string, DataCubeSettingValue>();
55
+
56
+ getSettingValues?: (() => DataCubeSettingValues | undefined) | undefined;
57
+ onSettingValuesChanged?:
58
+ | ((values: DataCubeSettingValues) => void)
59
+ | undefined;
60
+ gridClientLicense?: string | undefined;
61
+
62
+ constructor(dataCube: DataCubeState, options?: DataCubeOptions | undefined) {
63
+ makeObservable(this, {
64
+ values: observable,
65
+ save: action,
66
+ valuesHashCode: computed,
67
+
68
+ currentValues: observable,
69
+ resetDefaultValues: action,
70
+ currentValuesHashCode: computed,
71
+ });
72
+
73
+ this.dataCube = dataCube;
74
+ this.getSettingValues = options?.getSettingValues;
75
+ this.onSettingValuesChanged = options?.onSettingValuesChanged;
76
+
77
+ this.display = this.dataCube.engine.layout.newDisplay(
78
+ 'Settings',
79
+ () => <DataCubeSettingsPanel />,
80
+ {
81
+ x: -50,
82
+ y: 50,
83
+ width: 600,
84
+ height: 400,
85
+ minWidth: 300,
86
+ minHeight: 200,
87
+ center: false,
88
+ },
89
+ );
90
+
91
+ const CORE_SETTINGS: DataCubeSetting[] = [
92
+ {
93
+ key: DataCubeSettingKey.DEBUGGER__ENABLE_DEBUG_MODE,
94
+ title: `Debug Mode: Enabled`,
95
+ description: `Enables debug logging when running data queries, updating snapshots, etc.`,
96
+ group: DataCubeSettingGroup.DEBUG,
97
+ type: DataCubeSettingType.BOOLEAN,
98
+ defaultValue: false,
99
+ } satisfies DataCubeSetting<boolean>,
100
+ {
101
+ key: DataCubeSettingKey.GRID_CLIENT__SUPPRESS_LARGE_DATASET_WARNING,
102
+ title: `Large Dataset Warning: Disabled`,
103
+ description: `Suggests user to enable pagination when handling large datasets to improve performance.`,
104
+ group: DataCubeSettingGroup.GRID,
105
+ type: DataCubeSettingType.BOOLEAN,
106
+ defaultValue: false,
107
+ } satisfies DataCubeSetting<boolean>,
108
+ {
109
+ key: DataCubeSettingKey.GRID_CLIENT__ROW_BUFFER,
110
+ title: `Row Buffer`,
111
+ description: `Sets the number of rows the grid renders outside of the viewable area. e.g. if the buffer is 10 and your grid is showing 50 rows (as that's all that fits on your screen without scrolling), then the grid will actually render 70 in total (10 extra above and 10 extra below). Then when you scroll, the grid will already have 10 rows ready and waiting to show, no redraw is needed. A low small buffer will make initial draws of the grid faster; whereas a big one will reduce the redraw visible vertically scrolling.`,
112
+ group: DataCubeSettingGroup.GRID,
113
+ type: DataCubeSettingType.NUMERIC,
114
+ defaultValue: 50,
115
+ numericValueMin: 10,
116
+ numericValueStep: 10,
117
+ action: (newValue) =>
118
+ this.dataCube.runTaskForEachView((view) => {
119
+ view.grid.client.updateGridOptions({
120
+ rowBuffer: newValue,
121
+ });
122
+ }),
123
+ } satisfies DataCubeSetting<number>,
124
+ {
125
+ key: DataCubeSettingKey.GRID_CLIENT__PURGE_CLOSED_ROW_NODES,
126
+ title: `Refresh Group Node Data: Enabled`,
127
+ description: `Forces refresh data when group node is opened.`,
128
+ group: DataCubeSettingGroup.GRID,
129
+ type: DataCubeSettingType.BOOLEAN,
130
+ defaultValue: false,
131
+ action: (newValue) =>
132
+ this.dataCube.runTaskForEachView((view) => {
133
+ view.grid.client.updateGridOptions({
134
+ purgeClosedRowNodes: newValue,
135
+ });
136
+ }),
137
+ } satisfies DataCubeSetting<boolean>,
138
+ {
139
+ key: DataCubeSettingKey.GRID_CLIENT__ACTION__REFRESH_FAILED_DATA_FETCHES,
140
+ title: `Refresh Failed Data Fetch: Action`,
141
+ description: `Manually re-runs all failed data fetches in the grid.`,
142
+ group: DataCubeSettingGroup.GRID,
143
+ type: DataCubeSettingType.ACTION,
144
+ action: () => this.dataCube.refreshFailedDataFetches(),
145
+ defaultValue: undefined,
146
+ } satisfies DataCubeSetting,
147
+ ];
148
+
149
+ [...CORE_SETTINGS, ...(options?.getSettingItems?.() ?? [])].forEach(
150
+ (configuration) => {
151
+ this.configurations.set(configuration.key, configuration);
152
+ this.setValue(configuration.key, configuration.defaultValue, [
153
+ this.defaultValues,
154
+ this.values,
155
+ this.currentValues,
156
+ ]);
157
+ },
158
+ );
159
+
160
+ const settingValues = this.getSettingValues?.() ?? {};
161
+ Object.keys(settingValues).forEach((key) => {
162
+ const value = settingValues[key];
163
+ // for unknown settings (e.g. outdated settings, settings' keys changed, etc.), we ignore them
164
+ const configuration = this.configurations.get(key);
165
+ if (!configuration) {
166
+ return;
167
+ }
168
+ this.setValue(key, value, [this.values, this.currentValues]);
169
+ });
170
+
171
+ // NOTE: if we support explicity setting values from options, they should
172
+ // be processed here, as they should override the settings retrieved from
173
+ // cache.
174
+
175
+ this.defaultValuesHashCode = this.computeValuesHashCode(this.defaultValues);
176
+ }
177
+
178
+ private setValue(
179
+ key: string,
180
+ value: unknown,
181
+ valueIndexes: Map<string, unknown>[],
182
+ ) {
183
+ const configuration = this.configurations.get(key);
184
+ if (!configuration) {
185
+ this.dataCube.engine.logWarning(
186
+ LogEvent.create(
187
+ DataCubeEvent.SETTINGS__FAILURE__FOUND_UNREGISTERED_SETTING,
188
+ ),
189
+ `Can't set value for unregistered setting '${key}'`,
190
+ );
191
+ return false;
192
+ }
193
+ switch (configuration.type) {
194
+ case DataCubeSettingType.BOOLEAN: {
195
+ if (
196
+ !(
197
+ isBoolean(value) ||
198
+ (value === undefined && configuration.valueOptional)
199
+ )
200
+ ) {
201
+ this.dataCube.engine.logWarning(
202
+ LogEvent.create(
203
+ DataCubeEvent.SETTINGS__FAILURE__FOUND_UNREGISTERED_SETTING,
204
+ ),
205
+ `Can't set value for setting '${key}': boolean value expected`,
206
+ );
207
+ return false;
208
+ }
209
+ break;
210
+ }
211
+ case DataCubeSettingType.NUMERIC: {
212
+ if (
213
+ !(
214
+ isNumber(value) ||
215
+ (value === undefined && configuration.valueOptional)
216
+ )
217
+ ) {
218
+ this.dataCube.engine.logWarning(
219
+ LogEvent.create(
220
+ DataCubeEvent.SETTINGS__FAILURE__FOUND_UNREGISTERED_SETTING,
221
+ ),
222
+ `Can't set value for setting '${key}': numeric value expected`,
223
+ );
224
+ return false;
225
+ }
226
+ break;
227
+ }
228
+ case DataCubeSettingType.STRING: {
229
+ if (
230
+ !(
231
+ isString(value) ||
232
+ (value === undefined && configuration.valueOptional)
233
+ )
234
+ ) {
235
+ this.dataCube.engine.logWarning(
236
+ LogEvent.create(
237
+ DataCubeEvent.SETTINGS__FAILURE__FOUND_UNREGISTERED_SETTING,
238
+ ),
239
+ `Can't set value for setting '${key}': string value expected`,
240
+ );
241
+ return false;
242
+ }
243
+ break;
244
+ }
245
+ case DataCubeSettingType.ACTION: {
246
+ return false;
247
+ }
248
+ default:
249
+ throw new UnsupportedOperationError(
250
+ `Can't set value for unsupported setting type '${configuration.type}'`,
251
+ );
252
+ }
253
+ valueIndexes.forEach((valueIndex) => {
254
+ runInAction(() => valueIndex.set(key, value));
255
+ });
256
+ return true;
257
+ }
258
+
259
+ private getConfiguration(key: string) {
260
+ const configuration = this.configurations.get(key);
261
+ if (!configuration) {
262
+ this.dataCube.engine.logWarning(
263
+ LogEvent.create(
264
+ DataCubeEvent.SETTINGS__FAILURE__FOUND_UNREGISTERED_SETTING,
265
+ ),
266
+ `Can't retrieve value for unregistered setting '${key}'`,
267
+ );
268
+ throw new IllegalStateError(
269
+ `Can't retrieve value for unregistered setting '${key}'`,
270
+ );
271
+ }
272
+ return configuration;
273
+ }
274
+
275
+ getBooleanValue(key: string) {
276
+ const value = this.values.get(key);
277
+ const configuration = this.getConfiguration(key);
278
+ if (
279
+ configuration.type !== DataCubeSettingType.BOOLEAN ||
280
+ !isBoolean(value)
281
+ ) {
282
+ this.dataCube.engine.logWarning(
283
+ LogEvent.create(
284
+ DataCubeEvent.SETTINGS__FAILURE__RETRIEVE_INCOMPATIBLE_VALUE,
285
+ ),
286
+ `Can't retrieve boolean value for setting '${key}'`,
287
+ );
288
+ throw new IllegalStateError(
289
+ `Can't retrieve boolean value for setting '${key}'`,
290
+ );
291
+ }
292
+ return value;
293
+ }
294
+
295
+ getNumericValue(key: string) {
296
+ const value = this.values.get(key);
297
+ const configuration = this.getConfiguration(key);
298
+ if (
299
+ configuration.type !== DataCubeSettingType.NUMERIC ||
300
+ !isNumber(value)
301
+ ) {
302
+ this.dataCube.engine.logWarning(
303
+ LogEvent.create(
304
+ DataCubeEvent.SETTINGS__FAILURE__RETRIEVE_INCOMPATIBLE_VALUE,
305
+ ),
306
+ `Can't retrieve numeric value for setting '${key}'`,
307
+ );
308
+ throw new IllegalStateError(
309
+ `Can't retrieve numeric value for setting '${key}'`,
310
+ );
311
+ }
312
+ return value;
313
+ }
314
+
315
+ getStringValue(key: string) {
316
+ const value = this.values.get(key);
317
+ const configuration = this.getConfiguration(key);
318
+ if (configuration.type !== DataCubeSettingType.STRING || !isString(value)) {
319
+ this.dataCube.engine.logWarning(
320
+ LogEvent.create(
321
+ DataCubeEvent.SETTINGS__FAILURE__RETRIEVE_INCOMPATIBLE_VALUE,
322
+ ),
323
+ `Can't retrieve string value for setting '${key}'`,
324
+ );
325
+ throw new IllegalStateError(
326
+ `Can't retrieve string value for setting '${key}'`,
327
+ );
328
+ }
329
+ return value;
330
+ }
331
+
332
+ updateValue(key: string, value: DataCubeSettingValue) {
333
+ const configuration = this.configurations.get(key);
334
+ if (!configuration) {
335
+ this.dataCube.engine.logWarning(
336
+ LogEvent.create(
337
+ DataCubeEvent.SETTINGS__FAILURE__FOUND_UNREGISTERED_SETTING,
338
+ ),
339
+ `Can't set value for unregistered setting '${key}'`,
340
+ );
341
+ return;
342
+ }
343
+
344
+ if (!this.setValue(key, value, [this.values, this.currentValues])) {
345
+ return;
346
+ }
347
+
348
+ // trigger hook
349
+ this.onSettingValuesChanged?.(this.getCurrentSettingValues());
350
+
351
+ // trigger action
352
+ configuration.action?.(value);
353
+ }
354
+
355
+ private computeValuesHashCode(values: Map<string, DataCubeSettingValue>) {
356
+ return hashArray(
357
+ Array.from(values.entries())
358
+ .toSorted((a, b) => a[0].localeCompare(b[0]))
359
+ .map(([key, value]) => `${key}:${value}`),
360
+ );
361
+ }
362
+
363
+ get valuesHashCode() {
364
+ return this.computeValuesHashCode(this.values);
365
+ }
366
+
367
+ get currentValuesHashCode() {
368
+ return this.computeValuesHashCode(this.currentValues);
369
+ }
370
+
371
+ resetDefaultValues() {
372
+ this.currentValues.clear();
373
+ this.defaultValues.forEach((value, key) =>
374
+ this.currentValues.set(key, value),
375
+ );
376
+ }
377
+
378
+ private getCurrentSettingValues(): DataCubeSettingValues {
379
+ const settingValues: DataCubeSettingValues = {};
380
+ this.values.forEach((value, key) => {
381
+ const configuration = this.configurations.get(key);
382
+ // skip if value is the same as default value
383
+ if (configuration && value !== configuration.defaultValue) {
384
+ settingValues[key] = value;
385
+ }
386
+ });
387
+ return settingValues;
388
+ }
389
+
390
+ save() {
391
+ const changedSettingKeys = new Set<string>();
392
+ this.values.forEach((value, key) => {
393
+ if (value !== this.currentValues.get(key)) {
394
+ changedSettingKeys.add(key);
395
+ }
396
+ });
397
+
398
+ // update values
399
+ this.values.clear();
400
+ this.currentValues.forEach((value, key) => this.values.set(key, value));
401
+
402
+ // trigger hook
403
+ this.onSettingValuesChanged?.(this.getCurrentSettingValues());
404
+
405
+ // trigger action
406
+ let requiresReload = false;
407
+ for (const key of changedSettingKeys) {
408
+ const configuration = this.configurations.get(key);
409
+ if (configuration?.requiresReload) {
410
+ requiresReload = true;
411
+ }
412
+ if (configuration?.action) {
413
+ configuration.action(this.values.get(key));
414
+ }
415
+ }
416
+
417
+ if (requiresReload) {
418
+ this.dataCube.reload();
419
+ }
420
+ }
421
+ }
@@ -18,10 +18,10 @@ import { type DataCubeEngine } from './core/DataCubeEngine.js';
18
18
  import { DataCubeViewState } from './view/DataCubeViewState.js';
19
19
  import type { DisplayState } from './core/DataCubeLayoutManagerState.js';
20
20
  import { DocumentationPanel } from '../components/core/DataCubeDocumentationPanel.js';
21
- import { DataCubeSettingsPanel } from '../components/core/DataCubeSettingsPanel.js';
22
21
  import {
23
22
  ActionState,
24
23
  assertErrorThrown,
24
+ uuid,
25
25
  type DocumentationEntry,
26
26
  } from '@finos/legend-shared';
27
27
  import {
@@ -33,24 +33,20 @@ import { action, makeObservable, observable } from 'mobx';
33
33
  import { DataCubeSettings } from './DataCubeSettings.js';
34
34
  import type { DataCubeAPI } from './DataCubeAPI.js';
35
35
  import type { DataCubeOptions } from './DataCubeOptions.js';
36
+ import type { DataCubeQuery } from './core/models/DataCubeQuery.js';
36
37
 
37
38
  export class DataCubeState implements DataCubeAPI {
39
+ uuid = uuid();
40
+
38
41
  readonly engine: DataCubeEngine;
42
+
43
+ readonly query: DataCubeQuery;
39
44
  readonly settings!: DataCubeSettings;
40
- readonly initState = ActionState.create();
41
- readonly settingsDisplay: DisplayState;
42
45
  readonly documentationDisplay: DisplayState;
43
- // NOTE: when we support multiview, there can be multiple view states to support
44
- // the first one in that list will be taken as the main view state
45
- readonly view: DataCubeViewState;
46
+ readonly initializeState = ActionState.create();
46
47
 
48
+ onInitialized?: ((dataCube: DataCubeState) => void) | undefined;
47
49
  onNameChanged?: ((name: string, source: DataCubeSource) => void) | undefined;
48
- onSettingChanged?:
49
- | ((
50
- key: string,
51
- value: string | number | boolean | object | undefined,
52
- ) => void)
53
- | undefined;
54
50
  innerHeaderComponent?:
55
51
  | ((dataCube: DataCubeState) => React.ReactNode)
56
52
  | undefined;
@@ -58,32 +54,31 @@ export class DataCubeState implements DataCubeAPI {
58
54
  currentDocumentationEntry?: DocumentationEntry | undefined;
59
55
  currentActionAlert?: ActionAlert | undefined;
60
56
 
61
- constructor(engine: DataCubeEngine, options?: DataCubeOptions | undefined) {
57
+ // NOTE: when we support multiview, there can be multiple view states to support
58
+ // the first one in that list will be taken as the main view state
59
+ view: DataCubeViewState;
60
+
61
+ constructor(
62
+ query: DataCubeQuery,
63
+ engine: DataCubeEngine,
64
+ options?: DataCubeOptions | undefined,
65
+ ) {
62
66
  makeObservable(this, {
63
67
  currentDocumentationEntry: observable,
64
68
  openDocumentationEntry: action,
65
69
 
66
70
  currentActionAlert: observable,
67
71
  alertAction: action,
72
+
73
+ uuid: observable,
74
+ reload: action,
68
75
  });
69
76
 
77
+ this.query = query;
70
78
  this.engine = engine;
71
- this.settings = new DataCubeSettings(this);
79
+ this.settings = new DataCubeSettings(this, options);
72
80
  this.view = new DataCubeViewState(this);
73
81
 
74
- this.settingsDisplay = this.engine.layout.newDisplay(
75
- 'Settings',
76
- () => <DataCubeSettingsPanel />,
77
- {
78
- x: -50,
79
- y: 50,
80
- width: 600,
81
- height: 400,
82
- minWidth: 300,
83
- minHeight: 200,
84
- center: false,
85
- },
86
- );
87
82
  this.documentationDisplay = this.engine.layout.newDisplay(
88
83
  'Documentation',
89
84
  () => <DocumentationPanel />,
@@ -98,26 +93,14 @@ export class DataCubeState implements DataCubeAPI {
98
93
  },
99
94
  );
100
95
 
96
+ this.onInitialized = options?.onInitialized;
101
97
  this.onNameChanged = options?.onNameChanged;
102
- this.onSettingChanged = options?.onSettingChanged;
103
98
  this.innerHeaderComponent = options?.innerHeaderComponent;
99
+ }
104
100
 
105
- this.settings.enableDebugMode =
106
- options?.enableDebugMode !== undefined
107
- ? options.enableDebugMode
108
- : this.settings.enableDebugMode;
109
- this.settings.gridClientRowBuffer =
110
- options?.gridClientRowBuffer !== undefined
111
- ? options.gridClientRowBuffer
112
- : this.settings.gridClientRowBuffer;
113
- this.settings.gridClientPurgeClosedRowNodes =
114
- options?.gridClientPurgeClosedRowNodes !== undefined
115
- ? options.gridClientPurgeClosedRowNodes
116
- : this.settings.gridClientPurgeClosedRowNodes;
117
- this.settings.gridClientSuppressLargeDatasetWarning =
118
- options?.gridClientSuppressLargeDatasetWarning !== undefined
119
- ? options.gridClientSuppressLargeDatasetWarning
120
- : this.settings.gridClientSuppressLargeDatasetWarning;
101
+ reload() {
102
+ this.view = new DataCubeViewState(this);
103
+ this.uuid = uuid();
121
104
  }
122
105
 
123
106
  getSettings() {
@@ -145,16 +128,20 @@ export class DataCubeState implements DataCubeAPI {
145
128
  }
146
129
 
147
130
  async initialize() {
148
- if (!this.initState.isInInitialState) {
149
- this.engine.logDebug('REPL store is re-initialized');
131
+ if (!this.initializeState.isInInitialState) {
132
+ this.engine.logDebug('DataCube state is re-initialized');
150
133
  return;
151
134
  }
152
- this.initState.inProgress();
135
+ this.initializeState.inProgress();
153
136
 
154
137
  try {
155
- await this.engine.initialize();
156
- this.initState.pass();
157
- } catch (error: unknown) {
138
+ await this.engine.initialize({
139
+ gridClientLicense: this.settings.gridClientLicense,
140
+ });
141
+
142
+ this.onInitialized?.(this);
143
+ this.initializeState.pass();
144
+ } catch (error) {
158
145
  assertErrorThrown(error);
159
146
  this.alertAction({
160
147
  message: `Initialization Failure: ${error.message}`,
@@ -162,7 +149,7 @@ export class DataCubeState implements DataCubeAPI {
162
149
  type: AlertType.ERROR,
163
150
  actions: [],
164
151
  });
165
- this.initState.fail();
152
+ this.initializeState.fail();
166
153
  }
167
154
  }
168
155
  }