@finos/legend-application-studio 28.3.4 → 28.4.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 (55) hide show
  1. package/lib/application/LegendStudioApplicationConfig.d.ts +5 -0
  2. package/lib/application/LegendStudioApplicationConfig.d.ts.map +1 -1
  3. package/lib/application/LegendStudioApplicationConfig.js +7 -1
  4. package/lib/application/LegendStudioApplicationConfig.js.map +1 -1
  5. package/lib/components/editor/editor-group/FunctionEditor.d.ts.map +1 -1
  6. package/lib/components/editor/editor-group/FunctionEditor.js +1 -1
  7. package/lib/components/editor/editor-group/FunctionEditor.js.map +1 -1
  8. package/lib/components/editor/editor-group/data-editor/RelationalCSVDataEditor.d.ts +5 -0
  9. package/lib/components/editor/editor-group/data-editor/RelationalCSVDataEditor.d.ts.map +1 -1
  10. package/lib/components/editor/editor-group/mapping-editor/DEPRECATED__MappingTestEditor.d.ts.map +1 -1
  11. package/lib/components/editor/editor-group/mapping-editor/DEPRECATED__MappingTestEditor.js +1 -1
  12. package/lib/components/editor/editor-group/mapping-editor/DEPRECATED__MappingTestEditor.js.map +1 -1
  13. package/lib/components/editor/editor-group/mapping-editor/MappingExecutionBuilder.d.ts.map +1 -1
  14. package/lib/components/editor/editor-group/mapping-editor/MappingExecutionBuilder.js +1 -1
  15. package/lib/components/editor/editor-group/mapping-editor/MappingExecutionBuilder.js.map +1 -1
  16. package/lib/components/editor/editor-group/mapping-editor/MappingTestableEditor.d.ts.map +1 -1
  17. package/lib/components/editor/editor-group/mapping-editor/MappingTestableEditor.js +1 -1
  18. package/lib/components/editor/editor-group/mapping-editor/MappingTestableEditor.js.map +1 -1
  19. package/lib/components/editor/editor-group/service-editor/ServiceExecutionQueryEditor.d.ts +4 -1
  20. package/lib/components/editor/editor-group/service-editor/ServiceExecutionQueryEditor.d.ts.map +1 -1
  21. package/lib/components/editor/editor-group/service-editor/ServiceExecutionQueryEditor.js +52 -4
  22. package/lib/components/editor/editor-group/service-editor/ServiceExecutionQueryEditor.js.map +1 -1
  23. package/lib/components/editor/editor-group/service-editor/testable/ServiceTestDataEditor.d.ts +23 -1
  24. package/lib/components/editor/editor-group/service-editor/testable/ServiceTestDataEditor.d.ts.map +1 -1
  25. package/lib/components/editor/editor-group/service-editor/testable/ServiceTestDataEditor.js +101 -8
  26. package/lib/components/editor/editor-group/service-editor/testable/ServiceTestDataEditor.js.map +1 -1
  27. package/lib/components/editor/editor-group/uml-editor/ClassQueryBuilder.d.ts.map +1 -1
  28. package/lib/components/editor/editor-group/uml-editor/ClassQueryBuilder.js +1 -1
  29. package/lib/components/editor/editor-group/uml-editor/ClassQueryBuilder.js.map +1 -1
  30. package/lib/components/editor/side-bar/Explorer.d.ts.map +1 -1
  31. package/lib/components/editor/side-bar/Explorer.js +8 -2
  32. package/lib/components/editor/side-bar/Explorer.js.map +1 -1
  33. package/lib/index.css +1 -1
  34. package/lib/package.json +8 -8
  35. package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingExecutionQueryBuilderState.d.ts +2 -2
  36. package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingExecutionQueryBuilderState.d.ts.map +1 -1
  37. package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingExecutionQueryBuilderState.js +3 -3
  38. package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingExecutionQueryBuilderState.js.map +1 -1
  39. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.d.ts +38 -1
  40. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.d.ts.map +1 -1
  41. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.js +195 -6
  42. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.js.map +1 -1
  43. package/package.json +19 -19
  44. package/src/application/LegendStudioApplicationConfig.ts +10 -0
  45. package/src/components/editor/editor-group/FunctionEditor.tsx +1 -0
  46. package/src/components/editor/editor-group/data-editor/RelationalCSVDataEditor.tsx +1 -1
  47. package/src/components/editor/editor-group/mapping-editor/DEPRECATED__MappingTestEditor.tsx +1 -0
  48. package/src/components/editor/editor-group/mapping-editor/MappingExecutionBuilder.tsx +1 -0
  49. package/src/components/editor/editor-group/mapping-editor/MappingTestableEditor.tsx +1 -0
  50. package/src/components/editor/editor-group/service-editor/ServiceExecutionQueryEditor.tsx +107 -7
  51. package/src/components/editor/editor-group/service-editor/testable/ServiceTestDataEditor.tsx +296 -5
  52. package/src/components/editor/editor-group/uml-editor/ClassQueryBuilder.tsx +1 -0
  53. package/src/components/editor/side-bar/Explorer.tsx +17 -0
  54. package/src/stores/editor/editor-state/element-editor-state/mapping/MappingExecutionQueryBuilderState.ts +6 -2
  55. package/src/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.ts +337 -11
