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

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/__lib__/LegendDataCubeUserData.js +21 -0
  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/{stores/model/DataCubeGenericSource.d.ts → components/query-builder/LegendDataCubeNewQueryBuilder.d.ts} +4 -3
  29. package/lib/components/query-builder/LegendDataCubeNewQueryBuilder.d.ts.map +1 -0
  30. package/lib/components/query-builder/LegendDataCubeNewQueryBuilder.js +46 -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 +79 -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 +97 -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/DataCubeSourceEditor.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/{source/SavedQuerySourceEditor.d.ts → query-builder/source-builder/LegendQueryDataCubeSourceBuilder.d.ts} +4 -4
  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 +43 -0
  60. package/lib/stores/LegendDataCubeBaseStore.d.ts.map +1 -0
  61. package/lib/stores/LegendDataCubeBaseStore.js +130 -0
  62. package/lib/stores/LegendDataCubeBaseStore.js.map +1 -0
  63. package/lib/stores/LegendDataCubeDataCubeEngine.d.ts +57 -0
  64. package/lib/stores/LegendDataCubeDataCubeEngine.d.ts.map +1 -0
  65. package/lib/stores/LegendDataCubeDataCubeEngine.js +250 -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 +33 -0
  72. package/lib/stores/query-builder/LegendDataCubeNewQueryState.d.ts.map +1 -0
  73. package/lib/stores/query-builder/LegendDataCubeNewQueryState.js +94 -0
  74. package/lib/stores/query-builder/LegendDataCubeNewQueryState.js.map +1 -0
  75. package/lib/stores/query-builder/LegendDataCubeQueryBuilderStore.d.ts +59 -0
  76. package/lib/stores/query-builder/LegendDataCubeQueryBuilderStore.d.ts.map +1 -0
  77. package/lib/stores/query-builder/LegendDataCubeQueryBuilderStore.js +219 -0
  78. package/lib/stores/query-builder/LegendDataCubeQueryBuilderStore.js.map +1 -0
  79. package/lib/stores/query-builder/LegendDataCubeQueryLoaderState.d.ts +53 -0
  80. package/lib/stores/query-builder/LegendDataCubeQueryLoaderState.d.ts.map +1 -0
  81. package/lib/stores/query-builder/LegendDataCubeQueryLoaderState.js +198 -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 +32 -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 +36 -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 +90 -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 +112 -0
  105. package/src/components/query-builder/LegendDataCubeQueryBuilder.tsx +148 -0
  106. package/src/components/query-builder/LegendDataCubeQueryBuilderStoreProvider.tsx +56 -0
  107. package/src/components/query-builder/LegendDataCubeQueryLoader.tsx +309 -0
  108. package/src/components/query-builder/LegendDataCubeQuerySaver.tsx +112 -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 +315 -0
  111. package/src/stores/LegendDataCubeBaseStore.ts +217 -0
  112. package/src/stores/LegendDataCubeDataCubeEngine.ts +489 -0
  113. package/src/stores/model/LegendQueryDataCubeSource.ts +46 -0
  114. package/src/stores/query-builder/LegendDataCubeNewQueryState.tsx +153 -0
  115. package/src/stores/query-builder/LegendDataCubeQueryBuilderStore.tsx +307 -0
  116. package/src/stores/query-builder/LegendDataCubeQueryLoaderState.tsx +260 -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 +43 -0
  119. package/src/stores/query-builder/source-builder/LegendQueryDataCubeSourceBuilderState.ts +143 -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,112 @@
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 { observer } from 'mobx-react-lite';
18
+ import { LegendDataCubeSourceBuilderType } from '../../stores/query-builder/source-builder/LegendDataCubeSourceBuilderState.js';
19
+ import { useDropdownMenu } from '@finos/legend-art';
20
+ import {
21
+ FormButton,
22
+ FormDropdownMenu,
23
+ FormDropdownMenuItem,
24
+ FormDropdownMenuTrigger,
25
+ } from '@finos/legend-data-cube';
26
+ import { LegendQueryDataCubeSourceBuilderState } from '../../stores/query-builder/source-builder/LegendQueryDataCubeSourceBuilderState.js';
27
+ import { LegendQueryDataCubeSourceBuilder } from './source-builder/LegendQueryDataCubeSourceBuilder.js';
28
+ import { AdhocQueryDataCubeSourceBuilder } from './source-builder/AdhocQueryDataCubeSourceBuilder.js';
29
+ import { AdhocQueryDataCubeSourceBuilderState } from '../../stores/query-builder/source-builder/AdhocQueryDataCubeSourceBuilderState.js';
30
+ import { useLegendDataCubeQueryBuilderStore } from './LegendDataCubeQueryBuilderStoreProvider.js';
31
+
32
+ export const LegendDataCubeNewQueryBuilder = observer(() => {
33
+ const store = useLegendDataCubeQueryBuilderStore();
34
+ const state = store.newQueryState;
35
+ const sourceBuilder = state.sourceBuilder;
36
+ const selectedSourceType = sourceBuilder.label;
37
+ const [
38
+ openSourceTypeDropdown,
39
+ closeSourceTypeDropdown,
40
+ sourceTypeDropdownProps,
41
+ sourceTypeDropdownPropsOpen,
42
+ ] = useDropdownMenu();
43
+
44
+ return (
45
+ <>
46
+ <div className="h-[calc(100%_-_40px)] w-full px-2 pt-2">
47
+ <div className="h-full w-full overflow-auto border border-neutral-300 bg-white">
48
+ <div className="h-full w-full select-none p-2">
49
+ <div className="flex h-6 w-full items-center">
50
+ <div className="flex h-full w-32 flex-shrink-0 items-center text-sm">
51
+ Choose Source Type:
52
+ </div>
53
+ <FormDropdownMenuTrigger
54
+ className="w-80"
55
+ onClick={openSourceTypeDropdown}
56
+ open={sourceTypeDropdownPropsOpen}
57
+ >
58
+ {selectedSourceType}
59
+ </FormDropdownMenuTrigger>
60
+ <FormDropdownMenu className="w-80" {...sourceTypeDropdownProps}>
61
+ {[
62
+ LegendDataCubeSourceBuilderType.LEGEND_QUERY,
63
+ LegendDataCubeSourceBuilderType.ADHOC_QUERY,
64
+ ].map((type) => (
65
+ <FormDropdownMenuItem
66
+ key={type}
67
+ onClick={() => {
68
+ state.changeSourceBuilder(type);
69
+ closeSourceTypeDropdown();
70
+ }}
71
+ autoFocus={type === selectedSourceType}
72
+ >
73
+ {type}
74
+ </FormDropdownMenuItem>
75
+ ))}
76
+ </FormDropdownMenu>
77
+ </div>
78
+ <div className="-ml-2 mb-2 mt-2 h-[1px] w-[calc(100%_+_16px)] bg-neutral-200" />
79
+ <div className="h-[calc(100%_-_40px)] w-full">
80
+ {sourceBuilder instanceof
81
+ LegendQueryDataCubeSourceBuilderState && (
82
+ <LegendQueryDataCubeSourceBuilder
83
+ sourceBuilder={sourceBuilder}
84
+ />
85
+ )}
86
+ {sourceBuilder instanceof
87
+ AdhocQueryDataCubeSourceBuilderState && (
88
+ <AdhocQueryDataCubeSourceBuilder
89
+ sourceBuilder={sourceBuilder}
90
+ />
91
+ )}
92
+ </div>
93
+ </div>
94
+ </div>
95
+ </div>
96
+ <div className="flex h-10 items-center justify-end px-2">
97
+ <FormButton onClick={() => state.display.close()}>Cancel</FormButton>
98
+ <FormButton
99
+ className="ml-2"
100
+ disabled={!sourceBuilder.isValid || state.finalizeState.isInProgress}
101
+ onClick={() => {
102
+ state
103
+ .finalize()
104
+ .catch((error) => store.alertService.alertUnhandledError(error));
105
+ }}
106
+ >
107
+ OK
108
+ </FormButton>
109
+ </div>
110
+ </>
111
+ );
112
+ });
@@ -0,0 +1,148 @@
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 { observer } from 'mobx-react-lite';
18
+ import {
19
+ DataCube,
20
+ FormButton,
21
+ type DataCubeSettingValues,
22
+ DataCubePlaceholder,
23
+ } from '@finos/legend-data-cube';
24
+ import {} from '@finos/legend-art';
25
+ import {
26
+ useLegendDataCubeQueryBuilderStore,
27
+ withLegendDataCubeQueryBuilderStore,
28
+ } from './LegendDataCubeQueryBuilderStoreProvider.js';
29
+ import { useParams } from '@finos/legend-application/browser';
30
+ import {
31
+ LEGEND_DATA_CUBE_ROUTE_PATTERN_TOKEN,
32
+ type LegendDataCubeQueryBuilderQueryPathParams,
33
+ } from '../../__lib__/LegendDataCubeNavigation.js';
34
+ import { useEffect } from 'react';
35
+ import { LegendDataCubeSettingStorageKey } from '../../__lib__/LegendDataCubeSetting.js';
36
+
37
+ const LegendDataCubeQueryBuilderHeader = observer(() => {
38
+ const store = useLegendDataCubeQueryBuilderStore();
39
+
40
+ return (
41
+ <div className="flex h-full items-center">
42
+ <FormButton compact={true} onClick={() => store.loader.display.open()}>
43
+ Load Query
44
+ </FormButton>
45
+ <FormButton
46
+ compact={true}
47
+ className="ml-1.5"
48
+ onClick={() => store.newQueryState.display.open()}
49
+ >
50
+ New Query
51
+ </FormButton>
52
+ <FormButton
53
+ compact={true}
54
+ className="ml-1.5"
55
+ disabled={!store.builder?.dataCube}
56
+ onClick={() => store.saverDisplay.open()}
57
+ >
58
+ Save Query
59
+ </FormButton>
60
+ </div>
61
+ );
62
+ });
63
+
64
+ export const LegendDataCubeQueryBuilder = withLegendDataCubeQueryBuilderStore(
65
+ observer(() => {
66
+ const store = useLegendDataCubeQueryBuilderStore();
67
+ const builder = store.builder;
68
+ const application = store.application;
69
+ const params = useParams<LegendDataCubeQueryBuilderQueryPathParams>();
70
+ const queryId = params[LEGEND_DATA_CUBE_ROUTE_PATTERN_TOKEN.QUERY_ID];
71
+
72
+ useEffect(() => {
73
+ if (queryId !== store.builder?.persistentQuery?.id) {
74
+ store
75
+ .loadQuery(queryId)
76
+ .catch((error) => store.alertService.alertUnhandledError(error));
77
+ }
78
+ }, [store, queryId]);
79
+
80
+ useEffect(() => {
81
+ if (!store.builder && !queryId) {
82
+ store.loader.display.open();
83
+ }
84
+ }, [store, queryId]);
85
+
86
+ if (!builder) {
87
+ return (
88
+ <DataCubePlaceholder
89
+ title="[ Legend DataCube ]"
90
+ layoutManager={store.layoutService.manager}
91
+ taskManager={store.taskService.manager}
92
+ headerContent={<LegendDataCubeQueryBuilderHeader />}
93
+ menuItems={[
94
+ {
95
+ label: 'See Documentation',
96
+ action: () => {
97
+ const url = application.documentationService.url;
98
+ if (url) {
99
+ application.navigationService.navigator.visitAddress(url);
100
+ }
101
+ },
102
+ disabled: true, // TODO: enable when we set up the documentation websit
103
+ },
104
+ ]}
105
+ >
106
+ <div className="h-full w-full p-2">
107
+ <div>Create a new query to start</div>
108
+ <FormButton
109
+ className="mt-1.5"
110
+ onClick={() => store.newQueryState.display.open()}
111
+ >
112
+ New Query
113
+ </FormButton>
114
+ </div>
115
+ </DataCubePlaceholder>
116
+ );
117
+ }
118
+ return (
119
+ <DataCube
120
+ key={builder.uuid} // used as mechanism to reload data-cube component when changing between queries or create/edit mode
121
+ query={builder.query}
122
+ engine={store.baseStore.engine}
123
+ options={{
124
+ layoutManager: store.layoutService.manager,
125
+ taskManager: store.taskService.manager,
126
+ gridClientLicense: store.baseStore.gridClientLicense,
127
+ onInitialized(event) {
128
+ builder.setDataCube(event.api);
129
+ },
130
+ innerHeaderRenderer: () => <LegendDataCubeQueryBuilderHeader />,
131
+ settingsData: {
132
+ configurations: store.baseStore.settings,
133
+ values: application.settingService.getObjectValue(
134
+ LegendDataCubeSettingStorageKey.DATA_CUBE,
135
+ ) as DataCubeSettingValues | undefined,
136
+ },
137
+ onSettingsChanged(values) {
138
+ application.settingService.persistValue(
139
+ LegendDataCubeSettingStorageKey.DATA_CUBE,
140
+ values,
141
+ );
142
+ },
143
+ documentationUrl: application.documentationService.url,
144
+ }}
145
+ />
146
+ );
147
+ }),
148
+ );
@@ -0,0 +1,56 @@
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 { guaranteeNonNullable } from '@finos/legend-shared';
18
+ import { useLocalObservable } from 'mobx-react-lite';
19
+ import { createContext, useContext } from 'react';
20
+ import { LegendDataCubeQueryBuilderStore } from '../../stores/query-builder/LegendDataCubeQueryBuilderStore.js';
21
+ import { useLegendDataCubeBaseStore } from '../LegendDataCubeFrameworkProvider.js';
22
+
23
+ const LegendDataCubeQueryBuilderStoreContext = createContext<
24
+ LegendDataCubeQueryBuilderStore | undefined
25
+ >(undefined);
26
+ const LegendDataCubeQueryBuilderStoreProvider = (props: {
27
+ children: React.ReactNode;
28
+ }) => {
29
+ const { children } = props;
30
+ const baseStore = useLegendDataCubeBaseStore();
31
+ const store = useLocalObservable(
32
+ () => new LegendDataCubeQueryBuilderStore(baseStore),
33
+ );
34
+ return (
35
+ <LegendDataCubeQueryBuilderStoreContext.Provider value={store}>
36
+ {children}
37
+ </LegendDataCubeQueryBuilderStoreContext.Provider>
38
+ );
39
+ };
40
+
41
+ export const useLegendDataCubeQueryBuilderStore = () =>
42
+ guaranteeNonNullable(
43
+ useContext(LegendDataCubeQueryBuilderStoreContext),
44
+ `Can't find query builder store in context`,
45
+ );
46
+
47
+ export const withLegendDataCubeQueryBuilderStore = (
48
+ WrappedComponent: React.FC,
49
+ ) =>
50
+ function WithLegendDataCubeQueryBuilderStore() {
51
+ return (
52
+ <LegendDataCubeQueryBuilderStoreProvider>
53
+ <WrappedComponent />
54
+ </LegendDataCubeQueryBuilderStoreProvider>
55
+ );
56
+ };
@@ -0,0 +1,309 @@
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 { observer } from 'mobx-react-lite';
18
+ import { cn, DataCubeIcon, useDropdownMenu } from '@finos/legend-art';
19
+ import {
20
+ debounce,
21
+ formatDistanceToNow,
22
+ quantifyList,
23
+ } from '@finos/legend-shared';
24
+ import { useRef, useMemo, useEffect } from 'react';
25
+ import {
26
+ FormButton,
27
+ FormCheckbox,
28
+ FormDropdownMenu,
29
+ FormDropdownMenuItem,
30
+ FormDropdownMenuTrigger,
31
+ FormTextInput,
32
+ } from '@finos/legend-data-cube';
33
+ import { useLegendDataCubeQueryBuilderStore } from './LegendDataCubeQueryBuilderStoreProvider.js';
34
+ import {
35
+ DATA_CUBE_QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT,
36
+ DataCubeQuerySortByType,
37
+ } from '../../stores/query-builder/LegendDataCubeQueryLoaderState.js';
38
+
39
+ const LegendDataCubeQuerySearcher = observer(() => {
40
+ const store = useLegendDataCubeQueryBuilderStore();
41
+ const state = store.loader;
42
+
43
+ const searchInputRef = useRef<HTMLInputElement>(null);
44
+ const searchResults = state.queries;
45
+
46
+ useEffect(() => {
47
+ searchInputRef.current?.focus();
48
+ }, [state]);
49
+
50
+ // search text
51
+ const debouncedLoadQueries = useMemo(
52
+ () =>
53
+ debounce((input: string) => {
54
+ state
55
+ .searchQueries(input)
56
+ .catch((error) => store.alertService.alertUnhandledError(error));
57
+ }, 500),
58
+ [store, state],
59
+ );
60
+ const onSearchTextChange: React.ChangeEventHandler<HTMLInputElement> = (
61
+ event,
62
+ ) => {
63
+ if (event.target.value !== state.searchText) {
64
+ state.setSearchText(event.target.value);
65
+ debouncedLoadQueries.cancel();
66
+ debouncedLoadQueries(event.target.value);
67
+ }
68
+ };
69
+ const clearSearches = () => {
70
+ state.setSearchText('');
71
+ debouncedLoadQueries.cancel();
72
+ debouncedLoadQueries('');
73
+ };
74
+
75
+ // filter and sort
76
+ const toggleShowCurrentUserQueriesOnly = () => {
77
+ state.setShowCurrentUserQueriesOnly(!state.showCurrentUserQueriesOnly);
78
+ debouncedLoadQueries.cancel();
79
+ debouncedLoadQueries(state.searchText);
80
+ };
81
+
82
+ const [
83
+ openSortDropdown,
84
+ closeSortDropdown,
85
+ sortDropdownProps,
86
+ sortDropdownPropsOpen,
87
+ ] = useDropdownMenu();
88
+ const applySort = (value: DataCubeQuerySortByType) => {
89
+ state.setSortBy(value);
90
+ debouncedLoadQueries.cancel();
91
+ debouncedLoadQueries(state.searchText);
92
+ };
93
+
94
+ useEffect(() => {
95
+ state
96
+ .searchQueries('')
97
+ .catch((error) => store.alertService.alertUnhandledError(error));
98
+ }, [store, state]);
99
+
100
+ return (
101
+ <div className="h-full">
102
+ <div className="p-1.5">
103
+ <div className="relative flex h-6 w-full items-center justify-between">
104
+ <FormTextInput
105
+ ref={searchInputRef}
106
+ className={cn('h-6 w-full pl-6 pr-1', {
107
+ 'pr-6': Boolean(state.searchText),
108
+ })}
109
+ onChange={onSearchTextChange}
110
+ value={state.searchText}
111
+ placeholder="Search for queries by name or ID"
112
+ />
113
+ <div className="absolute flex aspect-square h-full items-center justify-center">
114
+ <DataCubeIcon.Search className="text-lg text-neutral-600" />
115
+ </div>
116
+ {Boolean(state.searchText) && (
117
+ <>
118
+ <button
119
+ className="absolute right-0 flex aspect-square h-full items-center justify-center"
120
+ tabIndex={-1}
121
+ onClick={clearSearches}
122
+ title="Clear"
123
+ >
124
+ <DataCubeIcon.X />
125
+ </button>
126
+ </>
127
+ )}
128
+ </div>
129
+ <div className="mt-1 flex h-6 w-full items-center">
130
+ <div className="flex w-[calc(100%_-_128px)] items-center">
131
+ <div className="w-10 text-sm">Filters:</div>
132
+ <div className="flex h-6 w-[calc(100%_-_40px)] overflow-x-auto">
133
+ <FormCheckbox
134
+ label="Mine Only"
135
+ checked={state.showCurrentUserQueriesOnly}
136
+ onChange={toggleShowCurrentUserQueriesOnly}
137
+ />
138
+ </div>
139
+ </div>
140
+
141
+ <div>
142
+ <FormDropdownMenuTrigger
143
+ className="w-32"
144
+ onClick={openSortDropdown}
145
+ open={sortDropdownPropsOpen}
146
+ disabled={!state.canPerformAdvancedSearch(state.searchText)}
147
+ >
148
+ Sort by: {state.sortBy}
149
+ </FormDropdownMenuTrigger>
150
+ <FormDropdownMenu className="w-32" {...sortDropdownProps}>
151
+ {Object.values(DataCubeQuerySortByType).map((option) => (
152
+ <FormDropdownMenuItem
153
+ key={option}
154
+ onClick={() => {
155
+ applySort(option);
156
+ closeSortDropdown();
157
+ }}
158
+ autoFocus={option === state.sortBy}
159
+ >
160
+ {option}
161
+ </FormDropdownMenuItem>
162
+ ))}
163
+ </FormDropdownMenu>
164
+ </div>
165
+ </div>
166
+ </div>
167
+ <div className="mx-1.5 mb-1 h-[1px] bg-neutral-200" />
168
+ <div className="h-[calc(100%_-_71px)]">
169
+ <div className="h-full overflow-y-auto">
170
+ {state.searchState.hasCompleted && (
171
+ <>
172
+ <div className="mb-1 flex h-5 w-full items-center px-1.5 text-sm text-neutral-600">
173
+ {state.showingDefaultQueries ? (
174
+ `Refine your search to get better matches`
175
+ ) : searchResults.length >=
176
+ DATA_CUBE_QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT ? (
177
+ <>
178
+ {`Found ${DATA_CUBE_QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT}+ matches`}{' '}
179
+ <DataCubeIcon.AlertInfo
180
+ className="ml-1 text-lg"
181
+ title="Some queries are not listed, refine your search to get better matches"
182
+ />
183
+ </>
184
+ ) : (
185
+ `Found ${quantifyList(searchResults, 'match', 'matches')}`
186
+ )}
187
+ </div>
188
+ {searchResults
189
+ .slice(0, DATA_CUBE_QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT)
190
+ .map((query, idx) => (
191
+ <div
192
+ className="mx-1.5 mb-0.5 flex h-[42px] w-[calc(100%_-_12px)] cursor-pointer border border-neutral-200 bg-neutral-100 hover:bg-neutral-200"
193
+ key={query.id}
194
+ title="Click to choose query"
195
+ onClick={() => state.setSelectedQuery(query)}
196
+ >
197
+ <div className="w-[calc(100%_-_16px)]">
198
+ <div className="h-6 w-4/5 overflow-hidden text-ellipsis whitespace-nowrap px-1.5 leading-6">
199
+ {query.name}
200
+ </div>
201
+ <div className="flex h-[18px] items-start justify-between px-1.5">
202
+ <div className="flex">
203
+ <DataCubeIcon.ClockEdit className="text-sm text-neutral-500" />
204
+ <div className="ml-1 text-sm text-neutral-500">
205
+ {query.lastUpdatedAt
206
+ ? formatDistanceToNow(
207
+ new Date(query.lastUpdatedAt),
208
+ {
209
+ includeSeconds: true,
210
+ addSuffix: true,
211
+ },
212
+ )
213
+ : '(unknown)'}
214
+ </div>
215
+ </div>
216
+ <div className="flex">
217
+ <DataCubeIcon.User className="text-sm text-neutral-500" />
218
+ <div className="ml-1 text-sm text-neutral-500">
219
+ {query.owner}
220
+ </div>
221
+ </div>
222
+ </div>
223
+ </div>
224
+ <div className="flex h-full w-4 items-center justify-center">
225
+ <DataCubeIcon.ChevronRight className="text-neutral-600" />
226
+ </div>
227
+ </div>
228
+ ))}
229
+ </>
230
+ )}
231
+ {!state.searchState.hasCompleted && (
232
+ <div className="mb-1 flex h-5 w-full items-center px-1.5 text-sm text-neutral-600">
233
+ <DataCubeIcon.Loader className="animate-spin stroke-2 text-lg" />
234
+ <span className="ml-1">Searching...</span>
235
+ </div>
236
+ )}
237
+ </div>
238
+ </div>
239
+ </div>
240
+ );
241
+ });
242
+
243
+ export const LegendDataCubeQueryLoader = observer(() => {
244
+ const store = useLegendDataCubeQueryBuilderStore();
245
+ const state = store.loader;
246
+ const query = state.selectedQuery;
247
+
248
+ return (
249
+ <>
250
+ <div className="h-[calc(100%_-_40px)] w-full px-2 pt-2">
251
+ <div className="h-full w-full overflow-auto border border-neutral-300 bg-white">
252
+ {!query ? (
253
+ <LegendDataCubeQuerySearcher />
254
+ ) : (
255
+ <div className="h-full w-full p-1.5">
256
+ <div className="mb-0.5 flex h-[42px] w-full border border-neutral-200 bg-neutral-100">
257
+ <div className="w-full">
258
+ <div className="h-6 w-4/5 overflow-hidden text-ellipsis whitespace-nowrap px-1.5 leading-6">
259
+ {query.name}
260
+ </div>
261
+ <div className="flex h-[18px] items-start justify-between px-1.5">
262
+ <div className="flex">
263
+ <DataCubeIcon.ClockEdit className="text-sm text-neutral-500" />
264
+ <div className="ml-1 text-sm text-neutral-500">
265
+ {query.lastUpdatedAt
266
+ ? formatDistanceToNow(new Date(query.lastUpdatedAt), {
267
+ includeSeconds: true,
268
+ addSuffix: true,
269
+ })
270
+ : '(unknown)'}
271
+ </div>
272
+ </div>
273
+ <div className="flex">
274
+ <DataCubeIcon.User className="text-sm text-neutral-500" />
275
+ <div className="ml-1 text-sm text-neutral-500">
276
+ {query.owner}
277
+ </div>
278
+ </div>
279
+ </div>
280
+ </div>
281
+ </div>
282
+
283
+ <FormButton
284
+ className="mt-1.5"
285
+ onClick={() => state.setSelectedQuery(undefined)}
286
+ >
287
+ Select Another Query
288
+ </FormButton>
289
+ </div>
290
+ )}
291
+ </div>
292
+ </div>
293
+ <div className="flex h-10 items-center justify-end px-2">
294
+ <FormButton onClick={() => state.display.close()}>Cancel</FormButton>
295
+ <FormButton
296
+ className="ml-2"
297
+ disabled={!query || state.finalizeState.isInProgress}
298
+ onClick={() => {
299
+ state
300
+ .finalize()
301
+ .catch((error) => store.alertService.alertUnhandledError(error));
302
+ }}
303
+ >
304
+ OK
305
+ </FormButton>
306
+ </div>
307
+ </>
308
+ );
309
+ });