@finos/legend-extension-dsl-service 0.0.1

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 (68) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +3 -0
  3. package/lib/components/studio/DSL_Service_LegendStudioApplicationPlugin.d.ts +22 -0
  4. package/lib/components/studio/DSL_Service_LegendStudioApplicationPlugin.d.ts.map +1 -0
  5. package/lib/components/studio/DSL_Service_LegendStudioApplicationPlugin.js +59 -0
  6. package/lib/components/studio/DSL_Service_LegendStudioApplicationPlugin.js.map +1 -0
  7. package/lib/components/studio/ServiceQueryEditor.d.ts +25 -0
  8. package/lib/components/studio/ServiceQueryEditor.d.ts.map +1 -0
  9. package/lib/components/studio/ServiceQueryEditor.js +190 -0
  10. package/lib/components/studio/ServiceQueryEditor.js.map +1 -0
  11. package/lib/components/studio/ServiceQueryEditorReviewAction.d.ts +19 -0
  12. package/lib/components/studio/ServiceQueryEditorReviewAction.d.ts.map +1 -0
  13. package/lib/components/studio/ServiceQueryEditorReviewAction.js +71 -0
  14. package/lib/components/studio/ServiceQueryEditorReviewAction.js.map +1 -0
  15. package/lib/components/studio/ServiceQueryEditorStoreProvider.d.ts +31 -0
  16. package/lib/components/studio/ServiceQueryEditorStoreProvider.d.ts.map +1 -0
  17. package/lib/components/studio/ServiceQueryEditorStoreProvider.js +40 -0
  18. package/lib/components/studio/ServiceQueryEditorStoreProvider.js.map +1 -0
  19. package/lib/components/studio/ServiceQueryEditorWorkspaceStatus.d.ts +19 -0
  20. package/lib/components/studio/ServiceQueryEditorWorkspaceStatus.d.ts.map +1 -0
  21. package/lib/components/studio/ServiceQueryEditorWorkspaceStatus.js +69 -0
  22. package/lib/components/studio/ServiceQueryEditorWorkspaceStatus.js.map +1 -0
  23. package/lib/components/studio/UpdateProjectServiceQuerySetup.d.ts +18 -0
  24. package/lib/components/studio/UpdateProjectServiceQuerySetup.d.ts.map +1 -0
  25. package/lib/components/studio/UpdateProjectServiceQuerySetup.js +182 -0
  26. package/lib/components/studio/UpdateProjectServiceQuerySetup.js.map +1 -0
  27. package/lib/components/studio/UpdateServiceQuerySetup.d.ts +18 -0
  28. package/lib/components/studio/UpdateServiceQuerySetup.d.ts.map +1 -0
  29. package/lib/components/studio/UpdateServiceQuerySetup.js +172 -0
  30. package/lib/components/studio/UpdateServiceQuerySetup.js.map +1 -0
  31. package/lib/index.css +17 -0
  32. package/lib/index.css.map +1 -0
  33. package/lib/index.d.ts +17 -0
  34. package/lib/index.d.ts.map +1 -0
  35. package/lib/index.js +17 -0
  36. package/lib/index.js.map +1 -0
  37. package/lib/package.json +84 -0
  38. package/lib/stores/studio/DSL_Service_LegendStudioRouter.d.ts +53 -0
  39. package/lib/stores/studio/DSL_Service_LegendStudioRouter.d.ts.map +1 -0
  40. package/lib/stores/studio/DSL_Service_LegendStudioRouter.js +62 -0
  41. package/lib/stores/studio/DSL_Service_LegendStudioRouter.js.map +1 -0
  42. package/lib/stores/studio/ServiceQueryEditorStore.d.ts +64 -0
  43. package/lib/stores/studio/ServiceQueryEditorStore.d.ts.map +1 -0
  44. package/lib/stores/studio/ServiceQueryEditorStore.js +260 -0
  45. package/lib/stores/studio/ServiceQueryEditorStore.js.map +1 -0
  46. package/lib/stores/studio/UpdateProjectServiceQuerySetupStore.d.ts +46 -0
  47. package/lib/stores/studio/UpdateProjectServiceQuerySetupStore.d.ts.map +1 -0
  48. package/lib/stores/studio/UpdateProjectServiceQuerySetupStore.js +184 -0
  49. package/lib/stores/studio/UpdateProjectServiceQuerySetupStore.js.map +1 -0
  50. package/lib/stores/studio/UpdateServiceQuerySetupStore.d.ts +48 -0
  51. package/lib/stores/studio/UpdateServiceQuerySetupStore.d.ts.map +1 -0
  52. package/lib/stores/studio/UpdateServiceQuerySetupStore.js +184 -0
  53. package/lib/stores/studio/UpdateServiceQuerySetupStore.js.map +1 -0
  54. package/package.json +84 -0
  55. package/src/components/studio/DSL_Service_LegendStudioApplicationPlugin.tsx +71 -0
  56. package/src/components/studio/ServiceQueryEditor.tsx +551 -0
  57. package/src/components/studio/ServiceQueryEditorReviewAction.tsx +172 -0
  58. package/src/components/studio/ServiceQueryEditorStoreProvider.tsx +89 -0
  59. package/src/components/studio/ServiceQueryEditorWorkspaceStatus.tsx +121 -0
  60. package/src/components/studio/UpdateProjectServiceQuerySetup.tsx +479 -0
  61. package/src/components/studio/UpdateServiceQuerySetup.tsx +476 -0
  62. package/src/index.ts +17 -0
  63. package/src/stores/studio/DSL_Service_LegendStudioRouter.ts +159 -0
  64. package/src/stores/studio/ServiceQueryEditorStore.ts +487 -0
  65. package/src/stores/studio/UpdateProjectServiceQuerySetupStore.ts +281 -0
  66. package/src/stores/studio/UpdateServiceQuerySetupStore.ts +314 -0
  67. package/tsconfig.json +58 -0
  68. package/tsconfig.package.json +38 -0
