@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.
- package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.d.ts +1 -1
- package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.js +3 -3
- package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.js.map +1 -1
- package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.d.ts +3 -0
- package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.js +72 -52
- package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.js.map +1 -1
- package/lib/components/editor/editor-group/dataProduct/DataProductEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js +22 -1
- package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js.map +1 -1
- package/lib/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.d.ts +23 -0
- package/lib/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.d.ts.map +1 -0
- package/lib/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.js +267 -0
- package/lib/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.js.map +1 -0
- package/lib/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.js +113 -75
- package/lib/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.js.map +1 -1
- package/lib/components/editor/editor-group/testable/TestableSharedComponents.d.ts.map +1 -1
- package/lib/components/editor/editor-group/testable/TestableSharedComponents.js +39 -5
- package/lib/components/editor/editor-group/testable/TestableSharedComponents.js.map +1 -1
- package/lib/components/editor/side-bar/DevMetadataPanel.d.ts.map +1 -1
- package/lib/components/editor/side-bar/DevMetadataPanel.js +37 -6
- package/lib/components/editor/side-bar/DevMetadataPanel.js.map +1 -1
- 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/element-editor-state/data/EmbeddedDataState.d.ts +17 -2
- 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 +56 -49
- package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts +4 -1
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js +4 -0
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.d.ts +113 -0
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.d.ts.map +1 -0
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.js +647 -0
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.js.map +1 -0
- package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.d.ts +18 -4
- 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 +214 -53
- package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.d.ts +17 -1
- package/lib/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.js +46 -1
- package/lib/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.js.map +1 -1
- package/lib/stores/editor/sidebar-state/dev-metadata/DevMetadataState.d.ts +9 -0
- package/lib/stores/editor/sidebar-state/dev-metadata/DevMetadataState.d.ts.map +1 -1
- package/lib/stores/editor/sidebar-state/dev-metadata/DevMetadataState.js +55 -0
- package/lib/stores/editor/sidebar-state/dev-metadata/DevMetadataState.js.map +1 -1
- package/package.json +16 -16
- package/src/components/editor/editor-group/data-editor/EmbeddedDataEditor.tsx +3 -0
- package/src/components/editor/editor-group/data-editor/RelationElementsDataEditor.tsx +331 -231
- package/src/components/editor/editor-group/dataProduct/DataProductEditor.tsx +32 -0
- package/src/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.tsx +935 -0
- package/src/components/editor/editor-group/function-activator/testable/FunctionTestableEditor.tsx +425 -308
- package/src/components/editor/editor-group/testable/TestableSharedComponents.tsx +160 -15
- package/src/components/editor/side-bar/DevMetadataPanel.tsx +194 -10
- package/src/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.ts +82 -51
- package/src/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.ts +4 -0
- package/src/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.ts +927 -0
- package/src/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.ts +303 -72
- package/src/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.ts +66 -0
- package/src/stores/editor/sidebar-state/dev-metadata/DevMetadataState.ts +76 -0
- package/tsconfig.json +2 -0
|
@@ -48,6 +48,14 @@ const NewRelationElementModal = observer(
|
|
|
48
48
|
(props: { dataState: RelationElementsDataState; isReadOnly: boolean }) => {
|
|
49
49
|
const { isReadOnly, dataState } = props;
|
|
50
50
|
const applicationStore = dataState.editorStore.applicationStore;
|
|
51
|
+
const availableAccessorOptions = dataState.availableAccessorOptions;
|
|
52
|
+
const hasAccessorOptions =
|
|
53
|
+
dataState.accessorOptions !== undefined &&
|
|
54
|
+
availableAccessorOptions.length > 0;
|
|
55
|
+
|
|
56
|
+
const [selectedAccessor, setSelectedAccessor] = useState<
|
|
57
|
+
string | undefined
|
|
58
|
+
>(availableAccessorOptions[0]?.value);
|
|
51
59
|
|
|
52
60
|
enum PathType {
|
|
53
61
|
SCHEMA_TABLE = 'Schema and Table',
|
|
@@ -83,17 +91,29 @@ const NewRelationElementModal = observer(
|
|
|
83
91
|
const closeModal = (): void =>
|
|
84
92
|
dataState.setShowNewRelationElementModal(false);
|
|
85
93
|
const handleSubmit = (): void => {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
94
|
+
if (hasAccessorOptions && selectedAccessor) {
|
|
95
|
+
const option = availableAccessorOptions.find(
|
|
96
|
+
(o) => o.value === selectedAccessor,
|
|
97
|
+
);
|
|
98
|
+
if (option) {
|
|
99
|
+
const relationElement = new RelationElement();
|
|
100
|
+
relationElement.paths = [option.value];
|
|
101
|
+
relationElement.columns = option.columns;
|
|
102
|
+
relationElement.rows = [];
|
|
103
|
+
dataState.addRelationElement(relationElement);
|
|
104
|
+
}
|
|
105
|
+
} else {
|
|
106
|
+
const path: string[] = [];
|
|
107
|
+
if (pathType && schemaName && tableName) {
|
|
108
|
+
path.push(schemaName);
|
|
109
|
+
path.push(tableName);
|
|
110
|
+
}
|
|
111
|
+
const relationElement = new RelationElement();
|
|
112
|
+
relationElement.columns = [];
|
|
113
|
+
relationElement.rows = [];
|
|
114
|
+
relationElement.paths = path;
|
|
115
|
+
dataState.addRelationElement(relationElement);
|
|
90
116
|
}
|
|
91
|
-
const relationElement = new RelationElement();
|
|
92
|
-
relationElement.columns = [];
|
|
93
|
-
relationElement.rows = [];
|
|
94
|
-
relationElement.paths = path;
|
|
95
|
-
|
|
96
|
-
dataState.addRelationElement(relationElement);
|
|
97
117
|
closeModal();
|
|
98
118
|
};
|
|
99
119
|
|
|
@@ -112,48 +132,84 @@ const NewRelationElementModal = observer(
|
|
|
112
132
|
onSubmit={(event) => {
|
|
113
133
|
event.preventDefault();
|
|
114
134
|
handleSubmit();
|
|
115
|
-
closeModal();
|
|
116
135
|
}}
|
|
117
136
|
className="modal modal--dark search-modal"
|
|
118
137
|
>
|
|
119
138
|
<div className="modal__title">Add Relation Element</div>
|
|
120
139
|
<div className="relational-data-editor__identifier">
|
|
121
|
-
|
|
122
|
-
<CustomSelectorInput
|
|
123
|
-
className="explorer__new-element-modal__driver__dropdown"
|
|
124
|
-
options={pathTypeOptions}
|
|
125
|
-
onChange={onPathTypeChange}
|
|
126
|
-
value={pathType}
|
|
127
|
-
isClearable={false}
|
|
128
|
-
darkMode={
|
|
129
|
-
!applicationStore.layoutService
|
|
130
|
-
.TEMPORARY__isLightColorThemeEnabled
|
|
131
|
-
}
|
|
132
|
-
/>
|
|
133
|
-
</div>
|
|
134
|
-
<>
|
|
135
|
-
<div className="relational-data-editor__identifier__values">
|
|
136
|
-
<input
|
|
137
|
-
className="panel__content__form__section__input"
|
|
138
|
-
disabled={isReadOnly}
|
|
139
|
-
placeholder="schemaName"
|
|
140
|
-
value={schemaName}
|
|
141
|
-
onChange={changeSchemaValue}
|
|
142
|
-
/>
|
|
143
|
-
</div>
|
|
140
|
+
{hasAccessorOptions ? (
|
|
144
141
|
<div className="relational-data-editor__identifier__values">
|
|
145
|
-
<
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
142
|
+
<div className="panel__content__form__section__header__label">
|
|
143
|
+
{dataState.accessorTypeLabel}
|
|
144
|
+
</div>
|
|
145
|
+
<CustomSelectorInput
|
|
146
|
+
className="explorer__new-element-modal__driver__dropdown"
|
|
147
|
+
options={availableAccessorOptions.map((o) => ({
|
|
148
|
+
value: o.value,
|
|
149
|
+
label: o.label,
|
|
150
|
+
}))}
|
|
151
|
+
onChange={(
|
|
152
|
+
val: { value: string; label: string } | null,
|
|
153
|
+
): void => {
|
|
154
|
+
setSelectedAccessor(val?.value);
|
|
155
|
+
}}
|
|
156
|
+
value={
|
|
157
|
+
selectedAccessor
|
|
158
|
+
? {
|
|
159
|
+
value: selectedAccessor,
|
|
160
|
+
label: selectedAccessor,
|
|
161
|
+
}
|
|
162
|
+
: null
|
|
163
|
+
}
|
|
164
|
+
placeholder={`Select ${dataState.accessorTypeLabel ?? 'option'}...`}
|
|
165
|
+
isClearable={false}
|
|
166
|
+
darkMode={
|
|
167
|
+
!applicationStore.layoutService
|
|
168
|
+
.TEMPORARY__isLightColorThemeEnabled
|
|
169
|
+
}
|
|
151
170
|
/>
|
|
152
171
|
</div>
|
|
153
|
-
|
|
172
|
+
) : (
|
|
173
|
+
<>
|
|
174
|
+
<div className="relational-data-editor__identifier__values">
|
|
175
|
+
<CustomSelectorInput
|
|
176
|
+
className="explorer__new-element-modal__driver__dropdown"
|
|
177
|
+
options={pathTypeOptions}
|
|
178
|
+
onChange={onPathTypeChange}
|
|
179
|
+
value={pathType}
|
|
180
|
+
isClearable={false}
|
|
181
|
+
darkMode={
|
|
182
|
+
!applicationStore.layoutService
|
|
183
|
+
.TEMPORARY__isLightColorThemeEnabled
|
|
184
|
+
}
|
|
185
|
+
/>
|
|
186
|
+
</div>
|
|
187
|
+
<div className="relational-data-editor__identifier__values">
|
|
188
|
+
<input
|
|
189
|
+
className="panel__content__form__section__input"
|
|
190
|
+
disabled={isReadOnly}
|
|
191
|
+
placeholder="schemaName"
|
|
192
|
+
value={schemaName}
|
|
193
|
+
onChange={changeSchemaValue}
|
|
194
|
+
/>
|
|
195
|
+
</div>
|
|
196
|
+
<div className="relational-data-editor__identifier__values">
|
|
197
|
+
<input
|
|
198
|
+
className="relational-data-editor__identifier__values panel__content__form__section__input"
|
|
199
|
+
disabled={isReadOnly}
|
|
200
|
+
placeholder="tableName"
|
|
201
|
+
value={tableName}
|
|
202
|
+
onChange={changeTableValue}
|
|
203
|
+
/>
|
|
204
|
+
</div>
|
|
205
|
+
</>
|
|
206
|
+
)}
|
|
154
207
|
</div>
|
|
155
208
|
<div className="search-modal__actions">
|
|
156
|
-
<button
|
|
209
|
+
<button
|
|
210
|
+
className="btn btn--dark"
|
|
211
|
+
disabled={isReadOnly || (hasAccessorOptions && !selectedAccessor)}
|
|
212
|
+
>
|
|
157
213
|
Add
|
|
158
214
|
</button>
|
|
159
215
|
</div>
|
|
@@ -167,30 +223,30 @@ export const RelationElementEditor = observer(
|
|
|
167
223
|
(props: {
|
|
168
224
|
relationElementState: RelationElementState;
|
|
169
225
|
isReadOnly: boolean;
|
|
226
|
+
hideColumnDefinitions?: boolean;
|
|
170
227
|
}) => {
|
|
171
|
-
const { relationElementState, isReadOnly } = props;
|
|
228
|
+
const { relationElementState, isReadOnly, hideColumnDefinitions } = props;
|
|
172
229
|
const editorStore = useEditorStore();
|
|
173
230
|
const embeddedData = relationElementState.relationElement;
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
);
|
|
231
|
+
const canEditColumns =
|
|
232
|
+
!isReadOnly && relationElementState.supportsColumnEditing;
|
|
177
233
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
178
234
|
|
|
179
235
|
const addColumn = (): void => {
|
|
180
|
-
if (
|
|
236
|
+
if (canEditColumns) {
|
|
181
237
|
const columnName = `column_${embeddedData.columns.length + 1}`;
|
|
182
238
|
relationElementState.addColumn(columnName);
|
|
183
239
|
}
|
|
184
240
|
};
|
|
185
241
|
|
|
186
242
|
const removeColumn = (index: number): void => {
|
|
187
|
-
if (
|
|
243
|
+
if (canEditColumns) {
|
|
188
244
|
relationElementState.removeColumn(index);
|
|
189
245
|
}
|
|
190
246
|
};
|
|
191
247
|
|
|
192
248
|
const updateColumn = (index: number, value: string): void => {
|
|
193
|
-
if (
|
|
249
|
+
if (canEditColumns) {
|
|
194
250
|
const column = embeddedData.columns[index];
|
|
195
251
|
if (column) {
|
|
196
252
|
relationElementState.updateColumn(index, value);
|
|
@@ -239,39 +295,13 @@ export const RelationElementEditor = observer(
|
|
|
239
295
|
}
|
|
240
296
|
};
|
|
241
297
|
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
let mimeType = '';
|
|
246
|
-
|
|
247
|
-
switch (exportFormat) {
|
|
248
|
-
case 'json':
|
|
249
|
-
content = relationElementState.exportJSON();
|
|
250
|
-
filename = 'test_data.json';
|
|
251
|
-
mimeType = 'application/json';
|
|
252
|
-
break;
|
|
253
|
-
case 'csv':
|
|
254
|
-
content = relationElementState.exportCSV();
|
|
255
|
-
filename = 'test_data.csv';
|
|
256
|
-
mimeType = 'text/csv';
|
|
257
|
-
break;
|
|
258
|
-
case 'sql':
|
|
259
|
-
content = relationElementState.exportSQL();
|
|
260
|
-
filename = 'test_data.sql';
|
|
261
|
-
mimeType = 'text/sql';
|
|
262
|
-
break;
|
|
263
|
-
default:
|
|
264
|
-
content = relationElementState.exportJSON();
|
|
265
|
-
filename = 'test_data.json';
|
|
266
|
-
mimeType = 'application/json';
|
|
267
|
-
break;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
const blob = new Blob([content], { type: mimeType });
|
|
298
|
+
const exportCSV = (): void => {
|
|
299
|
+
const content = relationElementState.exportCSV();
|
|
300
|
+
const blob = new Blob([content], { type: 'text/csv' });
|
|
271
301
|
const url = URL.createObjectURL(blob);
|
|
272
302
|
const a = document.createElement('a');
|
|
273
303
|
a.href = url;
|
|
274
|
-
a.download =
|
|
304
|
+
a.download = 'test_data.csv';
|
|
275
305
|
document.body.appendChild(a);
|
|
276
306
|
a.click();
|
|
277
307
|
document.body.removeChild(a);
|
|
@@ -301,53 +331,101 @@ export const RelationElementEditor = observer(
|
|
|
301
331
|
|
|
302
332
|
return (
|
|
303
333
|
<div className="relation-test-data-editor__content">
|
|
304
|
-
<div className="relation-test-data-
|
|
334
|
+
<div className="relation-test-data-editor__data">
|
|
305
335
|
<div className="relation-test-data-editor__section-header">
|
|
306
|
-
<div className="relation-test-data-editor__section-
|
|
307
|
-
|
|
336
|
+
<div className="relation-test-data-editor__section-header__left">
|
|
337
|
+
<div className="relation-test-data-editor__section-title">
|
|
338
|
+
Test Data ({embeddedData.rows.length} rows)
|
|
339
|
+
</div>
|
|
308
340
|
</div>
|
|
309
|
-
<
|
|
310
|
-
className="
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
<
|
|
325
|
-
className="relation-test-data-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
341
|
+
<div className="relation-test-data-editor__toolbar">
|
|
342
|
+
<div className="relation-test-data-editor__toolbar__left">
|
|
343
|
+
<div className="relation-test-data-editor__action-control">
|
|
344
|
+
<span className="relation-test-data-editor__action-control__label">
|
|
345
|
+
Add Column
|
|
346
|
+
</span>
|
|
347
|
+
<button
|
|
348
|
+
className="btn--icon btn--dark btn--sm"
|
|
349
|
+
onClick={addColumn}
|
|
350
|
+
disabled={!canEditColumns}
|
|
351
|
+
title="Add Column"
|
|
352
|
+
>
|
|
353
|
+
<PlusIcon />
|
|
354
|
+
</button>
|
|
355
|
+
</div>
|
|
356
|
+
<div className="relation-test-data-editor__action-control">
|
|
357
|
+
<span className="relation-test-data-editor__action-control__label">
|
|
358
|
+
Add Row
|
|
359
|
+
</span>
|
|
360
|
+
<button
|
|
361
|
+
className="btn--icon btn--dark btn--sm"
|
|
362
|
+
onClick={addRow}
|
|
363
|
+
disabled={isReadOnly || embeddedData.columns.length === 0}
|
|
364
|
+
title="Add Row"
|
|
365
|
+
>
|
|
366
|
+
<PlusIcon />
|
|
367
|
+
</button>
|
|
368
|
+
</div>
|
|
369
|
+
</div>
|
|
370
|
+
<div className="relation-test-data-editor__toolbar__right">
|
|
371
|
+
<div className="relation-test-data-editor__import-controls">
|
|
372
|
+
<span className="relation-test-data-editor__import-controls__label">
|
|
373
|
+
Upload CSV
|
|
374
|
+
</span>
|
|
375
|
+
<input
|
|
376
|
+
ref={fileInputRef}
|
|
377
|
+
type="file"
|
|
378
|
+
accept=".csv"
|
|
379
|
+
onChange={handleFileUpload}
|
|
380
|
+
style={{ display: 'none' }}
|
|
381
|
+
disabled={isReadOnly}
|
|
382
|
+
/>
|
|
383
|
+
<button
|
|
384
|
+
className="btn--icon btn--dark btn--sm"
|
|
385
|
+
onClick={() => fileInputRef.current?.click()}
|
|
386
|
+
disabled={isReadOnly}
|
|
387
|
+
title="Upload CSV"
|
|
388
|
+
>
|
|
389
|
+
<UploadIcon />
|
|
390
|
+
</button>
|
|
391
|
+
</div>
|
|
340
392
|
</div>
|
|
341
|
-
))}
|
|
342
|
-
</div>
|
|
343
|
-
</div>
|
|
344
|
-
|
|
345
|
-
<div className="relation-test-data-editor__data">
|
|
346
|
-
<div className="relation-test-data-editor__section-header">
|
|
347
|
-
<div className="relation-test-data-editor__section-title">
|
|
348
|
-
Test Data ({embeddedData.rows.length} rows)
|
|
349
393
|
</div>
|
|
350
394
|
</div>
|
|
395
|
+
{!hideColumnDefinitions ? (
|
|
396
|
+
<div className="relation-test-data-editor__columns">
|
|
397
|
+
<div className="relation-test-data-editor__section-header">
|
|
398
|
+
<div className="relation-test-data-editor__section-title">
|
|
399
|
+
Column Definitions
|
|
400
|
+
</div>
|
|
401
|
+
</div>
|
|
402
|
+
<div className="relation-test-data-editor__columns-grid">
|
|
403
|
+
{embeddedData.columns.map((column, index) => (
|
|
404
|
+
<div
|
|
405
|
+
key={`column-${guaranteeNonNullable(index)}`}
|
|
406
|
+
className="relation-test-data-editor__column-row"
|
|
407
|
+
>
|
|
408
|
+
<input
|
|
409
|
+
className="relation-test-data-editor__column-input"
|
|
410
|
+
type="text"
|
|
411
|
+
value={column}
|
|
412
|
+
onChange={(e) => updateColumn(index, e.target.value)}
|
|
413
|
+
placeholder="Column Name"
|
|
414
|
+
disabled={!canEditColumns}
|
|
415
|
+
/>
|
|
416
|
+
<button
|
|
417
|
+
className="btn--icon btn--caution btn--dark btn--sm"
|
|
418
|
+
onClick={() => removeColumn(index)}
|
|
419
|
+
disabled={!canEditColumns}
|
|
420
|
+
title="Remove Column"
|
|
421
|
+
>
|
|
422
|
+
<TimesIcon />
|
|
423
|
+
</button>
|
|
424
|
+
</div>
|
|
425
|
+
))}
|
|
426
|
+
</div>
|
|
427
|
+
</div>
|
|
428
|
+
) : null}
|
|
351
429
|
{embeddedData.rows.length === 0 ? (
|
|
352
430
|
<div className="relation-test-data-editor__empty-data">
|
|
353
431
|
<div className="relation-test-data-editor__empty-text">
|
|
@@ -357,71 +435,82 @@ export const RelationElementEditor = observer(
|
|
|
357
435
|
</div>
|
|
358
436
|
) : (
|
|
359
437
|
<div className="relation-test-data-editor__data-grid">
|
|
360
|
-
<
|
|
361
|
-
|
|
362
|
-
<
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
438
|
+
<table className="relation-test-data-editor__table">
|
|
439
|
+
<thead>
|
|
440
|
+
<tr>
|
|
441
|
+
{embeddedData.columns.map((column, columnIndex) => (
|
|
442
|
+
<th
|
|
443
|
+
key={column}
|
|
444
|
+
className="relation-test-data-editor__th"
|
|
445
|
+
>
|
|
446
|
+
<div className="relation-test-data-editor__th__inner">
|
|
447
|
+
<span className="relation-test-data-editor__th__label">
|
|
448
|
+
{column}
|
|
449
|
+
</span>
|
|
450
|
+
<button
|
|
451
|
+
className="relation-test-data-editor__th__delete"
|
|
452
|
+
onClick={() => removeColumn(columnIndex)}
|
|
453
|
+
disabled={!canEditColumns}
|
|
454
|
+
title={`Remove column ${column}`}
|
|
455
|
+
>
|
|
456
|
+
<TimesIcon />
|
|
457
|
+
</button>
|
|
458
|
+
</div>
|
|
459
|
+
</th>
|
|
460
|
+
))}
|
|
461
|
+
<th className="relation-test-data-editor__th relation-test-data-editor__th--actions" />
|
|
462
|
+
</tr>
|
|
463
|
+
</thead>
|
|
464
|
+
<tbody>
|
|
465
|
+
{embeddedData.rows.map((_row, rowIndex) => (
|
|
466
|
+
<tr
|
|
467
|
+
key={`row-${guaranteeNonNullable(rowIndex)}`}
|
|
468
|
+
className="relation-test-data-editor__tr"
|
|
385
469
|
>
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
470
|
+
{embeddedData.columns.map((column, columnIndex) => (
|
|
471
|
+
<td
|
|
472
|
+
key={column}
|
|
473
|
+
className="relation-test-data-editor__td"
|
|
474
|
+
>
|
|
475
|
+
<input
|
|
476
|
+
type="text"
|
|
477
|
+
value={relationElementState.getDisplayValue(
|
|
478
|
+
rowIndex,
|
|
479
|
+
columnIndex,
|
|
480
|
+
)}
|
|
481
|
+
onChange={(e) =>
|
|
482
|
+
updateCellValue(
|
|
483
|
+
rowIndex,
|
|
484
|
+
columnIndex,
|
|
485
|
+
e.target.value,
|
|
486
|
+
)
|
|
487
|
+
}
|
|
488
|
+
disabled={isReadOnly}
|
|
489
|
+
className="relation-test-data-editor__data-input"
|
|
490
|
+
/>
|
|
491
|
+
</td>
|
|
492
|
+
))}
|
|
493
|
+
<td className="relation-test-data-editor__td relation-test-data-editor__td--actions">
|
|
494
|
+
<button
|
|
495
|
+
className="btn--icon btn--caution btn--dark btn--sm relation-test-data-editor__icon-button--compact"
|
|
496
|
+
onClick={() => removeRow(rowIndex)}
|
|
497
|
+
disabled={isReadOnly}
|
|
498
|
+
title="Remove Row"
|
|
499
|
+
>
|
|
500
|
+
<TimesIcon />
|
|
501
|
+
</button>
|
|
502
|
+
</td>
|
|
503
|
+
</tr>
|
|
396
504
|
))}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
className="btn--icon btn--caution btn--dark btn--sm"
|
|
400
|
-
onClick={() => removeRow(rowIndex)}
|
|
401
|
-
disabled={isReadOnly}
|
|
402
|
-
title="Remove Row"
|
|
403
|
-
>
|
|
404
|
-
<TimesIcon />
|
|
405
|
-
</button>
|
|
406
|
-
</div>
|
|
407
|
-
</div>
|
|
408
|
-
))}
|
|
505
|
+
</tbody>
|
|
506
|
+
</table>
|
|
409
507
|
</div>
|
|
410
508
|
)}
|
|
411
509
|
|
|
412
|
-
<div className="relation-test-data-
|
|
413
|
-
<div className="relation-test-data-
|
|
510
|
+
<div className="relation-test-data-editor__footer-actions">
|
|
511
|
+
<div className="relation-test-data-editor__footer-actions__left">
|
|
414
512
|
<button
|
|
415
513
|
className="btn--icon btn--dark btn--sm"
|
|
416
|
-
onClick={addRow}
|
|
417
|
-
disabled={isReadOnly || embeddedData.columns.length === 0}
|
|
418
|
-
title="Add Row"
|
|
419
|
-
>
|
|
420
|
-
<PlusIcon />
|
|
421
|
-
</button>
|
|
422
|
-
|
|
423
|
-
<button
|
|
424
|
-
className="btn--icon btn--caution btn--dark btn--sm"
|
|
425
514
|
onClick={handleClearData}
|
|
426
515
|
disabled={isReadOnly || embeddedData.rows.length === 0}
|
|
427
516
|
title="Clear All Data"
|
|
@@ -429,48 +518,20 @@ export const RelationElementEditor = observer(
|
|
|
429
518
|
<TrashIcon />
|
|
430
519
|
</button>
|
|
431
520
|
</div>
|
|
432
|
-
<div className="relation-test-data-
|
|
433
|
-
<
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
</select>
|
|
447
|
-
<button
|
|
448
|
-
className="btn--icon btn--dark btn--sm"
|
|
449
|
-
onClick={exportData}
|
|
450
|
-
disabled={isReadOnly}
|
|
451
|
-
title={`Export as ${exportFormat.toUpperCase()}`}
|
|
452
|
-
>
|
|
453
|
-
<FileImportIcon />
|
|
454
|
-
</button>
|
|
455
|
-
</div>
|
|
456
|
-
|
|
457
|
-
<div className="relation-test-data-editor__import-controls">
|
|
458
|
-
<input
|
|
459
|
-
ref={fileInputRef}
|
|
460
|
-
type="file"
|
|
461
|
-
accept=".csv"
|
|
462
|
-
onChange={handleFileUpload}
|
|
463
|
-
style={{ display: 'none' }}
|
|
464
|
-
disabled={isReadOnly}
|
|
465
|
-
/>
|
|
466
|
-
<button
|
|
467
|
-
className="btn--icon btn--dark btn--sm"
|
|
468
|
-
onClick={() => fileInputRef.current?.click()}
|
|
469
|
-
disabled={isReadOnly}
|
|
470
|
-
title="Upload a file of CSV"
|
|
471
|
-
>
|
|
472
|
-
<UploadIcon />
|
|
473
|
-
</button>
|
|
521
|
+
<div className="relation-test-data-editor__footer-actions__right">
|
|
522
|
+
<div className="relation-test-data-editor__action-control">
|
|
523
|
+
<span className="relation-test-data-editor__action-control__label">
|
|
524
|
+
Export CSV
|
|
525
|
+
</span>
|
|
526
|
+
<button
|
|
527
|
+
className="btn--icon btn--dark btn--sm"
|
|
528
|
+
onClick={exportCSV}
|
|
529
|
+
disabled={isReadOnly}
|
|
530
|
+
title="Export as CSV"
|
|
531
|
+
>
|
|
532
|
+
<FileImportIcon />
|
|
533
|
+
</button>
|
|
534
|
+
</div>
|
|
474
535
|
</div>
|
|
475
536
|
</div>
|
|
476
537
|
</div>
|
|
@@ -480,15 +541,37 @@ export const RelationElementEditor = observer(
|
|
|
480
541
|
);
|
|
481
542
|
|
|
482
543
|
export const RelationElementsDataEditor = observer(
|
|
483
|
-
(props: {
|
|
484
|
-
|
|
544
|
+
(props: {
|
|
545
|
+
dataState: RelationElementsDataState;
|
|
546
|
+
isReadOnly: boolean;
|
|
547
|
+
isSharedData?: boolean | undefined;
|
|
548
|
+
hideColumnDefinitions?: boolean;
|
|
549
|
+
}) => {
|
|
550
|
+
const { dataState, isReadOnly, isSharedData, hideColumnDefinitions } =
|
|
551
|
+
props;
|
|
485
552
|
|
|
486
553
|
useApplicationNavigationContext(
|
|
487
554
|
LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.EMBEDDED_DATA_RELATIONAL_EDITOR,
|
|
488
555
|
);
|
|
489
556
|
|
|
490
557
|
const addRelationElement = (): void => {
|
|
491
|
-
|
|
558
|
+
const doAdd = (): void => {
|
|
559
|
+
if (
|
|
560
|
+
dataState.accessorOptions !== undefined &&
|
|
561
|
+
dataState.availableAccessorOptions.length === 0
|
|
562
|
+
) {
|
|
563
|
+
dataState.editorStore.applicationStore.notificationService.notifyWarning(
|
|
564
|
+
`All referenced ${dataState.accessorTypeLabel ?? 'item'}s' data is already present`,
|
|
565
|
+
);
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
dataState.setShowNewRelationElementModal(true);
|
|
569
|
+
};
|
|
570
|
+
if (dataState.refreshAccessorOptions) {
|
|
571
|
+
dataState.refreshAccessorOptions().then(doAdd).catch(doAdd);
|
|
572
|
+
} else {
|
|
573
|
+
doAdd();
|
|
574
|
+
}
|
|
492
575
|
};
|
|
493
576
|
|
|
494
577
|
const changeRelationElement = (
|
|
@@ -532,16 +615,30 @@ export const RelationElementsDataEditor = observer(
|
|
|
532
615
|
) : (
|
|
533
616
|
<span>{relationElementState.relationElement.paths[0]}</span>
|
|
534
617
|
)}
|
|
618
|
+
{!isReadOnly && !isSharedData && (
|
|
619
|
+
<button
|
|
620
|
+
className="service-editor__tab__close-btn"
|
|
621
|
+
onClick={(e): void => {
|
|
622
|
+
e.stopPropagation();
|
|
623
|
+
dataState.deleteRelationElement(relationElementState);
|
|
624
|
+
}}
|
|
625
|
+
title="Delete"
|
|
626
|
+
>
|
|
627
|
+
<TimesIcon />
|
|
628
|
+
</button>
|
|
629
|
+
)}
|
|
535
630
|
</div>
|
|
536
631
|
))}
|
|
537
632
|
</div>
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
633
|
+
{!isSharedData && (
|
|
634
|
+
<button
|
|
635
|
+
onClick={addRelationElement}
|
|
636
|
+
disabled={isReadOnly}
|
|
637
|
+
title="Add Relation Element"
|
|
638
|
+
>
|
|
639
|
+
<PlusIcon />
|
|
640
|
+
</button>
|
|
641
|
+
)}
|
|
545
642
|
</div>
|
|
546
643
|
{dataState.relationElementStates.length === 0 ||
|
|
547
644
|
dataState.activeRelationElement === undefined ? (
|
|
@@ -556,6 +653,9 @@ export const RelationElementsDataEditor = observer(
|
|
|
556
653
|
<RelationElementEditor
|
|
557
654
|
relationElementState={dataState.activeRelationElement}
|
|
558
655
|
isReadOnly={isReadOnly}
|
|
656
|
+
{...(hideColumnDefinitions !== undefined
|
|
657
|
+
? { hideColumnDefinitions }
|
|
658
|
+
: {})}
|
|
559
659
|
/>
|
|
560
660
|
)}
|
|
561
661
|
</PanelContent>
|