@finos/legend-application-studio 24.2.0 → 25.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.
Files changed (93) hide show
  1. package/lib/components/editor/ActivityBar.d.ts +0 -7
  2. package/lib/components/editor/ActivityBar.d.ts.map +1 -1
  3. package/lib/components/editor/ActivityBar.js +15 -16
  4. package/lib/components/editor/ActivityBar.js.map +1 -1
  5. package/lib/components/editor/__test-utils__/EditorComponentTestUtils.d.ts +2 -2
  6. package/lib/components/editor/__test-utils__/EditorComponentTestUtils.d.ts.map +1 -1
  7. package/lib/components/editor/__test-utils__/EditorComponentTestUtils.js +3 -3
  8. package/lib/components/editor/__test-utils__/EditorComponentTestUtils.js.map +1 -1
  9. package/lib/components/editor/edit-panel/mapping-editor/testable/MappingTestableEditor.js +2 -2
  10. package/lib/components/editor/edit-panel/mapping-editor/testable/MappingTestableEditor.js.map +1 -1
  11. package/lib/components/editor/editor-group/GrammarTextEditor.d.ts.map +1 -1
  12. package/lib/components/editor/editor-group/GrammarTextEditor.js +3 -9
  13. package/lib/components/editor/editor-group/GrammarTextEditor.js.map +1 -1
  14. package/lib/components/editor/editor-group/ModelImporter.d.ts.map +1 -1
  15. package/lib/components/editor/editor-group/ModelImporter.js +1 -1
  16. package/lib/components/editor/editor-group/ModelImporter.js.map +1 -1
  17. package/lib/components/editor/editor-group/connection-editor/RelationalDatabaseConnectionEditor.d.ts.map +1 -1
  18. package/lib/components/editor/editor-group/connection-editor/RelationalDatabaseConnectionEditor.js +15 -16
  19. package/lib/components/editor/editor-group/connection-editor/RelationalDatabaseConnectionEditor.js.map +1 -1
  20. package/lib/components/editor/editor-group/diff-editor/EntityChangeConflictEditor.d.ts.map +1 -1
  21. package/lib/components/editor/editor-group/diff-editor/EntityChangeConflictEditor.js +3 -9
  22. package/lib/components/editor/editor-group/diff-editor/EntityChangeConflictEditor.js.map +1 -1
  23. package/lib/components/editor/editor-group/mapping-editor/DEPRECATED__MappingTestEditor.js +1 -1
  24. package/lib/components/editor/editor-group/mapping-editor/DEPRECATED__MappingTestEditor.js.map +1 -1
  25. package/lib/components/editor/editor-group/mapping-editor/MappingExecutionBuilder.js +1 -1
  26. package/lib/components/editor/editor-group/mapping-editor/MappingExecutionBuilder.js.map +1 -1
  27. package/lib/components/editor/editor-group/project-configuration-editor/ProjectConfigurationEditor.js +4 -2
  28. package/lib/components/editor/editor-group/project-configuration-editor/ProjectConfigurationEditor.js.map +1 -1
  29. package/lib/components/editor/editor-group/service-editor/ServiceEditor.js +1 -1
  30. package/lib/components/editor/editor-group/service-editor/ServiceEditor.js.map +1 -1
  31. package/lib/components/editor/editor-group/service-editor/ServiceExecutionQueryEditor.d.ts.map +1 -1
  32. package/lib/components/editor/editor-group/service-editor/ServiceExecutionQueryEditor.js +2 -2
  33. package/lib/components/editor/editor-group/service-editor/ServiceExecutionQueryEditor.js.map +1 -1
  34. package/lib/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.js +1 -1
  35. package/lib/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.js.map +1 -1
  36. package/lib/components/editor/editor-group/uml-editor/ClassQueryBuilder.d.ts +12 -0
  37. package/lib/components/editor/editor-group/uml-editor/ClassQueryBuilder.d.ts.map +1 -1
  38. package/lib/components/editor/editor-group/uml-editor/ClassQueryBuilder.js +106 -12
  39. package/lib/components/editor/editor-group/uml-editor/ClassQueryBuilder.js.map +1 -1
  40. package/lib/components/editor/side-bar/WorkflowManager.d.ts.map +1 -1
  41. package/lib/components/editor/side-bar/WorkflowManager.js +1 -1
  42. package/lib/components/editor/side-bar/WorkflowManager.js.map +1 -1
  43. package/lib/components/editor/side-bar/testable/GlobalTestRunner.d.ts.map +1 -1
  44. package/lib/components/editor/side-bar/testable/GlobalTestRunner.js +8 -7
  45. package/lib/components/editor/side-bar/testable/GlobalTestRunner.js.map +1 -1
  46. package/lib/components/project-view/ProjectViewer.d.ts.map +1 -1
  47. package/lib/components/project-view/ProjectViewer.js +2 -2
  48. package/lib/components/project-view/ProjectViewer.js.map +1 -1
  49. package/lib/index.css +2 -2
  50. package/lib/index.css.map +1 -1
  51. package/lib/index.d.ts +0 -1
  52. package/lib/index.d.ts.map +1 -1
  53. package/lib/index.js +0 -1
  54. package/lib/index.js.map +1 -1
  55. package/lib/package.json +2 -2
  56. package/lib/stores/LegendStudioApplicationPlugin.d.ts +9 -0
  57. package/lib/stores/LegendStudioApplicationPlugin.d.ts.map +1 -1
  58. package/lib/stores/LegendStudioApplicationPlugin.js.map +1 -1
  59. package/lib/stores/editor/EditorStore.d.ts +3 -3
  60. package/lib/stores/editor/EditorStore.d.ts.map +1 -1
  61. package/lib/stores/editor/EditorStore.js.map +1 -1
  62. package/lib/stores/editor/editor-state/element-editor-state/connection/ConnectionEditorState.d.ts +23 -23
  63. package/lib/stores/editor/editor-state/element-editor-state/connection/ConnectionEditorState.d.ts.map +1 -1
  64. package/lib/stores/editor/editor-state/element-editor-state/connection/ConnectionEditorState.js +23 -23
  65. package/lib/stores/editor/editor-state/element-editor-state/connection/ConnectionEditorState.js.map +1 -1
  66. package/package.json +12 -12
  67. package/src/components/editor/ActivityBar.tsx +100 -96
  68. package/src/components/editor/__test-utils__/EditorComponentTestUtils.tsx +5 -5
  69. package/src/components/editor/edit-panel/mapping-editor/testable/MappingTestableEditor.tsx +2 -2
  70. package/src/components/editor/editor-group/GrammarTextEditor.tsx +2 -11
  71. package/src/components/editor/editor-group/ModelImporter.tsx +0 -1
  72. package/src/components/editor/editor-group/connection-editor/RelationalDatabaseConnectionEditor.tsx +15 -17
  73. package/src/components/editor/editor-group/diff-editor/EntityChangeConflictEditor.tsx +2 -11
  74. package/src/components/editor/editor-group/mapping-editor/DEPRECATED__MappingTestEditor.tsx +1 -1
  75. package/src/components/editor/editor-group/mapping-editor/MappingExecutionBuilder.tsx +1 -1
  76. package/src/components/editor/editor-group/project-configuration-editor/ProjectConfigurationEditor.tsx +6 -6
  77. package/src/components/editor/editor-group/service-editor/ServiceEditor.tsx +1 -1
  78. package/src/components/editor/editor-group/service-editor/ServiceExecutionQueryEditor.tsx +0 -2
  79. package/src/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.tsx +1 -1
  80. package/src/components/editor/editor-group/uml-editor/ClassQueryBuilder.tsx +267 -31
  81. package/src/components/editor/side-bar/WorkflowManager.tsx +0 -1
  82. package/src/components/editor/side-bar/testable/GlobalTestRunner.tsx +11 -22
  83. package/src/components/project-view/ProjectViewer.tsx +27 -29
  84. package/src/index.ts +0 -1
  85. package/src/stores/LegendStudioApplicationPlugin.ts +15 -0
  86. package/src/stores/editor/EditorStore.ts +2 -2
  87. package/src/stores/editor/editor-state/element-editor-state/connection/ConnectionEditorState.ts +23 -23
  88. package/tsconfig.json +0 -1
  89. package/lib/stores/extensions/STO_ProjectOverview_LegendStudioApplicationPlugin_Extension.d.ts +0 -31
  90. package/lib/stores/extensions/STO_ProjectOverview_LegendStudioApplicationPlugin_Extension.d.ts.map +0 -1
  91. package/lib/stores/extensions/STO_ProjectOverview_LegendStudioApplicationPlugin_Extension.js +0 -17
  92. package/lib/stores/extensions/STO_ProjectOverview_LegendStudioApplicationPlugin_Extension.js.map +0 -1
  93. package/src/stores/extensions/STO_ProjectOverview_LegendStudioApplicationPlugin_Extension.ts +0 -40
