@finos/legend-application-studio 28.8.0 → 28.9.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.
Files changed (81) hide show
  1. package/lib/__lib__/LegendStudioNavigation.d.ts +6 -0
  2. package/lib/__lib__/LegendStudioNavigation.d.ts.map +1 -1
  3. package/lib/__lib__/LegendStudioNavigation.js +5 -0
  4. package/lib/__lib__/LegendStudioNavigation.js.map +1 -1
  5. package/lib/components/LegendStudioWebApplication.d.ts.map +1 -1
  6. package/lib/components/LegendStudioWebApplication.js +4 -1
  7. package/lib/components/LegendStudioWebApplication.js.map +1 -1
  8. package/lib/components/ShowcaseManager.d.ts.map +1 -1
  9. package/lib/components/ShowcaseManager.js +6 -1
  10. package/lib/components/ShowcaseManager.js.map +1 -1
  11. package/lib/components/editor/editor-group/GrammarTextEditor.js +1 -1
  12. package/lib/components/editor/editor-group/GrammarTextEditor.js.map +1 -1
  13. package/lib/components/editor/side-bar/Explorer.d.ts.map +1 -1
  14. package/lib/components/editor/side-bar/Explorer.js +3 -2
  15. package/lib/components/editor/side-bar/Explorer.js.map +1 -1
  16. package/lib/components/project-view/ProjectViewer.d.ts.map +1 -1
  17. package/lib/components/project-view/ProjectViewer.js +37 -5
  18. package/lib/components/project-view/ProjectViewer.js.map +1 -1
  19. package/lib/components/showcase/ShowcaseViewer.d.ts +18 -0
  20. package/lib/components/showcase/ShowcaseViewer.d.ts.map +1 -0
  21. package/lib/components/showcase/ShowcaseViewer.js +147 -0
  22. package/lib/components/showcase/ShowcaseViewer.js.map +1 -0
  23. package/lib/components/showcase/ShowcaseViewerStoreProvider.d.ts +23 -0
  24. package/lib/components/showcase/ShowcaseViewerStoreProvider.d.ts.map +1 -0
  25. package/lib/components/showcase/ShowcaseViewerStoreProvider.js +36 -0
  26. package/lib/components/showcase/ShowcaseViewerStoreProvider.js.map +1 -0
  27. package/lib/index.css +2 -2
  28. package/lib/index.css.map +1 -1
  29. package/lib/package.json +1 -1
  30. package/lib/stores/LegendStudioBaseStore.d.ts.map +1 -1
  31. package/lib/stores/LegendStudioBaseStore.js +1 -0
  32. package/lib/stores/LegendStudioBaseStore.js.map +1 -1
  33. package/lib/stores/editor/EditorMode.d.ts +4 -0
  34. package/lib/stores/editor/EditorMode.d.ts.map +1 -1
  35. package/lib/stores/editor/EditorMode.js +9 -0
  36. package/lib/stores/editor/EditorMode.js.map +1 -1
  37. package/lib/stores/editor/EditorStore.d.ts.map +1 -1
  38. package/lib/stores/editor/EditorStore.js +1 -3
  39. package/lib/stores/editor/EditorStore.js.map +1 -1
  40. package/lib/stores/editor/StandardEditorMode.d.ts +1 -0
  41. package/lib/stores/editor/StandardEditorMode.d.ts.map +1 -1
  42. package/lib/stores/editor/StandardEditorMode.js +4 -0
  43. package/lib/stores/editor/StandardEditorMode.js.map +1 -1
  44. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.d.ts.map +1 -1
  45. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.js +20 -4
  46. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.js.map +1 -1
  47. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestingHelper.d.ts +3 -0
  48. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestingHelper.d.ts.map +1 -1
  49. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestingHelper.js +17 -2
  50. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestingHelper.js.map +1 -1
  51. package/lib/stores/project-view/ProjectViewerEditorMode.d.ts +3 -0
  52. package/lib/stores/project-view/ProjectViewerEditorMode.d.ts.map +1 -1
  53. package/lib/stores/project-view/ProjectViewerEditorMode.js +10 -0
  54. package/lib/stores/project-view/ProjectViewerEditorMode.js.map +1 -1
  55. package/lib/stores/showcase/ShowcaseViewerEditorMode.d.ts +28 -0
  56. package/lib/stores/showcase/ShowcaseViewerEditorMode.d.ts.map +1 -0
  57. package/lib/stores/showcase/ShowcaseViewerEditorMode.js +40 -0
  58. package/lib/stores/showcase/ShowcaseViewerEditorMode.js.map +1 -0
  59. package/lib/stores/showcase/ShowcaseViewerStore.d.ts +32 -0
  60. package/lib/stores/showcase/ShowcaseViewerStore.d.ts.map +1 -0
  61. package/lib/stores/showcase/ShowcaseViewerStore.js +189 -0
  62. package/lib/stores/showcase/ShowcaseViewerStore.js.map +1 -0
  63. package/package.json +7 -7
  64. package/src/__lib__/LegendStudioNavigation.ts +11 -0
  65. package/src/components/LegendStudioWebApplication.tsx +11 -1
  66. package/src/components/ShowcaseManager.tsx +26 -2
  67. package/src/components/editor/editor-group/GrammarTextEditor.tsx +1 -1
  68. package/src/components/editor/side-bar/Explorer.tsx +20 -12
  69. package/src/components/project-view/ProjectViewer.tsx +139 -4
  70. package/src/components/showcase/ShowcaseViewer.tsx +418 -0
  71. package/src/components/showcase/ShowcaseViewerStoreProvider.tsx +56 -0
  72. package/src/stores/LegendStudioBaseStore.ts +1 -0
  73. package/src/stores/editor/EditorMode.ts +14 -0
  74. package/src/stores/editor/EditorStore.ts +1 -8
  75. package/src/stores/editor/StandardEditorMode.ts +7 -0
  76. package/src/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.ts +31 -9
  77. package/src/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestingHelper.ts +23 -0
  78. package/src/stores/project-view/ProjectViewerEditorMode.ts +17 -0
  79. package/src/stores/showcase/ShowcaseViewerEditorMode.ts +51 -0
  80. package/src/stores/showcase/ShowcaseViewerStore.ts +285 -0
  81. package/tsconfig.json +4 -0
