@finos/legend-application-studio 28.21.3 → 28.21.5

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 (66) hide show
  1. package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.d.ts +1 -1
  2. package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.d.ts.map +1 -1
  3. package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.js +3 -3
  4. package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.js.map +1 -1
  5. package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.d.ts +3 -0
  6. package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.d.ts.map +1 -1
  7. package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.js +72 -52
  8. package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.js.map +1 -1
  9. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.d.ts.map +1 -1
  10. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js +22 -1
  11. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js.map +1 -1
  12. package/lib/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.d.ts +23 -0
  13. package/lib/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.d.ts.map +1 -0
  14. package/lib/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.js +267 -0
  15. package/lib/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.js.map +1 -0
  16. package/lib/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.d.ts.map +1 -1
  17. package/lib/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.js +113 -75
  18. package/lib/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.js.map +1 -1
  19. package/lib/components/editor/editor-group/testable/TestableSharedComponents.d.ts.map +1 -1
  20. package/lib/components/editor/editor-group/testable/TestableSharedComponents.js +39 -5
  21. package/lib/components/editor/editor-group/testable/TestableSharedComponents.js.map +1 -1
  22. package/lib/components/editor/side-bar/DevMetadataPanel.d.ts.map +1 -1
  23. package/lib/components/editor/side-bar/DevMetadataPanel.js +37 -6
  24. package/lib/components/editor/side-bar/DevMetadataPanel.js.map +1 -1
  25. package/lib/index.css +2 -2
  26. package/lib/index.css.map +1 -1
  27. package/lib/package.json +1 -1
  28. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.d.ts +17 -2
  29. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.d.ts.map +1 -1
  30. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.js +56 -49
  31. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.js.map +1 -1
  32. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts +4 -1
  33. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts.map +1 -1
  34. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js +4 -0
  35. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js.map +1 -1
  36. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.d.ts +113 -0
  37. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.d.ts.map +1 -0
  38. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.js +647 -0
  39. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.js.map +1 -0
  40. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.d.ts +18 -4
  41. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.d.ts.map +1 -1
  42. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js +214 -53
  43. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js.map +1 -1
  44. package/lib/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.d.ts +17 -1
  45. package/lib/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.d.ts.map +1 -1
  46. package/lib/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.js +46 -1
  47. package/lib/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.js.map +1 -1
  48. package/lib/stores/editor/sidebar-state/dev-metadata/DevMetadataState.d.ts +9 -0
  49. package/lib/stores/editor/sidebar-state/dev-metadata/DevMetadataState.d.ts.map +1 -1
  50. package/lib/stores/editor/sidebar-state/dev-metadata/DevMetadataState.js +55 -0
  51. package/lib/stores/editor/sidebar-state/dev-metadata/DevMetadataState.js.map +1 -1
  52. package/package.json +16 -16
  53. package/src/components/editor/editor-group/data-editor/EmbeddedDataEditor.tsx +3 -0
  54. package/src/components/editor/editor-group/data-editor/RelationElementsDataEditor.tsx +331 -231
  55. package/src/components/editor/editor-group/dataProduct/DataProductEditor.tsx +32 -0
  56. package/src/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.tsx +935 -0
  57. package/src/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.tsx +425 -308
  58. package/src/components/editor/editor-group/testable/TestableSharedComponents.tsx +160 -15
  59. package/src/components/editor/side-bar/DevMetadataPanel.tsx +194 -10
  60. package/src/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.ts +82 -51
  61. package/src/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.ts +4 -0
  62. package/src/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.ts +927 -0
  63. package/src/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.ts +303 -72
  64. package/src/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.ts +66 -0
  65. package/src/stores/editor/sidebar-state/dev-metadata/DevMetadataState.ts +76 -0
  66. package/tsconfig.json +2 -0
@@ -32,6 +32,10 @@ import {
32
32
  } from '@finos/legend-graph';
