@finos/legend-application-data-cube 0.1.6 → 0.1.7

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 (181) hide show
  1. package/lib/__lib__/LegendDataCubeNavigation.d.ts +5 -5
  2. package/lib/__lib__/LegendDataCubeNavigation.d.ts.map +1 -1
  3. package/lib/__lib__/LegendDataCubeNavigation.js +5 -5
  4. package/lib/__lib__/LegendDataCubeNavigation.js.map +1 -1
  5. package/lib/{stores/source/CubeInputSource.js → __lib__/LegendDataCubeSetting.d.ts} +6 -14
  6. package/lib/__lib__/LegendDataCubeSetting.d.ts.map +1 -0
  7. package/lib/__lib__/LegendDataCubeSetting.js +25 -0
  8. package/lib/__lib__/LegendDataCubeSetting.js.map +1 -0
  9. package/lib/{stores/model/DataCubeQueryContent.js → __lib__/LegendDataCubeUserData.d.ts} +4 -5
  10. package/lib/__lib__/LegendDataCubeUserData.d.ts.map +1 -0
  11. package/lib/{stores/model/DataCubeGenericSource.d.ts → __lib__/LegendDataCubeUserData.js} +6 -3
  12. package/lib/__lib__/LegendDataCubeUserData.js.map +1 -0
  13. package/lib/application/LegendDataCube.d.ts.map +1 -1
  14. package/lib/application/LegendDataCube.js.map +1 -1
  15. package/lib/application/LegendDataCubeApplicationConfig.d.ts +1 -1
  16. package/lib/application/LegendDataCubeApplicationConfig.d.ts.map +1 -1
  17. package/lib/application/LegendDataCubeApplicationConfig.js +3 -1
  18. package/lib/application/LegendDataCubeApplicationConfig.js.map +1 -1
  19. package/lib/application/LegendDataCubePluginManager.d.ts.map +1 -1
  20. package/lib/application/LegendDataCubePluginManager.js.map +1 -1
  21. package/lib/components/LegendDataCubeFrameworkProvider.d.ts +2 -2
  22. package/lib/components/LegendDataCubeFrameworkProvider.d.ts.map +1 -1
  23. package/lib/components/LegendDataCubeFrameworkProvider.js +5 -5
  24. package/lib/components/LegendDataCubeFrameworkProvider.js.map +1 -1
  25. package/lib/components/LegendDataCubeWebApplication.d.ts.map +1 -1
  26. package/lib/components/LegendDataCubeWebApplication.js +25 -6
  27. package/lib/components/LegendDataCubeWebApplication.js.map +1 -1
  28. package/lib/components/{source/DataCubeSourceEditor.d.ts → query-builder/LegendDataCubeNewQueryBuilder.d.ts} +4 -4
  29. package/lib/components/query-builder/LegendDataCubeNewQueryBuilder.d.ts.map +1 -0
  30. package/lib/components/query-builder/LegendDataCubeNewQueryBuilder.js +45 -0
  31. package/lib/components/query-builder/LegendDataCubeNewQueryBuilder.js.map +1 -0
  32. package/{src/stores/model/DataCubeGenericSource.ts → lib/components/query-builder/LegendDataCubeQueryBuilder.d.ts} +2 -2
  33. package/lib/components/query-builder/LegendDataCubeQueryBuilder.d.ts.map +1 -0
  34. package/lib/components/query-builder/LegendDataCubeQueryBuilder.js +85 -0
  35. package/lib/components/query-builder/LegendDataCubeQueryBuilder.js.map +1 -0
  36. package/lib/components/query-builder/LegendDataCubeQueryBuilderStoreProvider.d.ts +19 -0
  37. package/lib/components/query-builder/LegendDataCubeQueryBuilderStoreProvider.d.ts.map +1 -0
  38. package/lib/components/query-builder/LegendDataCubeQueryBuilderStoreProvider.js +33 -0
  39. package/lib/components/query-builder/LegendDataCubeQueryBuilderStoreProvider.js.map +1 -0
  40. package/lib/components/{source/ExistingDataCubeQuery.d.ts → query-builder/LegendDataCubeQueryLoader.d.ts} +2 -2
  41. package/lib/components/query-builder/LegendDataCubeQueryLoader.d.ts.map +1 -0
  42. package/lib/components/query-builder/LegendDataCubeQueryLoader.js +99 -0
  43. package/lib/components/query-builder/LegendDataCubeQueryLoader.js.map +1 -0
  44. package/lib/components/{DataCubeEditor.d.ts → query-builder/LegendDataCubeQuerySaver.d.ts} +2 -2
  45. package/lib/components/query-builder/LegendDataCubeQuerySaver.d.ts.map +1 -0
  46. package/lib/components/query-builder/LegendDataCubeQuerySaver.js +49 -0
  47. package/lib/components/query-builder/LegendDataCubeQuerySaver.js.map +1 -0
  48. package/lib/components/{source/SavedQuerySourceEditor.d.ts → query-builder/source-builder/AdhocQueryDataCubeSourceBuilder.d.ts} +4 -4
  49. package/lib/components/query-builder/source-builder/AdhocQueryDataCubeSourceBuilder.d.ts.map +1 -0
  50. package/lib/components/query-builder/source-builder/AdhocQueryDataCubeSourceBuilder.js +22 -0
  51. package/lib/components/query-builder/source-builder/AdhocQueryDataCubeSourceBuilder.js.map +1 -0
  52. package/lib/components/query-builder/source-builder/LegendQueryDataCubeSourceBuilder.d.ts +22 -0
  53. package/lib/components/query-builder/source-builder/LegendQueryDataCubeSourceBuilder.d.ts.map +1 -0
  54. package/lib/components/query-builder/source-builder/LegendQueryDataCubeSourceBuilder.js +97 -0
  55. package/lib/components/query-builder/source-builder/LegendQueryDataCubeSourceBuilder.js.map +1 -0
  56. package/lib/index.css +2 -2
  57. package/lib/index.css.map +1 -1
  58. package/lib/package.json +2 -2
  59. package/lib/stores/LegendDataCubeBaseStore.d.ts +41 -0
  60. package/lib/stores/LegendDataCubeBaseStore.d.ts.map +1 -0
  61. package/lib/stores/LegendDataCubeBaseStore.js +123 -0
  62. package/lib/stores/LegendDataCubeBaseStore.js.map +1 -0
  63. package/lib/stores/LegendDataCubeDataCubeEngine.d.ts +65 -0
  64. package/lib/stores/LegendDataCubeDataCubeEngine.d.ts.map +1 -0
  65. package/lib/stores/LegendDataCubeDataCubeEngine.js +249 -0
  66. package/lib/stores/LegendDataCubeDataCubeEngine.js.map +1 -0
  67. package/lib/stores/model/LegendQueryDataCubeSource.d.ts +32 -0
  68. package/lib/stores/model/LegendQueryDataCubeSource.d.ts.map +1 -0
  69. package/lib/stores/model/LegendQueryDataCubeSource.js +35 -0
  70. package/lib/stores/model/LegendQueryDataCubeSource.js.map +1 -0
  71. package/lib/stores/query-builder/LegendDataCubeNewQueryState.d.ts +34 -0
  72. package/lib/stores/query-builder/LegendDataCubeNewQueryState.d.ts.map +1 -0
  73. package/lib/stores/query-builder/LegendDataCubeNewQueryState.js +92 -0
  74. package/lib/stores/query-builder/LegendDataCubeNewQueryState.js.map +1 -0
  75. package/lib/stores/query-builder/LegendDataCubeQueryBuilderStore.d.ts +52 -0
  76. package/lib/stores/query-builder/LegendDataCubeQueryBuilderStore.d.ts.map +1 -0
  77. package/lib/stores/query-builder/LegendDataCubeQueryBuilderStore.js +211 -0
  78. package/lib/stores/query-builder/LegendDataCubeQueryBuilderStore.js.map +1 -0
  79. package/lib/stores/query-builder/LegendDataCubeQueryLoaderState.d.ts +54 -0
  80. package/lib/stores/query-builder/LegendDataCubeQueryLoaderState.d.ts.map +1 -0
  81. package/lib/stores/query-builder/LegendDataCubeQueryLoaderState.js +197 -0
  82. package/lib/stores/query-builder/LegendDataCubeQueryLoaderState.js.map +1 -0
  83. package/lib/stores/{model/DataCubeQueryContent.d.ts → query-builder/source-builder/AdhocQueryDataCubeSourceBuilderState.d.ts} +7 -7
  84. package/lib/stores/query-builder/source-builder/AdhocQueryDataCubeSourceBuilderState.d.ts.map +1 -0
  85. package/lib/stores/{model/LegendSavedQuerySource.js → query-builder/source-builder/AdhocQueryDataCubeSourceBuilderState.js} +12 -7
  86. package/lib/stores/query-builder/source-builder/AdhocQueryDataCubeSourceBuilderState.js.map +1 -0
  87. package/lib/stores/query-builder/source-builder/LegendDataCubeSourceBuilderState.d.ts +33 -0
  88. package/lib/stores/query-builder/source-builder/LegendDataCubeSourceBuilderState.d.ts.map +1 -0
  89. package/lib/stores/query-builder/source-builder/LegendDataCubeSourceBuilderState.js +31 -0
  90. package/lib/stores/query-builder/source-builder/LegendDataCubeSourceBuilderState.js.map +1 -0
  91. package/lib/stores/query-builder/source-builder/LegendQueryDataCubeSourceBuilderState.d.ts +31 -0
  92. package/lib/stores/query-builder/source-builder/LegendQueryDataCubeSourceBuilderState.d.ts.map +1 -0
  93. package/lib/stores/query-builder/source-builder/LegendQueryDataCubeSourceBuilderState.js +84 -0
  94. package/lib/stores/query-builder/source-builder/LegendQueryDataCubeSourceBuilderState.js.map +1 -0
  95. package/package.json +11 -11
  96. package/src/__lib__/LegendDataCubeNavigation.ts +7 -7
  97. package/src/{stores/model/DataCubeQueryContent.ts → __lib__/LegendDataCubeSetting.ts} +6 -6
  98. package/{lib/stores/model/DataCubeGenericSource.js → src/__lib__/LegendDataCubeUserData.ts} +5 -2
  99. package/src/application/LegendDataCube.tsx +1 -0
  100. package/src/application/LegendDataCubeApplicationConfig.ts +6 -4
  101. package/src/application/LegendDataCubePluginManager.ts +1 -0
  102. package/src/components/LegendDataCubeFrameworkProvider.tsx +7 -7
  103. package/src/components/LegendDataCubeWebApplication.tsx +48 -12
  104. package/src/components/query-builder/LegendDataCubeNewQueryBuilder.tsx +115 -0
  105. package/src/components/query-builder/LegendDataCubeQueryBuilder.tsx +213 -0
  106. package/src/components/query-builder/LegendDataCubeQueryBuilderStoreProvider.tsx +56 -0
  107. package/src/components/query-builder/LegendDataCubeQueryLoader.tsx +310 -0
  108. package/src/components/query-builder/LegendDataCubeQuerySaver.tsx +106 -0
  109. package/src/{stores/source/CubeInputSource.ts → components/query-builder/source-builder/AdhocQueryDataCubeSourceBuilder.tsx} +14 -19
  110. package/src/components/query-builder/source-builder/LegendQueryDataCubeSourceBuilder.tsx +313 -0
  111. package/src/stores/LegendDataCubeBaseStore.ts +198 -0
  112. package/src/stores/LegendDataCubeDataCubeEngine.ts +494 -0
  113. package/src/stores/model/LegendQueryDataCubeSource.ts +46 -0
  114. package/src/stores/query-builder/LegendDataCubeNewQueryState.tsx +139 -0
  115. package/src/stores/query-builder/LegendDataCubeQueryBuilderStore.tsx +296 -0
  116. package/src/stores/query-builder/LegendDataCubeQueryLoaderState.tsx +258 -0
  117. package/src/stores/{source/LegendCubeViewer.ts → query-builder/source-builder/AdhocQueryDataCubeSourceBuilderState.ts} +15 -8
  118. package/src/stores/query-builder/source-builder/LegendDataCubeSourceBuilderState.ts +40 -0
  119. package/src/stores/query-builder/source-builder/LegendQueryDataCubeSourceBuilderState.ts +125 -0
  120. package/tsconfig.json +18 -15
  121. package/lib/components/DataCubeEditor.d.ts.map +0 -1
  122. package/lib/components/DataCubeEditor.js +0 -59
  123. package/lib/components/DataCubeEditor.js.map +0 -1
  124. package/lib/components/source/DataCubeSourceEditor.d.ts.map +0 -1
  125. package/lib/components/source/DataCubeSourceEditor.js +0 -43
  126. package/lib/components/source/DataCubeSourceEditor.js.map +0 -1
  127. package/lib/components/source/ExistingDataCubeQuery.d.ts.map +0 -1
  128. package/lib/components/source/ExistingDataCubeQuery.js +0 -36
  129. package/lib/components/source/ExistingDataCubeQuery.js.map +0 -1
  130. package/lib/components/source/SavedQuerySourceEditor.d.ts.map +0 -1
  131. package/lib/components/source/SavedQuerySourceEditor.js +0 -25
  132. package/lib/components/source/SavedQuerySourceEditor.js.map +0 -1
  133. package/lib/stores/LegendDataCubeEditorStore.d.ts +0 -50
  134. package/lib/stores/LegendDataCubeEditorStore.d.ts.map +0 -1
  135. package/lib/stores/LegendDataCubeEditorStore.js +0 -153
  136. package/lib/stores/LegendDataCubeEditorStore.js.map +0 -1
  137. package/lib/stores/engine/LegendExecutionDataCubeEngine.d.ts +0 -52
  138. package/lib/stores/engine/LegendExecutionDataCubeEngine.d.ts.map +0 -1
  139. package/lib/stores/engine/LegendExecutionDataCubeEngine.js +0 -149
  140. package/lib/stores/engine/LegendExecutionDataCubeEngine.js.map +0 -1
  141. package/lib/stores/model/DataCubeGenericSource.d.ts.map +0 -1
  142. package/lib/stores/model/DataCubeGenericSource.js.map +0 -1
  143. package/lib/stores/model/DataCubeGenericSourceHelper.d.ts +0 -24
  144. package/lib/stores/model/DataCubeGenericSourceHelper.d.ts.map +0 -1
  145. package/lib/stores/model/DataCubeGenericSourceHelper.js +0 -58
  146. package/lib/stores/model/DataCubeGenericSourceHelper.js.map +0 -1
  147. package/lib/stores/model/DataCubeQueryContent.d.ts.map +0 -1
  148. package/lib/stores/model/DataCubeQueryContent.js.map +0 -1
  149. package/lib/stores/model/LegendSavedQuerySource.d.ts +0 -21
  150. package/lib/stores/model/LegendSavedQuerySource.d.ts.map +0 -1
  151. package/lib/stores/model/LegendSavedQuerySource.js.map +0 -1
  152. package/lib/stores/source/CubeInputSource.d.ts +0 -32
  153. package/lib/stores/source/CubeInputSource.d.ts.map +0 -1
  154. package/lib/stores/source/CubeInputSource.js.map +0 -1
  155. package/lib/stores/source/CubeInputSourceLoader.d.ts +0 -37
  156. package/lib/stores/source/CubeInputSourceLoader.d.ts.map +0 -1
  157. package/lib/stores/source/CubeInputSourceLoader.js +0 -39
  158. package/lib/stores/source/CubeInputSourceLoader.js.map +0 -1
  159. package/lib/stores/source/LegendCubeViewer.d.ts +0 -23
  160. package/lib/stores/source/LegendCubeViewer.d.ts.map +0 -1
  161. package/lib/stores/source/LegendCubeViewer.js +0 -24
  162. package/lib/stores/source/LegendCubeViewer.js.map +0 -1
  163. package/lib/stores/source/LegendDataCubeSourceBuilder.d.ts +0 -34
  164. package/lib/stores/source/LegendDataCubeSourceBuilder.d.ts.map +0 -1
  165. package/lib/stores/source/LegendDataCubeSourceBuilder.js +0 -70
  166. package/lib/stores/source/LegendDataCubeSourceBuilder.js.map +0 -1
  167. package/lib/stores/source/SavedQueryInputSourceState.d.ts +0 -35
  168. package/lib/stores/source/SavedQueryInputSourceState.d.ts.map +0 -1
  169. package/lib/stores/source/SavedQueryInputSourceState.js +0 -81
  170. package/lib/stores/source/SavedQueryInputSourceState.js.map +0 -1
  171. package/src/components/DataCubeEditor.tsx +0 -190
  172. package/src/components/source/DataCubeSourceEditor.tsx +0 -133
  173. package/src/components/source/ExistingDataCubeQuery.tsx +0 -101
  174. package/src/components/source/SavedQuerySourceEditor.tsx +0 -62
  175. package/src/stores/LegendDataCubeEditorStore.ts +0 -237
  176. package/src/stores/engine/LegendExecutionDataCubeEngine.ts +0 -267
  177. package/src/stores/model/DataCubeGenericSourceHelper.ts +0 -97
  178. package/src/stores/model/LegendSavedQuerySource.ts +0 -26
  179. package/src/stores/source/CubeInputSourceLoader.ts +0 -56
  180. package/src/stores/source/LegendDataCubeSourceBuilder.ts +0 -98
  181. package/src/stores/source/SavedQueryInputSourceState.ts +0 -142