@@ -393,7 +393,7 @@ const MappingExecutionQueryEditor = observer(
393
393
  inputValue={queryState.lambdaString}
394
394
  isReadOnly={true}
395
395
  language={CODE_EDITOR_LANGUAGE.PURE}
396
- showMiniMap={false}
396
+ hideMinimap={true}
397
397
  />
398
398
  </div>
399
399
  </PanelContent>
@@ -517,12 +517,12 @@ export const ProjectConfigurationEditor = observer(() => {
517
517
  selectedTab === CONFIGURATION_EDITOR_TAB.PROJECT_DEPENDENCIES &&
518
518
  !configState.associatedProjectsAndVersionsFetched
519
519
  ) {
520
- flowResult(configState.fectchAssociatedProjectsAndVersions()).catch(
521
- applicationStore.alertUnhandledError,
522
- );
523
- flowResult(
524
- configState.projectDependencyEditorState.fetchDependencyReport(),
525
- ).catch(applicationStore.alertUnhandledError);
520
+ Promise.all([
521
+ flowResult(configState.fectchAssociatedProjectsAndVersions()),
522
+ flowResult(
523
+ configState.projectDependencyEditorState.fetchDependencyReport(),
524
+ ),
525
+ ]).catch(applicationStore.alertUnhandledError);
526
526
  }
527
527
  }, [applicationStore, configState, selectedTab]);