33
33
  import {
34
34
  ContentType,
35
+ csvDecodeValue,
36
+ csvEncodeValue,
37
+ csvStringify,
38
+ parseCSVContent,
35
39
  guaranteeNonEmptyString,
36
40
  tryToFormatLosslessJSONString,
37
41
  UnsupportedOperationError,
@@ -211,8 +215,12 @@ export class ModelStoreDataState extends EmbeddedDataState {
211
215
 
212
216
  export class RelationElementState {
213
217
  relationElement: RelationElement;
218
+ supportsColumnEditing: boolean;
214
219
 
215
- constructor(relationElement: RelationElement) {
220
+ constructor(
221
+ relationElement: RelationElement,
222
+ options?: { supportsColumnEditing?: boolean },
223
+ ) {
216
224
  makeObservable(this, {
217
225
  relationElement: observable,
218
226
  addColumn: action,
@@ -224,6 +232,7 @@ export class RelationElementState {
224
232
  clearAllData: action,
225
233
  importCSV: action,
226
234
  });
235
+ this.supportsColumnEditing = options?.supportsColumnEditing ?? true;
227
236
  this.relationElement = relationElement;
228
237
  this.relationElement = observe_RelationElement(relationElement);
229
238
  }
@@ -268,10 +277,16 @@ export class RelationElementState {
268
277
 
269
278
  updateRow(rowIndex: number, columnIndex: number, value: string): void {
270
279
  if (this.relationElement.rows[rowIndex]) {
271
- this.relationElement.rows[rowIndex].values[columnIndex] = value;
280
+ this.relationElement.rows[rowIndex].values[columnIndex] =
281
+ csvEncodeValue(value);
272
282
  }
273
283
  }
274
284
 
285
+ getDisplayValue(rowIndex: number, columnIndex: number): string {
286
+ const value = this.relationElement.rows[rowIndex]?.values[columnIndex];
287
+ return value !== undefined ? csvDecodeValue(value) : '';
288
+ }
289
+
275
290
  clearAllData(): void {
276
291
  this.relationElement.rows.splice(0);
277
292
  }
@@ -280,7 +295,9 @@ export class RelationElementState {
280
295
  return JSON.stringify(
281
296
  {
282
297
  columns: this.relationElement.columns,
283
- data: this.relationElement.rows,
298
+ data: this.relationElement.rows.map((row) => ({
299
+ values: row.values.map((v) => csvDecodeValue(v)),
300
+ })),
284
301
  },
285
302
  null,
286
303
  2,
@@ -305,7 +322,7 @@ export class RelationElementState {
305
322
  const insertStatements = this.relationElement.rows.map((row) => {
306
323
  const values = this.relationElement.columns
307
324
  .map((col, colIndex) => {
308
- const value = row.values[colIndex] ?? '';
325
+ const value = csvDecodeValue(row.values[colIndex] ?? '');
309
326
  if (value !== '') {
310
327
  return `'${value.replace(/'/g, "''")}'`;
311
328
  }
@@ -319,75 +336,50 @@ export class RelationElementState {
319
336
  }
320
337
 
321
338
  exportCSV(): string {
322
- const headers = this.relationElement.columns.map((col) => col);
323
- const csvLines = [headers.join(',')];
324
-
325
- this.relationElement.rows.forEach((row) => {
326
- const values = headers.map((header, headerIndex) => {
327
- const value = row.values[headerIndex] ?? '';
328
- if (value.includes(',') || value.includes('"')) {
329
- return `"${value.replace(/"/g, '""')}"`;
330
- }
331
- return value;
332
- });
333
- csvLines.push(values.join(','));
334
- });
335
-
336
- return csvLines.join('\n');
337
- }
338
-
339
- private parseCSVLine(line: string): string[] {
340
- const result: string[] = [];
341
- let current = '';
342
- let inQuotes = false;
343
-
344
- for (let i = 0; i < line.length; i++) {
345
- const char = line[i];
346
- if (char === '"') {
347
- inQuotes = !inQuotes;
348
- } else if (char === ',' && !inQuotes) {
349
- result.push(current.trim());
350
- current = '';
351
- } else {
352
- current += char;
353
- }
354
- }
355
- result.push(current.trim());
356
- return result;
339
+ // decode so that csvStringify does not double encode
340
+ const data = this.relationElement.rows.map((row) =>
341
+ row.values.map((v) => csvDecodeValue(v)),
342
+ );
343
+ return csvStringify([this.relationElement.columns, ...data]);
357
344
  }
358
345
 
359
346
  importCSV(csvContent: string): void {
360
- const lines = csvContent.trim().split('\n');
361
- if (lines.length === 0) {
347
+ const parsed = parseCSVContent(csvContent);
348
+ if (parsed.length === 0) {
362
349
  return;
363
350
  }
364
351
 
365
- const firstLine = lines[0];
366
- if (!firstLine) {
352
+ const headers = parsed[0];
353
+ if (!headers) {
367
354
  return;
368
355
  }
369
356
 
370
- const headers = this.parseCSVLine(firstLine);
371
357
  this.relationElement.columns = headers;
372
-
373
- this.relationElement.rows = lines.slice(1).map((line) => {
374
- const values = this.parseCSVLine(line);
358
+ this.relationElement.rows = parsed.slice(1).map((values) => {
375
359
  const row = new RelationRowTestData();
376
- row.values = [];
377
- headers.forEach((header, index) => {
378
- row.values[index] = values[index] ?? '';
379
- });
360
+ row.values = headers.map((_, index) =>
361
+ csvEncodeValue(values[index] ?? ''),
362
+ );
380
363
  return observe_RelationRowTestData(row);
381
364
  });
382
365
  }
383
366
  }
384
367
 
368
+ export interface RelationElementAccessorOption {
369
+ label: string;
370
+ value: string;
371
+ columns: string[];
372
+ }
373
+
385
374
  export class RelationElementsDataState extends EmbeddedDataState {
386
375
  override embeddedData: RelationElementsData;
387
376
  showImportCSVModal = false;
388
377
  showNewRelationElementModal = false;
389
378
  activeRelationElement: RelationElementState | undefined;
390
379
  relationElementStates: RelationElementState[];
380
+ accessorOptions: RelationElementAccessorOption[] | undefined;
381
+ accessorTypeLabel: string | undefined;
382
+ refreshAccessorOptions: (() => Promise<void>) | undefined;
391
383
 
392
384
  constructor(editorStore: EditorStore, embeddedData: RelationElementsData) {
393
385
  super(editorStore, embeddedData);
@@ -396,10 +388,15 @@ export class RelationElementsDataState extends EmbeddedDataState {
396
388
  showImportCSVModal: observable,
397
389
  showNewRelationElementModal: observable,
398
390
  activeRelationElement: observable,
391
+ relationElementStates: observable,
392
+ accessorOptions: observable,
393
+ accessorTypeLabel: observable,
399
394
  setActiveRelationElement: action,
400
395
  setShowImportCSVModal: action,
401
396
  setShowNewRelationElementModal: action,
402
397
  addRelationElement: action,
398
+ deleteRelationElement: action,
399
+ setAccessorOptions: action,
403
400
  });
404
401
  this.embeddedData = embeddedData;
405
402
  this.relationElementStates = embeddedData.relationElements.map(
@@ -423,6 +420,18 @@ export class RelationElementsDataState extends EmbeddedDataState {
423
420
  this.setActiveRelationElement(newElementState);
424
421
  }
425
422
 
423
+ deleteRelationElement(relationElementState: RelationElementState): void {
424
+ const idx = this.relationElementStates.indexOf(relationElementState);
425
+ if (idx === -1) {
426
+ return;
427
+ }
428
+ this.relationElementStates.splice(idx, 1);
429
+ this.embeddedData.relationElements.splice(idx, 1);
430
+ if (this.activeRelationElement === relationElementState) {
431
+ this.setActiveRelationElement(this.relationElementStates[0]);
432
+ }
433
+ }
434
+
426
435
  setShowImportCSVModal(show: boolean): void {
427
436
  this.showImportCSVModal = show;
428
437
  }
@@ -430,6 +439,28 @@ export class RelationElementsDataState extends EmbeddedDataState {
430
439
  setShowNewRelationElementModal(show: boolean): void {
431
440
  this.showNewRelationElementModal = show;
432
441
  }
442
+
443
+ setAccessorOptions(
444
+ options: RelationElementAccessorOption[] | undefined,
445
+ typeLabel: string | undefined,
446
+ ): void {
447
+ this.accessorOptions = options;
448
+ this.accessorTypeLabel = typeLabel;
449
+ }
450
+
451
+ setRefreshAccessorOptions(fn: (() => Promise<void>) | undefined): void {
452
+ this.refreshAccessorOptions = fn;
453
+ }
454
+
455
+ get availableAccessorOptions(): RelationElementAccessorOption[] {
456
+ if (!this.accessorOptions) {
457
+ return [];
458
+ }
459
+ const existingPaths = new Set(
460
+ this.relationElementStates.map((s) => s.relationElement.paths.join('.')),
461
+ );
462
+ return this.accessorOptions.filter((opt) => !existingPaths.has(opt.value));
463
+ }
433
464
  }
434
465
 
435
466
  export class RelationalCSVDataTableState {
@@ -109,6 +109,7 @@ import {
109
109
  modelAccessPointGroup_setMapping,
110
110
  dataProduct_setSupportInfoIfAbsent,
111
111
  } from '../../../../graph-modifier/DSL_DataProduct_GraphModifierHelper.js';
112
+ import { DataProductTestableState } from './testable/DataProductTestableState.js';
112
113
  import { LambdaEditorState, LineageState } from '@finos/legend-query-builder';
113
114
  import {
114
115
  DataProductElementEditorInitialConfiguration,
@@ -129,6 +130,7 @@ export enum DATA_PRODUCT_TAB {
129
130
  SUPPORT = 'Support',
130
131
  APG = 'APG',
131
132
  OPERATIONAL = 'Operational',
133
+ TESTING = 'Testing',
132
134
  }
133
135
 
134
136
  export enum DATA_PRODUCT_TYPE {
@@ -966,6 +968,7 @@ export class DataProductEditorState extends ElementEditorState {
966
968
  selectedGroupState: AccessPointGroupState | undefined;
967
969
  selectedTab: DATA_PRODUCT_TAB;
968
970
  modelledDataProduct = false;
971
+ testableState: DataProductTestableState;
969
972
 
970
973
  constructor(
971
974
  editorStore: EditorStore,
@@ -1015,6 +1018,7 @@ export class DataProductEditorState extends ElementEditorState {
1015
1018
  this.deployOnOpen = elementConfig.deployOnOpen ?? false;
1016
1019
  }
1017
1020
  this.selectedTab = DATA_PRODUCT_TAB.HOME;
1021
+ this.testableState = new DataProductTestableState(this);
1018
1022
  }
1019
1023
 
1020
1024
  setDeployOnOpen(value: boolean): void {