@@ -0,0 +1,296 @@
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 { action, makeObservable, observable } from 'mobx';
18
+ import type {
19
+ LegendDataCubeApplicationStore,
20
+ LegendDataCubeBaseStore,
21
+ } from '../LegendDataCubeBaseStore.js';
22
+ import {
23
+ DataCubeConfiguration,
24
+ DataCubeQuery,
25
+ DEFAULT_SMALL_ALERT_WINDOW_CONFIG,
26
+ type DataCubeState,
27
+ type DisplayState,
28
+ } from '@finos/legend-data-cube';
29
+ import { LegendDataCubeNewQueryState } from './LegendDataCubeNewQueryState.js';
30
+ import { PersistentDataCubeQuery } from '@finos/legend-graph';
31
+ import {
32
+ ActionState,
33
+ assertErrorThrown,
34
+ formatDate,
35
+ isString,
36
+ uuid,
37
+ } from '@finos/legend-shared';
38
+ import type { LegendDataCubeDataCubeEngine } from '../LegendDataCubeDataCubeEngine.js';
39
+ import { LegendDataCubeQuerySaver } from '../../components/query-builder/LegendDataCubeQuerySaver.js';
40
+ import { generateQueryBuilderRoute } from '../../__lib__/LegendDataCubeNavigation.js';
41
+ import { LegendDataCubeQueryLoaderState } from './LegendDataCubeQueryLoaderState.js';
42
+ import {
43
+ LegendDataCubeUserDataKey,
44
+ RECENTLY_VIEWED_QUERIES_LIMIT,
45
+ } from '../../__lib__/LegendDataCubeUserData.js';
46
+
47
+ export class LegendDataCubeQueryBuilderState {
48
+ uuid = uuid();
49
+ startTime = Date.now();
50
+ query!: DataCubeQuery;
51
+ persistentQuery?: PersistentDataCubeQuery | undefined;
52
+ dataCube?: DataCubeState | undefined;
53
+
54
+ constructor(
55
+ query: DataCubeQuery,
56
+ persistentQuery?: PersistentDataCubeQuery | undefined,
57
+ ) {
58
+ makeObservable(this, {
59
+ dataCube: observable,
60
+ setDataCube: action,
61
+
62
+ query: observable,
63
+ persistentQuery: observable,
64
+ setPersistentQuery: action,
65
+ });
66
+
67
+ this.query = query;
68
+ this.persistentQuery = persistentQuery;
69
+ }
70
+
71
+ setDataCube(val: DataCubeState | undefined) {
72
+ this.dataCube = val;
73
+ }
74
+
75
+ setPersistentQuery(val: PersistentDataCubeQuery) {
76
+ this.persistentQuery = val;
77
+ this.query = DataCubeQuery.serialization.fromJson(val.content);
78
+ this.startTime = Date.now();
79
+ }
80
+ }
81
+
82
+ export class LegendDataCubeQueryBuilderStore {
83
+ readonly application: LegendDataCubeApplicationStore;
84
+ readonly baseStore: LegendDataCubeBaseStore;
85
+ readonly engine: LegendDataCubeDataCubeEngine;
86
+
87
+ readonly newQueryState: LegendDataCubeNewQueryState;
88
+
89
+ readonly saveQueryState = ActionState.create();
90
+ readonly saverDisplay: DisplayState;
91
+
92
+ readonly loadQueryState = ActionState.create();
93
+ loader: LegendDataCubeQueryLoaderState;
94
+ builder?: LegendDataCubeQueryBuilderState | undefined;
95
+
96
+ constructor(baseStore: LegendDataCubeBaseStore) {
97
+ makeObservable(this, {
98
+ builder: observable,
99
+ setBuilder: action,
100
+ });
101
+
102
+ this.application = baseStore.application;
103
+ this.baseStore = baseStore;
104
+ this.engine = baseStore.engine;
105
+
106
+ this.newQueryState = new LegendDataCubeNewQueryState(this);
107
+ this.loader = new LegendDataCubeQueryLoaderState(this);
108
+ this.saverDisplay = this.engine.layout.newDisplay(
109
+ 'Save Query',
110
+ () => <LegendDataCubeQuerySaver />,
111
+ {
112
+ ...DEFAULT_SMALL_ALERT_WINDOW_CONFIG,
113
+ height: 140,
114
+ },
115
+ );
116
+ }
117
+
118
+ setBuilder(val: LegendDataCubeQueryBuilderState | undefined) {
119
+ this.builder = val;
120
+ }
121
+
122
+ private updateWindowTitle(persistentQuery: PersistentDataCubeQuery) {
123
+ this.application.layoutService.setWindowTitle(
124
+ `\u229E ${persistentQuery.name}${this.builder ? ` - ${formatDate(new Date(this.builder.startTime), 'HH:mm:ss EEE MMM dd yyyy')}` : ''}`,
125
+ );
126
+ }
127
+
128
+ getRecentlyViewedQueries() {
129
+ const data = this.application.userDataService.getObjectValue(
130
+ LegendDataCubeUserDataKey.RECENTLY_VIEWED_QUERIES,
131
+ );
132
+ return data && Array.isArray(data) && data.every((id) => isString(id))
133
+ ? data
134
+ : [];
135
+ }
136
+
137
+ async loadQuery(queryId: string | undefined) {
138
+ if (queryId !== this.builder?.persistentQuery?.id) {
139
+ if (!queryId) {
140
+ this.setBuilder(undefined);
141
+ return;
142
+ }
143
+
144
+ this.loadQueryState.inProgress();
145
+
146
+ try {
147
+ const persistentQuery =
148
+ await this.baseStore.graphManager.getDataCubeQuery(queryId);
149
+ const query = DataCubeQuery.serialization.fromJson(
150
+ persistentQuery.content,
151
+ );
152
+ this.setBuilder(
153
+ new LegendDataCubeQueryBuilderState(query, persistentQuery),
154
+ );
155
+ this.updateWindowTitle(persistentQuery);
156
+
157
+ // update the list of stack of recently viewed queries
158
+ const recentlyViewedQueries = this.getRecentlyViewedQueries();
159
+ const idx = recentlyViewedQueries.findIndex((data) => data === queryId);
160
+ if (idx === -1) {
161
+ if (recentlyViewedQueries.length >= RECENTLY_VIEWED_QUERIES_LIMIT) {
162
+ recentlyViewedQueries.pop();
163
+ }
164
+ recentlyViewedQueries.unshift(queryId);
165
+ } else {
166
+ recentlyViewedQueries.splice(idx, 1);
167
+ recentlyViewedQueries.unshift(queryId);
168
+ }
169
+ this.application.userDataService.persistValue(
170
+ LegendDataCubeUserDataKey.RECENTLY_VIEWED_QUERIES,
171
+ recentlyViewedQueries,
172
+ );
173
+
174
+ this.loadQueryState.pass();
175
+ } catch (error) {
176
+ assertErrorThrown(error);
177
+ this.engine.alertError(error, {
178
+ message: `Query Load Failure: ${error.message}`,
179
+ });
180
+ this.loadQueryState.fail();
181
+ }
182
+ }
183
+ }
184
+
185
+ private async generatePersistentQuery(
186
+ dataCube: DataCubeState,
187
+ name: string,
188
+ existingPersistentQuery?: PersistentDataCubeQuery | undefined,
189
+ ) {
190
+ const currentSnapshot = dataCube.view.snapshotManager.currentSnapshot;
191
+
192
+ const query = new DataCubeQuery();
193
+ query.source = dataCube.query.source;
194
+ query.configuration = DataCubeConfiguration.serialization.fromJson(
195
+ currentSnapshot.data.configuration,
196
+ );
197
+ query.query = await this.engine.getPartialQueryCode(currentSnapshot);
198
+
199
+ let persistentQuery: PersistentDataCubeQuery;
200
+ if (existingPersistentQuery) {
201
+ persistentQuery = existingPersistentQuery.clone();
202
+ } else {
203
+ persistentQuery = new PersistentDataCubeQuery();
204
+ persistentQuery.id = uuid();
205
+ }
206
+ persistentQuery.name = name;
207
+ persistentQuery.content = DataCubeQuery.serialization.toJson(query);
208
+ return persistentQuery;
209
+ }
210
+
211
+ async createQuery(name: string) {
212
+ if (!this.builder?.dataCube || this.saveQueryState.isInProgress) {
213
+ return;
214
+ }
215
+
216
+ this.saveQueryState.inProgress();
217
+ try {
218
+ const persistentQuery = await this.generatePersistentQuery(
219
+ this.builder.dataCube,
220
+ name,
221
+ );
222
+
223
+ const newQuery =
224
+ await this.baseStore.graphManager.createDataCubeQuery(persistentQuery);
225
+ // NOTE: reload is the cleanest, least bug-prone handling here
226
+ // but we can opt for just updating the URL to reflect the new query
227
+ // as an optimization. Also, it helps preserve the edition history
228
+ // on the existing data-cube.
229
+ //
230
+ // Another way to avoid reloading the whole app it to force update
231
+ // the <DataCube/> component using the key prop that ties to an ID
232
+ // of the builder.
233
+ this.application.navigationService.navigator.updateCurrentLocation(
234
+ generateQueryBuilderRoute(newQuery.id),
235
+ );
236
+ this.builder.setPersistentQuery(persistentQuery);
237
+ this.updateWindowTitle(persistentQuery);
238
+
239
+ this.saverDisplay.close();
240
+ this.saveQueryState.pass();
241
+ } catch (error) {
242
+ assertErrorThrown(error);
243
+ this.engine.alertError(error, {
244
+ message: `Query Creation Failure: ${error.message}`,
245
+ });
246
+ this.saveQueryState.fail();
247
+ }
248
+ }
249
+
250
+ async saveQuery(name: string, saveAsNewQuery: boolean) {
251
+ if (!this.builder?.dataCube || this.saveQueryState.isInProgress) {
252
+ return;
253
+ }
254
+
255
+ this.saveQueryState.inProgress();
256
+ try {
257
+ const persistentQuery = await this.generatePersistentQuery(
258
+ this.builder.dataCube,
259
+ name,
260
+ this.builder.persistentQuery,
261
+ );
262
+
263
+ if (saveAsNewQuery) {
264
+ persistentQuery.id = uuid();
265
+ const newQuery =
266
+ await this.baseStore.graphManager.createDataCubeQuery(
267
+ persistentQuery,
268
+ );
269
+ // NOTE: reload is the cleanest, least bug-prone handling here
270
+ // but we can opt for just updating the URL to reflect the new query
271
+ // as an optimization. Also, it helps preserve the edition history
272
+ // on the existing data-cube.
273
+ //
274
+ // Another way to avoid reloading the whole app it to force update
275
+ // the <DataCube/> component using the key prop that ties to an ID
276
+ // of the builder.
277
+ this.application.navigationService.navigator.updateCurrentLocation(
278
+ generateQueryBuilderRoute(newQuery.id),
279
+ );
280
+ } else {
281
+ await this.baseStore.graphManager.updateDataCubeQuery(persistentQuery);
282
+ }
283
+ this.builder.setPersistentQuery(persistentQuery);
284
+ this.updateWindowTitle(persistentQuery);
285
+
286
+ this.saverDisplay.close();
287
+ this.saveQueryState.pass();
288
+ } catch (error) {
289
+ assertErrorThrown(error);
290
+ this.engine.alertError(error, {
291
+ message: `Query Update Failure: ${error.message}`,
292
+ });
293
+ this.saveQueryState.fail();
294
+ }
295
+ }
296
+ }
@@ -0,0 +1,258 @@
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 {
18
+ APPLICATION_EVENT,
19
+ DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH,
20
+ type GenericLegendApplicationStore,
21
+ } from '@finos/legend-application';
22
+ import {
23
+ type LightPersistentDataCubeQuery,
24
+ QuerySearchSpecification,
25
+ QuerySearchSortBy,
26
+ } from '@finos/legend-graph';
27
+ import { ActionState, assertErrorThrown, LogEvent } from '@finos/legend-shared';
28
+ import { makeObservable, observable, action } from 'mobx';
29
+ import type { LegendDataCubeDataCubeEngine } from '../LegendDataCubeDataCubeEngine.js';
30
+ import type { LegendDataCubeQueryBuilderStore } from './LegendDataCubeQueryBuilderStore.js';
31
+ import { LegendDataCubeUserDataKey } from '../../__lib__/LegendDataCubeUserData.js';
32
+ import {
33
+ DEFAULT_TOOL_PANEL_WINDOW_CONFIG,
34
+ type DisplayState,
35
+ } from '@finos/legend-data-cube';
36
+ import { LegendDataCubeQueryLoader } from '../../components/query-builder/LegendDataCubeQueryLoader.js';
37
+ import { generateQueryBuilderRoute } from '../../__lib__/LegendDataCubeNavigation.js';
38
+
39
+ export const DATA_CUBE_QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT = 50;
40
+ export const DATA_CUBE_QUERY_LOADER_DEFAULT_QUERY_SEARCH_LIMIT = 10;
41
+
42
+ export enum DataCubeQuerySortByType {
43
+ LAST_CREATED = 'Last Created',
44
+ LAST_VIEWED = 'Last Viewed',
45
+ LAST_UPDATED = 'Last Updated',
46
+ }
47
+
48
+ export class LegendDataCubeQueryLoaderState {
49
+ readonly application: GenericLegendApplicationStore;
50
+ readonly store: LegendDataCubeQueryBuilderStore;
51
+ readonly engine: LegendDataCubeDataCubeEngine;
52
+ readonly display: DisplayState;
53
+
54
+ readonly searchState = ActionState.create();
55
+ readonly finalizeState = ActionState.create();
56
+ queries: LightPersistentDataCubeQuery[] = [];
57
+ selectedQuery?: LightPersistentDataCubeQuery | undefined;
58
+
59
+ searchText = '';
60
+ showCurrentUserQueriesOnly = false;
61
+ showingDefaultQueries = true;
62
+ sortBy = DataCubeQuerySortByType.LAST_VIEWED;
63
+
64
+ constructor(store: LegendDataCubeQueryBuilderStore) {
65
+ makeObservable(this, {
66
+ showingDefaultQueries: observable,
67
+ setShowingDefaultQueries: action,
68
+
69
+ searchText: observable,
70
+ setSearchText: action,
71
+
72
+ queries: observable,
73
+ setQueries: action,
74
+
75
+ showCurrentUserQueriesOnly: observable,
76
+ setShowCurrentUserQueriesOnly: action,
77
+
78
+ sortBy: observable,
79
+ setSortBy: action,
80
+
81
+ selectedQuery: observable,
82
+ setSelectedQuery: action,
83
+ });
84
+
85
+ this.application = store.application;
86
+ this.store = store;
87
+ this.engine = store.engine;
88
+ this.display = this.engine.layout.newDisplay(
89
+ 'Load Query',
90
+ () => <LegendDataCubeQueryLoader />,
91
+ {
92
+ ...DEFAULT_TOOL_PANEL_WINDOW_CONFIG,
93
+ width: 500,
94
+ minWidth: 500,
95
+ },
96
+ );
97
+ }
98
+
99
+ setSearchText(val: string) {
100
+ this.searchText = val;
101
+ }
102
+
103
+ setQueries(val: LightPersistentDataCubeQuery[]) {
104
+ this.queries = val;
105
+ }
106
+
107
+ setShowingDefaultQueries(val: boolean) {
108
+ this.showingDefaultQueries = val;
109
+ }
110
+
111
+ setShowCurrentUserQueriesOnly(val: boolean): void {
112
+ this.showCurrentUserQueriesOnly = val;
113
+ }
114
+
115
+ setSortBy(val: DataCubeQuerySortByType) {
116
+ this.sortBy = val;
117
+ }
118
+
119
+ private getQuerySearchSortBy(sortByValue: string) {
120
+ switch (sortByValue) {
121
+ case DataCubeQuerySortByType.LAST_CREATED:
122
+ return QuerySearchSortBy.SORT_BY_CREATE;
123
+ case DataCubeQuerySortByType.LAST_UPDATED:
124
+ return QuerySearchSortBy.SORT_BY_UPDATE;
125
+ case DataCubeQuerySortByType.LAST_VIEWED:
126
+ return QuerySearchSortBy.SORT_BY_VIEW;
127
+ default:
128
+ return undefined;
129
+ }
130
+ }
131
+
132
+ setSelectedQuery(query: LightPersistentDataCubeQuery | undefined) {
133
+ this.selectedQuery = query;
134
+ }
135
+
136
+ canPerformAdvancedSearch(searchText: string) {
137
+ return !(
138
+ searchText.length < DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH &&
139
+ !this.showCurrentUserQueriesOnly
140
+ );
141
+ }
142
+
143
+ async searchQueries(searchText: string) {
144
+ // for the initial search, i.e. no search config is specified, fetch the default queries if possible
145
+ if (!this.canPerformAdvancedSearch(searchText)) {
146
+ if (!searchText) {
147
+ this.setShowingDefaultQueries(true);
148
+ this.searchState.inProgress();
149
+ this.setQueries([]);
150
+ let defaultQueries: LightPersistentDataCubeQuery[] = [];
151
+ try {
152
+ // first, try to fetch recently viewed queries
153
+ try {
154
+ const recentlyViewedQueryIDs =
155
+ this.store.getRecentlyViewedQueries();
156
+ if (recentlyViewedQueryIDs.length) {
157
+ defaultQueries =
158
+ await this.engine.graphManager.getDataCubeQueries(
159
+ recentlyViewedQueryIDs,
160
+ );
161
+ }
162
+ } catch (error) {
163
+ assertErrorThrown(error);
164
+ // if there's an error fetching recently viewed queries, most likely because
165
+ // some queries have been removed, just remove them all from the cached user data
166
+ this.application.userDataService.persistValue(
167
+ LegendDataCubeUserDataKey.RECENTLY_VIEWED_QUERIES,
168
+ undefined,
169
+ );
170
+ }
171
+ // if there's no recently viewed queries, just fetch queries of the current user
172
+ if (!defaultQueries.length) {
173
+ const searchSpecification = new QuerySearchSpecification();
174
+ searchSpecification.limit =
175
+ DATA_CUBE_QUERY_LOADER_DEFAULT_QUERY_SEARCH_LIMIT;
176
+ searchSpecification.showCurrentUserQueriesOnly = true;
177
+ defaultQueries =
178
+ await this.engine.graphManager.searchDataCubeQueries(
179
+ searchSpecification,
180
+ );
181
+ }
182
+ this.setQueries(defaultQueries);
183
+ this.searchState.pass();
184
+ } catch (error) {
185
+ assertErrorThrown(error);
186
+ this.engine.logError(
187
+ LogEvent.create(APPLICATION_EVENT.GENERIC_FAILURE),
188
+ error,
189
+ );
190
+ this.searchState.fail();
191
+ }
192
+ }
193
+ return;
194
+ }
195
+
196
+ this.setShowingDefaultQueries(false);
197
+ this.searchState.inProgress();
198
+
199
+ try {
200
+ const searchSpecification =
201
+ QuerySearchSpecification.createDefault(searchText);
202
+ searchSpecification.limit =
203
+ DATA_CUBE_QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT + 1;
204
+ searchSpecification.showCurrentUserQueriesOnly =
205
+ this.showCurrentUserQueriesOnly;
206
+ const querySearchSortBy = this.getQuerySearchSortBy(this.sortBy);
207
+ if (querySearchSortBy) {
208
+ searchSpecification.sortByOption = querySearchSortBy;
209
+ }
210
+ this.setQueries(
211
+ await this.engine.graphManager.searchDataCubeQueries(
212
+ searchSpecification,
213
+ ),
214
+ );
215
+
216
+ // if sorting is not configured, sort by name
217
+ if (!querySearchSortBy) {
218
+ this.setQueries(
219
+ this.queries.toSorted((a, b) => a.name.localeCompare(b.name)),
220
+ );
221
+ }
222
+
223
+ this.searchState.pass();
224
+ } catch (error) {
225
+ assertErrorThrown(error);
226
+ this.engine.alertError(error, {
227
+ message: `Query Search Failure: ${error.message}`,
228
+ });
229
+ this.searchState.fail();
230
+ }
231
+ }
232
+
233
+ async finalize() {
234
+ if (!this.selectedQuery) {
235
+ return;
236
+ }
237
+
238
+ this.finalizeState.inProgress();
239
+ try {
240
+ // just simply change the route here and the new query ID will get picked up
241
+ // and handled by the query builder to load the new query.
242
+ this.application.navigationService.navigator.updateCurrentLocation(
243
+ generateQueryBuilderRoute(this.selectedQuery.id),
244
+ );
245
+
246
+ // reset
247
+ this.setSelectedQuery(undefined);
248
+ this.display.close();
249
+ this.finalizeState.pass();
250
+ } catch (error) {
251
+ assertErrorThrown(error);
252
+ this.engine.alertError(error, {
253
+ message: `Query Load Failure: ${error.message}`,
254
+ });
255
+ this.finalizeState.fail();
256
+ }
257
+ }
258
+ }
@@ -14,15 +14,22 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import type { DataCubeEngine } from '@finos/legend-data-cube';
18
- import type { DataCubeGenericSource } from '../model/DataCubeGenericSource.js';
17
+ import { type PlainObject } from '@finos/legend-shared';
18
+ import {
19
+ LegendDataCubeSourceBuilderState,
20
+ LegendDataCubeSourceBuilderType,
21
+ } from './LegendDataCubeSourceBuilderState.js';
19
22
 