@@ -0,0 +1,418 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { observer } from 'mobx-react-lite';
18
+ import {
19
+ useEditorStore,
20
+ withEditorStore,
21
+ } from '../editor/EditorStoreProvider.js';
22
+ import {
23
+ useShowcaseViewerStore,
24
+ withShowcaseViewerStore,
25
+ } from './ShowcaseViewerStoreProvider.js';
26
+ import { useParams } from '@finos/legend-application/browser';
27
+ import type { ShowcaseViewerPathParams } from '../../__lib__/LegendStudioNavigation.js';
28
+ import { isNonNullable } from '@finos/legend-shared';
29
+ import { Fragment, useEffect } from 'react';
30
+ import {
31
+ getCollapsiblePanelGroupProps,
32
+ useResizeDetector,
33
+ type ResizablePanelHandlerProps,
34
+ ResizablePanel,
35
+ ResizablePanelSplitter,
36
+ ResizablePanelGroup,
37
+ FileTrayIcon,
38
+ clsx,
39
+ HackerIcon,
40
+ AssistantIcon,
41
+ ReadMeIcon,
42
+ FireIcon,
43
+ HammerIcon,
44
+ TerminalIcon,
45
+ TrashIcon,
46
+ ResizablePanelSplitterLine,
47
+ } from '@finos/legend-art';
48
+ import { useApplicationStore, useCommands } from '@finos/legend-application';
49
+ import { flowResult } from 'mobx';
50
+ import { EditorGroup } from '../editor/editor-group/EditorGroup.js';
51
+ import { GrammarTextEditor } from '../editor/editor-group/GrammarTextEditor.js';
52
+ import { ProjectSearchCommand } from '../editor/command-center/ProjectSearchCommand.js';
53
+ import { EmbeddedQueryBuilder } from '../editor/EmbeddedQueryBuilder.js';
54
+ import {
55
+ ACTIVITY_MODE,
56
+ GRAPH_EDITOR_MODE,
57
+ } from '../../stores/editor/EditorConfig.js';
58
+ import { ActivityBarMenu } from '../editor/ActivityBar.js';
59
+ import type { ActivityBarItemConfig } from '@finos/legend-lego/application';
60
+ import { useLegendStudioApplicationStore } from '../LegendStudioFrameworkProvider.js';
61
+ import { LEGEND_STUDIO_TEST_ID } from '../../__lib__/LegendStudioTesting.js';
62
+ import { Explorer } from '../editor/side-bar/Explorer.js';
63
+ import { PanelGroup } from '../editor/panel-group/PanelGroup.js';
64
+
65
+ const ShowcaseViewerStatusBar = observer(() => {
66
+ const editorStore = useEditorStore();
67
+ const showcaseStore = useShowcaseViewerStore();
68
+ const showcase = showcaseStore._showcase;
69
+ const applicationStore = useLegendStudioApplicationStore();
70
+ const handleTextModeClick = applicationStore.guardUnhandledError(() =>
71
+ flowResult(editorStore.toggleTextMode()),
72
+ );
73
+ const editable =
74
+ editorStore.graphManagerState.graphBuildState.hasCompleted &&
75
+ editorStore.isInitialized;
76
+ const togglePanel = (): void => editorStore.panelGroupDisplayState.toggle();
77
+
78
+ const compile = applicationStore.guardUnhandledError(() =>
79
+ flowResult(editorStore.graphEditorMode.globalCompile()),
80
+ );
81
+ const generate = applicationStore.guardUnhandledError(() =>
82
+ flowResult(editorStore.graphState.graphGenerationState.globalGenerate()),
83
+ );
84
+ const emptyGenerationEntities = applicationStore.guardUnhandledError(() =>
85
+ flowResult(editorStore.graphState.graphGenerationState.clearGenerations()),
86
+ );
87
+ const toggleAssistant = (): void =>
88
+ applicationStore.assistantService.toggleAssistant();
89
+
90
+ return (
91
+ <div
92
+ data-testid={LEGEND_STUDIO_TEST_ID.STATUS_BAR}
93
+ className="editor__status-bar project-view__status-bar"
94
+ >
95
+ <div className="editor__status-bar__left">
96
+ {showcase && (
97
+ <div className="editor__status-bar__workspace">
98
+ <div className="editor__status-bar__workspace__icon">
99
+ <ReadMeIcon />
100
+ </div>
101
+ <div className="editor__status-bar__workspace__project">
102
+ <button
103
+ className="editor__status-bar__workspace__project"
104
+ tabIndex={-1}
105
+ >
106
+ {`Showcase : ${showcase.title}`}
107
+ </button>
108
+ </div>
109
+ </div>
110
+ )}
111
+ </div>
112
+ <div className="editor__status-bar__right">
113
+ <button
114
+ className={clsx(
115
+ 'editor__status-bar__action editor__status-bar__generate-btn',
116
+ {
117
+ 'editor__status-bar__generate-btn--wiggling':
118
+ editorStore.graphState.graphGenerationState
119
+ .isRunningGlobalGenerate,
120
+ },
121
+ )}
122
+ disabled={
123
+ editorStore.graphState.isApplicationUpdateOperationIsRunning
124
+ }
125
+ onClick={generate}
126
+ tabIndex={-1}
127
+ title="Generate (F10)"
128
+ >
129
+ <FireIcon />
130
+ </button>
131
+ <button
132
+ className={clsx(
133
+ 'editor__status-bar__action editor__status-bar__clear__generation-btn ',
134
+
135
+ {
136
+ 'editor__status-bar__action editor__status-bar__clear__generation-btn--wiggling':
137
+ editorStore.graphState.graphGenerationState
138
+ .clearingGenerationEntitiesState.isInProgress,
139
+ },
140
+ )}
141
+ disabled={
142
+ editorStore.graphState.isApplicationUpdateOperationIsRunning ||
143
+ !editable
144
+ }
145
+ onClick={emptyGenerationEntities}
146
+ tabIndex={-1}
147
+ title="Clear generation entities"
148
+ >
149
+ <TrashIcon />
150
+ </button>
151
+ <button
152
+ className={clsx(
153
+ 'editor__status-bar__action editor__status-bar__compile-btn',
154
+ {
155
+ 'editor__status-bar__compile-btn--wiggling':
156
+ editorStore.graphState.isRunningGlobalCompile,
157
+ },
158
+ )}
159
+ disabled={
160
+ editorStore.graphState.isApplicationUpdateOperationIsRunning ||
161
+ !editable
162
+ }
163
+ onClick={compile}
164
+ tabIndex={-1}
165
+ title="Compile (F9)"
166
+ >
167
+ <HammerIcon />
168
+ </button>
169
+ <button
170
+ className={clsx(
171
+ 'editor__status-bar__action editor__status-bar__action__toggler',
172
+ {
173
+ 'editor__status-bar__action__toggler--active':
174
+ editorStore.panelGroupDisplayState.isOpen,
175
+ },
176
+ )}
177
+ onClick={togglePanel}
178
+ tabIndex={-1}
179
+ title="Toggle panel (Ctrl + `)"
180
+ >
181
+ <TerminalIcon />
182
+ </button>
183
+ <button
184
+ className={clsx(
185
+ 'editor__status-bar__action editor__status-bar__action__toggler',
186
+ {
187
+ 'editor__status-bar__action__toggler--active':
188
+ editorStore.graphEditorMode.mode ===
189
+ GRAPH_EDITOR_MODE.GRAMMAR_TEXT,
190
+ },
191
+ )}
192
+ onClick={handleTextModeClick}
193
+ tabIndex={-1}
194
+ title="Toggle text mode (F8)"
195
+ >
196
+ <HackerIcon />
197
+ </button>
198
+ <button
199
+ className={clsx(
200
+ 'editor__status-bar__action editor__status-bar__action__toggler',
201
+ {
202
+ 'editor__status-bar__action__toggler--active':
203
+ !applicationStore.assistantService.isHidden,
204
+ },
205
+ )}
206
+ onClick={toggleAssistant}
207
+ tabIndex={-1}
208
+ title="Toggle assistant"
209
+ >
210
+ <AssistantIcon />
211
+ </button>
212
+ </div>
213
+ </div>
214
+ );
215
+ });
216
+
217
+ const ShowcaseViewerActivityBar = observer(() => {
218
+ const editorStore = useEditorStore();
219
+
220
+ const changeActivity =
221
+ (activity: string): (() => void) =>
222
+ (): void =>
223
+ editorStore.setActiveActivity(activity);
224
+ // tabs
225
+ const activities: ActivityBarItemConfig[] = (
226
+ [
227
+ {
228
+ mode: ACTIVITY_MODE.EXPLORER,
229
+ title: 'Explorer (Ctrl + Shift + X)',
230
+ icon: <FileTrayIcon />,
231
+ },
232
+ ] as (ActivityBarItemConfig | boolean)[]
233
+ ).filter((activity): activity is ActivityBarItemConfig => Boolean(activity));
234
+
235
+ return (
236
+ <div className="activity-bar">
237
+ <ActivityBarMenu />
238
+ <div className="activity-bar__items">
239
+ {activities.map((activity) => (
240
+ <button
241
+ key={activity.mode}
242
+ className={clsx('activity-bar__item', {
243
+ 'activity-bar__item--active':
244
+ editorStore.sideBarDisplayState.isOpen &&
245
+ editorStore.activeActivity === activity.mode,
246
+ })}
247
+ onClick={changeActivity(activity.mode)}
248
+ tabIndex={-1}
249
+ title={activity.title}
250
+ >
251
+ {activity.icon}
252
+ </button>
253
+ ))}
254
+ </div>
255
+ </div>
256
+ );
257
+ });
258
+
259
+ const ShowcaseViewerSideBar = observer(() => {
260
+ const editorStore = useEditorStore();
261
+ const renderSideBar = (): React.ReactNode => {
262
+ switch (editorStore.activeActivity) {
263
+ case ACTIVITY_MODE.EXPLORER:
264
+ return <Explorer />;
265
+ default:
266
+ return null;
267
+ }
268
+ };
269
+ return (
270
+ <div className="side-bar">
271
+ <div className="side-bar__view">{renderSideBar()}</div>
272
+ </div>
273
+ );
274
+ });
275
+
276
+ export const ShowcaseViewer = withEditorStore(
277
+ withShowcaseViewerStore(
278
+ observer(() => {
279
+ const params = useParams<ShowcaseViewerPathParams>();
280
+ const showcaseStore = useShowcaseViewerStore();
281
+ const applicationStore = useApplicationStore();
282
+ const editorStore = useEditorStore();
283
+
284
+ // Extensions
285
+ const extraEditorExtensionComponents = editorStore.pluginManager
286
+ .getApplicationPlugins()
287
+ .flatMap(
288
+ (plugin) =>
289
+ plugin.getExtraEditorExtensionComponentRendererConfigurations?.() ??
290
+ [],
291
+ )
292
+ .filter(isNonNullable)
293
+ .map((config) => (
294
+ <Fragment key={config.key}>{config.renderer(editorStore)}</Fragment>
295
+ ));
296
+
297
+ // layout
298
+ const resizeSideBar = (handleProps: ResizablePanelHandlerProps): void =>
299
+ editorStore.sideBarDisplayState.setSize(
300
+ (handleProps.domElement as HTMLDivElement).getBoundingClientRect()
301
+ .width,
302
+ );
303
+ const sideBarCollapsiblePanelGroupProps = getCollapsiblePanelGroupProps(
304
+ editorStore.sideBarDisplayState.size === 0,
305
+ {
306
+ onStopResize: resizeSideBar,
307
+ size: editorStore.sideBarDisplayState.size,
308
+ },
309
+ );
310
+ const resizePanel = (handleProps: ResizablePanelHandlerProps): void =>
311
+ editorStore.panelGroupDisplayState.setSize(
312
+ (handleProps.domElement as HTMLDivElement).getBoundingClientRect()
313
+ .height,
314
+ );
315
+ const collapsiblePanelGroupProps = getCollapsiblePanelGroupProps(
316
+ editorStore.panelGroupDisplayState.size === 0,
317
+ {
318
+ onStopResize: resizePanel,
319
+ size: editorStore.panelGroupDisplayState.size,
320
+ },
321
+ );
322
+ const collapsibleSideBarGroupProps = getCollapsiblePanelGroupProps(
323
+ editorStore.sideBarDisplayState.size === 0,
324
+ {
325
+ onStopResize: resizeSideBar,
326
+ size: editorStore.sideBarDisplayState.size,
327
+ },
328
+ );
329
+ const maximizedCollapsiblePanelGroupProps = getCollapsiblePanelGroupProps(
330
+ editorStore.panelGroupDisplayState.isMaximized,
331
+ );
332
+ const { ref, width, height } = useResizeDetector<HTMLDivElement>();
333
+ useEffect(() => {
334
+ if (ref.current) {
335
+ editorStore.panelGroupDisplayState.setMaxSize(
336
+ ref.current.offsetHeight,
337
+ );
338
+ }
339
+ }, [ref, editorStore, width, height]);
340
+
341
+ // initialize
342
+ useEffect(() => {
343
+ flowResult(showcaseStore.initialize(params)).catch(
344
+ applicationStore.alertUnhandledError,
345
+ );
346
+ }, [applicationStore, showcaseStore, params]);
347
+
348
+ useCommands(editorStore);
349
+
350
+ return (
351
+ <div className="app__page">
352
+ <div className="editor viewer">
353
+ <div className="editor__body">
354
+ <ShowcaseViewerActivityBar />
355
+ <div ref={ref} className="editor__content-container">
356
+ <div className="editor__content">
357
+ <ResizablePanelGroup orientation="vertical">
358
+ <ResizablePanel
359
+ {...sideBarCollapsiblePanelGroupProps.collapsiblePanel}
360
+ direction={1}
361
+ >
362
+ <ShowcaseViewerSideBar />
363
+ </ResizablePanel>
364
+ <ResizablePanelSplitter />
365
+ <ResizablePanel
366
+ {...collapsibleSideBarGroupProps.remainingPanel}
367
+ minSize={300}
368
+ >
369
+ <ResizablePanelGroup orientation="horizontal">
370
+ <ResizablePanel
371
+ {...maximizedCollapsiblePanelGroupProps.collapsiblePanel}
372
+ {...(editorStore.panelGroupDisplayState.size === 0
373
+ ? collapsiblePanelGroupProps.remainingPanel
374
+ : {})}
375
+ >
376
+ {editorStore.graphEditorMode.mode ===
377
+ GRAPH_EDITOR_MODE.FORM && <EditorGroup />}
378
+ {editorStore.graphEditorMode.mode ===
379
+ GRAPH_EDITOR_MODE.GRAMMAR_TEXT && (
380
+ <GrammarTextEditor />
381
+ )}
382
+ </ResizablePanel>
383
+ <ResizablePanelSplitter>
384
+ <ResizablePanelSplitterLine
385
+ color={
386
+ editorStore.panelGroupDisplayState.isMaximized
387
+ ? 'transparent'
388
+ : 'var(--color-dark-grey-250)'
389
+ }
390
+ />
391
+ </ResizablePanelSplitter>
392
+ <ResizablePanel
393
+ {...collapsiblePanelGroupProps.collapsiblePanel}
394
+ {...(editorStore.panelGroupDisplayState.isMaximized
395
+ ? maximizedCollapsiblePanelGroupProps.remainingPanel
396
+ : {})}
397
+ direction={-1}
398
+ >
399
+ <PanelGroup />
400
+ </ResizablePanel>
401
+ </ResizablePanelGroup>
402
+ </ResizablePanel>
403
+ </ResizablePanelGroup>
404
+ </div>
405
+ </div>
406
+ </div>
407
+ {editorStore.graphManagerState.graphBuildState.hasSucceeded && (
408
+ <ProjectSearchCommand />
409
+ )}
410
+ <ShowcaseViewerStatusBar />
411
+ <EmbeddedQueryBuilder />
412
+ {extraEditorExtensionComponents}
413
+ </div>
414
+ </div>
415
+ );
416
+ }),
417
+ ),
418
+ );
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { createContext, useContext } from 'react';
18
+ import { ShowcaseViewerStore } from '../../stores/showcase/ShowcaseViewerStore.js';
19
+ import { useEditorStore } from '../editor/EditorStoreProvider.js';
20
+ import { useLocalObservable } from 'mobx-react-lite';
21
+ import { guaranteeNonNullable } from '@finos/legend-shared';
22
+ import { EDITOR_MODE } from '../../stores/editor/EditorConfig.js';
23
+ import { ShowcaseViewerEditorMode } from '../../stores/showcase/ShowcaseViewerEditorMode.js';
24
+
25
+ const ShowcaseViewerStoreContext = createContext<
26
+ ShowcaseViewerStore | undefined
27
+ >(undefined);
28
+
29
+ export const ShowcaseViewerStoreProvider: React.FC<{
30
+ children: React.ReactNode;
31
+ }> = ({ children }) => {
32
+ const editorStore = useEditorStore();
33
+ editorStore.setMode(EDITOR_MODE.VIEWER);
34
+ const store = useLocalObservable(() => new ShowcaseViewerStore(editorStore));
35
+ editorStore.setEditorMode(new ShowcaseViewerEditorMode(store));
36
+ return (
37
+ <ShowcaseViewerStoreContext.Provider value={store}>
38
+ {children}
39
+ </ShowcaseViewerStoreContext.Provider>
40
+ );
41
+ };
42
+
43
+ export const useShowcaseViewerStore = (): ShowcaseViewerStore =>
44
+ guaranteeNonNullable(
45
+ useContext(ShowcaseViewerStoreContext),
46
+ `Can't find showcase viewer store in context`,
47
+ );
48
+
49
+ export const withShowcaseViewerStore = (WrapperComponent: React.FC): React.FC =>
50
+ function WithShowcaseViewerStore() {
51
+ return (
52
+ <ShowcaseViewerStoreProvider>
53
+ <WrapperComponent />
54
+ </ShowcaseViewerStoreProvider>
55
+ );
56
+ };
@@ -124,6 +124,7 @@ export class LegendStudioBaseStore {
124
124
  LEGEND_STUDIO_SDLC_BYPASSED_ROUTE_PATTERN.VIEW_BY_GAV,
125
125
  LEGEND_STUDIO_SDLC_BYPASSED_ROUTE_PATTERN.VIEW_BY_GAV_ENTITY,
126
126
  LEGEND_STUDIO_SDLC_BYPASSED_ROUTE_PATTERN.PREVIEW_BY_GAV_ENTITY,
127
+ LEGEND_STUDIO_SDLC_BYPASSED_ROUTE_PATTERN.SHOWCASE_PROJECT,
127
128
  ],
