@finos/legend-application-query 8.1.3 → 9.0.0
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/lib/application/LegendQuery.d.ts.map +1 -1
- package/lib/application/LegendQuery.js +7 -9
- package/lib/application/LegendQuery.js.map +1 -1
- package/lib/application/LegendQueryApplicationConfig.d.ts +4 -0
- package/lib/application/LegendQueryApplicationConfig.d.ts.map +1 -1
- package/lib/application/LegendQueryApplicationConfig.js +4 -0
- package/lib/application/LegendQueryApplicationConfig.js.map +1 -1
- package/lib/components/{QuerySetupStoreProvider.d.ts → CloneQueryServiceSetup.d.ts} +2 -7
- package/lib/components/CloneQueryServiceSetup.d.ts.map +1 -0
- package/lib/components/CloneQueryServiceSetup.js +137 -0
- package/lib/components/CloneQueryServiceSetup.js.map +1 -0
- package/lib/components/Core_LegendQueryApplicationPlugin.d.ts +24 -0
- package/lib/components/Core_LegendQueryApplicationPlugin.d.ts.map +1 -0
- package/lib/components/Core_LegendQueryApplicationPlugin.js +144 -0
- package/lib/components/Core_LegendQueryApplicationPlugin.js.map +1 -0
- package/lib/components/CreateMappingQuerySetup.d.ts +18 -0
- package/lib/components/CreateMappingQuerySetup.d.ts.map +1 -0
- package/lib/components/CreateMappingQuerySetup.js +160 -0
- package/lib/components/CreateMappingQuerySetup.js.map +1 -0
- package/lib/components/EditExistingQuerySetup.d.ts +18 -0
- package/lib/components/EditExistingQuerySetup.d.ts.map +1 -0
- package/lib/components/EditExistingQuerySetup.js +107 -0
- package/lib/components/EditExistingQuerySetup.js.map +1 -0
- package/lib/components/LegendQueryApplication.d.ts.map +1 -1
- package/lib/components/LegendQueryApplication.js +4 -2
- package/lib/components/LegendQueryApplication.js.map +1 -1
- package/lib/components/LoadProjectServiceQuerySetup.d.ts +18 -0
- package/lib/components/LoadProjectServiceQuerySetup.d.ts.map +1 -0
- package/lib/components/LoadProjectServiceQuerySetup.js +63 -0
- package/lib/components/LoadProjectServiceQuerySetup.js.map +1 -0
- package/lib/components/QueryEditor.d.ts.map +1 -1
- package/lib/components/QueryEditor.js +31 -33
- package/lib/components/QueryEditor.js.map +1 -1
- package/lib/components/QueryProductionizerSetup.d.ts +18 -0
- package/lib/components/QueryProductionizerSetup.d.ts.map +1 -0
- package/lib/components/QueryProductionizerSetup.js +85 -0
- package/lib/components/QueryProductionizerSetup.js.map +1 -0
- package/lib/components/QuerySetup.d.ts +20 -5
- package/lib/components/QuerySetup.d.ts.map +1 -1
- package/lib/components/QuerySetup.js +69 -473
- package/lib/components/QuerySetup.js.map +1 -1
- package/lib/components/UpdateExistingServiceQuerySetup.d.ts +18 -0
- package/lib/components/UpdateExistingServiceQuerySetup.d.ts.map +1 -0
- package/lib/components/UpdateExistingServiceQuerySetup.js +69 -0
- package/lib/components/UpdateExistingServiceQuerySetup.js.map +1 -0
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/index.d.ts +2 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -3
- package/lib/index.js.map +1 -1
- package/lib/package.json +5 -8
- package/lib/stores/CloneServiceQuerySetupStore.d.ts +41 -0
- package/lib/stores/CloneServiceQuerySetupStore.d.ts.map +1 -0
- package/lib/stores/CloneServiceQuerySetupStore.js +98 -0
- package/lib/stores/CloneServiceQuerySetupStore.js.map +1 -0
- package/lib/stores/CreateMappingQuerySetupStore.d.ts +40 -0
- package/lib/stores/CreateMappingQuerySetupStore.d.ts.map +1 -0
- package/lib/stores/CreateMappingQuerySetupStore.js +97 -0
- package/lib/stores/CreateMappingQuerySetupStore.js.map +1 -0
- package/lib/stores/EditExistingQuerySetupStore.d.ts +33 -0
- package/lib/stores/EditExistingQuerySetupStore.d.ts.map +1 -0
- package/lib/stores/EditExistingQuerySetupStore.js +85 -0
- package/lib/stores/EditExistingQuerySetupStore.js.map +1 -0
- package/lib/stores/LegendQueryApplicationPlugin.d.ts +21 -16
- package/lib/stores/LegendQueryApplicationPlugin.d.ts.map +1 -1
- package/lib/stores/LegendQueryApplicationPlugin.js +4 -0
- package/lib/stores/LegendQueryApplicationPlugin.js.map +1 -1
- package/lib/stores/LegendQueryRouter.d.ts +28 -1
- package/lib/stores/LegendQueryRouter.d.ts.map +1 -1
- package/lib/stores/LegendQueryRouter.js +33 -3
- package/lib/stores/LegendQueryRouter.js.map +1 -1
- package/lib/stores/LoadProjectServiceQuerySetupStore.d.ts +27 -0
- package/lib/stores/LoadProjectServiceQuerySetupStore.d.ts.map +1 -0
- package/lib/stores/LoadProjectServiceQuerySetupStore.js +61 -0
- package/lib/stores/LoadProjectServiceQuerySetupStore.js.map +1 -0
- package/lib/stores/QueryEditorStore.d.ts +6 -2
- package/lib/stores/QueryEditorStore.d.ts.map +1 -1
- package/lib/stores/QueryEditorStore.js +35 -17
- package/lib/stores/QueryEditorStore.js.map +1 -1
- package/lib/stores/QueryEditorStoreTestUtils.d.ts.map +1 -1
- package/lib/stores/QueryEditorStoreTestUtils.js +3 -0
- package/lib/stores/QueryEditorStoreTestUtils.js.map +1 -1
- package/lib/stores/QueryProductionizerSetupStore.d.ts +32 -0
- package/lib/stores/QueryProductionizerSetupStore.d.ts.map +1 -0
- package/lib/stores/QueryProductionizerSetupStore.js +101 -0
- package/lib/stores/QueryProductionizerSetupStore.js.map +1 -0
- package/lib/stores/QuerySetupStore.d.ts +22 -85
- package/lib/stores/QuerySetupStore.d.ts.map +1 -1
- package/lib/stores/QuerySetupStore.js +78 -408
- package/lib/stores/QuerySetupStore.js.map +1 -1
- package/lib/stores/UpdateExistingServiceQuerySetupStore.d.ts +28 -0
- package/lib/stores/UpdateExistingServiceQuerySetupStore.d.ts.map +1 -0
- package/lib/stores/UpdateExistingServiceQuerySetupStore.js +73 -0
- package/lib/stores/UpdateExistingServiceQuerySetupStore.js.map +1 -0
- package/package.json +13 -16
- package/src/application/LegendQuery.tsx +7 -8
- package/src/application/LegendQueryApplicationConfig.ts +14 -0
- package/src/components/CloneQueryServiceSetup.tsx +312 -0
- package/src/components/Core_LegendQueryApplicationPlugin.tsx +184 -0
- package/src/components/CreateMappingQuerySetup.tsx +352 -0
- package/src/components/EditExistingQuerySetup.tsx +280 -0
- package/src/components/LegendQueryApplication.tsx +14 -2
- package/src/components/LoadProjectServiceQuerySetup.tsx +131 -0
- package/src/components/QueryEditor.tsx +127 -81
- package/src/components/QueryProductionizerSetup.tsx +206 -0
- package/src/components/QuerySetup.tsx +285 -1183
- package/src/components/UpdateExistingServiceQuerySetup.tsx +153 -0
- package/src/index.ts +3 -2
- package/src/stores/CloneServiceQuerySetupStore.ts +151 -0
- package/src/stores/CreateMappingQuerySetupStore.ts +155 -0
- package/src/stores/EditExistingQuerySetupStore.ts +111 -0
- package/src/stores/LegendQueryApplicationPlugin.ts +27 -27
- package/src/stores/LegendQueryRouter.ts +95 -12
- package/src/stores/LoadProjectServiceQuerySetupStore.ts +87 -0
- package/src/stores/QueryEditorStore.ts +90 -24
- package/src/stores/QueryEditorStoreTestUtils.ts +3 -0
- package/src/stores/QueryProductionizerSetupStore.ts +143 -0
- package/src/stores/QuerySetupStore.ts +111 -604
- package/src/stores/UpdateExistingServiceQuerySetupStore.ts +118 -0
- package/tsconfig.json +13 -1
- package/lib/components/QuerySetupStoreProvider.d.ts.map +0 -1
- package/lib/components/QuerySetupStoreProvider.js +0 -34
- package/lib/components/QuerySetupStoreProvider.js.map +0 -1
- package/src/components/QuerySetupStoreProvider.tsx +0 -56
@@ -0,0 +1,352 @@
|
|
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
|
+
ArrowLeftIcon,
|
19
|
+
ArrowRightIcon,
|
20
|
+
BlankPanelContent,
|
21
|
+
clsx,
|
22
|
+
CustomSelectorInput,
|
23
|
+
PanelLoadingIndicator,
|
24
|
+
} from '@finos/legend-art';
|
25
|
+
import { getNullableFirstElement, guaranteeType } from '@finos/legend-shared';
|
26
|
+
import { flowResult } from 'mobx';
|
27
|
+
import { observer, useLocalObservable } from 'mobx-react-lite';
|
28
|
+
import { useContext, useEffect } from 'react';
|
29
|
+
import {
|
30
|
+
generateMappingQueryCreatorRoute,
|
31
|
+
generateQuerySetupRoute,
|
32
|
+
} from '../stores/LegendQueryRouter.js';
|
33
|
+
import {
|
34
|
+
LATEST_VERSION_ALIAS,
|
35
|
+
SNAPSHOT_VERSION_ALIAS,
|
36
|
+
useDepotServerClient,
|
37
|
+
} from '@finos/legend-server-depot';
|
38
|
+
import {
|
39
|
+
useApplicationStore,
|
40
|
+
buildElementOption,
|
41
|
+
type PackageableElementOption,
|
42
|
+
} from '@finos/legend-application';
|
43
|
+
import { useLegendQueryApplicationStore } from './LegendQueryBaseStoreProvider.js';
|
44
|
+
import { CreateMappingQuerySetupStore } from '../stores/CreateMappingQuerySetupStore.js';
|
45
|
+
import {
|
46
|
+
BaseQuerySetup,
|
47
|
+
BaseQuerySetupStoreContext,
|
48
|
+
buildProjectOption,
|
49
|
+
buildVersionOption,
|
50
|
+
type ProjectOption,
|
51
|
+
type VersionOption,
|
52
|
+
} from './QuerySetup.js';
|
53
|
+
import { compareSemVerVersions } from '@finos/legend-storage';
|
54
|
+
import type { Mapping, PackageableRuntime } from '@finos/legend-graph';
|
55
|
+
|
56
|
+
const CreateMappingQuerySetupStoreProvider: React.FC<{
|
57
|
+
children: React.ReactNode;
|
58
|
+
}> = ({ children }) => {
|
59
|
+
const applicationStore = useLegendQueryApplicationStore();
|
60
|
+
const depotServerClient = useDepotServerClient();
|
61
|
+
const store = useLocalObservable(
|
62
|
+
() => new CreateMappingQuerySetupStore(applicationStore, depotServerClient),
|
63
|
+
);
|
64
|
+
return (
|
65
|
+
<BaseQuerySetupStoreContext.Provider value={store}>
|
66
|
+
{children}
|
67
|
+
</BaseQuerySetupStoreContext.Provider>
|
68
|
+
);
|
69
|
+
};
|
70
|
+
|
71
|
+
const useCreateMappingQuerySetupStore = (): CreateMappingQuerySetupStore =>
|
72
|
+
guaranteeType(
|
73
|
+
useContext(BaseQuerySetupStoreContext),
|
74
|
+
CreateMappingQuerySetupStore,
|
75
|
+
`Can't find query setup store in context`,
|
76
|
+
);
|
77
|
+
|
78
|
+
const CreateMappingQuerySetupContent = observer(() => {
|
79
|
+
const setupStore = useCreateMappingQuerySetupStore();
|
80
|
+
const applicationStore = useApplicationStore();
|
81
|
+
|
82
|
+
// actions
|
83
|
+
const back = (): void => {
|
84
|
+
applicationStore.navigator.goToLocation(generateQuerySetupRoute());
|
85
|
+
};
|
86
|
+
const next = (): void => {
|
87
|
+
if (
|
88
|
+
setupStore.currentProject &&
|
89
|
+
setupStore.currentVersionId &&
|
90
|
+
setupStore.currentMapping &&
|
91
|
+
setupStore.currentRuntime
|
92
|
+
) {
|
93
|
+
applicationStore.navigator.goToLocation(
|
94
|
+
generateMappingQueryCreatorRoute(
|
95
|
+
setupStore.currentProject.groupId,
|
96
|
+
setupStore.currentProject.artifactId,
|
97
|
+
setupStore.currentVersionId,
|
98
|
+
setupStore.currentMapping.path,
|
99
|
+
setupStore.currentRuntime.path,
|
100
|
+
),
|
101
|
+
);
|
102
|
+
}
|
103
|
+
};
|
104
|
+
const canProceed =
|
105
|
+
setupStore.currentProject &&
|
106
|
+
setupStore.currentVersionId &&
|
107
|
+
setupStore.currentMapping &&
|
108
|
+
setupStore.currentRuntime;
|
109
|
+
|
110
|
+
// project
|
111
|
+
const projectOptions = setupStore.projects.map(buildProjectOption);
|
112
|
+
const selectedProjectOption = setupStore.currentProject
|
113
|
+
? buildProjectOption(setupStore.currentProject)
|
114
|
+
: null;
|
115
|
+
const projectSelectorPlaceholder = setupStore.loadProjectsState.isInProgress
|
116
|
+
? 'Loading projects'
|
117
|
+
: setupStore.loadProjectsState.hasFailed
|
118
|
+
? 'Error fetching projects'
|
119
|
+
: setupStore.projects.length
|
120
|
+
? 'Choose a project'
|
121
|
+
: 'You have no projects, please create or acquire access for at least one';
|
122
|
+
const onProjectOptionChange = (option: ProjectOption | null): void => {
|
123
|
+
if (option?.value !== setupStore.currentProject) {
|
124
|
+
setupStore.setCurrentProject(option?.value);
|
125
|
+
// cascade
|
126
|
+
setupStore.setCurrentVersionId(undefined);
|
127
|
+
setupStore.setCurrentMapping(undefined);
|
128
|
+
setupStore.setCurrentRuntime(undefined);
|
129
|
+
}
|
130
|
+
};
|
131
|
+
|
132
|
+
// version
|
133
|
+
const versionOptions = [
|
134
|
+
LATEST_VERSION_ALIAS,
|
135
|
+
SNAPSHOT_VERSION_ALIAS,
|
136
|
+
...(setupStore.currentProject?.versions ?? []),
|
137
|
+
]
|
138
|
+
.slice()
|
139
|
+
.sort((v1, v2) => compareSemVerVersions(v2, v1))
|
140
|
+
.map(buildVersionOption);
|
141
|
+
const selectedVersionOption = setupStore.currentVersionId
|
142
|
+
? buildVersionOption(setupStore.currentVersionId)
|
143
|
+
: null;
|
144
|
+
const versionSelectorPlaceholder = !setupStore.currentProject
|
145
|
+
? 'No project selected'
|
146
|
+
: 'Choose a version';
|
147
|
+
const onVersionOptionChange = async (
|
148
|
+
option: VersionOption | null,
|
149
|
+
): Promise<void> => {
|
150
|
+
if (option?.value !== setupStore.currentVersionId) {
|
151
|
+
setupStore.setCurrentVersionId(option?.value);
|
152
|
+
// cascade
|
153
|
+
setupStore.setCurrentMapping(undefined);
|
154
|
+
setupStore.setCurrentRuntime(undefined);
|
155
|
+
if (setupStore.currentProject && setupStore.currentVersionId) {
|
156
|
+
await flowResult(
|
157
|
+
setupStore.surveyMappingRuntimeCompatibility(
|
158
|
+
setupStore.currentProject,
|
159
|
+
setupStore.currentVersionId,
|
160
|
+
),
|
161
|
+
).catch(applicationStore.alertUnhandledError);
|
162
|
+
}
|
163
|
+
}
|
164
|
+
};
|
165
|
+
|
166
|
+
// mapping
|
167
|
+
const mappingOptions = setupStore.mappingRuntimeCompatibilitySurveyResult.map(
|
168
|
+
(result) => buildElementOption(result.mapping),
|
169
|
+
);
|
170
|
+
const selectedMappingOption = setupStore.currentMapping
|
171
|
+
? {
|
172
|
+
label: setupStore.currentMapping.name,
|
173
|
+
value: setupStore.currentMapping,
|
174
|
+
}
|
175
|
+
: null;
|
176
|
+
const mappingSelectorPlaceholder = mappingOptions.length
|
177
|
+
? 'Choose a mapping'
|
178
|
+
: 'No mapping available';
|
179
|
+
const onMappingOptionChange = (
|
180
|
+
option: PackageableElementOption<Mapping> | null,
|
181
|
+
): void => {
|
182
|
+
setupStore.setCurrentMapping(option?.value);
|
183
|
+
// cascade
|
184
|
+
if (setupStore.currentMapping) {
|
185
|
+
setupStore.setCurrentRuntime(
|
186
|
+
getNullableFirstElement(setupStore.compatibleRuntimes),
|
187
|
+
);
|
188
|
+
} else {
|
189
|
+
setupStore.setCurrentRuntime(undefined);
|
190
|
+
}
|
191
|
+
};
|
192
|
+
|
193
|
+
// runtime
|
194
|
+
const runtimeOptions = setupStore.compatibleRuntimes.map(buildElementOption);
|
195
|
+
const selectedRuntimeOption = setupStore.currentRuntime
|
196
|
+
? {
|
197
|
+
label: setupStore.currentRuntime.name,
|
198
|
+
value: setupStore.currentRuntime,
|
199
|
+
}
|
200
|
+
: null;
|
201
|
+
const runtimeSelectorPlaceholder = !setupStore.currentMapping
|
202
|
+
? 'No mapping specified'
|
203
|
+
: runtimeOptions.length
|
204
|
+
? 'Choose a runtime'
|
205
|
+
: 'No runtime available';
|
206
|
+
const onRuntimeOptionChange = (
|
207
|
+
option: PackageableElementOption<PackageableRuntime> | null,
|
208
|
+
): void => {
|
209
|
+
setupStore.setCurrentRuntime(option?.value);
|
210
|
+
};
|
211
|
+
|
212
|
+
useEffect(() => {
|
213
|
+
flowResult(setupStore.loadProjects()).catch(
|
214
|
+
applicationStore.alertUnhandledError,
|
215
|
+
);
|
216
|
+
}, [setupStore, applicationStore]);
|
217
|
+
|
218
|
+
return (
|
219
|
+
<div className="query-setup__wizard query-setup__create-query">
|
220
|
+
<div className="query-setup__wizard__header query-setup__create-query__header">
|
221
|
+
<button
|
222
|
+
className="query-setup__wizard__header__btn"
|
223
|
+
onClick={back}
|
224
|
+
title="Back to Main Menu"
|
225
|
+
>
|
226
|
+
<ArrowLeftIcon />
|
227
|
+
</button>
|
228
|
+
<div className="query-setup__wizard__header__title">
|
229
|
+
Creating a new query...
|
230
|
+
</div>
|
231
|
+
<button
|
232
|
+
className={clsx('query-setup__wizard__header__btn', {
|
233
|
+
'query-setup__wizard__header__btn--ready': canProceed,
|
234
|
+
})}
|
235
|
+
onClick={next}
|
236
|
+
disabled={!canProceed}
|
237
|
+
title="Create a new query"
|
238
|
+
>
|
239
|
+
<ArrowRightIcon />
|
240
|
+
</button>
|
241
|
+
</div>
|
242
|
+
<div className="query-setup__wizard__content">
|
243
|
+
<div className="query-setup__create-query__project">
|
244
|
+
<div className="query-setup__wizard__group">
|
245
|
+
<div className="query-setup__wizard__group__title">Project</div>
|
246
|
+
<CustomSelectorInput
|
247
|
+
className="query-setup__wizard__selector"
|
248
|
+
options={projectOptions}
|
249
|
+
disabled={
|
250
|
+
setupStore.loadProjectsState.isInProgress ||
|
251
|
+
!projectOptions.length
|
252
|
+
}
|
253
|
+
isLoading={setupStore.loadProjectsState.isInProgress}
|
254
|
+
onChange={onProjectOptionChange}
|
255
|
+
value={selectedProjectOption}
|
256
|
+
placeholder={projectSelectorPlaceholder}
|
257
|
+
isClearable={true}
|
258
|
+
escapeClearsValue={true}
|
259
|
+
darkMode={true}
|
260
|
+
/>
|
261
|
+
</div>
|
262
|
+
<div className="query-setup__wizard__group">
|
263
|
+
<div className="query-setup__wizard__group__title">Version</div>
|
264
|
+
<CustomSelectorInput
|
265
|
+
className="query-setup__wizard__selector"
|
266
|
+
options={versionOptions}
|
267
|
+
disabled={!setupStore.currentProject}
|
268
|
+
onChange={onVersionOptionChange}
|
269
|
+
value={selectedVersionOption}
|
270
|
+
placeholder={versionSelectorPlaceholder}
|
271
|
+
isClearable={true}
|
272
|
+
escapeClearsValue={true}
|
273
|
+
darkMode={true}
|
274
|
+
/>
|
275
|
+
</div>
|
276
|
+
</div>
|
277
|
+
<div className="query-setup__create-query__graph">
|
278
|
+
{(!setupStore.currentProject ||
|
279
|
+
!setupStore.currentVersionId ||
|
280
|
+
!setupStore.surveyMappingRuntimeCompatibilityState
|
281
|
+
.hasSucceeded) && (
|
282
|
+
<div className="query-setup__create-query__graph__loader">
|
283
|
+
<PanelLoadingIndicator
|
284
|
+
isLoading={
|
285
|
+
Boolean(setupStore.currentProject) &&
|
286
|
+
Boolean(setupStore.currentVersionId) &&
|
287
|
+
!setupStore.surveyMappingRuntimeCompatibilityState
|
288
|
+
.hasSucceeded
|
289
|
+
}
|
290
|
+
/>
|
291
|
+
<BlankPanelContent>
|
292
|
+
{setupStore.surveyMappingRuntimeCompatibilityState.isInProgress
|
293
|
+
? `Surveying runtime and mapping compatibility...`
|
294
|
+
: setupStore.surveyMappingRuntimeCompatibilityState.hasFailed
|
295
|
+
? `Can't load runtime and mapping`
|
296
|
+
: 'Project and version must be specified'}
|
297
|
+
</BlankPanelContent>
|
298
|
+
</div>
|
299
|
+
)}
|
300
|
+
{setupStore.currentProject &&
|
301
|
+
setupStore.currentVersionId &&
|
302
|
+
setupStore.surveyMappingRuntimeCompatibilityState.hasSucceeded && (
|
303
|
+
<>
|
304
|
+
<div className="query-setup__wizard__group">
|
305
|
+
<div className="query-setup__wizard__group__title">
|
306
|
+
Mapping
|
307
|
+
</div>
|
308
|
+
<CustomSelectorInput
|
309
|
+
className="query-setup__wizard__selector"
|
310
|
+
options={mappingOptions}
|
311
|
+
disabled={!mappingOptions.length}
|
312
|
+
onChange={onMappingOptionChange}
|
313
|
+
value={selectedMappingOption}
|
314
|
+
placeholder={mappingSelectorPlaceholder}
|
315
|
+
isClearable={true}
|
316
|
+
escapeClearsValue={true}
|
317
|
+
darkMode={true}
|
318
|
+
/>
|
319
|
+
</div>
|
320
|
+
<div className="query-setup__wizard__group">
|
321
|
+
<div className="query-setup__wizard__group__title">
|
322
|
+
Runtime
|
323
|
+
</div>
|
324
|
+
<CustomSelectorInput
|
325
|
+
className="query-setup__wizard__selector"
|
326
|
+
options={runtimeOptions}
|
327
|
+
disabled={
|
328
|
+
!mappingOptions.length || !setupStore.currentMapping
|
329
|
+
}
|
330
|
+
onChange={onRuntimeOptionChange}
|
331
|
+
value={selectedRuntimeOption}
|
332
|
+
placeholder={runtimeSelectorPlaceholder}
|
333
|
+
isClearable={true}
|
334
|
+
escapeClearsValue={true}
|
335
|
+
darkMode={true}
|
336
|
+
/>
|
337
|
+
</div>
|
338
|
+
</>
|
339
|
+
)}
|
340
|
+
</div>
|
341
|
+
</div>
|
342
|
+
</div>
|
343
|
+
);
|
344
|
+
});
|
345
|
+
|
346
|
+
export const CreateMappingQuerySetup: React.FC = () => (
|
347
|
+
<CreateMappingQuerySetupStoreProvider>
|
348
|
+
<BaseQuerySetup>
|
349
|
+
<CreateMappingQuerySetupContent />
|
350
|
+
</BaseQuerySetup>
|
351
|
+
</CreateMappingQuerySetupStoreProvider>
|
352
|
+
);
|
@@ -0,0 +1,280 @@
|
|
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
|
+
type SelectComponent,
|
19
|
+
ArrowLeftIcon,
|
20
|
+
ArrowRightIcon,
|
21
|
+
BlankPanelContent,
|
22
|
+
clsx,
|
23
|
+
CustomSelectorInput,
|
24
|
+
PanelLoadingIndicator,
|
25
|
+
SearchIcon,
|
26
|
+
UserIcon,
|
27
|
+
} from '@finos/legend-art';
|
28
|
+
import { debounce, guaranteeType } from '@finos/legend-shared';
|
29
|
+
import { flowResult } from 'mobx';
|
30
|
+
import { observer, useLocalObservable } from 'mobx-react-lite';
|
31
|
+
import { useContext, useEffect, useMemo, useRef, useState } from 'react';
|
32
|
+
import {
|
33
|
+
generateExistingQueryEditorRoute,
|
34
|
+
generateQuerySetupRoute,
|
35
|
+
} from '../stores/LegendQueryRouter.js';
|
36
|
+
import { useDepotServerClient } from '@finos/legend-server-depot';
|
37
|
+
import {
|
38
|
+
useApplicationStore,
|
39
|
+
EDITOR_LANGUAGE,
|
40
|
+
TextInputEditor,
|
41
|
+
} from '@finos/legend-application';
|
42
|
+
import {
|
43
|
+
type QueryOption,
|
44
|
+
buildQueryOption,
|
45
|
+
} from '@finos/legend-query-builder';
|
46
|
+
import { useLegendQueryApplicationStore } from './LegendQueryBaseStoreProvider.js';
|
47
|
+
import { EditExistingQuerySetupStore } from '../stores/EditExistingQuerySetupStore.js';
|
48
|
+
import { BaseQuerySetup, BaseQuerySetupStoreContext } from './QuerySetup.js';
|
49
|
+
|
50
|
+
const EditExistingQuerySetupStoreProvider: React.FC<{
|
51
|
+
children: React.ReactNode;
|
52
|
+
}> = ({ children }) => {
|
53
|
+
const applicationStore = useLegendQueryApplicationStore();
|
54
|
+
const depotServerClient = useDepotServerClient();
|
55
|
+
const store = useLocalObservable(
|
56
|
+
() => new EditExistingQuerySetupStore(applicationStore, depotServerClient),
|
57
|
+
);
|
58
|
+
return (
|
59
|
+
<BaseQuerySetupStoreContext.Provider value={store}>
|
60
|
+
{children}
|
61
|
+
</BaseQuerySetupStoreContext.Provider>
|
62
|
+
);
|
63
|
+
};
|
64
|
+
|
65
|
+
const useEditExistingQuerySetupStore = (): EditExistingQuerySetupStore =>
|
66
|
+
guaranteeType(
|
67
|
+
useContext(BaseQuerySetupStoreContext),
|
68
|
+
EditExistingQuerySetupStore,
|
69
|
+
`Can't find query setup store in context`,
|
70
|
+
);
|
71
|
+
|
72
|
+
const EditExistingQuerySetupContent = observer(() => {
|
73
|
+
const setupStore = useEditExistingQuerySetupStore();
|
74
|
+
const applicationStore = useApplicationStore();
|
75
|
+
const querySearchRef = useRef<SelectComponent>(null);
|
76
|
+
const [searchText, setSearchText] = useState('');
|
77
|
+
|
78
|
+
// actions
|
79
|
+
const back = (): void => {
|
80
|
+
applicationStore.navigator.goToLocation(generateQuerySetupRoute());
|
81
|
+
};
|
82
|
+
const next = (): void => {
|
83
|
+
if (setupStore.currentQuery) {
|
84
|
+
applicationStore.navigator.goToLocation(
|
85
|
+
generateExistingQueryEditorRoute(setupStore.currentQuery.id),
|
86
|
+
);
|
87
|
+
}
|
88
|
+
};
|
89
|
+
const canProceed = setupStore.currentQuery;
|
90
|
+
|
91
|
+
// query
|
92
|
+
const queryOptions = setupStore.queries.map(buildQueryOption);
|
93
|
+
const selectedQueryOption = setupStore.currentQuery
|
94
|
+
? buildQueryOption(setupStore.currentQuery)
|
95
|
+
: null;
|
96
|
+
const onQueryOptionChange = (option: QueryOption | null): void => {
|
97
|
+
if (option?.value !== setupStore.currentQuery) {
|
98
|
+
setupStore.setCurrentQuery(option?.value.id);
|
99
|
+
}
|
100
|
+
};
|
101
|
+
const formatQueryOptionLabel = (option: QueryOption): React.ReactNode => {
|
102
|
+
const deleteQuery: React.MouseEventHandler<HTMLButtonElement> = (event) => {
|
103
|
+
event.preventDefault();
|
104
|
+
event.stopPropagation();
|
105
|
+
setupStore.graphManagerState.graphManager
|
106
|
+
.deleteQuery(option.value.id)
|
107
|
+
.then(() =>
|
108
|
+
flowResult(setupStore.loadQueries('')).catch(
|
109
|
+
applicationStore.alertUnhandledError,
|
110
|
+
),
|
111
|
+
)
|
112
|
+
.catch(applicationStore.alertUnhandledError);
|
113
|
+
};
|
114
|
+
if (option.value.id === setupStore.currentQuery?.id) {
|
115
|
+
return option.label;
|
116
|
+
}
|
117
|
+
return (
|
118
|
+
<div className="query-setup__existing-query__query-option">
|
119
|
+
<div
|
120
|
+
className="query-setup__existing-query__query-option__label"
|
121
|
+
title={option.label}
|
122
|
+
>
|
123
|
+
{option.label}
|
124
|
+
</div>
|
125
|
+
{setupStore.showCurrentUserQueriesOnly && (
|
126
|
+
<button
|
127
|
+
className="query-setup__existing-query__query-option__action"
|
128
|
+
tabIndex={-1}
|
129
|
+
onClick={deleteQuery}
|
130
|
+
>
|
131
|
+
Delete
|
132
|
+
</button>
|
133
|
+
)}
|
134
|
+
{!setupStore.showCurrentUserQueriesOnly && Boolean(option.value.owner) && (
|
135
|
+
<div
|
136
|
+
className={clsx('query-setup__existing-query__query-option__user', {
|
137
|
+
'query-setup__existing-query__query-option__user--mine':
|
138
|
+
option.value.isCurrentUserQuery,
|
139
|
+
})}
|
140
|
+
>
|
141
|
+
{option.value.isCurrentUserQuery ? 'mine' : option.value.owner}
|
142
|
+
</div>
|
143
|
+
)}
|
144
|
+
</div>
|
145
|
+
);
|
146
|
+
};
|
147
|
+
|
148
|
+
// search text
|
149
|
+
const debouncedLoadQueries = useMemo(
|
150
|
+
() =>
|
151
|
+
debounce((input: string): void => {
|
152
|
+
flowResult(setupStore.loadQueries(input)).catch(
|
153
|
+
applicationStore.alertUnhandledError,
|
154
|
+
);
|
155
|
+
}, 500),
|
156
|
+
[applicationStore, setupStore],
|
157
|
+
);
|
158
|
+
const onSearchTextChange = (value: string): void => {
|
159
|
+
if (value !== searchText) {
|
160
|
+
setSearchText(value);
|
161
|
+
debouncedLoadQueries.cancel();
|
162
|
+
debouncedLoadQueries(value);
|
163
|
+
}
|
164
|
+
};
|
165
|
+
|
166
|
+
// show current user queries only
|
167
|
+
const toggleShowCurrentUserQueriesOnly = (): void => {
|
168
|
+
setupStore.setShowCurrentUserQueriesOnly(
|
169
|
+
!setupStore.showCurrentUserQueriesOnly,
|
170
|
+
);
|
171
|
+
debouncedLoadQueries.cancel();
|
172
|
+
debouncedLoadQueries(searchText);
|
173
|
+
};
|
174
|
+
|
175
|
+
useEffect(() => {
|
176
|
+
flowResult(setupStore.loadQueries('')).catch(
|
177
|
+
applicationStore.alertUnhandledError,
|
178
|
+
);
|
179
|
+
}, [setupStore, applicationStore]);
|
180
|
+
|
181
|
+
useEffect(() => {
|
182
|
+
querySearchRef.current?.focus();
|
183
|
+
}, []);
|
184
|
+
|
185
|
+
return (
|
186
|
+
<div className="query-setup__wizard query-setup__existing-query">
|
187
|
+
<div className="query-setup__wizard__header query-setup__existing-query__header">
|
188
|
+
<button
|
189
|
+
className="query-setup__wizard__header__btn"
|
190
|
+
onClick={back}
|
191
|
+
title="Back to Main Menu"
|
192
|
+
>
|
193
|
+
<ArrowLeftIcon />
|
194
|
+
</button>
|
195
|
+
<div className="query-setup__wizard__header__title">
|
196
|
+
Loading an existing query...
|
197
|
+
</div>
|
198
|
+
<button
|
199
|
+
className={clsx('query-setup__wizard__header__btn', {
|
200
|
+
'query-setup__wizard__header__btn--ready': canProceed,
|
201
|
+
})}
|
202
|
+
onClick={next}
|
203
|
+
disabled={!canProceed}
|
204
|
+
title="Edit query"
|
205
|
+
>
|
206
|
+
<ArrowRightIcon />
|
207
|
+
</button>
|
208
|
+
</div>
|
209
|
+
<div className="query-setup__wizard__content">
|
210
|
+
<div className="query-setup__wizard__group query-setup__wizard__group--inline">
|
211
|
+
<div className="query-setup__wizard__group__title">
|
212
|
+
<SearchIcon />
|
213
|
+
</div>
|
214
|
+
<div className="query-setup__existing-query__input">
|
215
|
+
<CustomSelectorInput
|
216
|
+
ref={querySearchRef}
|
217
|
+
className="query-setup__wizard__selector"
|
218
|
+
options={queryOptions}
|
219
|
+
isLoading={setupStore.loadQueriesState.isInProgress}
|
220
|
+
onInputChange={onSearchTextChange}
|
221
|
+
inputValue={searchText}
|
222
|
+
onChange={onQueryOptionChange}
|
223
|
+
value={selectedQueryOption}
|
224
|
+
placeholder="Search for query by name..."
|
225
|
+
isClearable={true}
|
226
|
+
escapeClearsValue={true}
|
227
|
+
darkMode={true}
|
228
|
+
formatOptionLabel={formatQueryOptionLabel}
|
229
|
+
/>
|
230
|
+
<button
|
231
|
+
className={clsx('query-setup__existing-query__btn', {
|
232
|
+
'query-setup__existing-query__btn--active':
|
233
|
+
setupStore.showCurrentUserQueriesOnly,
|
234
|
+
})}
|
235
|
+
tabIndex={-1}
|
236
|
+
title={`[${
|
237
|
+
setupStore.showCurrentUserQueriesOnly ? 'on' : 'off'
|
238
|
+
}] Toggle show only queries of current user`}
|
239
|
+
onClick={toggleShowCurrentUserQueriesOnly}
|
240
|
+
>
|
241
|
+
<UserIcon />
|
242
|
+
</button>
|
243
|
+
</div>
|
244
|
+
</div>
|
245
|
+
<div className="query-setup__existing-query__preview">
|
246
|
+
<PanelLoadingIndicator
|
247
|
+
isLoading={setupStore.loadQueryState.isInProgress}
|
248
|
+
/>
|
249
|
+
{setupStore.currentQuery && (
|
250
|
+
<>
|
251
|
+
{!setupStore.currentQueryInfo && (
|
252
|
+
<BlankPanelContent>{`Can't preview query`}</BlankPanelContent>
|
253
|
+
)}
|
254
|
+
{setupStore.currentQueryInfo && (
|
255
|
+
<TextInputEditor
|
256
|
+
inputValue={setupStore.currentQueryInfo.content}
|
257
|
+
isReadOnly={true}
|
258
|
+
language={EDITOR_LANGUAGE.PURE}
|
259
|
+
showMiniMap={false}
|
260
|
+
hideGutter={true}
|
261
|
+
/>
|
262
|
+
)}
|
263
|
+
</>
|
264
|
+
)}
|
265
|
+
{!setupStore.currentQuery && (
|
266
|
+
<BlankPanelContent>No query to preview</BlankPanelContent>
|
267
|
+
)}
|
268
|
+
</div>
|
269
|
+
</div>
|
270
|
+
</div>
|
271
|
+
);
|
272
|
+
});
|
273
|
+
|
274
|
+
export const EditExistingQuerySetup: React.FC = () => (
|
275
|
+
<EditExistingQuerySetupStoreProvider>
|
276
|
+
<BaseQuerySetup>
|
277
|
+
<EditExistingQuerySetupContent />
|
278
|
+
</BaseQuerySetup>
|
279
|
+
</EditExistingQuerySetupStoreProvider>
|
280
|
+
);
|
@@ -16,7 +16,7 @@
|
|
16
16
|
|
17
17
|
import { observer } from 'mobx-react-lite';
|
18
18
|
import { LEGEND_QUERY_ROUTE_PATTERN } from '../stores/LegendQueryRouter.js';
|
19
|
-
import {
|
19
|
+
import { QuerySetupLandingPage } from './QuerySetup.js';
|
20
20
|
import {
|
21
21
|
MappingQueryCreator,
|
22
22
|
ExistingQueryEditor,
|
@@ -35,6 +35,8 @@ import {
|
|
35
35
|
LegendQueryBaseStoreProvider,
|
36
36
|
useLegendQueryApplicationStore,
|
37
37
|
} from './LegendQueryBaseStoreProvider.js';
|
38
|
+
import { EditExistingQuerySetup } from './EditExistingQuerySetup.js';
|
39
|
+
import { CreateMappingQuerySetup } from './CreateMappingQuerySetup.js';
|
38
40
|
|
39
41
|
const LegendQueryApplicationRoot = observer(() => {
|
40
42
|
const applicationStore = useLegendQueryApplicationStore();
|
@@ -48,7 +50,17 @@ const LegendQueryApplicationRoot = observer(() => {
|
|
48
50
|
<Route
|
49
51
|
exact={true}
|
50
52
|
path={LEGEND_QUERY_ROUTE_PATTERN.SETUP}
|
51
|
-
component={
|
53
|
+
component={QuerySetupLandingPage}
|
54
|
+
/>
|
55
|
+
<Route
|
56
|
+
exact={true}
|
57
|
+
path={LEGEND_QUERY_ROUTE_PATTERN.EDIT_EXISTING_QUERY_SETUP}
|
58
|
+
component={EditExistingQuerySetup}
|
59
|
+
/>
|
60
|
+
<Route
|
61
|
+
exact={true}
|
62
|
+
path={LEGEND_QUERY_ROUTE_PATTERN.CREATE_MAPPING_QUERY_SETUP}
|
63
|
+
component={CreateMappingQuerySetup}
|
52
64
|
/>
|
53
65
|
<Route
|
54
66
|
exact={true}
|