20
- export class LegendCubeViewer {
21
- source: DataCubeGenericSource;
22
- engine: DataCubeEngine;
23
+ export class AdhocQueryDataCubeSourceBuilderState extends LegendDataCubeSourceBuilderState {
24
+ override get label(): LegendDataCubeSourceBuilderType {
25
+ return LegendDataCubeSourceBuilderType.ADHOC_QUERY;
26
+ }
27
+
28
+ override get isValid(): boolean {
29
+ return false;
30
+ }
23
31
 
24
- constructor(source: DataCubeGenericSource, engine: DataCubeEngine) {
25
- this.source = source;
26
- this.engine = engine;
32
+ override build(): Promise<PlainObject> {
33
+ throw new Error('Method not implemented.');
27
34
  }
28
35
  }
@@ -0,0 +1,40 @@
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 { ActionState, type PlainObject } from '@finos/legend-shared';
18
+ import type { LegendDataCubeApplicationStore } from '../../LegendDataCubeBaseStore.js';
19
+ import type { LegendDataCubeNewQueryState } from '../LegendDataCubeNewQueryState.js';
20
+ import type { LegendDataCubeDataCubeEngine } from '../../LegendDataCubeDataCubeEngine.js';
21
+
22
+ export enum LegendDataCubeSourceBuilderType {
23
+ LEGEND_QUERY = 'Legend Query',
24
+ ADHOC_QUERY = 'Ad hoc Query',
25
+ }
26
+
27
+ export abstract class LegendDataCubeSourceBuilderState {
28
+ readonly application: LegendDataCubeApplicationStore;
29
+ readonly engine: LegendDataCubeDataCubeEngine;
30
+ readonly buildState = ActionState.create();
31
+
32
+ constructor(newQueryState: LegendDataCubeNewQueryState) {
33
+ this.application = newQueryState.application;
34
+ this.engine = newQueryState.engine;
35
+ }
36
+
37
+ abstract get label(): LegendDataCubeSourceBuilderType;
38
+ abstract get isValid(): boolean;
39
+ abstract build(): Promise<PlainObject>;
40
+ }