128
129
  )
129
130
  ) {
@@ -29,4 +29,18 @@ export abstract class EditorMode {
29
29
  elementPath: string,
30
30
  dependencyProject: ProjectDependency,
31
31
  ): string;
32
+
33
+ abstract get isInitialized(): boolean;
34
+
35
+ get supportSdlcOperations(): boolean {
36
+ return true;
37
+ }
38
+
39
+ get disableEditing(): boolean {
40
+ return false;
41
+ }
42
+
43
+ get label(): string | undefined {
44
+ return undefined;
45
+ }
32
46
  }
@@ -102,7 +102,6 @@ import type { LegendStudioApplicationStore } from '../LegendStudioBaseStore.js';
102
102
  import { EmbeddedQueryBuilderState } from './EmbeddedQueryBuilderState.js';
103
103
  import { LEGEND_STUDIO_COMMAND_KEY } from '../../__lib__/LegendStudioCommand.js';
104
104
  import { EditorTabManagerState } from './EditorTabManagerState.js';
105
- import type { ProjectViewerEditorMode } from '../project-view/ProjectViewerEditorMode.js';
106
105
  import { GraphEditFormModeState } from './GraphEditFormModeState.js';
107
106
  import type { GraphEditorMode } from './GraphEditorMode.js';
108
107
  import { GraphEditGrammarModeState } from './GraphEditGrammarModeState.js';
