@finos/legend-application-data-cube 0.2.4 → 0.2.6
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.
- package/README.md +1 -1
- package/lib/__lib__/LegendDataCubeNavigation.d.ts +9 -5
- package/lib/__lib__/LegendDataCubeNavigation.d.ts.map +1 -1
- package/lib/__lib__/LegendDataCubeNavigation.js +9 -5
- package/lib/__lib__/LegendDataCubeNavigation.js.map +1 -1
- package/lib/__lib__/LegendDataCubeUserData.d.ts +2 -2
- package/lib/__lib__/LegendDataCubeUserData.d.ts.map +1 -1
- package/lib/__lib__/LegendDataCubeUserData.js +2 -2
- package/lib/__lib__/LegendDataCubeUserData.js.map +1 -1
- package/lib/application/LegendDataCubeApplicationConfig.d.ts +4 -0
- package/lib/application/LegendDataCubeApplicationConfig.d.ts.map +1 -1
- package/lib/application/LegendDataCubeApplicationConfig.js +5 -0
- package/lib/application/LegendDataCubeApplicationConfig.js.map +1 -1
- package/lib/components/LegendDataCubeBlockingWindow.d.ts +29 -0
- package/lib/components/LegendDataCubeBlockingWindow.d.ts.map +1 -0
- package/lib/components/LegendDataCubeBlockingWindow.js +75 -0
- package/lib/components/LegendDataCubeBlockingWindow.js.map +1 -0
- package/lib/components/LegendDataCubeWebApplication.js +2 -2
- package/lib/components/LegendDataCubeWebApplication.js.map +1 -1
- package/lib/components/builder/LegendDataCubeBuilder.d.ts +20 -0
- package/lib/components/builder/LegendDataCubeBuilder.d.ts.map +1 -0
- package/lib/components/builder/LegendDataCubeBuilder.js +162 -0
- package/lib/components/builder/LegendDataCubeBuilder.js.map +1 -0
- package/lib/components/builder/LegendDataCubeBuilderStoreProvider.d.ts +19 -0
- package/lib/components/builder/LegendDataCubeBuilderStoreProvider.d.ts.map +1 -0
- package/lib/components/builder/LegendDataCubeBuilderStoreProvider.js +34 -0
- package/lib/components/builder/LegendDataCubeBuilderStoreProvider.js.map +1 -0
- package/lib/components/{query-builder/LegendDataCubeQuerySaver.d.ts → builder/LegendDataCubeCreator.d.ts} +2 -2
- package/lib/components/builder/LegendDataCubeCreator.d.ts.map +1 -0
- package/lib/components/{query-builder/LegendDataCubeNewQueryBuilder.js → builder/LegendDataCubeCreator.js} +10 -10
- package/lib/components/builder/LegendDataCubeCreator.js.map +1 -0
- package/lib/components/builder/LegendDataCubeDeleteConfirmation.d.ts +19 -0
- package/lib/components/builder/LegendDataCubeDeleteConfirmation.d.ts.map +1 -0
- package/lib/components/builder/LegendDataCubeDeleteConfirmation.js +43 -0
- package/lib/components/builder/LegendDataCubeDeleteConfirmation.js.map +1 -0
- package/lib/components/{query-builder/LegendDataCubeQueryLoader.d.ts → builder/LegendDataCubeLoader.d.ts} +2 -2
- package/lib/components/builder/LegendDataCubeLoader.d.ts.map +1 -0
- package/lib/components/builder/LegendDataCubeLoader.js +113 -0
- package/lib/components/builder/LegendDataCubeLoader.js.map +1 -0
- package/lib/components/{query-builder/LegendDataCubeNewQueryBuilder.d.ts → builder/LegendDataCubeSaver.d.ts} +2 -2
- package/lib/components/builder/LegendDataCubeSaver.d.ts.map +1 -0
- package/lib/components/builder/LegendDataCubeSaver.js +73 -0
- package/lib/components/builder/LegendDataCubeSaver.js.map +1 -0
- package/lib/components/{query-builder/LegendDataCubeQueryBuilder.d.ts → builder/LegendDataCubeSourceViewer.d.ts} +4 -2
- package/lib/components/builder/LegendDataCubeSourceViewer.d.ts.map +1 -0
- package/lib/components/builder/LegendDataCubeSourceViewer.js +46 -0
- package/lib/components/builder/LegendDataCubeSourceViewer.js.map +1 -0
- package/lib/components/{query-builder/source-builder → builder/source}/AdhocQueryDataCubeSourceBuilder.d.ts +1 -1
- package/lib/components/builder/source/AdhocQueryDataCubeSourceBuilder.d.ts.map +1 -0
- package/lib/components/builder/source/AdhocQueryDataCubeSourceBuilder.js.map +1 -0
- package/lib/components/{query-builder/source-builder → builder/source}/LegendQueryDataCubeSourceBuilder.d.ts +1 -1
- package/lib/components/builder/source/LegendQueryDataCubeSourceBuilder.d.ts.map +1 -0
- package/lib/components/{query-builder/source-builder → builder/source}/LegendQueryDataCubeSourceBuilder.js +13 -13
- package/lib/components/builder/source/LegendQueryDataCubeSourceBuilder.js.map +1 -0
- package/lib/index.css +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/LegendDataCubeCacheManager.d.ts.map +1 -1
- package/lib/stores/LegendDataCubeCacheManager.js +11 -12
- package/lib/stores/LegendDataCubeCacheManager.js.map +1 -1
- package/lib/stores/LegendDataCubeDataCubeEngine.d.ts +1 -1
- package/lib/stores/LegendDataCubeDataCubeEngine.d.ts.map +1 -1
- package/lib/stores/LegendDataCubeDataCubeEngine.js +5 -11
- package/lib/stores/LegendDataCubeDataCubeEngine.js.map +1 -1
- package/lib/stores/builder/LegendDataCubeBuilderStore.d.ts +80 -0
- package/lib/stores/builder/LegendDataCubeBuilderStore.d.ts.map +1 -0
- package/lib/stores/builder/LegendDataCubeBuilderStore.js +353 -0
- package/lib/stores/builder/LegendDataCubeBuilderStore.js.map +1 -0
- package/lib/stores/{query-builder/LegendDataCubeNewQueryState.d.ts → builder/LegendDataCubeCreatorState.d.ts} +5 -5
- package/lib/stores/builder/LegendDataCubeCreatorState.d.ts.map +1 -0
- package/lib/stores/{query-builder/LegendDataCubeNewQueryState.js → builder/LegendDataCubeCreatorState.js} +17 -17
- package/lib/stores/builder/LegendDataCubeCreatorState.js.map +1 -0
- package/lib/stores/{query-builder/LegendDataCubeQueryLoaderState.d.ts → builder/LegendDataCubeLoaderState.d.ts} +20 -20
- package/lib/stores/builder/LegendDataCubeLoaderState.d.ts.map +1 -0
- package/lib/stores/builder/LegendDataCubeLoaderState.js +187 -0
- package/lib/stores/builder/LegendDataCubeLoaderState.js.map +1 -0
- package/lib/stores/builder/source/AdhocQueryDataCubeSourceBuilderState.d.ts.map +1 -0
- package/lib/stores/builder/source/AdhocQueryDataCubeSourceBuilderState.js.map +1 -0
- package/lib/stores/builder/source/LegendDataCubeSourceBuilderState.d.ts.map +1 -0
- package/lib/stores/{query-builder/source-builder → builder/source}/LegendDataCubeSourceBuilderState.js +1 -1
- package/lib/stores/builder/source/LegendDataCubeSourceBuilderState.js.map +1 -0
- package/lib/stores/builder/source/LegendQueryDataCubeSourceBuilderState.d.ts.map +1 -0
- package/lib/stores/builder/source/LegendQueryDataCubeSourceBuilderState.js.map +1 -0
- package/package.json +5 -5
- package/src/__lib__/LegendDataCubeNavigation.ts +15 -7
- package/src/__lib__/LegendDataCubeUserData.ts +2 -2
- package/src/application/LegendDataCubeApplicationConfig.ts +12 -0
- package/src/components/LegendDataCubeBlockingWindow.tsx +120 -0
- package/src/components/LegendDataCubeWebApplication.tsx +3 -3
- package/src/components/builder/LegendDataCubeBuilder.tsx +331 -0
- package/src/components/{query-builder/LegendDataCubeQueryBuilderStoreProvider.tsx → builder/LegendDataCubeBuilderStoreProvider.tsx} +19 -16
- package/src/components/{query-builder/LegendDataCubeNewQueryBuilder.tsx → builder/LegendDataCubeCreator.tsx} +9 -9
- package/src/components/builder/LegendDataCubeDeleteConfirmation.tsx +87 -0
- package/src/components/{query-builder/LegendDataCubeQueryLoader.tsx → builder/LegendDataCubeLoader.tsx} +122 -59
- package/src/components/builder/LegendDataCubeSaver.tsx +184 -0
- package/src/components/builder/LegendDataCubeSourceViewer.tsx +108 -0
- package/src/components/{query-builder/source-builder → builder/source}/AdhocQueryDataCubeSourceBuilder.tsx +1 -1
- package/src/components/{query-builder/source-builder → builder/source}/LegendQueryDataCubeSourceBuilder.tsx +16 -15
- package/src/stores/LegendDataCubeCacheManager.ts +11 -12
- package/src/stores/LegendDataCubeDataCubeEngine.ts +4 -14
- package/src/stores/builder/LegendDataCubeBuilderStore.tsx +516 -0
- package/src/stores/{query-builder/LegendDataCubeNewQueryState.tsx → builder/LegendDataCubeCreatorState.tsx} +23 -21
- package/src/stores/builder/LegendDataCubeLoaderState.tsx +248 -0
- package/src/stores/{query-builder/source-builder → builder/source}/LegendDataCubeSourceBuilderState.ts +1 -1
- package/tsconfig.json +16 -13
- package/lib/components/query-builder/LegendDataCubeNewQueryBuilder.d.ts.map +0 -1
- package/lib/components/query-builder/LegendDataCubeNewQueryBuilder.js.map +0 -1
- package/lib/components/query-builder/LegendDataCubeQueryBuilder.d.ts.map +0 -1
- package/lib/components/query-builder/LegendDataCubeQueryBuilder.js +0 -93
- package/lib/components/query-builder/LegendDataCubeQueryBuilder.js.map +0 -1
- package/lib/components/query-builder/LegendDataCubeQueryBuilderStoreProvider.d.ts +0 -19
- package/lib/components/query-builder/LegendDataCubeQueryBuilderStoreProvider.d.ts.map +0 -1
- package/lib/components/query-builder/LegendDataCubeQueryBuilderStoreProvider.js +0 -33
- package/lib/components/query-builder/LegendDataCubeQueryBuilderStoreProvider.js.map +0 -1
- package/lib/components/query-builder/LegendDataCubeQueryLoader.d.ts.map +0 -1
- package/lib/components/query-builder/LegendDataCubeQueryLoader.js +0 -97
- package/lib/components/query-builder/LegendDataCubeQueryLoader.js.map +0 -1
- package/lib/components/query-builder/LegendDataCubeQuerySaver.d.ts.map +0 -1
- package/lib/components/query-builder/LegendDataCubeQuerySaver.js +0 -51
- package/lib/components/query-builder/LegendDataCubeQuerySaver.js.map +0 -1
- package/lib/components/query-builder/source-builder/AdhocQueryDataCubeSourceBuilder.d.ts.map +0 -1
- package/lib/components/query-builder/source-builder/AdhocQueryDataCubeSourceBuilder.js.map +0 -1
- package/lib/components/query-builder/source-builder/LegendQueryDataCubeSourceBuilder.d.ts.map +0 -1
- package/lib/components/query-builder/source-builder/LegendQueryDataCubeSourceBuilder.js.map +0 -1
- package/lib/stores/query-builder/LegendDataCubeNewQueryState.d.ts.map +0 -1
- package/lib/stores/query-builder/LegendDataCubeNewQueryState.js.map +0 -1
- package/lib/stores/query-builder/LegendDataCubeQueryBuilderStore.d.ts +0 -58
- package/lib/stores/query-builder/LegendDataCubeQueryBuilderStore.d.ts.map +0 -1
- package/lib/stores/query-builder/LegendDataCubeQueryBuilderStore.js +0 -228
- package/lib/stores/query-builder/LegendDataCubeQueryBuilderStore.js.map +0 -1
- package/lib/stores/query-builder/LegendDataCubeQueryLoaderState.d.ts.map +0 -1
- package/lib/stores/query-builder/LegendDataCubeQueryLoaderState.js +0 -198
- package/lib/stores/query-builder/LegendDataCubeQueryLoaderState.js.map +0 -1
- package/lib/stores/query-builder/source-builder/AdhocQueryDataCubeSourceBuilderState.d.ts.map +0 -1
- package/lib/stores/query-builder/source-builder/AdhocQueryDataCubeSourceBuilderState.js.map +0 -1
- package/lib/stores/query-builder/source-builder/LegendDataCubeSourceBuilderState.d.ts.map +0 -1
- package/lib/stores/query-builder/source-builder/LegendDataCubeSourceBuilderState.js.map +0 -1
- package/lib/stores/query-builder/source-builder/LegendQueryDataCubeSourceBuilderState.d.ts.map +0 -1
- package/lib/stores/query-builder/source-builder/LegendQueryDataCubeSourceBuilderState.js.map +0 -1
- package/src/components/query-builder/LegendDataCubeQueryBuilder.tsx +0 -164
- package/src/components/query-builder/LegendDataCubeQuerySaver.tsx +0 -116
- package/src/stores/query-builder/LegendDataCubeQueryBuilderStore.tsx +0 -323
- package/src/stores/query-builder/LegendDataCubeQueryLoaderState.tsx +0 -260
- /package/lib/components/{query-builder/source-builder → builder/source}/AdhocQueryDataCubeSourceBuilder.js +0 -0
- /package/lib/stores/{query-builder/source-builder → builder/source}/AdhocQueryDataCubeSourceBuilderState.d.ts +0 -0
- /package/lib/stores/{query-builder/source-builder → builder/source}/AdhocQueryDataCubeSourceBuilderState.js +0 -0
- /package/lib/stores/{query-builder/source-builder → builder/source}/LegendDataCubeSourceBuilderState.d.ts +0 -0
- /package/lib/stores/{query-builder/source-builder → builder/source}/LegendQueryDataCubeSourceBuilderState.d.ts +0 -0
- /package/lib/stores/{query-builder/source-builder → builder/source}/LegendQueryDataCubeSourceBuilderState.js +0 -0
- /package/src/stores/{query-builder/source-builder → builder/source}/AdhocQueryDataCubeSourceBuilderState.ts +0 -0
- /package/src/stores/{query-builder/source-builder → builder/source}/LegendQueryDataCubeSourceBuilderState.ts +0 -0
|
@@ -15,7 +15,13 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { observer } from 'mobx-react-lite';
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
cn,
|
|
20
|
+
DataCubeIcon,
|
|
21
|
+
DropdownMenu,
|
|
22
|
+
DropdownMenuItem,
|
|
23
|
+
useDropdownMenu,
|
|
24
|
+
} from '@finos/legend-art';
|
|
19
25
|
import {
|
|
20
26
|
debounce,
|
|
21
27
|
formatDistanceToNow,
|
|
@@ -30,29 +36,30 @@ import {
|
|
|
30
36
|
FormDropdownMenuTrigger,
|
|
31
37
|
FormTextInput,
|
|
32
38
|
} from '@finos/legend-data-cube';
|
|
33
|
-
import {
|
|
39
|
+
import { useLegendDataCubeBuilderStore } from './LegendDataCubeBuilderStoreProvider.js';
|
|
34
40
|
import {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
} from '../../stores/
|
|
41
|
+
DATA_CUBE_LOADER_TYPEAHEAD_SEARCH_LIMIT,
|
|
42
|
+
DataCubeSortByType,
|
|
43
|
+
} from '../../stores/builder/LegendDataCubeLoaderState.js';
|
|
44
|
+
import { useApplicationStore } from '@finos/legend-application';
|
|
38
45
|
|
|
39
|
-
const
|
|
40
|
-
const store =
|
|
46
|
+
const LegendDataCubeSearcher = observer(() => {
|
|
47
|
+
const store = useLegendDataCubeBuilderStore();
|
|
41
48
|
const state = store.loader;
|
|
42
49
|
|
|
43
50
|
const searchInputRef = useRef<HTMLInputElement>(null);
|
|
44
|
-
const searchResults = state.
|
|
51
|
+
const searchResults = state.searchResults;
|
|
45
52
|
|
|
46
53
|
useEffect(() => {
|
|
47
54
|
searchInputRef.current?.focus();
|
|
48
55
|
}, [state]);
|
|
49
56
|
|
|
50
57
|
// search text
|
|
51
|
-
const
|
|
58
|
+
const debouncedLoader = useMemo(
|
|
52
59
|
() =>
|
|
53
60
|
debounce((input: string) => {
|
|
54
61
|
state
|
|
55
|
-
.
|
|
62
|
+
.searchDataCubes(input)
|
|
56
63
|
.catch((error) => store.alertService.alertUnhandledError(error));
|
|
57
64
|
}, 500),
|
|
58
65
|
[store, state],
|
|
@@ -62,21 +69,21 @@ const LegendDataCubeQuerySearcher = observer(() => {
|
|
|
62
69
|
) => {
|
|
63
70
|
if (event.target.value !== state.searchText) {
|
|
64
71
|
state.setSearchText(event.target.value);
|
|
65
|
-
|
|
66
|
-
|
|
72
|
+
debouncedLoader.cancel();
|
|
73
|
+
debouncedLoader(event.target.value);
|
|
67
74
|
}
|
|
68
75
|
};
|
|
69
76
|
const clearSearches = () => {
|
|
70
77
|
state.setSearchText('');
|
|
71
|
-
|
|
72
|
-
|
|
78
|
+
debouncedLoader.cancel();
|
|
79
|
+
debouncedLoader('');
|
|
73
80
|
};
|
|
74
81
|
|
|
75
82
|
// filter and sort
|
|
76
|
-
const
|
|
77
|
-
state.
|
|
78
|
-
|
|
79
|
-
|
|
83
|
+
const toggleShowCurrentUserResultsOnly = () => {
|
|
84
|
+
state.setShowCurrentUserResultsOnly(!state.showCurrentUserResultsOnly);
|
|
85
|
+
debouncedLoader.cancel();
|
|
86
|
+
debouncedLoader(state.searchText);
|
|
80
87
|
};
|
|
81
88
|
|
|
82
89
|
const [
|
|
@@ -85,15 +92,15 @@ const LegendDataCubeQuerySearcher = observer(() => {
|
|
|
85
92
|
sortDropdownProps,
|
|
86
93
|
sortDropdownPropsOpen,
|
|
87
94
|
] = useDropdownMenu();
|
|
88
|
-
const applySort = (value:
|
|
95
|
+
const applySort = (value: DataCubeSortByType) => {
|
|
89
96
|
state.setSortBy(value);
|
|
90
|
-
|
|
91
|
-
|
|
97
|
+
debouncedLoader.cancel();
|
|
98
|
+
debouncedLoader(state.searchText);
|
|
92
99
|
};
|
|
93
100
|
|
|
94
101
|
useEffect(() => {
|
|
95
102
|
state
|
|
96
|
-
.
|
|
103
|
+
.searchDataCubes('')
|
|
97
104
|
.catch((error) => store.alertService.alertUnhandledError(error));
|
|
98
105
|
}, [store, state]);
|
|
99
106
|
|
|
@@ -108,7 +115,7 @@ const LegendDataCubeQuerySearcher = observer(() => {
|
|
|
108
115
|
})}
|
|
109
116
|
onChange={onSearchTextChange}
|
|
110
117
|
value={state.searchText}
|
|
111
|
-
placeholder="Search for
|
|
118
|
+
placeholder="Search for DataCube(s) by name or ID"
|
|
112
119
|
/>
|
|
113
120
|
<div className="absolute flex aspect-square h-full items-center justify-center">
|
|
114
121
|
<DataCubeIcon.Search className="text-lg text-neutral-600" />
|
|
@@ -132,8 +139,8 @@ const LegendDataCubeQuerySearcher = observer(() => {
|
|
|
132
139
|
<div className="flex h-6 w-[calc(100%_-_40px)] overflow-x-auto">
|
|
133
140
|
<FormCheckbox
|
|
134
141
|
label="Mine Only"
|
|
135
|
-
checked={state.
|
|
136
|
-
onChange={
|
|
142
|
+
checked={state.showCurrentUserResultsOnly}
|
|
143
|
+
onChange={toggleShowCurrentUserResultsOnly}
|
|
137
144
|
/>
|
|
138
145
|
</div>
|
|
139
146
|
</div>
|
|
@@ -148,7 +155,7 @@ const LegendDataCubeQuerySearcher = observer(() => {
|
|
|
148
155
|
Sort by: {state.sortBy}
|
|
149
156
|
</FormDropdownMenuTrigger>
|
|
150
157
|
<FormDropdownMenu className="w-32" {...sortDropdownProps}>
|
|
151
|
-
{Object.values(
|
|
158
|
+
{Object.values(DataCubeSortByType).map((option) => (
|
|
152
159
|
<FormDropdownMenuItem
|
|
153
160
|
key={option}
|
|
154
161
|
onClick={() => {
|
|
@@ -170,15 +177,15 @@ const LegendDataCubeQuerySearcher = observer(() => {
|
|
|
170
177
|
{state.searchState.hasCompleted && (
|
|
171
178
|
<>
|
|
172
179
|
<div className="mb-1 flex h-5 w-full items-center px-1.5 text-sm text-neutral-600">
|
|
173
|
-
{state.
|
|
180
|
+
{state.showingDefaultResults ? (
|
|
174
181
|
`Refine your search to get better matches`
|
|
175
182
|
) : searchResults.length >=
|
|
176
|
-
|
|
183
|
+
DATA_CUBE_LOADER_TYPEAHEAD_SEARCH_LIMIT ? (
|
|
177
184
|
<>
|
|
178
|
-
{`Found ${
|
|
185
|
+
{`Found ${DATA_CUBE_LOADER_TYPEAHEAD_SEARCH_LIMIT}+ matches`}{' '}
|
|
179
186
|
<DataCubeIcon.AlertInfo
|
|
180
187
|
className="ml-1 text-lg"
|
|
181
|
-
title="Some
|
|
188
|
+
title="Some DataCubes are not listed, refine your search to get better matches"
|
|
182
189
|
/>
|
|
183
190
|
</>
|
|
184
191
|
) : (
|
|
@@ -186,25 +193,25 @@ const LegendDataCubeQuerySearcher = observer(() => {
|
|
|
186
193
|
)}
|
|
187
194
|
</div>
|
|
188
195
|
{searchResults
|
|
189
|
-
.slice(0,
|
|
190
|
-
.map((
|
|
196
|
+
.slice(0, DATA_CUBE_LOADER_TYPEAHEAD_SEARCH_LIMIT)
|
|
197
|
+
.map((result, idx) => (
|
|
191
198
|
<div
|
|
192
199
|
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={
|
|
194
|
-
title="Click to choose
|
|
195
|
-
onClick={() => state.
|
|
200
|
+
key={result.id}
|
|
201
|
+
title="Click to choose DataCube"
|
|
202
|
+
onClick={() => state.setSelectedResult(result)}
|
|
196
203
|
>
|
|
197
204
|
<div className="w-[calc(100%_-_16px)]">
|
|
198
205
|
<div className="h-6 w-4/5 overflow-hidden text-ellipsis whitespace-nowrap px-1.5 leading-6">
|
|
199
|
-
{
|
|
206
|
+
{result.name}
|
|
200
207
|
</div>
|
|
201
208
|
<div className="flex h-[18px] items-start justify-between px-1.5">
|
|
202
209
|
<div className="flex">
|
|
203
210
|
<DataCubeIcon.ClockEdit className="text-sm text-neutral-500" />
|
|
204
211
|
<div className="ml-1 text-sm text-neutral-500">
|
|
205
|
-
{
|
|
212
|
+
{result.lastUpdatedAt
|
|
206
213
|
? formatDistanceToNow(
|
|
207
|
-
new Date(
|
|
214
|
+
new Date(result.lastUpdatedAt),
|
|
208
215
|
{
|
|
209
216
|
includeSeconds: true,
|
|
210
217
|
addSuffix: true,
|
|
@@ -216,7 +223,7 @@ const LegendDataCubeQuerySearcher = observer(() => {
|
|
|
216
223
|
<div className="flex">
|
|
217
224
|
<DataCubeIcon.User className="text-sm text-neutral-500" />
|
|
218
225
|
<div className="ml-1 text-sm text-neutral-500">
|
|
219
|
-
{
|
|
226
|
+
{result.owner}
|
|
220
227
|
</div>
|
|
221
228
|
</div>
|
|
222
229
|
</div>
|
|
@@ -240,52 +247,108 @@ const LegendDataCubeQuerySearcher = observer(() => {
|
|
|
240
247
|
);
|
|
241
248
|
});
|
|
242
249
|
|
|
243
|
-
export const
|
|
244
|
-
const store =
|
|
250
|
+
export const LegendDataCubeLoader = observer(() => {
|
|
251
|
+
const store = useLegendDataCubeBuilderStore();
|
|
252
|
+
const application = useApplicationStore();
|
|
245
253
|
const state = store.loader;
|
|
246
|
-
const
|
|
254
|
+
const selectedResult = state.selectedResult;
|
|
255
|
+
const [openManageDropdown, closeManageDropdown, manageDropdownProps] =
|
|
256
|
+
useDropdownMenu();
|
|
247
257
|
|
|
248
258
|
return (
|
|
249
259
|
<>
|
|
250
260
|
<div className="h-[calc(100%_-_40px)] w-full px-2 pt-2">
|
|
251
261
|
<div className="h-full w-full overflow-auto border border-neutral-300 bg-white">
|
|
252
|
-
{!
|
|
253
|
-
<
|
|
262
|
+
{!selectedResult ? (
|
|
263
|
+
<LegendDataCubeSearcher />
|
|
254
264
|
) : (
|
|
255
265
|
<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">
|
|
266
|
+
<div className="relative mb-0.5 flex h-[42px] w-full border border-neutral-200 bg-neutral-100">
|
|
257
267
|
<div className="w-full">
|
|
258
268
|
<div className="h-6 w-4/5 overflow-hidden text-ellipsis whitespace-nowrap px-1.5 leading-6">
|
|
259
|
-
{
|
|
269
|
+
{selectedResult.name}
|
|
260
270
|
</div>
|
|
271
|
+
<button
|
|
272
|
+
className="absolute right-0.5 top-0.5 flex aspect-square w-5 items-center justify-center text-neutral-500"
|
|
273
|
+
title="Copy ID to clipboard"
|
|
274
|
+
onClick={() => {
|
|
275
|
+
application.clipboardService
|
|
276
|
+
.copyTextToClipboard(selectedResult.id)
|
|
277
|
+
.catch((error) =>
|
|
278
|
+
store.alertService.alertUnhandledError(error),
|
|
279
|
+
);
|
|
280
|
+
}}
|
|
281
|
+
>
|
|
282
|
+
<DataCubeIcon.Clipboard />
|
|
283
|
+
</button>
|
|
261
284
|
<div className="flex h-[18px] items-start justify-between px-1.5">
|
|
262
285
|
<div className="flex">
|
|
263
286
|
<DataCubeIcon.ClockEdit className="text-sm text-neutral-500" />
|
|
264
287
|
<div className="ml-1 text-sm text-neutral-500">
|
|
265
|
-
{
|
|
266
|
-
? formatDistanceToNow(
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
288
|
+
{selectedResult.lastUpdatedAt
|
|
289
|
+
? formatDistanceToNow(
|
|
290
|
+
new Date(selectedResult.lastUpdatedAt),
|
|
291
|
+
{
|
|
292
|
+
includeSeconds: true,
|
|
293
|
+
addSuffix: true,
|
|
294
|
+
},
|
|
295
|
+
)
|
|
270
296
|
: '(unknown)'}
|
|
271
297
|
</div>
|
|
272
298
|
</div>
|
|
273
299
|
<div className="flex">
|
|
274
300
|
<DataCubeIcon.User className="text-sm text-neutral-500" />
|
|
275
301
|
<div className="ml-1 text-sm text-neutral-500">
|
|
276
|
-
{
|
|
302
|
+
{selectedResult.owner}
|
|
277
303
|
</div>
|
|
278
304
|
</div>
|
|
279
305
|
</div>
|
|
280
306
|
</div>
|
|
281
307
|
</div>
|
|
282
308
|
|
|
283
|
-
<
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
309
|
+
<div className="mt-1.5 flex justify-between">
|
|
310
|
+
<FormButton
|
|
311
|
+
className="flex items-center pl-1"
|
|
312
|
+
onClick={() => state.setSelectedResult(undefined)}
|
|
313
|
+
>
|
|
314
|
+
<DataCubeIcon.ChevronLeft className="mr-0.5" />
|
|
315
|
+
Go Back
|
|
316
|
+
</FormButton>
|
|
317
|
+
|
|
318
|
+
{store.canCurrentUserManageDataCube(selectedResult) && (
|
|
319
|
+
<>
|
|
320
|
+
<FormButton
|
|
321
|
+
className="flex w-[138px] items-center justify-start px-0"
|
|
322
|
+
onClick={openManageDropdown}
|
|
323
|
+
>
|
|
324
|
+
<div className="px-2.5">Manage DataCube</div>
|
|
325
|
+
<div className="flex h-4 w-4 items-center justify-center border-l border-neutral-400">
|
|
326
|
+
<DataCubeIcon.CaretDown className="text-sm" />
|
|
327
|
+
</div>
|
|
328
|
+
</FormButton>
|
|
329
|
+
<DropdownMenu
|
|
330
|
+
{...manageDropdownProps}
|
|
331
|
+
menuProps={{
|
|
332
|
+
classes: {
|
|
333
|
+
paper: 'rounded-none mt-[1px]',
|
|
334
|
+
list: 'w-[138px] p-0 rounded-none border border-neutral-400 bg-white max-h-40 overflow-y-auto py-0.5',
|
|
335
|
+
},
|
|
336
|
+
}}
|
|
337
|
+
>
|
|
338
|
+
<DropdownMenuItem
|
|
339
|
+
className="flex h-[22px] w-full items-center px-2.5 text-base hover:bg-neutral-100 focus:bg-neutral-100"
|
|
340
|
+
onClick={() => {
|
|
341
|
+
store.setDataCubeToDelete(selectedResult);
|
|
342
|
+
store.deleteConfirmationDisplay.open();
|
|
343
|
+
closeManageDropdown();
|
|
344
|
+
}}
|
|
345
|
+
>
|
|
346
|
+
Delete...
|
|
347
|
+
</DropdownMenuItem>
|
|
348
|
+
</DropdownMenu>
|
|
349
|
+
</>
|
|
350
|
+
)}
|
|
351
|
+
</div>
|
|
289
352
|
</div>
|
|
290
353
|
)}
|
|
291
354
|
</div>
|
|
@@ -294,7 +357,7 @@ export const LegendDataCubeQueryLoader = observer(() => {
|
|
|
294
357
|
<FormButton onClick={() => state.display.close()}>Cancel</FormButton>
|
|
295
358
|
<FormButton
|
|
296
359
|
className="ml-2"
|
|
297
|
-
disabled={!
|
|
360
|
+
disabled={!selectedResult || state.finalizeState.isInProgress}
|
|
298
361
|
onClick={() => {
|
|
299
362
|
state
|
|
300
363
|
.finalize()
|
|
@@ -0,0 +1,184 @@
|
|
|
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
|
+
DataCubeSpecification,
|
|
19
|
+
DEFAULT_REPORT_NAME,
|
|
20
|
+
FormBadge_Advanced,
|
|
21
|
+
FormButton,
|
|
22
|
+
FormCheckbox,
|
|
23
|
+
FormTextInput,
|
|
24
|
+
} from '@finos/legend-data-cube';
|
|
25
|
+
import { observer } from 'mobx-react-lite';
|
|
26
|
+
import { useEffect, useState } from 'react';
|
|
27
|
+
import { useLegendDataCubeBuilderStore } from './LegendDataCubeBuilderStoreProvider.js';
|
|
28
|
+
import { guaranteeNonNullable, returnUndefOnError } from '@finos/legend-shared';
|
|
29
|
+
|
|
30
|
+
export const LegendDataCubeSaver = observer(() => {
|
|
31
|
+
const [name, setName] = useState(DEFAULT_REPORT_NAME);
|
|
32
|
+
const [syncName, setSyncName] = useState(false);
|
|
33
|
+
const [autoEnableCache, setAutoEnableCache] = useState(false);
|
|
34
|
+
const [showAdvancedSettings, setShowAdvancedSettings] = useState(false);
|
|
35
|
+
const store = useLegendDataCubeBuilderStore();
|
|
36
|
+
const builder = guaranteeNonNullable(store.builder);
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
const persistentDataCube = builder.persistentDataCube;
|
|
40
|
+
const latestSpecification = persistentDataCube
|
|
41
|
+
? returnUndefOnError(() =>
|
|
42
|
+
DataCubeSpecification.serialization.fromJson(
|
|
43
|
+
persistentDataCube.content,
|
|
44
|
+
),
|
|
45
|
+
)
|
|
46
|
+
: undefined;
|
|
47
|
+
|
|
48
|
+
setName(
|
|
49
|
+
persistentDataCube?.name ??
|
|
50
|
+
builder.initialSpecification.configuration?.name ??
|
|
51
|
+
DEFAULT_REPORT_NAME,
|
|
52
|
+
);
|
|
53
|
+
setSyncName(false);
|
|
54
|
+
setAutoEnableCache(latestSpecification?.options?.autoEnableCache ?? false);
|
|
55
|
+
}, [builder]);
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<>
|
|
59
|
+
<div className="h-[calc(100%_-_40px)] w-full px-2 pt-2">
|
|
60
|
+
<div className="h-full w-full overflow-auto border border-neutral-300 bg-white">
|
|
61
|
+
<div className="h-full w-full select-none p-2">
|
|
62
|
+
<div className="flex h-5 w-full items-center">
|
|
63
|
+
<div className="flex h-full w-20 flex-shrink-0 items-center text-sm">
|
|
64
|
+
Name:
|
|
65
|
+
</div>
|
|
66
|
+
<FormTextInput
|
|
67
|
+
className="w-80"
|
|
68
|
+
value={name}
|
|
69
|
+
onChange={(event) => {
|
|
70
|
+
setName(event.target.value);
|
|
71
|
+
}}
|
|
72
|
+
autoFocus={true}
|
|
73
|
+
/>
|
|
74
|
+
</div>
|
|
75
|
+
<div className="mt-2 flex h-5 w-full items-center">
|
|
76
|
+
<div className="flex h-full w-20 flex-shrink-0" />
|
|
77
|
+
<FormCheckbox
|
|
78
|
+
label="Ensure report name is in sync with DataCube name"
|
|
79
|
+
checked={syncName}
|
|
80
|
+
onChange={() => setSyncName(!syncName)}
|
|
81
|
+
/>
|
|
82
|
+
</div>
|
|
83
|
+
{showAdvancedSettings && (
|
|
84
|
+
<>
|
|
85
|
+
<div className="my-2 h-[1px] w-full bg-neutral-200" />
|
|
86
|
+
<div className="mt-2 flex h-5 w-full items-center">
|
|
87
|
+
<div className="flex h-full w-20 flex-shrink-0 items-center text-sm">
|
|
88
|
+
Caching:
|
|
89
|
+
</div>
|
|
90
|
+
<FormCheckbox
|
|
91
|
+
label="Auto-enable caching"
|
|
92
|
+
checked={autoEnableCache}
|
|
93
|
+
onChange={() => setAutoEnableCache(!autoEnableCache)}
|
|
94
|
+
/>
|
|
95
|
+
<FormBadge_Advanced />
|
|
96
|
+
</div>
|
|
97
|
+
</>
|
|
98
|
+
)}
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
<div className="flex h-10 items-center justify-between px-2">
|
|
103
|
+
<div className="flex h-full items-center pl-1">
|
|
104
|
+
<FormCheckbox
|
|
105
|
+
label="Show advanced settings?"
|
|
106
|
+
checked={showAdvancedSettings}
|
|
107
|
+
onChange={() => setShowAdvancedSettings(!showAdvancedSettings)}
|
|
108
|
+
/>
|
|
109
|
+
<FormBadge_Advanced />
|
|
110
|
+
</div>
|
|
111
|
+
<div className="flex">
|
|
112
|
+
<FormButton onClick={() => store.saverDisplay.close()}>
|
|
113
|
+
Cancel
|
|
114
|
+
</FormButton>
|
|
115
|
+
{builder.persistentDataCube ? (
|
|
116
|
+
// updating existing DataCube
|
|
117
|
+
<>
|
|
118
|
+
<FormButton
|
|
119
|
+
className="ml-2"
|
|
120
|
+
disabled={
|
|
121
|
+
!builder.dataCube ||
|
|
122
|
+
store.saveState.isInProgress ||
|
|
123
|
+
!store.canCurrentUserManageDataCube(
|
|
124
|
+
builder.persistentDataCube,
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
onClick={() => {
|
|
128
|
+
store
|
|
129
|
+
.saveDataCube(name, {
|
|
130
|
+
syncName,
|
|
131
|
+
autoEnableCache,
|
|
132
|
+
saveAsNew: false,
|
|
133
|
+
})
|
|
134
|
+
.catch((error) =>
|
|
135
|
+
store.alertService.alertUnhandledError(error),
|
|
136
|
+
);
|
|
137
|
+
}}
|
|
138
|
+
>
|
|
139
|
+
Save
|
|
140
|
+
</FormButton>
|
|
141
|
+
<FormButton
|
|
142
|
+
className="ml-2"
|
|
143
|
+
disabled={!builder.dataCube || store.saveState.isInProgress}
|
|
144
|
+
onClick={() => {
|
|
145
|
+
store
|
|
146
|
+
.saveDataCube(name, {
|
|
147
|
+
syncName,
|
|
148
|
+
autoEnableCache,
|
|
149
|
+
saveAsNew: true,
|
|
150
|
+
})
|
|
151
|
+
.catch((error) =>
|
|
152
|
+
store.alertService.alertUnhandledError(error),
|
|
153
|
+
);
|
|
154
|
+
}}
|
|
155
|
+
>
|
|
156
|
+
Save As
|
|
157
|
+
</FormButton>
|
|
158
|
+
</>
|
|
159
|
+
) : (
|
|
160
|
+
// creating new DataCube
|
|
161
|
+
<>
|
|
162
|
+
<FormButton
|
|
163
|
+
className="ml-2"
|
|
164
|
+
disabled={!builder.dataCube || store.saveState.isInProgress}
|
|
165
|
+
onClick={() => {
|
|
166
|
+
store
|
|
167
|
+
.createNewDataCube(name, {
|
|
168
|
+
syncName,
|
|
169
|
+
autoEnableCache,
|
|
170
|
+
})
|
|
171
|
+
.catch((error) =>
|
|
172
|
+
store.alertService.alertUnhandledError(error),
|
|
173
|
+
);
|
|
174
|
+
}}
|
|
175
|
+
>
|
|
176
|
+
Save
|
|
177
|
+
</FormButton>
|
|
178
|
+
</>
|
|
179
|
+
)}
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
</>
|
|
183
|
+
);
|
|
184
|
+
});
|
|
@@ -0,0 +1,108 @@
|
|
|
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 { useLegendDataCubeBuilderStore } from './LegendDataCubeBuilderStoreProvider.js';
|
|
19
|
+
import { LegendQueryDataCubeSource } from '../../stores/model/LegendQueryDataCubeSource.js';
|
|
20
|
+
import { useLegendDataCubeApplicationStore } from '../LegendDataCubeFrameworkProvider.js';
|
|
21
|
+
import { EXTERNAL_APPLICATION_NAVIGATION__generateQueryViewUrl } from '../../__lib__/LegendDataCubeNavigation.js';
|
|
22
|
+
import { DataCubeIcon } from '@finos/legend-art';
|
|
23
|
+
|
|
24
|
+
export const LegendDataCubeSourceViewer = observer(() => {
|
|
25
|
+
const store = useLegendDataCubeBuilderStore();
|
|
26
|
+
const source = store.builder?.source;
|
|
27
|
+
const application = useLegendDataCubeApplicationStore();
|
|
28
|
+
|
|
29
|
+
if (!source) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
if (source instanceof LegendQueryDataCubeSource) {
|
|
33
|
+
const link = application.config.queryApplicationUrl
|
|
34
|
+
? EXTERNAL_APPLICATION_NAVIGATION__generateQueryViewUrl(
|
|
35
|
+
application.config.queryApplicationUrl,
|
|
36
|
+
source.info.id,
|
|
37
|
+
)
|
|
38
|
+
: undefined;
|
|
39
|
+
return (
|
|
40
|
+
<div className="h-full w-full px-2 pt-2">
|
|
41
|
+
<div className="h-[calc(100%_-_8px)] w-full border border-neutral-300 bg-white">
|
|
42
|
+
<div className="h-full w-full select-none p-2">
|
|
43
|
+
<div className="flex h-6">
|
|
44
|
+
<div className="flex h-6 items-center text-xl font-medium">
|
|
45
|
+
<DataCubeIcon.Table />
|
|
46
|
+
</div>
|
|
47
|
+
<div className="ml-1 flex h-6 items-center text-xl font-medium">
|
|
48
|
+
Legend Query
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
{link && (
|
|
52
|
+
<div className="mt-2 flex h-6 w-full">
|
|
53
|
+
<div className="flex h-full w-[calc(100%_-_20px)] items-center border border-r-0 border-neutral-400 px-1.5 font-bold text-sky-500 underline">
|
|
54
|
+
<a
|
|
55
|
+
href={link}
|
|
56
|
+
target="_blank"
|
|
57
|
+
rel="noopener noreferrer"
|
|
58
|
+
className="overflow-hidden overflow-ellipsis whitespace-nowrap"
|
|
59
|
+
>
|
|
60
|
+
{link}
|
|
61
|
+
</a>
|
|
62
|
+
</div>
|
|
63
|
+
<button
|
|
64
|
+
className="flex aspect-square h-full w-6 items-center justify-center border border-neutral-400 bg-neutral-300 hover:brightness-95"
|
|
65
|
+
onClick={() => {
|
|
66
|
+
store.application.clipboardService
|
|
67
|
+
.copyTextToClipboard(link)
|
|
68
|
+
.catch((error) =>
|
|
69
|
+
store.alertService.alertUnhandledError(error),
|
|
70
|
+
);
|
|
71
|
+
}}
|
|
72
|
+
title="Copy Link"
|
|
73
|
+
>
|
|
74
|
+
<DataCubeIcon.Clipboard />
|
|
75
|
+
</button>
|
|
76
|
+
</div>
|
|
77
|
+
)}
|
|
78
|
+
{!link && (
|
|
79
|
+
<div className="mt-2 flex h-6 w-full">
|
|
80
|
+
<div className="flex h-full w-[calc(100%_-_20px)] items-center border border-r-0 border-neutral-400 bg-neutral-200 px-1.5">
|
|
81
|
+
<div className="overflow-hidden overflow-ellipsis whitespace-nowrap">
|
|
82
|
+
{source.info.id}
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
<button
|
|
86
|
+
className="flex aspect-square h-full w-6 items-center justify-center border border-neutral-400 bg-neutral-300 hover:brightness-95"
|
|
87
|
+
onClick={() => {
|
|
88
|
+
application.clipboardService
|
|
89
|
+
.copyTextToClipboard(source.info.id)
|
|
90
|
+
.catch((error) =>
|
|
91
|
+
store.alertService.alertUnhandledError(error),
|
|
92
|
+
);
|
|
93
|
+
}}
|
|
94
|
+
title="Copy ID"
|
|
95
|
+
>
|
|
96
|
+
<DataCubeIcon.Clipboard />
|
|
97
|
+
</button>
|
|
98
|
+
</div>
|
|
99
|
+
)}
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
return (
|
|
106
|
+
<div className="h-full w-full px-2 pt-2">{`Can't display source`}</div>
|
|
107
|
+
);
|
|
108
|
+
});
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { observer } from 'mobx-react-lite';
|
|
18
|
-
import type { AdhocQueryDataCubeSourceBuilderState } from '../../../stores/
|
|
18
|
+
import type { AdhocQueryDataCubeSourceBuilderState } from '../../../stores/builder/source/AdhocQueryDataCubeSourceBuilderState.js';
|
|
19
19
|
import { FormBadge_WIP } from '@finos/legend-data-cube';
|
|
20
20
|
|
|
21
21
|
export const AdhocQueryDataCubeSourceBuilder = observer(
|