528
528
 
@@ -370,7 +370,7 @@ const ServiceGeneralEditor = observer(() => {
370
370
  <div className="panel__content__form__section__list__new-item">
371
371
  <CustomSelectorInput
372
372
  className="service-editor__owner__selector"
373
- placeholder={'Enter an owner...'}
373
+ placeholder="Enter an owner..."
374
374
  spellCheck={false}
375
375
  inputValue={searchText}
376
376
  options={userOptions}
@@ -84,7 +84,6 @@ const ServiceExecutionResultViewer = observer(
84
84
  inputValue={executionResultText ?? ''}
85
85
  isReadOnly={true}
86
86
  language={CODE_EDITOR_LANGUAGE.JSON}
87
- showMiniMap={true}
88
87
  />
89
88
  </ModalBody>
90
89
  <ModalFooter>
@@ -456,7 +455,6 @@ export const ServiceExecutionQueryEditor = observer(
456
455
  inputValue={queryState.lambdaString}
457
456
  isReadOnly={true}
458
457
  language={CODE_EDITOR_LANGUAGE.PURE}
459
- showMiniMap={true}
460
458
  />
461
459
  </div>
462
460
  <ExecutionPlanViewer
@@ -284,7 +284,7 @@ const ServiceTestSetupEditor = observer(
284
284
  darkMode={true}
285
285
  isMulti={true}
286
286
  disable={isReadOnly}
287
- placeholder={'Choose keys...'}
287
+ placeholder="Choose keys..."
288
288
  />
289
289
  </div>
290
290
  )}
@@ -19,15 +19,24 @@ import {
19
19
  PackageableElementExplicitReference,
20
20
  PureSingleExecution,
21
21
  Service,
22
+ ConcreteFunctionDefinition,
23
+ Multiplicity,
24
+ resolvePackagePathAndElementName,
25
+ ELEMENT_PATH_DELIMITER,
26
+ RawVariableExpression,
22
27
  } from '@finos/legend-graph';
23
28
  import {
24
29
  type QueryBuilderState,
25
30
  ClassQueryBuilderState,
26
31
  } from '@finos/legend-query-builder';
27
- import { assertErrorThrown, guaranteeNonNullable } from '@finos/legend-shared';
32
+ import {
33
+ assertErrorThrown,
34
+ guaranteeNonNullable,
35
+ prettyCONSTName,
36
+ } from '@finos/legend-shared';
28
37
  import { flowResult } from 'mobx';
29
38
  import { observer } from 'mobx-react-lite';
30
- import { useState } from 'react';
39
+ import { useRef, useState } from 'react';
31
40
  import type { EditorStore } from '../../../../stores/editor/EditorStore.js';
32
41
  import type { EmbeddedQueryBuilderState } from '../../../../stores/editor/EmbeddedQueryBuilderState.js';
33
42
  import {
@@ -36,6 +45,18 @@ import {
36
45
  } from '../../../../stores/graph-modifier/DSL_Service_GraphModifierHelper.js';
37
46
  import { useEditorStore } from '../../EditorStoreProvider.js';
38
47
  import { NewServiceModal } from '../service-editor/NewServiceModal.js';
48
+ import {
49
+ CaretDownIcon,
50
+ Dialog,
51
+ DropdownMenu,
52
+ MenuContent,
53
+ MenuContentItem,
54
+ MenuContentItemLabel,
55
+ ModalTitle,
56
+ PanelDivider,
57
+ PanelFormSection,
58
+ PanelFormValidatedTextField,
59
+ } from '@finos/legend-art';
39
60
 
40
61
  const promoteQueryToService = async (
41
62
  packagePath: string,
@@ -82,48 +103,263 @@ const promoteQueryToService = async (
82
103
  }
83
104
  };
84
105
 
106
+ export const promoteQueryToFunction = async (
107
+ packagePath: string,
108
+ functionName: string,
109
+ embeddedQueryBuilderState: EmbeddedQueryBuilderState,
110
+ queryBuilderState: QueryBuilderState,
111
+ ): Promise<void> => {
112
+ const editorStore = embeddedQueryBuilderState.editorStore;
113
+ const applicationStore = editorStore.applicationStore;
114
+ try {
115
+ const query = queryBuilderState.buildFromQuery();
116
+ const returnType = queryBuilderState.getQueryReturnType();
117
+ const _function = new ConcreteFunctionDefinition(
118
+ functionName,
119
+ PackageableElementExplicitReference.create(returnType),
120
+ Multiplicity.ONE,
121
+ );
122
+ // we will copy the body of the query to the body of the function and extract the parameters out
123
+ // to the function parameters
124
+ _function.expressionSequence = query.body as object[];
125
+ _function.parameters =
126
+ queryBuilderState.parametersState.parameterStates.map(
127
+ (e) =>
128
+ new RawVariableExpression(
129
+ e.parameter.name,
130
+ e.parameter.multiplicity,
131
+ PackageableElementExplicitReference.create(
132
+ guaranteeNonNullable(e.parameter.genericType?.value.rawType),
133
+ ),
134
+ ),
135
+ );
136
+ await flowResult(
137
+ editorStore.graphEditorMode.addElement(_function, packagePath, true),
138
+ );
139
+ await flowResult(
140
+ embeddedQueryBuilderState.setEmbeddedQueryBuilderConfiguration(undefined),
141
+ ).catch(applicationStore.alertUnhandledError);
142
+ applicationStore.notificationService.notifySuccess(
143
+ `Function '${_function.name}' created`,
144
+ );
145
+ } catch (error) {
146
+ assertErrorThrown(error);
147
+ applicationStore.notificationService.notifyError(error);
148
+ }
149
+ };
150
+
151
+ enum PROMOTE_QUERY_TYPE {
152
+ FUNCTION = 'FUNCTION',
153
+ SERVICE = 'SERVICE',
154
+ }
155
+
156
+ export const NewFunctionModal = observer(
157
+ (props: {
158
+ _class: Class | undefined;
159
+ close: () => void;
160
+ showModal: boolean;
161
+ promoteToFunction: (
162
+ packagePath: string,
163
+ functionName: string,
164
+ ) => Promise<void>;
165
+ isReadOnly?: boolean;
166
+ }) => {
167
+ const { isReadOnly, close, _class, showModal, promoteToFunction } = props;
168
+ const editorStore = useEditorStore();
169
+ const applicationStore = editorStore.applicationStore;
170
+ const nameRef = useRef<HTMLInputElement>(null);
171
+ const defaultFunctionname = _class
172
+ ? `${_class.name}_QueryFunction`
173
+ : `QueryFunction`;
174
+ const [functionPath, setFunctionPath] =
175
+ useState<string>(defaultFunctionname);
176
+ const [packagePath, funcName] = resolvePackagePathAndElementName(
177
+ functionPath,
178
+ _class?.package?.path ?? 'model::functions',
179
+ );
180
+ const [isValid, setIsValid] = useState(true);
181
+
182
+ const handleEnter = (): void => nameRef.current?.focus();
183
+ const create = (): void => {
184
+ if (functionPath && !isReadOnly && isValid) {
185
+ promoteToFunction(packagePath, funcName)
186
+ .then(() => close())
187
+ .catch(applicationStore.alertUnhandledError);
188
+ }
189
+ };
190
+
191
+ const validateElementDoesNotAlreadyExist = (
192
+ myFunctionName: string,
193
+ ): string | undefined => {
194
+ const elementAlreadyExists =
195
+ editorStore.graphManagerState.graph.allOwnElements
196
+ .map((s) => s.path)
197
+ .includes(packagePath + ELEMENT_PATH_DELIMITER + myFunctionName);
198
+
199
+ if (!elementAlreadyExists) {
200
+ return undefined;
201
+ } else {
202
+ return 'Element with same path already exists';
203
+ }
204
+ };
205
+
206
+ const changeValue = (value: string): void => {
207
+ setFunctionPath(value);
208
+ };
209
+
210
+ return (
211
+ <Dialog
212
+ open={showModal}
213
+ onClose={close}
214
+ TransitionProps={{
215
+ onEnter: handleEnter,
216
+ }}
217
+ PaperProps={{
218
+ classes: {
219
+ root: 'search-modal__inner-container',
220
+ },
221
+ }}
222
+ >
223
+ <form
224
+ onSubmit={(event) => {
225
+ event.preventDefault();
226
+ create();
227
+ }}
228
+ className="modal search-modal modal--dark"
229
+ >
230
+ <ModalTitle title="Promote to Function" />
231
+ <PanelFormValidatedTextField
232
+ ref={nameRef}
233
+ isReadOnly={isReadOnly ?? false}
234
+ update={(value: string | undefined): void => {
235
+ changeValue(value ?? '');
236
+ }}
237
+ validate={validateElementDoesNotAlreadyExist}
238
+ onValidate={(issue: string | undefined) => setIsValid(!issue)}
239
+ value={functionPath}
240
+ placeholder={`Enter a name, use ${ELEMENT_PATH_DELIMITER} to create new package(s) for the function`}
241
+ />
242
+ <PanelDivider />
243
+ <PanelFormSection>
244
+ <div className="search-modal__actions">
245
+ <button
246
+ className="btn btn--dark"
247
+ disabled={Boolean(isReadOnly) || !isValid}
248
+ onClick={create}
249
+ >
250
+ Create
251
+ </button>
252
+ </div>
253
+ </PanelFormSection>
254
+ </form>
255
+ </Dialog>
256
+ );
257
+ },
258
+ );
259
+
85
260
  const PromoteToServiceQueryBuilderAction = observer(
86
261
  (props: { queryBuilderState: QueryBuilderState }) => {
87
262
  const { queryBuilderState } = props;
88
263
  const editorStore = useEditorStore();
89
264
  const queryBuilderExtension = editorStore.embeddedQueryBuilderState;
90
- const [openNewServiceModal, setOpenNewServiceModal] = useState(false);
91
- const showNewServiceModal = (): void => setOpenNewServiceModal(true);
92
- const closeNewServiceModal = (): void => setOpenNewServiceModal(false);
93
- const allowPromoteToService = Boolean(
94
- queryBuilderState.mapping && queryBuilderState.runtimeValue,
265
+ const [promoteQueryModal, setPromoteQueryType] = useState<
266
+ PROMOTE_QUERY_TYPE | undefined
267
+ >(undefined);
268
+ const showPromoteQueryModal = (type: PROMOTE_QUERY_TYPE): void =>
269
+ setPromoteQueryType(type);
270
+ const closeNewServiceModal = (): void => setPromoteQueryType(undefined);
271
+ const allowPromotion = Boolean(
272
+ queryBuilderState.mapping &&
273
+ queryBuilderState.runtimeValue &&
274
+ !queryBuilderState.allValidationIssues.length,
95
275
  );
96
- const promoteToService = async (
97
- packagePath: string,
98
- serviceName: string,
99
- ): Promise<void> => {
100
- if (allowPromoteToService) {
101
- await promoteQueryToService(
102
- packagePath,
103
- serviceName,
104
- queryBuilderExtension,
105
- queryBuilderState,
276
+
277
+ const renderPromoteModal = (): React.ReactNode => {
278
+ if (
279
+ promoteQueryModal === PROMOTE_QUERY_TYPE.SERVICE &&
280
+ queryBuilderState.mapping
281
+ ) {
282
+ const promoteToService = async (
283
+ packagePath: string,
284
+ serviceName: string,
285
+ ): Promise<void> => {
286
+ if (allowPromotion) {
287
+ await promoteQueryToService(
288
+ packagePath,
289
+ serviceName,
290
+ queryBuilderExtension,
291
+ queryBuilderState,
292
+ );
293
+ }
294
+ };
295
+
296
+ return (
297
+ <NewServiceModal
298
+ mapping={queryBuilderState.mapping}
299
+ close={closeNewServiceModal}
300
+ showModal={true}
301
+ promoteToService={promoteToService}
302
+ />
303
+ );
304
+ } else if (promoteQueryModal === PROMOTE_QUERY_TYPE.FUNCTION) {
305
+ const promoteToFunction = async (
306
+ packagePath: string,
307
+ serviceName: string,
308
+ ): Promise<void> => {
309
+ if (allowPromotion) {
310
+ await promoteQueryToFunction(
311
+ packagePath,
312
+ serviceName,
313
+ queryBuilderExtension,
314
+ queryBuilderState,
315
+ );
316
+ }
317
+ };
318
+
319
+ return (
320
+ <NewFunctionModal
321
+ _class={queryBuilderState.class}
322
+ close={closeNewServiceModal}
323
+ showModal={true}
324
+ promoteToFunction={promoteToFunction}
325
+ />
106
326
  );
107
327
  }
328
+ return null;
108
329
  };
330
+
109
331
  return (
110
332
  <>
111
- <button
333
+ <DropdownMenu
112
334
  className="query-builder__dialog__header__custom-action"
113
- tabIndex={-1}
114
- onClick={showNewServiceModal}
115
- disabled={!allowPromoteToService}
335
+ title="Promote Query..."
336
+ content={
337
+ <MenuContent>
338
+ {Object.values(PROMOTE_QUERY_TYPE).map((type) => (
339
+ <MenuContentItem
340
+ key={type}
341
+ disabled={!allowPromotion}
342
+ onClick={(): void => showPromoteQueryModal(type)}
343
+ >
344
+ <MenuContentItemLabel className="query-builder__sub-header__menu-content">
345
+ {prettyCONSTName(type)}
346
+ </MenuContentItemLabel>
347
+ </MenuContentItem>
348
+ ))}
349
+ </MenuContent>
350
+ }
351
+ menuProps={{
352
+ anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
353
+ transformOrigin: { vertical: 'top', horizontal: 'right' },
354
+ elevation: 7,
355
+ }}
116
356
  >
117
- Promote to Service
118
- </button>
119
- {queryBuilderState.mapping && (
120
- <NewServiceModal
121
- mapping={queryBuilderState.mapping}
122
- close={closeNewServiceModal}
123
- showModal={openNewServiceModal}
124
- promoteToService={promoteToService}
125
- />
126
- )}
357
+ <div className="query-builder__sub-header__custom-action__label">
358
+ Promote To...
359
+ </div>
360
+ <CaretDownIcon className="query-builder__sub-header__custom-action__icon" />
361
+ </DropdownMenu>
362
+ {renderPromoteModal()}
127
363
  </>
128
364
  );
129
365
  },
@@ -242,7 +242,6 @@ const WorkflowJobLogsViewer = observer(
242
242
  inputValue={logs}
243
243
  isReadOnly={true}
244
244
  language={CODE_EDITOR_LANGUAGE.TEXT}
245
- showMiniMap={true}
246
245
  />
247
246
  </ModalBody>
248
247
  <ModalFooter>
@@ -72,7 +72,6 @@ import {
72
72
  getAtomicTest_TestResult,
73
73
  getAssertionStatus,
74
74
  } from '../../../../stores/editor/sidebar-state/testable/GlobalTestRunnerState.js';
75
- import type { STO_ProjectOverview_LegendStudioApplicationPlugin_Extension } from '../../../../stores/extensions/STO_ProjectOverview_LegendStudioApplicationPlugin_Extension.js';
76
75
  import { LEGEND_STUDIO_TEST_ID } from '../../../../__lib__/LegendStudioTesting.js';
77
76
  import { getElementTypeIcon } from '../../../ElementIconUtils.js';
78
77
  import { UnsupportedEditorPanel } from '../../editor-group/UnsupportedElementEditor.js';
@@ -206,7 +205,6 @@ const TestFailViewer = observer(
206
205
  inputValue={failure.error}
207
206
  isReadOnly={true}
208
207
  language={CODE_EDITOR_LANGUAGE.TEXT}
209
- showMiniMap={true}
210
208
  />
211
209
  )}
212
210
  {failure instanceof EqualToJsonAssertFail && (
@@ -431,17 +429,13 @@ export const GlobalTestRunner = observer(
431
429
  const editorStore = useEditorStore();
432
430
  const globalTestRunnerState = props.globalTestRunnerState;
433
431
  const isDispatchingAction = globalTestRunnerState.isDispatchingAction;
434
- const sdlcState = editorStore.sdlcState;
435
- const currentWorkspace = sdlcState.currentWorkspace;
436
- const plugins = editorStore.pluginManager.getApplicationPlugins();
437
432
  const testRunnerTabs = (Object.values(GLOBAL_TEST_RUNNER_TABS) as string[])
438
433
  .concat(
439
- plugins.flatMap(
440
- (plugin) =>
441
- (
442
- plugin as STO_ProjectOverview_LegendStudioApplicationPlugin_Extension
443
- ).getExtraTestRunnerTabsClassifiers?.() ?? [],
444
- ),
434
+ editorStore.pluginManager
435
+ .getApplicationPlugins()
436
+ .flatMap(
437
+ (plugin) => plugin.getExtraTestRunnerTabClassifiers?.() ?? [],
438
+ ),
445
439
  )
446
440
  .map((e) => ({
447
441
  value: e,
@@ -573,18 +567,13 @@ export const GlobalTestRunner = observer(
573
567
  </div>
574
568
  );
575
569
  } else {
576
- const extraTestRunnerTabEditorRenderers = plugins.flatMap(
577
- (plugin) =>
578
- (
579
- plugin as STO_ProjectOverview_LegendStudioApplicationPlugin_Extension
580
- ).getExtraTestRunnerTabsEditorRenderers?.() ?? [],
581
- );
582
- for (const editorRenderer of extraTestRunnerTabEditorRenderers) {
583
- const editor = editorRenderer(
584
- selectedTab,
585
- editorStore,
586
- currentWorkspace,
570
+ const extraTestRunnerTabEditorRenderers = editorStore.pluginManager
571
+ .getApplicationPlugins()
572
+ .flatMap(
573
+ (plugin) => plugin.getExtraTestRunnerTabEditorRenderers?.() ?? [],
587
574
  );
575
+ for (const editorRenderer of extraTestRunnerTabEditorRenderers) {
576
+ const editor = editorRenderer(selectedTab, editorStore);
588
577
  if (editor) {
589
578
  return editor;
590
579
  }
@@ -55,10 +55,6 @@ import {
55
55
  } from '../editor/EditorStoreProvider.js';
56
56
  import { useApplicationStore, useCommands } from '@finos/legend-application';
57
57
  import { useParams } from '@finos/legend-application/browser';
58
- import {
59
- ActivityBarMenu,
60
- type ActivityDisplay,
61
- } from '../editor/ActivityBar.js';
62
58
  import { Explorer } from '../editor/side-bar/Explorer.js';
63
59
  import { ProjectOverview } from '../editor/side-bar/ProjectOverview.js';
64
60
  import { WorkflowManager } from '../editor/side-bar/WorkflowManager.js';
@@ -67,6 +63,8 @@ import {
67
63
  useLegendStudioBaseStore,
68
64
  } from '../LegendStudioFrameworkProvider.js';
69
65
  import { EmbeddedQueryBuilder } from '../EmbeddedQueryBuilder.js';
66
+ import type { ActivityBarItemConfig } from '@finos/legend-lego/application';
67
+ import { ActivityBarMenu } from '../editor/ActivityBar.js';
70
68
 
71
69
  const ProjectViewerStatusBar = observer(() => {
72
70
  const params = useParams<ProjectViewerPathParams>();
@@ -204,31 +202,33 @@ const ProjectViewerActivityBar = observer(() => {
204
202
  const editorStore = useEditorStore();
205
203
 
206
204
  const changeActivity =
207
- (activity: ACTIVITY_MODE): (() => void) =>
205
+ (activity: string): (() => void) =>
208
206
  (): void =>
209
207
  editorStore.setActiveActivity(activity);
210
208
  // tabs
211
- const activities: ActivityDisplay[] = [
212
- {
213
- mode: ACTIVITY_MODE.EXPLORER,
214
- title: 'Explorer (Ctrl + Shift + X)',
215
- icon: <FileTrayIcon />,
216
- },
217
- baseStore.isSDLCAuthorized !== undefined && {
218
- mode: ACTIVITY_MODE.PROJECT_OVERVIEW,
219
- title: 'Project',
220
- icon: (
221
- <div className="activity-bar__project-overview-icon">
222
- <RepoIcon />
223
- </div>
224
- ),
225
- },
226
- viewerStore.workflowManagerState && {
227
- mode: ACTIVITY_MODE.WORKFLOW_MANAGER,
228
- title: 'WORKFLOW MANAGER',
229
- icon: <WrenchIcon />,
230
- },
231
- ].filter((activity): activity is ActivityDisplay => Boolean(activity));
209
+ const activities: ActivityBarItemConfig[] = (
210
+ [
211
+ {
212
+ mode: ACTIVITY_MODE.EXPLORER,
213
+ title: 'Explorer (Ctrl + Shift + X)',
214
+ icon: <FileTrayIcon />,
215
+ },
216
+ baseStore.isSDLCAuthorized !== undefined && {
217
+ mode: ACTIVITY_MODE.PROJECT_OVERVIEW,
218
+ title: 'Project',
219
+ icon: (
220
+ <div className="activity-bar__project-overview-icon">
221
+ <RepoIcon />
222
+ </div>
223
+ ),
224
+ },
225
+ viewerStore.workflowManagerState && {
226
+ mode: ACTIVITY_MODE.WORKFLOW_MANAGER,
227
+ title: 'WORKFLOW MANAGER',
228
+ icon: <WrenchIcon />,
229
+ },
230
+ ] as (ActivityBarItemConfig | boolean)[]
231
+ ).filter((activity): activity is ActivityBarItemConfig => Boolean(activity));
232
232
 
233
233
  return (
234
234
  <div className="activity-bar">
@@ -244,9 +244,7 @@ const ProjectViewerActivityBar = observer(() => {
244
244
  })}
245
245
  onClick={changeActivity(activity.mode)}
246
246
  tabIndex={-1}
247
- title={`${activity.title}${
248
- activity.info ? ` - ${activity.info}` : ''
249
- }`}
247
+ title={activity.title}
250
248
  >
251
249
  {activity.icon}
252
250
  </button>
package/src/index.ts CHANGED
@@ -91,7 +91,6 @@ export { getElementIcon } from './components/ElementIconUtils.js';
91
91
  */
92
92
 
93
93
  export * from './stores/extensions/DSL_Generation_LegendStudioApplicationPlugin_Extension.js';
94
- export * from './stores/extensions/STO_ProjectOverview_LegendStudioApplicationPlugin_Extension.js';
95
94
  export * from './stores/extensions/STO_Relational_LegendStudioApplicationPlugin_Extension.js';
96
95
 
97
96
  export { MINIMUM_SERVICE_OWNERS } from './stores/editor/editor-state/element-editor-state/service/ServiceEditorState.js';
@@ -77,6 +77,11 @@ export type TestableMetadataGetter = (
77
77
  editorStore: EditorStore,
78
78
  ) => TestableMetadata | undefined;
79
79
 
80
+ export type TestRunnerTabRenderer = (
81
+ selectedTab: string,
82
+ editorStore: EditorStore,
83
+ ) => React.ReactNode | undefined;
84
+
80
85
  export abstract class LegendStudioApplicationPlugin extends LegendApplicationPlugin {
81
86
  /**
82
87
  * This helps to better type-check for this empty abtract type
@@ -119,6 +124,16 @@ export abstract class LegendStudioApplicationPlugin extends LegendApplicationPlu
119
124
  * Get the list of extension for testables
120
125
  */
121
126
  getExtraTestableMetadata?(): TestableMetadataGetter[];
127
+
128
+ /**
129
+ * Get the list of the supported classifers for test runner tabs.
130
+ */
131
+ getExtraTestRunnerTabClassifiers?(): string[];
132
+
133
+ /**
134
+ * Get the list of renderers for the editor for a test runner tab.
135
+ */
136
+ getExtraTestRunnerTabEditorRenderers?(): TestRunnerTabRenderer[];
122
137
  }
123
138
 
124
139
  export type PureGrammarElementLabeler = (
@@ -159,7 +159,7 @@ export class EditorStore implements CommandRegistrar {
159
159
  default: 300,
160
160
  snap: 100,
161
161
  });
162
- activeActivity?: ACTIVITY_MODE = ACTIVITY_MODE.EXPLORER;
162
+ activeActivity?: string = ACTIVITY_MODE.EXPLORER;
163
163
  readonly sideBarDisplayState = new PanelDisplayState({
164
164
  initial: 300,
165
165
  default: 300,
@@ -839,7 +839,7 @@ export class EditorStore implements CommandRegistrar {
839
839
  }
840
840
 
841
841
  setActiveActivity(
842
- activity: ACTIVITY_MODE,
842
+ activity: string,
843
843
  options?: { keepShowingIfMatchedCurrent?: boolean },
844
844
  ): void {
845
845
  if (!this.sideBarDisplayState.isOpen) {