@finos/legend-application-studio 28.19.50 → 28.19.51
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.
- package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.js +5 -1
- package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.js.map +1 -1
- package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.d.ts +23 -0
- package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.d.ts.map +1 -0
- package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.js +197 -0
- package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.js.map +1 -0
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/editor/editor-state/ExternalFormatState.d.ts +2 -1
- package/lib/stores/editor/editor-state/ExternalFormatState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/ExternalFormatState.js +1 -0
- package/lib/stores/editor/editor-state/ExternalFormatState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.d.ts +30 -1
- package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.js +195 -1
- package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js +13 -5
- package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js.map +1 -1
- package/package.json +10 -10
- package/src/components/editor/editor-group/data-editor/EmbeddedDataEditor.tsx +9 -0
- package/src/components/editor/editor-group/data-editor/RelationElementsDataEditor.tsx +567 -0
- package/src/stores/editor/editor-state/ExternalFormatState.ts +1 -0
- package/src/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.ts +233 -0
- package/src/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.ts +24 -5
- package/tsconfig.json +1 -0
@@ -24,6 +24,11 @@ import {
|
|
24
24
|
ExternalFormatData,
|
25
25
|
ModelStoreData,
|
26
26
|
ModelEmbeddedData,
|
27
|
+
type RelationElement,
|
28
|
+
RelationElementsData,
|
29
|
+
RelationRowTestData,
|
30
|
+
observe_RelationRowTestData,
|
31
|
+
observe_RelationElement,
|
27
32
|
} from '@finos/legend-graph';
|
28
33
|
import {
|
29
34
|
ContentType,
|
@@ -64,6 +69,9 @@ export const createEmbeddedData = (
|
|
64
69
|
} else if (type === EmbeddedDataType.RELATIONAL_CSV) {
|
65
70
|
const relational = new RelationalCSVData();
|
66
71
|
return relational;
|
72
|
+
} else if (type === EmbeddedDataType.RELATION_ELEMENTS_DATA) {
|
73
|
+
const testData = new RelationElementsData();
|
74
|
+
return testData;
|
67
75
|
} else if (type === EmbeddedDataType.MODEL_STORE_DATA) {
|
68
76
|
const modelStoreData = new ModelStoreData();
|
69
77
|
return modelStoreData;
|
@@ -201,6 +209,229 @@ export class ModelStoreDataState extends EmbeddedDataState {
|
|
201
209
|
}
|
202
210
|
}
|
203
211
|
|
212
|
+
export class RelationElementState {
|
213
|
+
relationElement: RelationElement;
|
214
|
+
|
215
|
+
constructor(relationElement: RelationElement) {
|
216
|
+
makeObservable(this, {
|
217
|
+
relationElement: observable,
|
218
|
+
addColumn: action,
|
219
|
+
removeColumn: action,
|
220
|
+
updateColumn: action,
|
221
|
+
addRow: action,
|
222
|
+
removeRow: action,
|
223
|
+
updateRow: action,
|
224
|
+
clearAllData: action,
|
225
|
+
importCSV: action,
|
226
|
+
});
|
227
|
+
this.relationElement = relationElement;
|
228
|
+
this.relationElement = observe_RelationElement(relationElement);
|
229
|
+
}
|
230
|
+
|
231
|
+
addColumn(name: string): void {
|
232
|
+
this.relationElement.columns.push(name);
|
233
|
+
this.relationElement.rows.forEach((row) => {
|
234
|
+
row.values.push('');
|
235
|
+
});
|
236
|
+
}
|
237
|
+
|
238
|
+
removeColumn(index: number): void {
|
239
|
+
const columnToRemove = this.relationElement.columns[index];
|
240
|
+
if (columnToRemove) {
|
241
|
+
this.relationElement.columns.splice(index, 1);
|
242
|
+
this.relationElement.rows.forEach((row) => {
|
243
|
+
row.values.splice(index, 1);
|
244
|
+
});
|
245
|
+
}
|
246
|
+
}
|
247
|
+
|
248
|
+
updateColumn(index: number, name: string): void {
|
249
|
+
const oldName = this.relationElement.columns[index];
|
250
|
+
if (oldName && oldName !== name) {
|
251
|
+
this.relationElement.columns[index] = name;
|
252
|
+
}
|
253
|
+
}
|
254
|
+
|
255
|
+
addRow(): void {
|
256
|
+
const row = new RelationRowTestData();
|
257
|
+
row.values = [];
|
258
|
+
const newRow = observe_RelationRowTestData(row);
|
259
|
+
this.relationElement.columns.forEach((col) => {
|
260
|
+
newRow.values.push('');
|
261
|
+
});
|
262
|
+
this.relationElement.rows.push(newRow);
|
263
|
+
}
|
264
|
+
|
265
|
+
removeRow(index: number): void {
|
266
|
+
this.relationElement.rows.splice(index, 1);
|
267
|
+
}
|
268
|
+
|
269
|
+
updateRow(rowIndex: number, columnIndex: number, value: string): void {
|
270
|
+
if (this.relationElement.rows[rowIndex]) {
|
271
|
+
this.relationElement.rows[rowIndex].values[columnIndex] = value;
|
272
|
+
}
|
273
|
+
}
|
274
|
+
|
275
|
+
clearAllData(): void {
|
276
|
+
this.relationElement.rows.splice(0);
|
277
|
+
}
|
278
|
+
|
279
|
+
exportJSON(): string {
|
280
|
+
return JSON.stringify(
|
281
|
+
{
|
282
|
+
columns: this.relationElement.columns,
|
283
|
+
data: this.relationElement.rows,
|
284
|
+
},
|
285
|
+
null,
|
286
|
+
2,
|
287
|
+
);
|
288
|
+
}
|
289
|
+
|
290
|
+
exportSQL(): string {
|
291
|
+
if (
|
292
|
+
this.relationElement.columns.length === 0 ||
|
293
|
+
this.relationElement.rows.length === 0
|
294
|
+
) {
|
295
|
+
return '';
|
296
|
+
}
|
297
|
+
|
298
|
+
const tableName = 'test_data';
|
299
|
+
const defaultDataType = 'VARCHAR(1000)';
|
300
|
+
const columnDefs = this.relationElement.columns
|
301
|
+
.map((col) => `${col} ${defaultDataType}`)
|
302
|
+
.join(', ');
|
303
|
+
const createTable = `CREATE TABLE ${tableName} (${columnDefs});`;
|
304
|
+
|
305
|
+
const insertStatements = this.relationElement.rows.map((row) => {
|
306
|
+
const values = this.relationElement.columns
|
307
|
+
.map((col, colIndex) => {
|
308
|
+
const value = row.values[colIndex] ?? '';
|
309
|
+
if (value !== '') {
|
310
|
+
return `'${value.replace(/'/g, "''")}'`;
|
311
|
+
}
|
312
|
+
return 'NULL';
|
313
|
+
})
|
314
|
+
.join(', ');
|
315
|
+
return `INSERT INTO ${tableName} VALUES (${values});`;
|
316
|
+
});
|
317
|
+
|
318
|
+
return [createTable, '', ...insertStatements].join('\n');
|
319
|
+
}
|
320
|
+
|
321
|
+
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;
|
357
|
+
}
|
358
|
+
|
359
|
+
importCSV(csvContent: string): void {
|
360
|
+
const lines = csvContent.trim().split('\n');
|
361
|
+
if (lines.length === 0) {
|
362
|
+
return;
|
363
|
+
}
|
364
|
+
|
365
|
+
const firstLine = lines[0];
|
366
|
+
if (!firstLine) {
|
367
|
+
return;
|
368
|
+
}
|
369
|
+
|
370
|
+
const headers = this.parseCSVLine(firstLine);
|
371
|
+
this.relationElement.columns = headers;
|
372
|
+
|
373
|
+
this.relationElement.rows = lines.slice(1).map((line) => {
|
374
|
+
const values = this.parseCSVLine(line);
|
375
|
+
const row = new RelationRowTestData();
|
376
|
+
row.values = [];
|
377
|
+
headers.forEach((header, index) => {
|
378
|
+
row.values[index] = values[index] ?? '';
|
379
|
+
});
|
380
|
+
return observe_RelationRowTestData(row);
|
381
|
+
});
|
382
|
+
}
|
383
|
+
}
|
384
|
+
|
385
|
+
export class RelationElementsDataState extends EmbeddedDataState {
|
386
|
+
override embeddedData: RelationElementsData;
|
387
|
+
showImportCSVModal = false;
|
388
|
+
showNewRelationElementModal = false;
|
389
|
+
activeRelationElement: RelationElementState | undefined;
|
390
|
+
relationElementStates: RelationElementState[];
|
391
|
+
|
392
|
+
constructor(editorStore: EditorStore, embeddedData: RelationElementsData) {
|
393
|
+
super(editorStore, embeddedData);
|
394
|
+
makeObservable(this, {
|
395
|
+
embeddedData: observable,
|
396
|
+
showImportCSVModal: observable,
|
397
|
+
showNewRelationElementModal: observable,
|
398
|
+
activeRelationElement: observable,
|
399
|
+
setActiveRelationElement: action,
|
400
|
+
setShowImportCSVModal: action,
|
401
|
+
setShowNewRelationElementModal: action,
|
402
|
+
addRelationElement: action,
|
403
|
+
});
|
404
|
+
this.embeddedData = embeddedData;
|
405
|
+
this.relationElementStates = embeddedData.relationElements.map(
|
406
|
+
(relationElement) => new RelationElementState(relationElement),
|
407
|
+
);
|
408
|
+
this.activeRelationElement = this.relationElementStates[0];
|
409
|
+
}
|
410
|
+
|
411
|
+
label(): string {
|
412
|
+
return 'Relation Elements Test Data';
|
413
|
+
}
|
414
|
+
|
415
|
+
setActiveRelationElement(val: RelationElementState | undefined): void {
|
416
|
+
this.activeRelationElement = val;
|
417
|
+
}
|
418
|
+
|
419
|
+
addRelationElement(relationElement: RelationElement): void {
|
420
|
+
const newElementState = new RelationElementState(relationElement);
|
421
|
+
this.relationElementStates.push(newElementState);
|
422
|
+
this.embeddedData.relationElements.push(relationElement);
|
423
|
+
this.setActiveRelationElement(newElementState);
|
424
|
+
}
|
425
|
+
|
426
|
+
setShowImportCSVModal(show: boolean): void {
|
427
|
+
this.showImportCSVModal = show;
|
428
|
+
}
|
429
|
+
|
430
|
+
setShowNewRelationElementModal(show: boolean): void {
|
431
|
+
this.showNewRelationElementModal = show;
|
432
|
+
}
|
433
|
+
}
|
434
|
+
|
204
435
|
export class RelationalCSVDataTableState {
|
205
436
|
readonly editorStore: EditorStore;
|
206
437
|
table: RelationalCSVDataTable;
|
@@ -374,6 +605,8 @@ export function buildEmbeddedDataEditorState(
|
|
374
605
|
);
|
375
606
|
} else if (embeddedData instanceof RelationalCSVData) {
|
376
607
|
return new RelationalCSVDataState(editorStore, embeddedData);
|
608
|
+
} else if (embeddedData instanceof RelationElementsData) {
|
609
|
+
return new RelationElementsDataState(editorStore, embeddedData);
|
377
610
|
} else if (embeddedData instanceof DataElementReference) {
|
378
611
|
return new DataElementReferenceState(editorStore, embeddedData, options);
|
379
612
|
} else {
|
@@ -54,12 +54,13 @@ import {
|
|
54
54
|
InstanceValue,
|
55
55
|
PackageableElementReference,
|
56
56
|
Database,
|
57
|
-
RelationalCSVData,
|
58
57
|
PackageableElementExplicitReference,
|
59
58
|
observe_ValueSpecification,
|
60
59
|
buildLambdaVariableExpressions,
|
61
60
|
EqualTo,
|
62
61
|
ModelStore,
|
62
|
+
RelationElementsData,
|
63
|
+
CORE_PURE_PATH,
|
63
64
|
} from '@finos/legend-graph';
|
64
65
|
import {
|
65
66
|
TestablePackageableElementEditorState,
|
@@ -122,7 +123,14 @@ const resolveRuntimesFromQuery = (
|
|
122
123
|
): EngineRuntime[] | undefined => {
|
123
124
|
try {
|
124
125
|
const body = func.expressionSequence;
|
125
|
-
const rawLambda = new RawLambda(
|
126
|
+
const rawLambda = new RawLambda(
|
127
|
+
func.parameters.map((_param) =>
|
128
|
+
editorStore.graphManagerState.graphManager.serializeRawValueSpecification(
|
129
|
+
_param,
|
130
|
+
),
|
131
|
+
),
|
132
|
+
body,
|
133
|
+
);
|
126
134
|
const functions = new Map<string, SimpleFunctionExpression[]>();
|
127
135
|
const valueSpec =
|
128
136
|
editorStore.graphManagerState.graphManager.buildValueSpecification(
|
@@ -759,7 +767,18 @@ export class FunctionTestableState extends TestablePackageableElementEditorState
|
|
759
767
|
const functionSuite = new FunctionTestSuite();
|
760
768
|
functionSuite.id = suiteName;
|
761
769
|
const engineRuntimes = this.associatedRuntimes;
|
762
|
-
if (engineRuntimes?.length) {
|
770
|
+
if (!engineRuntimes?.length) {
|
771
|
+
const type = this.function.returnType.value.rawType;
|
772
|
+
if (
|
773
|
+
type.path === CORE_PURE_PATH.RELATION ||
|
774
|
+
type.path === CORE_PURE_PATH.TABULAR_DATASET
|
775
|
+
) {
|
776
|
+
this.editorStore.applicationStore.notificationService.notifyWarning(
|
777
|
+
`Unable to find runtime or function contains accessors incompatible for test suite creation`,
|
778
|
+
);
|
779
|
+
return;
|
780
|
+
}
|
781
|
+
} else {
|
763
782
|
try {
|
764
783
|
assertTrue(
|
765
784
|
engineRuntimes.length === 1,
|
@@ -791,9 +810,9 @@ export class FunctionTestableState extends TestablePackageableElementEditorState
|
|
791
810
|
const store = guaranteeNonNullable(stores[0]);
|
792
811
|
const data = new FunctionTestData();
|
793
812
|
if (store instanceof Database) {
|
794
|
-
const
|
813
|
+
const relation = new RelationElementsData();
|
795
814
|
data.element = PackageableElementExplicitReference.create(store);
|
796
|
-
data.data =
|
815
|
+
data.data = relation;
|
797
816
|
} else if (store instanceof ModelStore) {
|
798
817
|
const modelStoreData = createBareExternalFormat();
|
799
818
|
data.element = PackageableElementExplicitReference.create(store);
|
package/tsconfig.json
CHANGED
@@ -252,6 +252,7 @@
|
|
252
252
|
"./src/components/editor/editor-group/connection-editor/post-processor-editor/MapperPostProcessorEditor.tsx",
|
253
253
|
"./src/components/editor/editor-group/data-editor/DataElementEditor.tsx",
|
254
254
|
"./src/components/editor/editor-group/data-editor/EmbeddedDataEditor.tsx",
|
255
|
+
"./src/components/editor/editor-group/data-editor/RelationElementsDataEditor.tsx",
|
255
256
|
"./src/components/editor/editor-group/data-editor/RelationalCSVDataEditor.tsx",
|
256
257
|
"./src/components/editor/editor-group/dataProduct/DataProductEditor.tsx",
|
257
258
|
"./src/components/editor/editor-group/database/IsolatedQueryDatabase.tsx",
|