@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
@@ -20,6 +20,7 @@ import { guaranteeNonNullable } from '@finos/legend-shared';
20
20
  import { generatePath } from '@finos/legend-application/browser';
21
21
 
22
22
  export enum LEGEND_STUDIO_ROUTE_PATTERN_TOKEN {
23
+ SHOWCASE_PATH = 'showcasePath',
23
24
  PROJECT_ID = 'projectId',
24
25
  PATCH_RELEASE_VERSION_ID = 'patchReleaseVersionId',
25
26
  WORKSPACE_ID = 'workspaceId',
@@ -58,6 +59,7 @@ export const LEGEND_STUDIO_SDLC_BYPASSED_ROUTE_PATTERN = Object.freeze({
58
59
  VIEW_BY_GAV: `/view/archive/:${LEGEND_STUDIO_ROUTE_PATTERN_TOKEN.GAV}`,
59
60
  VIEW_BY_GAV_ENTITY: `/view/archive/:${LEGEND_STUDIO_ROUTE_PATTERN_TOKEN.GAV}/entity/:${LEGEND_STUDIO_ROUTE_PATTERN_TOKEN.ENTITY_PATH}`,
60
61
  PREVIEW_BY_GAV_ENTITY: `/view/archive/:${LEGEND_STUDIO_ROUTE_PATTERN_TOKEN.GAV}/entity/:${LEGEND_STUDIO_ROUTE_PATTERN_TOKEN.ENTITY_PATH}/preview`,
62
+ SHOWCASE_PROJECT: `/showcase/*`,
61
63
  });
62
64
 
63
65
  export type WorkspaceReviewPathParams = {
@@ -73,6 +75,10 @@ export type ProjectViewerPathParams = {
73
75
  [LEGEND_STUDIO_ROUTE_PATTERN_TOKEN.ENTITY_PATH]?: string;
74
76
  };
75
77
 
78
+ export type ShowcaseViewerPathParams = {
79
+ [0]?: string;
80
+ };
81
+
76
82
  export type WorkspaceEditorPathParams = {
77
83
  [LEGEND_STUDIO_ROUTE_PATTERN_TOKEN.PROJECT_ID]: string;
78
84
  [LEGEND_STUDIO_ROUTE_PATTERN_TOKEN.PATCH_RELEASE_VERSION_ID]?: string;
@@ -347,3 +353,8 @@ export const EXTERNAL_APPLICATION_NAVIGATION__generateServiceQueryCreatorUrl = (
347
353
  artifactId,
348
354
  versionId,
349
355
  )}/${servicePath}`;
356
+
357
+ export const generateShowcasePath = (projectPath: string): string =>
358
+ generatePath(LEGEND_STUDIO_SDLC_BYPASSED_ROUTE_PATTERN.SHOWCASE_PROJECT, {
359
+ 0: projectPath,
360
+ });
@@ -40,6 +40,7 @@ import {
40
40
  type TEMPORARY__ReactRouterComponentType,
41
41
  } from '@finos/legend-application/browser';
42
42
  import { LEGEND_STUDIO_DOCUMENTATION_KEY } from '../__lib__/LegendStudioDocumentation.js';
43
+ import { ShowcaseViewer } from './showcase/ShowcaseViewer.js';
43
44
 
44
45
  const NotFoundPage = observer(() => {
45
46
  const applicationStore = useApplicationStore();
@@ -114,7 +115,6 @@ export const LegendStudioWebApplicationRouter = observer(() => {
114
115
  applicationStore.alertUnhandledError,
115
116
  );
116
117
  }, [applicationStore, baseStore]);
117
-
118
118
  return (
119
119
  <div className="app">
120
120
  {baseStore.initState.hasCompleted && (
@@ -133,6 +133,16 @@ export const LegendStudioWebApplicationRouter = observer(() => {
133
133
  ProjectViewer as TEMPORARY__ReactRouterComponentType
134
134
  }
135
135
  />
136
+ <Route
137
+ exact={true}
138
+ path={
139
+ LEGEND_STUDIO_SDLC_BYPASSED_ROUTE_PATTERN.SHOWCASE_PROJECT
140
+ }
141
+ component={
142
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
143
+ ShowcaseViewer as TEMPORARY__ReactRouterComponentType
144
+ }
145
+ />
136
146
  <Route>
137
147
  <NotFoundPage />
138
148
  </Route>
@@ -48,6 +48,7 @@ import {
48
48
  CodeEditor,
49
49
  } from '@finos/legend-lego/code-editor';
50
50
  import React, { useEffect, useMemo, useRef } from 'react';
51
+ import { generateShowcasePath } from '../__lib__/LegendStudioNavigation.js';
51
52
 
52
53
  const ShowcasesExplorerTreeNodeContainer = observer(
53
54
  (
@@ -536,7 +537,14 @@ const ShowcaseViewer = observer(
536
537
  }) => {
537
538
  const { showcaseManagerState, showcase } = props;
538
539
  const prettyPath = showcase.path.replaceAll(/\s*\/\s*/g, ' / ');
539
-
540
+ const launchShowcase = (): void => {
541
+ const applicationStore = showcaseManagerState.applicationStore;
542
+ applicationStore.navigationService.navigator.visitAddress(
543
+ applicationStore.navigationService.navigator.generateAddress(
544
+ generateShowcasePath(showcase.path),
545
+ ),
546
+ );
547
+ };
540
548
  return (
541
549
  <div className="showcase-manager__view">
542
550
  <div className="showcase-manager__view__header">
@@ -583,7 +591,23 @@ const ShowcaseViewer = observer(
583
591
  </div>
584
592
  <div className="showcase-manager__view__content showcase-manager__viewer__content">
585
593
  <div className="showcase-manager__viewer__title">
586
- {showcase.title}
594
+ <div className="showcase-manager__viewer__title__label">
595
+ {showcase.title}
596
+ </div>
597
+ <div className="showcase-manager__viewer__title__action">
598
+ <div className="btn__dropdown-combo btn__dropdown-combo--primary showcase-manager__viewer__title__action-btn">
599
+ <button
600
+ className="btn__dropdown-combo__label"
601
+ onClick={launchShowcase}
602
+ title="Open Showcase Project"
603
+ tabIndex={-1}
604
+ >
605
+ <div className="btn__dropdown-combo__label__title">
606
+ Launch
607
+ </div>
608
+ </button>
609
+ </div>
610
+ </div>
587
611
  </div>
588
612
  <div className="showcase-manager__viewer__path">{prettyPath}</div>
589
613
  <div className="showcase-manager__viewer__code">
@@ -828,7 +828,7 @@ export const GrammarTextEditor = observer(() => {
828
828
  }
829
829
  }
830
830
  // Disable editing if user is in viewer mode
831
- editor.updateOptions({ readOnly: editorStore.isInViewerMode });
831
+ editor.updateOptions({ readOnly: editorStore.editorMode.disableEditing });
832
832
 
833
833
  // hover
834
834
  hoverProviderDisposer.current?.dispose();
@@ -1376,7 +1376,7 @@ const ProjectExplorerActionPanel = observer((props: { disabled: boolean }) => {
1376
1376
 
1377
1377
  return (
1378
1378
  <div className="panel__header__actions">
1379
- {!editorStore.isInViewerMode && (
1379
+ {
1380
1380
  <button
1381
1381
  className="panel__header__action"
1382
1382
  disabled={disabled}
@@ -1385,15 +1385,17 @@ const ProjectExplorerActionPanel = observer((props: { disabled: boolean }) => {
1385
1385
  >
1386
1386
  <FileImportIcon />
1387
1387
  </button>
1388
+ }
1389
+ {editorStore.editorMode.supportSdlcOperations && (
1390
+ <button
1391
+ className="panel__header__action panel__header__action--config"
1392
+ disabled={disabled}
1393
+ title="Project Configuration Panel"
1394
+ onClick={openConfigurationEditor}
1395
+ >
1396
+ <SettingsEthernetIcon />
1397
+ </button>
1388
1398
  )}
1389
- <button
1390
- className="panel__header__action panel__header__action--config"
1391
- disabled={disabled}
1392
- title="Project Configuration Panel"
1393
- onClick={openConfigurationEditor}
1394
- >
1395
- <SettingsEthernetIcon />
1396
- </button>
1397
1399
  {!editorStore.isInViewerMode && (
1398
1400
  <DropdownMenu
1399
1401
  className="panel__header__action"
@@ -1477,10 +1479,16 @@ export const Explorer = observer(() => {
1477
1479
  EXPLORER
1478
1480
  </div>
1479
1481
  </div>
1480
- {editorStore.isInViewerMode && (
1482
+ {editorStore.editorMode.disableEditing &&
1483
+ !editorStore.editorMode.label && (
1484
+ <div className="panel__header__title side-bar__header__title__viewer-mode-badge">
1485
+ <LockIcon />
1486
+ READ-ONLY
1487
+ </div>
1488
+ )}
1489
+ {editorStore.editorMode.label && (
1481
1490
  <div className="panel__header__title side-bar__header__title__viewer-mode-badge">
1482
- <LockIcon />
1483
- READ-ONLY
1491
+ {editorStore.editorMode.label}
1484
1492
  </div>
1485
1493
  )}
1486
1494
  </div>
@@ -37,6 +37,11 @@ import {
37
37
  FileTrayIcon,
38
38
  AssistantIcon,
39
39
  useResizeDetector,
40
+ FireIcon,
41
+ TrashIcon,
42
+ HammerIcon,
43
+ TerminalIcon,
44
+ ResizablePanelSplitterLine,
40
45
  } from '@finos/legend-art';
41
46
  import { isNonNullable } from '@finos/legend-shared';
42
47
  import {
@@ -65,6 +70,7 @@ import {
65
70
  import { EmbeddedQueryBuilder } from '../editor/EmbeddedQueryBuilder.js';
66
71
  import type { ActivityBarItemConfig } from '@finos/legend-lego/application';
67
72
  import { ActivityBarMenu } from '../editor/ActivityBar.js';
73
+ import { PanelGroup } from '../editor/panel-group/PanelGroup.js';
68
74
 
69
75
  const ProjectViewerStatusBar = observer(() => {
70
76
  const params = useParams<ProjectViewerPathParams>();
@@ -90,11 +96,26 @@ const ProjectViewerStatusBar = observer(() => {
90
96
  ? 'current'
91
97
  : ''
92
98
  }`;
99
+
100
+ const editable =
101
+ editorStore.graphManagerState.graphBuildState.hasCompleted &&
102
+ editorStore.isInitialized;
93
103
  const handleTextModeClick = applicationStore.guardUnhandledError(() =>
94
104
  flowResult(editorStore.toggleTextMode()),
95
105
  );
106
+ const compile = applicationStore.guardUnhandledError(() =>
107
+ flowResult(editorStore.graphEditorMode.globalCompile()),
108
+ );
109
+ const generate = applicationStore.guardUnhandledError(() =>
110
+ flowResult(editorStore.graphState.graphGenerationState.globalGenerate()),
111
+ );
112
+ const emptyGenerationEntities = applicationStore.guardUnhandledError(() =>
113
+ flowResult(editorStore.graphState.graphGenerationState.clearGenerations()),
114
+ );
115
+
96
116
  const toggleAssistant = (): void =>
97
117
  applicationStore.assistantService.toggleAssistant();
118
+ const togglePanel = (): void => editorStore.panelGroupDisplayState.toggle();
98
119
 
99
120
  return (
100
121
  <div
@@ -136,6 +157,76 @@ const ProjectViewerStatusBar = observer(() => {
136
157
  )}
137
158
  </div>
138
159
  <div className="editor__status-bar__right">
160
+ <button
161
+ className={clsx(
162
+ 'editor__status-bar__action editor__status-bar__generate-btn',
163
+ {
164
+ 'editor__status-bar__generate-btn--wiggling':
165
+ editorStore.graphState.graphGenerationState
166
+ .isRunningGlobalGenerate,
167
+ },
168
+ )}
169
+ disabled={
170
+ editorStore.graphState.isApplicationUpdateOperationIsRunning
171
+ }
172
+ onClick={generate}
173
+ tabIndex={-1}
174
+ title="Generate (F10)"
175
+ >
176
+ <FireIcon />
177
+ </button>
178
+ <button
179
+ className={clsx(
180
+ 'editor__status-bar__action editor__status-bar__clear__generation-btn ',
181
+
182
+ {
183
+ 'editor__status-bar__action editor__status-bar__clear__generation-btn--wiggling':
184
+ editorStore.graphState.graphGenerationState
185
+ .clearingGenerationEntitiesState.isInProgress,
186
+ },
187
+ )}
188
+ disabled={
189
+ editorStore.graphState.isApplicationUpdateOperationIsRunning ||
190
+ !editable
191
+ }
192
+ onClick={emptyGenerationEntities}
193
+ tabIndex={-1}
194
+ title="Clear generation entities"
195
+ >
196
+ <TrashIcon />
197
+ </button>
198
+ <button
199
+ className={clsx(
200
+ 'editor__status-bar__action editor__status-bar__compile-btn',
201
+ {
202
+ 'editor__status-bar__compile-btn--wiggling':
203
+ editorStore.graphState.isRunningGlobalCompile,
204
+ },
205
+ )}
206
+ disabled={
207
+ editorStore.graphState.isApplicationUpdateOperationIsRunning ||
208
+ !editable
209
+ }
210
+ onClick={compile}
211
+ tabIndex={-1}
212
+ title="Compile (F9)"
213
+ >
214
+ <HammerIcon />
215
+ </button>
216
+ <button
217
+ className={clsx(
218
+ 'editor__status-bar__action editor__status-bar__action__toggler',
219
+ {
220
+ 'editor__status-bar__action__toggler--active':
221
+ editorStore.panelGroupDisplayState.isOpen,
222
+ },
223
+ )}
224
+ onClick={togglePanel}
225
+ tabIndex={-1}
226
+ title="Toggle panel (Ctrl + `)"
227
+ >
228
+ <TerminalIcon />
229
+ </button>
139
230
  <button
140
231
  className={clsx(
141
232
  'editor__status-bar__action editor__status-bar__action__toggler',
@@ -288,6 +379,21 @@ export const ProjectViewer = withEditorStore(
288
379
  size: editorStore.sideBarDisplayState.size,
289
380
  },
290
381
  );
382
+ const resizePanel = (handleProps: ResizablePanelHandlerProps): void =>
383
+ editorStore.panelGroupDisplayState.setSize(
384
+ (handleProps.domElement as HTMLDivElement).getBoundingClientRect()
385
+ .height,
386
+ );
387
+ const maximizedCollapsiblePanelGroupProps = getCollapsiblePanelGroupProps(
388
+ editorStore.panelGroupDisplayState.isMaximized,
389
+ );
390
+ const collapsiblePanelGroupProps = getCollapsiblePanelGroupProps(
391
+ editorStore.panelGroupDisplayState.size === 0,
392
+ {
393
+ onStopResize: resizePanel,
394
+ size: editorStore.panelGroupDisplayState.size,
395
+ },
396
+ );
291
397
  const { ref, width, height } = useResizeDetector<HTMLDivElement>();
292
398
  useEffect(() => {
293
399
  if (ref.current) {
@@ -330,10 +436,39 @@ export const ProjectViewer = withEditorStore(
330
436
  {...sideBarCollapsiblePanelGroupProps.remainingPanel}
331
437
  minSize={300}
332
438
  >
333
- {editorStore.graphEditorMode.mode ===
334
- GRAPH_EDITOR_MODE.FORM && <EditorGroup />}
335
- {editorStore.graphEditorMode.mode ===
336
- GRAPH_EDITOR_MODE.GRAMMAR_TEXT && <GrammarTextEditor />}
439
+ <ResizablePanelGroup orientation="horizontal">
440
+ <ResizablePanel
441
+ {...maximizedCollapsiblePanelGroupProps.collapsiblePanel}
442
+ {...(editorStore.panelGroupDisplayState.size === 0
443
+ ? collapsiblePanelGroupProps.remainingPanel
444
+ : {})}
445
+ >
446
+ {editorStore.graphEditorMode.mode ===
447
+ GRAPH_EDITOR_MODE.FORM && <EditorGroup />}
448
+ {editorStore.graphEditorMode.mode ===
449
+ GRAPH_EDITOR_MODE.GRAMMAR_TEXT && (
450
+ <GrammarTextEditor />
451
+ )}
452
+ </ResizablePanel>
453
+ <ResizablePanelSplitter>
454
+ <ResizablePanelSplitterLine
455
+ color={
456
+ editorStore.panelGroupDisplayState.isMaximized
457
+ ? 'transparent'
458
+ : 'var(--color-dark-grey-250)'
459
+ }
460
+ />
461
+ </ResizablePanelSplitter>
462
+ <ResizablePanel
463
+ {...collapsiblePanelGroupProps.collapsiblePanel}
464
+ {...(editorStore.panelGroupDisplayState.isMaximized
465
+ ? maximizedCollapsiblePanelGroupProps.remainingPanel
466
+ : {})}
467
+ direction={-1}
468
+ >
469
+ <PanelGroup />
470
+ </ResizablePanel>
471
+ </ResizablePanelGroup>
337
472
  </ResizablePanel>
338
473
  </ResizablePanelGroup>
339
474
  </div>