@@ -0,0 +1,476 @@
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
+ createContext,
19
+ useContext,
20
+ useEffect,
21
+ useMemo,
22
+ useState,
23
+ useRef,
24
+ } from 'react';
25
+ import { observer, useLocalObservable } from 'mobx-react-lite';
26
+ import { debounce, guaranteeNonNullable } from '@finos/legend-shared';
27
+ import { useSDLCServerClient, WorkspaceType } from '@finos/legend-server-sdlc';
28
+ import {
29
+ type WorkspaceOption,
30
+ ActivityBarMenu,
31
+ buildWorkspaceOption,
32
+ LEGEND_STUDIO_TEST_ID,
33
+ useLegendStudioApplicationStore,
34
+ } from '@finos/legend-application-studio';
35
+ import { UpdateServiceQuerySetupStore } from '../../stores/studio/UpdateServiceQuerySetupStore.js';
36
+ import {
37
+ type ProjectData,
38
+ useDepotServerClient,
39
+ } from '@finos/legend-server-depot';
40
+ import { useParams } from 'react-router';
41
+ import {
42
+ type ServiceQueryUpdaterSetupPathParams,
43
+ generateServiceQueryUpdaterRoute,
44
+ } from '../../stores/studio/DSL_Service_LegendStudioRouter.js';
45
+ import { flowResult } from 'mobx';
46
+ import {
47
+ type ServiceInfo,
48
+ type ServiceOption,
49
+ buildServiceOption,
50
+ formatServiceOptionLabel,
51
+ } from '@finos/legend-query-builder';
52
+ import {
53
+ CircleNotchIcon,
54
+ clsx,
55
+ compareLabelFn,
56
+ createFilter,
57
+ CustomSelectorInput,
58
+ Dialog,
59
+ ErrorIcon,
60
+ GitBranchIcon,
61
+ Panel,
62
+ PanelLoadingIndicator,
63
+ PlusIcon,
64
+ PURE_ServiceIcon,
65
+ UserIcon,
66
+ UsersIcon,
67
+ } from '@finos/legend-art';
68
+
69
+ const UpdateServiceQuerySetupStoreContext = createContext<
70
+ UpdateServiceQuerySetupStore | undefined
71
+ >(undefined);
72
+
73
+ const UpdateServiceQuerySetupStoreProvider: React.FC<{
74
+ children: React.ReactNode;
75
+ }> = ({ children }) => {
76
+ const applicationStore = useLegendStudioApplicationStore();
77
+ const sdlcServerClient = useSDLCServerClient();
78
+ const depotServerClient = useDepotServerClient();
79
+ const store = useLocalObservable(
80
+ () =>
81
+ new UpdateServiceQuerySetupStore(
82
+ applicationStore,
83
+ sdlcServerClient,
84
+ depotServerClient,
85
+ ),
86
+ );
87
+ return (
88
+ <UpdateServiceQuerySetupStoreContext.Provider value={store}>
89
+ {children}
90
+ </UpdateServiceQuerySetupStoreContext.Provider>
91
+ );
92
+ };
93
+
94
+ const useUpdateServiceQuerySetupStore = (): UpdateServiceQuerySetupStore =>
95
+ guaranteeNonNullable(
96
+ useContext(UpdateServiceQuerySetupStoreContext),
97
+ `Can't find service query updater store in context`,
98
+ );
99
+
100
+ const withUpdateServiceQuerySetupStore = (
101
+ WrappedComponent: React.FC,
102
+ ): React.FC =>
103
+ function WithUpdateServiceQuerySetupStore() {
104
+ return (
105
+ <UpdateServiceQuerySetupStoreProvider>
106
+ <WrappedComponent />
107
+ </UpdateServiceQuerySetupStoreProvider>
108
+ );
109
+ };
110
+
111
+ const CreateWorkspaceModal = observer(
112
+ (props: {
113
+ selectedProject: ProjectData;
114
+ selectedSnapService: ServiceInfo;
115
+ }) => {
116
+ const { selectedProject, selectedSnapService } = props;
117
+ const setupStore = useUpdateServiceQuerySetupStore();
118
+ const applicationStore = useLegendStudioApplicationStore();
119
+ const workspaceNameInputRef = useRef<HTMLInputElement>(null);
120
+ const [workspaceName, setWorkspaceName] = useState('');
121
+
122
+ const workspaceAlreadyExists = Boolean(
123
+ setupStore.groupWorkspaces.find(
124
+ (workspace) => workspace.workspaceId === workspaceName,
125
+ ),
126
+ );
127
+ const createWorkspace = (): void => {
128
+ if (workspaceName && !workspaceAlreadyExists) {
129
+ flowResult(
130
+ setupStore.createWorkspace(
131
+ selectedProject.projectId,
132
+ workspaceName,
133
+ selectedSnapService.path,
134
+ ),
135
+ ).catch(applicationStore.alertUnhandledError);
136
+ }
137
+ };
138
+ const changeWorkspaceName: React.ChangeEventHandler<HTMLInputElement> = (
139
+ event,
140
+ ) => setWorkspaceName(event.target.value);
141
+
142
+ const handleEnter = (): void => {
143
+ workspaceNameInputRef.current?.focus();
144
+ };
145
+ const onClose = (): void => {
146
+ setupStore.setShowCreateWorkspaceModal(false);
147
+ };
148
+ const handleSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
149
+ event.preventDefault();
150
+ createWorkspace();
151
+ };
152
+
153
+ return (
154
+ <Dialog
155
+ open={setupStore.showCreateWorkspaceModal}
156
+ onClose={onClose}
157
+ TransitionProps={{
158
+ onEnter: handleEnter,
159
+ }}
160
+ classes={{ container: 'search-modal__container' }}
161
+ PaperProps={{ classes: { root: 'search-modal__inner-container' } }}
162
+ >
163
+ <form
164
+ onSubmit={handleSubmit}
165
+ className="modal modal--dark search-modal"
166
+ >
167
+ <div className="modal__title">Create New Workspace</div>
168
+ <Panel>
169
+ <PanelLoadingIndicator
170
+ isLoading={setupStore.createWorkspaceState.isInProgress}
171
+ />
172
+ <div className="panel__content--full">
173
+ <div className="input-group">
174
+ <input
175
+ className="input input--dark input-group__input"
176
+ ref={workspaceNameInputRef}
177
+ spellCheck={false}
178
+ disabled={setupStore.createWorkspaceState.isInProgress}
179
+ placeholder="MyWorkspace"
180
+ value={workspaceName}
181
+ onChange={changeWorkspaceName}
182
+ />
183
+ {workspaceAlreadyExists && (
184
+ <div className="input-group__error-message">
185
+ Workspace with same name already exists
186
+ </div>
187
+ )}
188
+ </div>
189
+ </div>
190
+ </Panel>
191
+ <div className="search-modal__actions">
192
+ <button
193
+ disabled={
194
+ setupStore.createWorkspaceState.isInProgress ||
195
+ !workspaceName ||
196
+ workspaceAlreadyExists
197
+ }
198
+ className="btn btn--dark"
199
+ >
200
+ Create
201
+ </button>
202
+ </div>
203
+ </form>
204
+ </Dialog>
205
+ );
206
+ },
207
+ );
208
+
209
+ export const UpdateServiceQuerySetup = withUpdateServiceQuerySetupStore(
210
+ observer(() => {
211
+ const params = useParams<ServiceQueryUpdaterSetupPathParams>();
212
+ const { serviceCoordinates } = params;
213
+ const setupStore = useUpdateServiceQuerySetupStore();
214
+ const applicationStore = useLegendStudioApplicationStore();
215
+ const [serviceSearchText, setServiceSearchText] = useState('');
216
+
217
+ // action
218
+ const disableProceedButton =
219
+ !setupStore.currentProject ||
220
+ !setupStore.currentGroupWorkspace ||
221
+ !setupStore.currentWorkspaceService;
222
+ const handleProceed = (): void => {
223
+ if (
224
+ setupStore.currentProject &&
225
+ setupStore.currentGroupWorkspace &&
226
+ setupStore.currentWorkspaceService
227
+ ) {
228
+ applicationStore.navigator.goTo(
229
+ generateServiceQueryUpdaterRoute(
230
+ setupStore.currentProject.groupId,
231
+ setupStore.currentProject.artifactId,
232
+ setupStore.currentWorkspaceService.path,
233
+ setupStore.currentGroupWorkspace.workspaceId,
234
+ ),
235
+ );
236
+ }
237
+ };
238
+
239
+ // services
240
+ const serviceOptions = setupStore.services.map(buildServiceOption);
241
+ const selectedServiceOption = setupStore.currentSnapshotService
242
+ ? buildServiceOption(setupStore.currentSnapshotService)
243
+ : null;
244
+ const onServiceOptionChange = (option: ServiceOption | null): void => {
245
+ if (option) {
246
+ flowResult(
247
+ setupStore.changeService(
248
+ option.value.groupId,
249
+ option.value.artifactId,
250
+ option.value.path,
251
+ ),
252
+ ).catch(applicationStore.alertUnhandledError);
253
+ } else {
254
+ setupStore.resetCurrentService();
255
+ }
256
+ };
257
+ const serviceFilterOption = createFilter({
258
+ ignoreCase: true,
259
+ ignoreAccents: false,
260
+ stringify: (option: ServiceOption): string =>
261
+ // NOTE: account for label, path, and URL pattern
262
+ `${option.label} - ${option.value.urlPattern ?? ''} - ${
263
+ option.value.path
264
+ }`,
265
+ });
266
+
267
+ // service search text
268
+ const debouncedLoadServices = useMemo(
269
+ () =>
270
+ debounce((input: string): void => {
271
+ flowResult(setupStore.loadServices(input)).catch(
272
+ applicationStore.alertUnhandledError,
273
+ );
274
+ }, 500),
275
+ [applicationStore, setupStore],
276
+ );
277
+ const onServiceSearchTextChange = (value: string): void => {
278
+ if (value !== serviceSearchText) {
279
+ setServiceSearchText(value);
280
+ debouncedLoadServices.cancel();
281
+ debouncedLoadServices(value);
282
+ }
283
+ };
284
+
285
+ // workspaces
286
+ const workspaceOptions = setupStore.groupWorkspaces
287
+ .map(buildWorkspaceOption)
288
+ .sort(compareLabelFn);
289
+ const selectedOption = setupStore.currentGroupWorkspace
290
+ ? buildWorkspaceOption(setupStore.currentGroupWorkspace)
291
+ : null;
292
+ const onWorkspaceChange = (option: WorkspaceOption | null): void => {
293
+ if (option) {
294
+ if (setupStore.currentSnapshotService) {
295
+ flowResult(
296
+ setupStore.changeWorkspace(
297
+ option.value,
298
+ setupStore.currentSnapshotService.path,
299
+ ),
300
+ ).catch(applicationStore.alertUnhandledError);
301
+ }
302
+ } else {
303
+ setupStore.resetCurrentGroupWorkspace();
304
+ }
305
+ };
306
+ const showCreateWorkspaceModal = (): void =>
307
+ setupStore.setShowCreateWorkspaceModal(true);
308
+ const formatWorkspaceOptionLabel = (
309
+ option: WorkspaceOption,
310
+ ): React.ReactNode => {
311
+ const isCurrentOptionInvalid =
312
+ // we can only check the current workspace
313
+ setupStore.currentGroupWorkspace === option.value &&
314
+ !setupStore.currentWorkspaceService &&
315
+ !setupStore.checkWorkspaceCompatibilityState.isInProgress;
316
+ return (
317
+ <div
318
+ className="workspace-selector__option"
319
+ title={
320
+ isCurrentOptionInvalid
321
+ ? `Selected workspace does not have the specified service${
322
+ setupStore.currentSnapshotService
323
+ ? ` '${setupStore.currentSnapshotService.path}'`
324
+ : ''
325
+ }\nPlease select another appropriate workspace or create and use a new workspace`
326
+ : setupStore.checkWorkspaceCompatibilityState.isInProgress
327
+ ? `Checking if the specified service is present in the workspace`
328
+ : undefined
329
+ }
330
+ >
331
+ <div className="workspace-selector__option__icon">
332
+ {option.value.workspaceType === WorkspaceType.GROUP ? (
333
+ <UsersIcon />
334
+ ) : (
335
+ <UserIcon />
336
+ )}
337
+ </div>
338
+ <div
339
+ className={clsx('workspace-selector__option__name', {
340
+ 'service-query-setup__workspace-selector__option__name--invalid':
341
+ isCurrentOptionInvalid,
342
+ })}
343
+ >
344
+ {option.label}
345
+ {isCurrentOptionInvalid && <ErrorIcon />}
346
+ {setupStore.checkWorkspaceCompatibilityState.isInProgress && (
347
+ <CircleNotchIcon className="service-query-setup__workspace-selector__option__loading-indicator" />
348
+ )}
349
+ </div>
350
+ </div>
351
+ );
352
+ };
353
+
354
+ useEffect(() => {
355
+ flowResult(setupStore.loadServices('')).catch(
356
+ applicationStore.alertUnhandledError,
357
+ );
358
+ }, [setupStore, applicationStore]);
359
+
360
+ useEffect(() => {
361
+ setupStore.initialize(serviceCoordinates);
362
+ }, [setupStore, serviceCoordinates]);
363
+
364
+ return (
365
+ <div className="app__page">
366
+ <div className="service-query-setup">
367
+ <div className="service-query-setup__body">
368
+ <div className="activity-bar">
369
+ <ActivityBarMenu />
370
+ </div>
371
+ <div
372
+ className="service-query-setup__content"
373
+ data-testid={LEGEND_STUDIO_TEST_ID.SETUP__CONTENT}
374
+ >
375
+ <div className="service-query-setup__content__main">
376
+ <div className="service-query-setup__title">
377
+ <div className="service-query-setup__title__header">
378
+ Update Service Query
379
+ </div>
380
+ </div>
381
+ <div className="service-query-setup__selector">
382
+ <div
383
+ className="service-query-setup__selector__icon"
384
+ title="service"
385
+ >
386
+ <PURE_ServiceIcon />
387
+ </div>
388
+ <CustomSelectorInput
389
+ className="service-query-setup__selector__input"
390
+ options={serviceOptions}
391
+ isLoading={setupStore.loadServicesState.isInProgress}
392
+ onInputChange={onServiceSearchTextChange}
393
+ inputValue={serviceSearchText}
394
+ value={selectedServiceOption}
395
+ onChange={onServiceOptionChange}
396
+ placeholder="Search for service..."
397
+ darkMode={true}
398
+ isClearable={true}
399
+ escapeClearsValue={true}
400
+ filterOption={serviceFilterOption}
401
+ formatOptionLabel={formatServiceOptionLabel}
402
+ />
403
+ </div>
404
+ <div className="service-query-setup__selector">
405
+ <div
406
+ className="service-query-setup__selector__icon"
407
+ title="workspace"
408
+ >
409
+ <GitBranchIcon className="service-query-setup__selector__icon--workspace" />
410
+ </div>
411
+ <CustomSelectorInput
412
+ className="service-query-setup__selector__input"
413
+ options={workspaceOptions}
414
+ disabled={
415
+ !setupStore.currentProject ||
416
+ !setupStore.currentSnapshotService ||
417
+ setupStore.loadWorkspacesState.isInProgress
418
+ }
419
+ isLoading={setupStore.loadWorkspacesState.isInProgress}
420
+ onChange={onWorkspaceChange}
421
+ formatOptionLabel={formatWorkspaceOptionLabel}
422
+ value={selectedOption}
423
+ placeholder={
424
+ setupStore.loadWorkspacesState.isInProgress
425
+ ? 'Loading workspaces...'
426
+ : !setupStore.currentProject
427
+ ? 'In order to select a workspace, a project must be selected'
428
+ : workspaceOptions.length
429
+ ? 'Choose an existing workspace'
430
+ : setupStore.loadWorkspacesState.hasFailed
431
+ ? `Can't fetch project workspaces. Please try again or select another service`
432
+ : 'You have no workspaces. Please create one to proceed...'
433
+ }
434
+ isClearable={true}
435
+ escapeClearsValue={true}
436
+ darkMode={true}
437
+ />
438
+ <button
439
+ className="service-query-setup__selector__action btn--dark"
440
+ onClick={showCreateWorkspaceModal}
441
+ disabled={!setupStore.currentProject}
442
+ tabIndex={-1}
443
+ title="Create a Workspace"
444
+ >
445
+ <PlusIcon />
446
+ </button>
447
+ </div>
448
+ {setupStore.showCreateWorkspaceModal &&
449
+ setupStore.currentProject &&
450
+ setupStore.currentSnapshotService && (
451
+ <CreateWorkspaceModal
452
+ selectedProject={setupStore.currentProject}
453
+ selectedSnapService={setupStore.currentSnapshotService}
454
+ />
455
+ )}
456
+ <div className="service-query-setup__actions">
457
+ <button
458
+ className="service-query-setup__next-btn btn--dark"
459
+ onClick={handleProceed}
460
+ disabled={disableProceedButton}
461
+ >
462
+ Edit Service Query
463
+ </button>
464
+ </div>
465
+ </div>
466
+ </div>
467
+ </div>
468
+ <div
469
+ data-testid={LEGEND_STUDIO_TEST_ID.STATUS_BAR}
470
+ className="editor__status-bar"
471
+ />
472
+ </div>
473
+ </div>
474
+ );
475
+ }),
476
+ );
package/src/index.ts ADDED
@@ -0,0 +1,17 @@
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
+ export { DSL_Service_LegendStudioApplicationPlugin } from './components/studio/DSL_Service_LegendStudioApplicationPlugin.js';
@@ -0,0 +1,159 @@
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 { generateExtensionUrlPattern } from '@finos/legend-application';
18
+ import { assertTrue, guaranteeNonEmptyString } from '@finos/legend-shared';
19
+ import {
20
+ generateGAVCoordinates,
21
+ parseGACoordinates,
22
+ } from '@finos/legend-storage';
23
+ import { generatePath } from 'react-router';
24
+
25
+ const SERVICE_COORDINATE_DELIMITER = '@';
26
+
27
+ export const parseServiceCoordinates = (
28
+ val: string,
29
+ ): {
30
+ servicePath: string;
31
+ groupId: string;
32
+ artifactId: string;
33
+ } => {
34
+ const parts = val.split(SERVICE_COORDINATE_DELIMITER);
35
+ assertTrue(
36
+ parts.length === 2,
37
+ `Can't parse service coordinates '${val}': expect the coordinates to follow format {servicePath}${SERVICE_COORDINATE_DELIMITER}{GACoordinates}`,
38
+ );
39
+ const { groupId, artifactId } = parseGACoordinates(
40
+ guaranteeNonEmptyString(
41
+ parts[1]?.trim(),
42
+ `Service coordinates GA coordinates are missing or empty`,
43
+ ),
44
+ );
45
+ return {
46
+ groupId,
47
+ artifactId,
48
+ servicePath: guaranteeNonEmptyString(
49
+ parts[0]?.trim(),
50
+ `Service coordinates service path is missing or empty`,
51
+ ),
52
+ };
53
+ };
54
+
55
+ export const generateServiceCoordinates = (
56
+ groupId: string,
57
+ artifactId: string,
58
+ servicePath: string,
59
+ ): string =>
60
+ `${servicePath}${SERVICE_COORDINATE_DELIMITER}${generateGAVCoordinates(
61
+ groupId,
62
+ artifactId,
63
+ undefined,
64
+ )}`;
65
+
66
+ export enum DSL_SERVICE_PATH_PARAM_TOKEN {
67
+ SERVICE_COORDINATES = 'serviceCoordinates',
68
+ PROJECT_ID = 'projectId',
69
+ GROUP_WORKSPACE_ID = 'groupWorkspaceId',
70
+ SERVICE_PATH = 'servicePath',
71
+ }
72
+
73
+ export const DSL_SERVICE_LEGEND_STUDIO_ROUTE_PATTERN = Object.freeze({
74
+ UPDATE_SERVICE_QUERY_SETUP: `/update-service-query/:${DSL_SERVICE_PATH_PARAM_TOKEN.SERVICE_COORDINATES}?`,
75
+ UPDATE_SERVICE_QUERY: `/update-service-query/:${DSL_SERVICE_PATH_PARAM_TOKEN.SERVICE_COORDINATES}/:${DSL_SERVICE_PATH_PARAM_TOKEN.GROUP_WORKSPACE_ID}`,
76
+ UPDATE_PROJECT_SERVICE_QUERY_SETUP: `/update-project-service-query/:${DSL_SERVICE_PATH_PARAM_TOKEN.PROJECT_ID}?`,
77
+ UPDATE_PROJECT_SERVICE_QUERY: `/update-project-service-query/:${DSL_SERVICE_PATH_PARAM_TOKEN.PROJECT_ID}/:${DSL_SERVICE_PATH_PARAM_TOKEN.GROUP_WORKSPACE_ID}/:${DSL_SERVICE_PATH_PARAM_TOKEN.SERVICE_PATH}`,
78
+ });
79
+
80
+ export interface ServiceQueryUpdaterSetupPathParams {
81
+ [DSL_SERVICE_PATH_PARAM_TOKEN.SERVICE_COORDINATES]?: string;
82
+ }
83
+
84
+ export const generateServiceQueryUpdaterSetupRoute = (
85
+ groupId?: string,
86
+ artifactId?: string,
87
+ servicePath?: string,
88
+ ): string =>
89
+ generatePath(
90
+ generateExtensionUrlPattern(
91
+ DSL_SERVICE_LEGEND_STUDIO_ROUTE_PATTERN.UPDATE_SERVICE_QUERY_SETUP,
92
+ ),
93
+ {
94
+ [DSL_SERVICE_PATH_PARAM_TOKEN.SERVICE_COORDINATES]:
95
+ groupId && artifactId && servicePath
96
+ ? generateServiceCoordinates(groupId, artifactId, servicePath)
97
+ : undefined,
98
+ },
99
+ );
100
+
101
+ export interface ServiceQueryUpdaterPathParams {
102
+ [DSL_SERVICE_PATH_PARAM_TOKEN.SERVICE_COORDINATES]: string;
103
+ [DSL_SERVICE_PATH_PARAM_TOKEN.GROUP_WORKSPACE_ID]: string;
104
+ }
105
+
106
+ export const generateServiceQueryUpdaterRoute = (
107
+ groupId: string,
108
+ artifactId: string,
109
+ servicePath: string,
110
+ groupWorkspaceId: string,
111
+ ): string =>
112
+ generatePath(
113
+ generateExtensionUrlPattern(
114
+ DSL_SERVICE_LEGEND_STUDIO_ROUTE_PATTERN.UPDATE_SERVICE_QUERY,
115
+ ),
116
+ {
117
+ [DSL_SERVICE_PATH_PARAM_TOKEN.SERVICE_COORDINATES]:
118
+ generateServiceCoordinates(groupId, artifactId, servicePath),
119
+ [DSL_SERVICE_PATH_PARAM_TOKEN.GROUP_WORKSPACE_ID]: groupWorkspaceId,
120
+ },
121
+ );
122
+
123
+ export interface ProjectServiceQueryUpdaterSetupPathParams {
124
+ [DSL_SERVICE_PATH_PARAM_TOKEN.PROJECT_ID]?: string;
125
+ }
126
+
127
+ export const generateProjectServiceQueryUpdaterSetupRoute = (
128
+ projectId?: string,
129
+ ): string =>
130
+ generatePath(
131
+ generateExtensionUrlPattern(
132
+ DSL_SERVICE_LEGEND_STUDIO_ROUTE_PATTERN.UPDATE_PROJECT_SERVICE_QUERY_SETUP,
133
+ ),
134
+ {
135
+ [DSL_SERVICE_PATH_PARAM_TOKEN.PROJECT_ID]: projectId,
136
+ },
137
+ );
138
+
139
+ export interface ProjectServiceQueryUpdaterPathParams {
140
+ [DSL_SERVICE_PATH_PARAM_TOKEN.PROJECT_ID]: string;
141
+ [DSL_SERVICE_PATH_PARAM_TOKEN.GROUP_WORKSPACE_ID]: string;
142
+ [DSL_SERVICE_PATH_PARAM_TOKEN.SERVICE_PATH]: string;
143
+ }
144
+
145
+ export const generateProjectServiceQueryUpdaterRoute = (
146
+ projectId: string,
147
+ groupWorkspaceId: string,
148
+ servicePath: string,
149
+ ): string =>
150
+ generatePath(
151
+ generateExtensionUrlPattern(
152
+ DSL_SERVICE_LEGEND_STUDIO_ROUTE_PATTERN.UPDATE_PROJECT_SERVICE_QUERY,
153
+ ),
154
+ {
155
+ [DSL_SERVICE_PATH_PARAM_TOKEN.PROJECT_ID]: projectId,
156
+ [DSL_SERVICE_PATH_PARAM_TOKEN.GROUP_WORKSPACE_ID]: groupWorkspaceId,
157
+ [DSL_SERVICE_PATH_PARAM_TOKEN.SERVICE_PATH]: servicePath,
158
+ },
159
+ );