@@ -296,13 +295,7 @@ export class EditorStore implements CommandRegistrar {
296
295
  get isInitialized(): boolean {
297
296
  if (this.isInViewerMode) {
298
297
  return (
299
- (Boolean(
300
- this.sdlcState.currentProject && this.sdlcState.currentWorkspace,
301
- ) ||
302
- Boolean(
303
- (this.sdlcState.editorStore.editorMode as ProjectViewerEditorMode)
304
- .viewerStore.projectGAVCoordinates,
305
- )) &&
298
+ this.editorMode.isInitialized &&
306
299
  this.graphManagerState.systemBuildState.hasSucceeded
307
300
  );
308
301
  } else {
@@ -58,4 +58,11 @@ export class StandardEditorMode extends EditorMode {
58
58
  elementPath,
59
59
  );
60
60
  }
61
+
62
+ override get isInitialized(): boolean {
63
+ return Boolean(
64
+ this.editorStore.sdlcState.currentProject &&
65
+ this.editorStore.sdlcState.currentWorkspace,
66
+ );
67
+ }
61
68
  }
@@ -81,6 +81,7 @@ import {
81
81
  createBareMappingTest,
82
82
  createGraphFetchQueryFromMappingAnalysis,
83
83
  generateStoreTestDataFromSetImpl,
84
+ isRelationalMappingTestSuite,
84
85
  } from './MappingTestingHelper.js';
85
86
  import { LEGEND_STUDIO_APP_EVENT } from '../../../../../../__lib__/LegendStudioEvent.js';
86
87
 
@@ -729,15 +730,36 @@ export class MappingTestableState {
729
730
  this.selectedTestSuite?.testStates.forEach((t) =>
730
731
  t.runningTestAction.inProgress(),
731
732
  );
732
- const input = new RunTestsTestableInput(this.mapping);
733
- suite.tests.forEach((t) =>
734
- input.unitTestIds.push(new UniqueTestId(suite, t)),
735
- );
736
- const testResults =
737
- (yield this.editorStore.graphManagerState.graphManager.runTests(
738
- [input],
739
- this.editorStore.graphManagerState.graph,
740
- )) as TestResult[];
733
+ let testResults: TestResult[];
734
+ if (isRelationalMappingTestSuite(suite)) {
735
+ // TEMPORARY RUN each test separately. This is done to help with performance
736
+ // specifically with running realtional mapping tests as we generate a plan during each test.
737
+ // with this change we would still do this but in parallel reducing the time to run the suite
738
+ const inputs = suite.tests.map((t) => {
739
+ const input = new RunTestsTestableInput(this.mapping);
740
+ input.unitTestIds.push(new UniqueTestId(suite, t));
741
+ return input;
742
+ });
743
+ const _testResults = (yield Promise.all(
744
+ inputs.map((i) =>
745
+ this.editorStore.graphManagerState.graphManager.runTests(
746
+ [i],
747
+ this.editorStore.graphManagerState.graph,
748
+ ),
749
+ ),
750
+ )) as TestResult[][];
751
+ testResults = _testResults.flat();
752
+ } else {
753
+ const input = new RunTestsTestableInput(this.mapping);
754
+ suite.tests.forEach((t) =>
755
+ input.unitTestIds.push(new UniqueTestId(suite, t)),
756
+ );
757
+ testResults =
758
+ (yield this.editorStore.graphManagerState.graphManager.runTests(
759
+ [input],
760
+ this.editorStore.graphManagerState.graph,
761
+ )) as TestResult[];
762
+ }
741
763
  this.handleNewResults(testResults);
742
764
  } catch (error) {
743
765
  assertErrorThrown(error);
@@ -45,6 +45,7 @@ import {
45
45
  PropertyGraphFetchTree,
46
46
  PropertyExplicitReference,
47
47
  type ObserverContext,
48
+ Database,
48
49
  } from '@finos/legend-graph';
49
50
  import {
50
51
  buildGetAllFunction,
@@ -61,6 +62,7 @@ import {
61
62
  import {
62
63
  assertErrorThrown,
63
64
  assertTrue,
65
+ filterByType,
64
66
  guaranteeNonNullable,
65
67
  } from '@finos/legend-shared';
66
68
  import type { DSL_Data_LegendStudioApplicationPlugin_Extension } from '../../../../../extensions/DSL_Data_LegendStudioApplicationPlugin_Extension.js';
@@ -103,6 +105,27 @@ export const createStoreBareModelStoreData = (
103
105
  return testData;
104
106
  };
105
107
 
108
+ export const isRelationalStoreTestData = (val: StoreTestData): boolean =>
109
+ val.store.value instanceof Database;
110
+
111
+ export const isRelationalMappingTest = (val: MappingTest): boolean => {
112
+ if (!val.storeTestData.length) {
113
+ return false;
114
+ }
115
+ return val.storeTestData.some((e) => isRelationalStoreTestData(e));
116
+ };
117
+
118
+ export const isRelationalMappingTestSuite = (
119
+ val: MappingTestSuite,
120
+ ): boolean => {
121
+ if (!val.tests.length) {
122
+ return false;
123
+ }
124
+ return val.tests
125
+ .filter(filterByType(MappingTest))
126
+ .some((e) => isRelationalMappingTest(e));
127
+ };
128
+
106
129
  export const generateStoreTestDataFromSetImpl = (
107
130
  setImpl: SetImplementation,
108
131
  editorStore: EditorStore,
@@ -76,4 +76,21 @@ export class ProjectViewerEditorMode extends EditorMode {
76
76
  elementPath,
77
77
  );
78
78
  }
79
+
80
+ override get isInitialized(): boolean {
81
+ return (
82
+ Boolean(
83
+ this.viewerStore.editorStore.sdlcState.currentProject &&
84
+ this.viewerStore.editorStore.sdlcState.currentWorkspace,
85
+ ) || Boolean(this.viewerStore.projectGAVCoordinates)
86
+ );
87
+ }
88
+
89
+ override get disableEditing(): boolean {
90
+ return true;
91
+ }
92
+
93
+ override get supportSdlcOperations(): boolean {
94
+ return !this.viewerStore.projectGAVCoordinates;
95
+ }
79
96
  }