@@ -16,7 +16,7 @@
16
16
 
17
17
  import { useEffect } from 'react';
18
18
  import { observer } from 'mobx-react-lite';
19
- import type { ServicePureExecutionState } from '../../../../stores/editor/editor-state/element-editor-state/service/ServiceExecutionState.js';
19
+ import { ServicePureExecutionState } from '../../../../stores/editor/editor-state/element-editor-state/service/ServiceExecutionState.js';
20
20
  import {
21
21
  Dialog,
22
22
  PanelLoadingIndicator,
@@ -32,12 +32,18 @@ import {
32
32
  ModalFooter,
33
33
  ModalHeader,
34
34
  } from '@finos/legend-art';
35
- import { assertErrorThrown } from '@finos/legend-shared';
35
+ import {
36
+ assertErrorThrown,
37
+ guaranteeNonNullable,
38
+ returnUndefOnError,
39
+ } from '@finos/legend-shared';
36
40
  import { flowResult } from 'mobx';
37
41
  import { useEditorStore } from '../../EditorStoreProvider.js';
38
42
  import {
39
- isStubbed_RawLambda,
43
+ type Service,
40
44
  KeyedExecutionParameter,
45
+ MultiExecutionParameters,
46
+ PureExecution,
41
47
  } from '@finos/legend-graph';
42
48
  import {
43
49
  type QueryBuilderState,
@@ -56,6 +62,9 @@ import {
56
62
  CodeEditor,
57
63
  } from '@finos/legend-lego/code-editor';
58
64
  import { EXTERNAL_APPLICATION_NAVIGATION__generateServiceQueryCreatorUrl } from '../../../../__lib__/LegendStudioNavigation.js';
65
+ import type { EditorStore } from '../../../../stores/editor/EditorStore.js';
66
+ import { pureExecution_setFunction } from '../../../../stores/graph-modifier/DSL_Service_GraphModifierHelper.js';
67
+ import { ServiceEditorState } from '../../../../stores/editor/editor-state/element-editor-state/service/ServiceEditorState.js';
59
68
 
60
69
  const ServiceExecutionResultViewer = observer(
61
70
  (props: { executionState: ServicePureExecutionState }) => {
@@ -114,7 +123,6 @@ export const ServiceExecutionQueryEditor = observer(
114
123
  applicationStore.guardUnhandledError(async () => {
115
124
  const selectedExecutionState =
116
125
  executionState.selectedExecutionContextState;
117
-
118
126
  await flowResult(
119
127
  embeddedQueryBuilderState.setEmbeddedQueryBuilderConfiguration({
120
128
  setupQueryBuilderState: (): QueryBuilderState => {
@@ -127,6 +135,9 @@ export const ServiceExecutionQueryEditor = observer(
127
135
  KeyedExecutionParameter
128
136
  ? selectedExecutionState.executionContext.key
129
137
  : undefined,
138
+ undefined,
139
+ undefined,
140
+ embeddedQueryBuilderState.editorStore.applicationStore.config.options.queryBuilderConfig,
130
141
  );
131
142
  queryBuilderState.initializeWithQuery(
132
143
  executionState.execution.func,
@@ -179,9 +190,7 @@ export const ServiceExecutionQueryEditor = observer(
179
190
  },
180
191
  },
181
192
  ],
182
- disableCompile: isStubbed_RawLambda(
183
- executionState.queryState.query,
184
- ),
193
+ disableCompile: true,
185
194
  }),
186
195
  );
187
196
  executionState.setOpeningQueryEditor(false);
@@ -435,3 +444,94 @@ export const ServiceExecutionQueryEditor = observer(
435
444
  );
436
445
  },
437
446
  );
447
+
448
+ export const queryService = async (
449
+ service: Service,
450
+ editorStore: EditorStore,
451
+ ): Promise<void> => {
452
+ const embeddedQueryBuilderState = editorStore.embeddedQueryBuilderState;
453
+ const applicationStore = editorStore.applicationStore;
454
+ const execution =
455
+ service.execution instanceof PureExecution ? service.execution : undefined;
456
+ const selectedExec =
457
+ execution instanceof MultiExecutionParameters
458
+ ? execution.singleExecutionParameters[0]?.key
459
+ : undefined;
460
+ await flowResult(
461
+ embeddedQueryBuilderState.setEmbeddedQueryBuilderConfiguration({
462
+ setupQueryBuilderState: (): QueryBuilderState => {
463
+ const queryBuilderState = new ServiceQueryBuilderState(
464
+ embeddedQueryBuilderState.editorStore.applicationStore,
465
+ embeddedQueryBuilderState.editorStore.graphManagerState,
466
+ service,
467
+ undefined,
468
+ selectedExec,
469
+ undefined,
470
+ undefined,
471
+ embeddedQueryBuilderState.editorStore.applicationStore.config.options.queryBuilderConfig,
472
+ );
473
+ if (execution) {
474
+ queryBuilderState.initializeWithQuery(execution.func);
475
+ }
476
+ return queryBuilderState;
477
+ },
478
+ actionConfigs: [
479
+ {
480
+ key: 'save-query-btn',
481
+ renderer: (queryBuilderState: QueryBuilderState): React.ReactNode => {
482
+ const save = applicationStore.guardUnhandledError(async () => {
483
+ try {
484
+ const rawLambda = queryBuilderState.buildQuery();
485
+ const serviceState = returnUndefOnError(() =>
486
+ editorStore.tabManagerState.getCurrentEditorState(
487
+ ServiceEditorState,
488
+ ),
489
+ );
490
+ if (
491
+ serviceState?.service === service &&
492
+ serviceState.executionState instanceof
493
+ ServicePureExecutionState
494
+ ) {
495
+ await flowResult(
496
+ serviceState.executionState.queryState.updateLamba(
497
+ rawLambda,
498
+ ),
499
+ );
500
+ } else {
501
+ pureExecution_setFunction(
502
+ guaranteeNonNullable(
503
+ execution,
504
+ 'Service execution expected to be a pure execution',
505
+ ),
506
+ rawLambda,
507
+ );
508
+ }
509
+ applicationStore.notificationService.notifySuccess(
510
+ `Service query is updated`,
511
+ );
512
+ embeddedQueryBuilderState.setEmbeddedQueryBuilderConfiguration(
513
+ undefined,
514
+ );
515
+ } catch (error) {
516
+ assertErrorThrown(error);
517
+ applicationStore.notificationService.notifyError(
518
+ `Can't save query: ${error.message}`,
519
+ );
520
+ }
521
+ });
522
+ return (
523
+ <button
524
+ className="query-builder__dialog__header__custom-action"
525
+ tabIndex={-1}
526
+ disabled={editorStore.isInViewerMode}
527
+ onClick={save}
528
+ >
529
+ Save Query
530
+ </button>
531
+ );
532
+ },
533
+ },
534
+ ],
535
+ }),
536
+ );
537
+ };
@@ -39,20 +39,26 @@ import {
39
39
  ResizablePanelGroup,
40
40
  ResizablePanelSplitter,
41
41
  ResizablePanelSplitterLine,
42
+ TimesIcon,
42
43
  } from '@finos/legend-art';
43
44
  import {
44
45
  type IdentifiedConnection,
45
46
  type ConnectionTestData,
46
47
  type DataElement,
48
+ type ValueSpecification,
47
49
  getAllIdentifiedServiceConnections,
48
50
  DataElementReference,
49
51
  PackageableElementExplicitReference,
52
+ Column,
50
53
  } from '@finos/legend-graph';
51
54
  import { observer } from 'mobx-react-lite';
52
55
  import { forwardRef, useState } from 'react';
53
- import type {
54
- ConnectionTestDataState,
55
- ServiceTestDataState,
56
+ import {
57
+ createMockPrimitiveValueSpecificationFromRelationalDataType,
58
+ type ConnectionTestDataState,
59
+ type RowIdentifierState,
60
+ type ServiceTestDataState,
61
+ type TableRowIdentifierState,
56
62
  } from '../../../../../stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.js';
57
63
  import type { EmbeddedDataTypeOption } from '../../../../../stores/editor/editor-state/element-editor-state/data/DataEditorState.js';
58
64
  import { EmbeddedDataEditor } from '../../data-editor/EmbeddedDataEditor.js';
@@ -64,11 +70,266 @@ import {
64
70
  useApplicationStore,
65
71
  } from '@finos/legend-application';
66
72
  import { buildElementOption } from '@finos/legend-lego/graph-editor';
67
- import { prettyCONSTName } from '@finos/legend-shared';
73
+ import {
74
+ filterByType,
75
+ getNullableFirstEntry,
76
+ guaranteeNonNullable,
77
+ prettyCONSTName,
78
+ } from '@finos/legend-shared';
68
79
  import type { DSL_Data_LegendStudioApplicationPlugin_Extension } from '../../../../../stores/extensions/DSL_Data_LegendStudioApplicationPlugin_Extension.js';
69
80
  import { useEditorStore } from '../../../EditorStoreProvider.js';
70
- import { LambdaParameterValuesEditor } from '@finos/legend-query-builder';
81
+ import {
82
+ BasicValueSpecificationEditor,
83
+ LambdaParameterValuesEditor,
84
+ } from '@finos/legend-query-builder';
71
85
  import { LEGEND_STUDIO_DOCUMENTATION_KEY } from '../../../../../__lib__/LegendStudioDocumentation.js';
86
+ import type { TableOption } from '../../data-editor/RelationalCSVDataEditor.js';
87
+ import { getPrimitiveTypeFromRelationalType } from '../../../../../stores/editor/utils/MockDataUtils.js';
88
+
89
+ export interface ColumnOption {
90
+ value: Column;
91
+ label: string;
92
+ }
93
+
94
+ export const RowIdentifierEditor = observer(
95
+ (props: {
96
+ tableRowIdentifierState: TableRowIdentifierState;
97
+ rowIdentifierState: RowIdentifierState;
98
+ }) => {
99
+ const { tableRowIdentifierState, rowIdentifierState } = props;
100
+ const columnOptions = tableRowIdentifierState.table.columns
101
+ .filter(filterByType(Column))
102
+ .map((_c) => ({
103
+ label: _c.name,
104
+ value: _c,
105
+ }));
106
+ const changeColumn = (val: ColumnOption): void => {
107
+ if (rowIdentifierState.column.name !== val.value.name) {
108
+ const valueSpec =
109
+ createMockPrimitiveValueSpecificationFromRelationalDataType(
110
+ guaranteeNonNullable(rowIdentifierState.column.type),
111
+ tableRowIdentifierState.connectionTestDataState.editorStore
112
+ .graphManagerState.graph,
113
+ tableRowIdentifierState.connectionTestDataState.editorStore
114
+ .changeDetectionState.observerContext,
115
+ );
116
+ if (valueSpec) {
117
+ rowIdentifierState.updateRowIdentifierValue(valueSpec);
118
+ rowIdentifierState.updateRowIdentifierColumn(val.value);
119
+ }
120
+ }
121
+ };
122
+
123
+ const resetNode = (): void => {
124
+ const valueSpec =
125
+ createMockPrimitiveValueSpecificationFromRelationalDataType(
126
+ guaranteeNonNullable(rowIdentifierState.column.type),
127
+ tableRowIdentifierState.connectionTestDataState.editorStore
128
+ .graphManagerState.graph,
129
+ tableRowIdentifierState.connectionTestDataState.editorStore
130
+ .changeDetectionState.observerContext,
131
+ );
132
+ if (valueSpec) {
133
+ rowIdentifierState.updateRowIdentifierValue(valueSpec);
134
+ }
135
+ };
136
+
137
+ return (
138
+ <div className="panel__content__form__section__list">
139
+ <div className="panel__content__form__section__list__new-item">
140
+ <CustomSelectorInput
141
+ className="service-editor__owner__selector"
142
+ placeholder="Choose a column..."
143
+ options={columnOptions}
144
+ onChange={changeColumn}
145
+ value={{
146
+ label: rowIdentifierState.column.name,
147
+
148
+ value: rowIdentifierState.column,
149
+ }}
150
+ darkMode={true}
151
+ />
152
+ <BasicValueSpecificationEditor
153
+ valueSpecification={rowIdentifierState.value}
154
+ setValueSpecification={(val: ValueSpecification): void => {
155
+ rowIdentifierState.updateRowIdentifierValue(val);
156
+ }}
157
+ graph={
158
+ tableRowIdentifierState.connectionTestDataState.editorStore
159
+ .graphManagerState.graph
160
+ }
161
+ obseverContext={
162
+ tableRowIdentifierState.connectionTestDataState.editorStore
163
+ .changeDetectionState.observerContext
164
+ }
165
+ typeCheckOption={{
166
+ expectedType: guaranteeNonNullable(
167
+ getPrimitiveTypeFromRelationalType(
168
+ guaranteeNonNullable(rowIdentifierState.column.type),
169
+ ),
170
+ ),
171
+ }}
172
+ resetValue={resetNode}
173
+ />
174
+ <button
175
+ className="btn--icon btn--dark btn--sm"
176
+ onClick={(): void =>
177
+ tableRowIdentifierState.removeRowIdentifierState(
178
+ rowIdentifierState,
179
+ )
180
+ }
181
+ tabIndex={-1}
182
+ title={'Remove Row'}
183
+ >
184
+ <TimesIcon />
185
+ </button>
186
+ </div>
187
+ </div>
188
+ );
189
+ },
190
+ );
191
+
192
+ export const TableRowIdentifierEditor = observer(
193
+ (props: {
194
+ connectionTestDataState: ConnectionTestDataState;
195
+ tableRowIdentifierState: TableRowIdentifierState;
196
+ }) => {
197
+ const { connectionTestDataState, tableRowIdentifierState } = props;
198
+ const tables = connectionTestDataState.getAvailableTables();
199
+ const tableOptions = tables.map((_t) => ({
200
+ label: `${_t.schema.name}.${_t.name}`,
201
+ value: _t,
202
+ }));
203
+
204
+ const changeTable = (val: TableOption): void => {
205
+ if (tableRowIdentifierState.table !== val.value) {
206
+ tableRowIdentifierState.updateTable(val.value);
207
+ tableRowIdentifierState.setNewRowIdentifierState([]);
208
+ }
209
+ };
210
+ const addNewRow = (): void => {
211
+ tableRowIdentifierState.addNewRowIdentifierState(
212
+ guaranteeNonNullable(
213
+ tableRowIdentifierState.table.columns.filter(filterByType(Column))[0],
214
+ ),
215
+ );
216
+ };
217
+ return (
218
+ <ModalBody className="lambda-parameter-values__modal__body">
219
+ <div className="panel__content__form__section">
220
+ <div className="panel__content__form__section__header__label">
221
+ Table
222
+ </div>
223
+ <div className="panel__content__form__section__header__prompt">
224
+ create seed data below based on root tables
225
+ </div>
226
+ <CustomSelectorInput
227
+ placeholder="Choose a root table..."
228
+ options={tableOptions}
229
+ onChange={changeTable}
230
+ value={{
231
+ label: `${tableRowIdentifierState.table.schema.name}.${tableRowIdentifierState.table.name}`,
232
+
233
+ value: tableRowIdentifierState.table,
234
+ }}
235
+ darkMode={true}
236
+ />
237
+ </div>
238
+ <div className="panel__content__form__section">
239
+ <div className="panel__content__form__section__header__label">
240
+ Seed Data
241
+ </div>
242
+ <div className="panel__content__form__section__header__prompt">
243
+ create value for primary key column
244
+ </div>
245
+ {tableRowIdentifierState.rowIdentifierStates.map(
246
+ (rowIdentifierState) => (
247
+ <RowIdentifierEditor
248
+ key={rowIdentifierState._UUID}
249
+ tableRowIdentifierState={tableRowIdentifierState}
250
+ rowIdentifierState={rowIdentifierState}
251
+ />
252
+ ),
253
+ )}
254
+ <div className="panel__content__form__section__list__new-item__add">
255
+ <button
256
+ className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
257
+ onClick={addNewRow}
258
+ tabIndex={-1}
259
+ title="Add Seed Data for column"
260
+ >
261
+ Add Row
262
+ </button>
263
+ </div>
264
+ </div>
265
+ </ModalBody>
266
+ );
267
+ },
268
+ );
269
+
270
+ export const SeedDataInputModal = observer(
271
+ (props: { connectionTestDataState: ConnectionTestDataState }) => {
272
+ const { connectionTestDataState } = props;
273
+ const applicationStore = useApplicationStore();
274
+ const useSeedDataInputModal = connectionTestDataState.useSeedDataInputModal;
275
+ const closeModal = (): void =>
276
+ connectionTestDataState.setUseSeedDataInputModal(false);
277
+ const generateWithSeedData = (): void => {
278
+ closeModal();
279
+ flowResult(connectionTestDataState.generateTestDataWithSeedData()).catch(
280
+ applicationStore.alertUnhandledError,
281
+ );
282
+ };
283
+ const addNewTable = (): void => {
284
+ const tables = connectionTestDataState.getAvailableTables();
285
+ if (tables[0]) {
286
+ connectionTestDataState.addNewTableIdentifierState(tables[0]);
287
+ }
288
+ };
289
+
290
+ return (
291
+ <Dialog
292
+ open={useSeedDataInputModal}
293
+ onClose={closeModal}
294
+ classes={{
295
+ root: 'editor-modal__root-container',
296
+ container: 'editor-modal__container',
297
+ paper: 'editor-modal__content',
298
+ }}
299
+ >
300
+ <Modal
301
+ darkMode={true}
302
+ className="editor-modal lambda-parameter-values__modal"
303
+ >
304
+ <ModalHeader title="Create Seed Data Input (BETA)" />
305
+ <ModalBody className="lambda-parameter-values__modal__body">
306
+ {connectionTestDataState.tableRowIdentifierStates.map(
307
+ (tableRowIdentifierState) => (
308
+ <TableRowIdentifierEditor
309
+ key={tableRowIdentifierState._UUID}
310
+ connectionTestDataState={connectionTestDataState}
311
+ tableRowIdentifierState={tableRowIdentifierState}
312
+ />
313
+ ),
314
+ )}
315
+ <button
316
+ className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
317
+ onClick={addNewTable}
318
+ tabIndex={-1}
319
+ title="Add Seed Data for table"
320
+ >
321
+ Add a Different Table
322
+ </button>
323
+ </ModalBody>
324
+ <ModalFooter>
325
+ <ModalFooterButton onClick={closeModal} text="Close" />
326
+ <ModalFooterButton onClick={generateWithSeedData} text="Generate" />
327
+ </ModalFooter>
328
+ </Modal>
329
+ </Dialog>
330
+ );
331
+ },
332
+ );
72
333
 
73
334
  export const UseDataElementModal = observer(
74
335
  (props: { connectionTestDataState: ConnectionTestDataState }) => {
@@ -201,6 +462,17 @@ export const ConnectionTestDataEditor = observer(
201
462
  }
202
463
  };
203
464
 
465
+ const generateTestDataWithSeedData = (): void => {
466
+ connectionTestDataState.setUseSeedDataInputModal(true);
467
+ connectionTestDataState.setNewTableIdentifierState([]);
468
+ const table = getNullableFirstEntry(
469
+ connectionTestDataState.getAvailableTables(),
470
+ );
471
+ if (table) {
472
+ connectionTestDataState.addNewTableIdentifierState(table);
473
+ }
474
+ };
475
+
204
476
  const generateQuerySchemas = (): void => {
205
477
  flowResult(connectionTestDataState.generateQuerySchemas()).catch(
206
478
  applicationStore.alertUnhandledError,
@@ -268,6 +540,16 @@ export const ConnectionTestDataEditor = observer(
268
540
  >
269
541
  Generate Query Schemas
270
542
  </MenuContentItem>
543
+ <MenuContentItem
544
+ className="btn__dropdown-combo__option"
545
+ onClick={generateTestDataWithSeedData}
546
+ disabled={
547
+ connectionTestDataState
548
+ .generatingTestDataWithSeedDataState.isInProgress
549
+ }
550
+ >
551
+ Generate with Seed Data (Beta)
552
+ </MenuContentItem>
271
553
  </MenuContent>
272
554
  }
273
555
  menuProps={{
@@ -316,6 +598,11 @@ export const ConnectionTestDataEditor = observer(
316
598
  connectionTestDataState={connectionTestDataState}
317
599
  />
318
600
  )}
601
+ {connectionTestDataState.useSeedDataInputModal && (
602
+ <SeedDataInputModal
603
+ connectionTestDataState={connectionTestDataState}
604
+ />
605
+ )}
319
606
  </div>
320
607
  );
321
608
  },
@@ -624,6 +911,10 @@ export const ServiceTestDataEditor = observer(
624
911
  Boolean(
625
912
  testDataState.selectedDataState?.generateSchemaQueryState
626
913
  .isInProgress,
914
+ ) ||
915
+ Boolean(
916
+ testDataState.selectedDataState
917
+ ?.generatingTestDataWithSeedDataState.isInProgress,
627
918
  )
628
919
  }
629
920
  />
@@ -379,6 +379,7 @@ export const queryClass = async (
379
379
  const queryBuilderState = new ClassQueryBuilderState(
380
380
  embeddedQueryBuilderState.editorStore.applicationStore,
381
381
  embeddedQueryBuilderState.editorStore.graphManagerState,
382
+ editorStore.applicationStore.config.options.queryBuilderConfig,
382
383
  );
383
384
  queryBuilderState.changeClass(_class);
384
385
  queryBuilderState.propagateClassChange(_class);
@@ -113,6 +113,7 @@ import {
113
113
  type FunctionActivatorConfiguration,
114
114
  Database,
115
115
  DEPENDENCY_ROOT_PACKAGE_PREFIX,
116
+ Service,
116
117
  } from '@finos/legend-graph';
117
118
  import {
118
119
  ActionAlertActionType,
@@ -145,6 +146,7 @@ import {
145
146
  import { DatabaseBuilderWizard } from '../editor-group/connection-editor/DatabaseBuilderWizard.js';
146
147
  import { FunctionEditorState } from '../../../stores/editor/editor-state/element-editor-state/FunctionEditorState.js';
147
148
  import { DatabaseModelBuilder } from '../editor-group/connection-editor/DatabaseModelBuilder.js';
149
+ import { queryService } from '../editor-group/service-editor/ServiceExecutionQueryEditor.js';
148
150
 
149
151
  const ElementRenamer = observer(() => {
150
152
  const editorStore = useEditorStore();
@@ -520,6 +522,13 @@ const ExplorerContextMenu = observer(
520
522
  }
521
523
  },
522
524
  );
525
+ const buildServiceQuery = editorStore.applicationStore.guardUnhandledError(
526
+ async () => {
527
+ if (node?.packageableElement instanceof Service) {
528
+ await queryService(node.packageableElement, editorStore);
529
+ }
530
+ },
531
+ );
523
532
  const generateSampleData = editorStore.applicationStore.guardUnhandledError(
524
533
  async () => {
525
534
  if (node?.packageableElement instanceof Class) {
@@ -852,6 +861,14 @@ const ExplorerContextMenu = observer(
852
861
  <MenuContentDivider />
853
862
  </>
854
863
  )}
864
+ {node.packageableElement instanceof Service && (
865
+ <>
866
+ <MenuContentItem onClick={buildServiceQuery}>
867
+ Query...
868
+ </MenuContentItem>
869
+ <MenuContentDivider />
870
+ </>
871
+ )}
855
872
  {node.packageableElement instanceof ConcreteFunctionDefinition && (
856
873
  <>
857
874
  {editorStore.applicationStore.config.options
@@ -15,7 +15,10 @@
15
15
  */
16
16
 
17
17
  import type { GenericLegendApplicationStore } from '@finos/legend-application';
18
- import { QueryBuilderState } from '@finos/legend-query-builder';
18
+ import {
19
+ type QueryBuilderConfig,
20
+ QueryBuilderState,
21
+ } from '@finos/legend-query-builder';
19
22
  import type { GraphManagerState, Mapping } from '@finos/legend-graph';
20
23
  import { renderMappingExecutionQueryBuilderSetupPanelContent } from '../../../../../components/editor/editor-group/mapping-editor/MappingExecutionQueryBuilder.js';
21
24
 
@@ -29,8 +32,9 @@ export class MappingExecutionQueryBuilderState extends QueryBuilderState {
29
32
  applicationStore: GenericLegendApplicationStore,
30
33
  graphManagerState: GraphManagerState,
31
34
  mapping: Mapping,
35
+ config: QueryBuilderConfig | undefined,
32
36
  ) {
33
- super(applicationStore, graphManagerState);
37
+ super(applicationStore, graphManagerState, config);
34
38
  this.executionMapping = mapping;
35
39
  this.executionContextState.mapping = mapping;
36
40
  }