@finos/legend-query-builder 2.1.6 → 2.1.7
Sign up to get free protection for your applications and to get access to all the features.
- package/lib/components/QueryBuilderResultPanel.d.ts.map +1 -1
- package/lib/components/QueryBuilderResultPanel.js +12 -12
- package/lib/components/QueryBuilderResultPanel.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderGraphFetchTreePanel.d.ts +12 -2
- package/lib/components/fetch-structure/QueryBuilderGraphFetchTreePanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderGraphFetchTreePanel.js +145 -20
- package/lib/components/fetch-structure/QueryBuilderGraphFetchTreePanel.js.map +1 -1
- package/lib/index.css +1 -17
- package/lib/index.css.map +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.d.ts +3 -0
- package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.d.ts.map +1 -1
- package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js +19 -1
- package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js.map +1 -1
- package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeValueSpecificationBuilder.js +11 -11
- package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeValueSpecificationBuilder.js.map +1 -1
- package/package.json +4 -4
- package/src/components/QueryBuilderResultPanel.tsx +17 -14
- package/src/components/fetch-structure/QueryBuilderGraphFetchTreePanel.tsx +384 -63
- package/src/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.ts +34 -0
- package/src/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeValueSpecificationBuilder.ts +11 -11
@@ -41,9 +41,21 @@ import {
|
|
41
41
|
ModalFooterButton,
|
42
42
|
ModalFooter,
|
43
43
|
SerializeIcon,
|
44
|
+
ResizablePanel,
|
45
|
+
ResizablePanelSplitter,
|
46
|
+
ResizablePanelGroup,
|
47
|
+
BufferIcon,
|
48
|
+
CustomSelectorInput,
|
49
|
+
FolderIcon,
|
44
50
|
} from '@finos/legend-art';
|
45
51
|
import { QUERY_BUILDER_TEST_ID } from '../../application/QueryBuilderTesting.js';
|
46
|
-
import {
|
52
|
+
import {
|
53
|
+
deepClone,
|
54
|
+
filterByType,
|
55
|
+
guaranteeNonNullable,
|
56
|
+
isNonNullable,
|
57
|
+
prettyCONSTName,
|
58
|
+
} from '@finos/legend-shared';
|
47
59
|
import {
|
48
60
|
type QueryBuilderGraphFetchTreeData,
|
49
61
|
type QueryBuilderGraphFetchTreeNodeData,
|
@@ -55,12 +67,51 @@ import {
|
|
55
67
|
QUERY_BUILDER_EXPLORER_TREE_DND_TYPE,
|
56
68
|
} from '../../stores/explorer/QueryBuilderExplorerState.js';
|
57
69
|
import {
|
70
|
+
type GraphFetchSerializationState,
|
71
|
+
GraphFetchExternalFormatSerializationState,
|
58
72
|
GraphFetchPureSerializationState,
|
59
73
|
PureSerializationConfig,
|
74
|
+
SERIALIZATION_TYPE,
|
60
75
|
type QueryBuilderGraphFetchTreeState,
|
61
76
|
} from '../../stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js';
|
62
77
|
import { getClassPropertyIcon } from '../shared/ElementIconUtils.js';
|
63
78
|
import { QueryBuilderTextEditorMode } from '../../stores/QueryBuilderTextEditorState.js';
|
79
|
+
import {
|
80
|
+
type PackageableElement,
|
81
|
+
Binding,
|
82
|
+
Package,
|
83
|
+
getDescendantsOfPackage,
|
84
|
+
} from '@finos/legend-graph';
|
85
|
+
import {
|
86
|
+
ActionAlertActionType,
|
87
|
+
ActionAlertType,
|
88
|
+
buildElementOption,
|
89
|
+
type PackageableElementOption,
|
90
|
+
} from '@finos/legend-application';
|
91
|
+
|
92
|
+
const getBindingFormatter = (props: {
|
93
|
+
darkMode?: boolean;
|
94
|
+
}): ((
|
95
|
+
option: PackageableElementOption<PackageableElement>,
|
96
|
+
) => React.ReactNode) =>
|
97
|
+
function BindingLabel(
|
98
|
+
option: PackageableElementOption<PackageableElement>,
|
99
|
+
): React.ReactNode {
|
100
|
+
const className = props.darkMode
|
101
|
+
? 'packageable-element-option-label--dark'
|
102
|
+
: 'packageable-element-option-label';
|
103
|
+
return (
|
104
|
+
<div className={className}>
|
105
|
+
<div className={`${className}__name`}>{option.label}</div>
|
106
|
+
{option.value.package && (
|
107
|
+
<div className={`${className}__tag`}>{option.value.path}</div>
|
108
|
+
)}
|
109
|
+
<div className={`${className}__tag`}>
|
110
|
+
{(option.value as Binding).contentType}
|
111
|
+
</div>
|
112
|
+
</div>
|
113
|
+
);
|
114
|
+
};
|
64
115
|
|
65
116
|
const QueryBuilderGraphFetchTreeNodeContainer: React.FC<
|
66
117
|
TreeNodeContainerProps<
|
@@ -287,22 +338,131 @@ const PureSerializationConfigModal = observer(
|
|
287
338
|
},
|
288
339
|
);
|
289
340
|
|
341
|
+
export const QueryBuilderGraphFetchExternalConfig = observer(
|
342
|
+
(props: {
|
343
|
+
graphFetchState: QueryBuilderGraphFetchTreeState;
|
344
|
+
serializationState: GraphFetchExternalFormatSerializationState;
|
345
|
+
serializationTreeData: QueryBuilderGraphFetchTreeData;
|
346
|
+
bindings: Binding[];
|
347
|
+
isReadOnly: boolean;
|
348
|
+
}) => {
|
349
|
+
const {
|
350
|
+
graphFetchState,
|
351
|
+
serializationState,
|
352
|
+
serializationTreeData,
|
353
|
+
bindings,
|
354
|
+
isReadOnly,
|
355
|
+
} = props;
|
356
|
+
const bindingOptions = bindings.map((result) => buildElementOption(result));
|
357
|
+
const selectedBinding = {
|
358
|
+
value: serializationState.targetBinding,
|
359
|
+
label: serializationState.targetBinding.name,
|
360
|
+
};
|
361
|
+
const onBindingChange = (
|
362
|
+
val: PackageableElementOption<Binding> | null,
|
363
|
+
): void => {
|
364
|
+
if (val !== null) {
|
365
|
+
serializationState.setBinding(val.value);
|
366
|
+
serializationState.setGraphFetchTree(serializationTreeData);
|
367
|
+
}
|
368
|
+
};
|
369
|
+
const onNodeSelect = (node: QueryBuilderGraphFetchTreeNodeData): void => {
|
370
|
+
if (node.childrenIds.length) {
|
371
|
+
node.isOpen = !node.isOpen;
|
372
|
+
}
|
373
|
+
};
|
374
|
+
const getChildNodes = (
|
375
|
+
node: QueryBuilderGraphFetchTreeNodeData,
|
376
|
+
): QueryBuilderGraphFetchTreeNodeData[] =>
|
377
|
+
node.childrenIds
|
378
|
+
.map((id) => serializationTreeData.nodes.get(id))
|
379
|
+
.filter(isNonNullable);
|
380
|
+
const removeNode = (node: QueryBuilderGraphFetchTreeNodeData): void => {
|
381
|
+
if (serializationTreeData.nodes.size === 1) {
|
382
|
+
graphFetchState.queryBuilderState.applicationStore.notificationService.notifyWarning(
|
383
|
+
'externalize serialization tree can not be empty',
|
384
|
+
);
|
385
|
+
} else {
|
386
|
+
removeNodeRecursively(serializationTreeData, node);
|
387
|
+
serializationState.setGraphFetchTree({ ...serializationTreeData });
|
388
|
+
}
|
389
|
+
};
|
390
|
+
|
391
|
+
return (
|
392
|
+
<div className="query-builder-graph-fetch-external-format">
|
393
|
+
<div className="service-execution-editor__configuration__items">
|
394
|
+
<div className="service-execution-editor__configuration__item">
|
395
|
+
<div className="btn--sm service-execution-editor__configuration__item__label">
|
396
|
+
<BufferIcon />
|
397
|
+
</div>
|
398
|
+
<CustomSelectorInput
|
399
|
+
className="panel__content__form__section__dropdown service-execution-editor__configuration__item__dropdown"
|
400
|
+
disabled={isReadOnly}
|
401
|
+
options={bindingOptions}
|
402
|
+
onChange={onBindingChange}
|
403
|
+
value={selectedBinding}
|
404
|
+
formatOptionLabel={getBindingFormatter({
|
405
|
+
darkMode: true,
|
406
|
+
})}
|
407
|
+
darkMode={true}
|
408
|
+
/>
|
409
|
+
</div>
|
410
|
+
<div className="service-execution-editor__configuration__item">
|
411
|
+
<div className="btn--sm service-execution-editor__configuration__item__label">
|
412
|
+
<FolderIcon />
|
413
|
+
</div>
|
414
|
+
<TreeView
|
415
|
+
components={{
|
416
|
+
TreeNodeContainer: QueryBuilderGraphFetchTreeNodeContainer,
|
417
|
+
}}
|
418
|
+
className="query-builder-graph-fetch-tree__container__tree"
|
419
|
+
treeData={serializationTreeData}
|
420
|
+
onNodeSelect={onNodeSelect}
|
421
|
+
getChildNodes={getChildNodes}
|
422
|
+
innerProps={{
|
423
|
+
isReadOnly,
|
424
|
+
removeNode,
|
425
|
+
}}
|
426
|
+
/>
|
427
|
+
</div>
|
428
|
+
</div>
|
429
|
+
</div>
|
430
|
+
);
|
431
|
+
},
|
432
|
+
);
|
433
|
+
|
290
434
|
export const QueryBuilderGraphFetchTreeExplorer = observer(
|
291
435
|
(props: {
|
292
436
|
graphFetchState: QueryBuilderGraphFetchTreeState;
|
293
|
-
|
437
|
+
serializationState: GraphFetchSerializationState;
|
294
438
|
treeData: QueryBuilderGraphFetchTreeData;
|
295
439
|
updateTreeData: (data: QueryBuilderGraphFetchTreeData) => void;
|
296
440
|
isReadOnly: boolean;
|
297
441
|
}) => {
|
298
442
|
const {
|
299
443
|
graphFetchState,
|
300
|
-
|
444
|
+
serializationState,
|
301
445
|
treeData,
|
302
446
|
updateTreeData,
|
303
447
|
isReadOnly,
|
304
448
|
} = props;
|
305
449
|
|
450
|
+
// Retrieve all bindings whose packageableElementIncludes contain the root class of main graph fetch tree
|
451
|
+
const compatibleBindings =
|
452
|
+
graphFetchState.queryBuilderState.graphManagerState.usableStores
|
453
|
+
.filter(filterByType(Binding))
|
454
|
+
.filter((b) => {
|
455
|
+
const elements = b.modelUnit.packageableElementIncludes.map(
|
456
|
+
(p) => p.value,
|
457
|
+
);
|
458
|
+
return elements
|
459
|
+
.filter(filterByType(Package))
|
460
|
+
.map((p) => Array.from(getDescendantsOfPackage(p)))
|
461
|
+
.flat()
|
462
|
+
.concat(elements.filter((e) => !(e instanceof Package)))
|
463
|
+
.includes(treeData.tree.class.value);
|
464
|
+
});
|
465
|
+
|
306
466
|
const onNodeSelect = (node: QueryBuilderGraphFetchTreeNodeData): void => {
|
307
467
|
if (node.childrenIds.length) {
|
308
468
|
node.isOpen = !node.isOpen;
|
@@ -319,6 +479,24 @@ export const QueryBuilderGraphFetchTreeExplorer = observer(
|
|
319
479
|
|
320
480
|
const removeNode = (node: QueryBuilderGraphFetchTreeNodeData): void => {
|
321
481
|
removeNodeRecursively(treeData, node);
|
482
|
+
if (treeData.nodes.size === 0) {
|
483
|
+
graphFetchState.setSerializationState(
|
484
|
+
new GraphFetchPureSerializationState(graphFetchState),
|
485
|
+
);
|
486
|
+
}
|
487
|
+
// Remove node from external format serialization tree as well
|
488
|
+
if (
|
489
|
+
serializationState instanceof
|
490
|
+
GraphFetchExternalFormatSerializationState &&
|
491
|
+
serializationState.treeData &&
|
492
|
+
serializationState.treeData.nodes.get(node.id)
|
493
|
+
) {
|
494
|
+
removeNodeRecursively(
|
495
|
+
serializationState.treeData,
|
496
|
+
guaranteeNonNullable(serializationState.treeData.nodes.get(node.id)),
|
497
|
+
);
|
498
|
+
updateTreeData({ ...serializationState.treeData });
|
499
|
+
}
|
322
500
|
updateTreeData({ ...treeData });
|
323
501
|
};
|
324
502
|
|
@@ -326,71 +504,202 @@ export const QueryBuilderGraphFetchTreeExplorer = observer(
|
|
326
504
|
graphFetchState.setChecked(!graphFetchState.isChecked);
|
327
505
|
|
328
506
|
const openConfigModal = (): void => {
|
329
|
-
|
507
|
+
if (serializationState instanceof GraphFetchPureSerializationState) {
|
508
|
+
serializationState.setConfigModal(true);
|
509
|
+
}
|
330
510
|
};
|
331
511
|
|
512
|
+
const onChangeSerializationType =
|
513
|
+
(implementationType: SERIALIZATION_TYPE): (() => void) =>
|
514
|
+
(): void => {
|
515
|
+
if (implementationType !== serializationState.getLabel()) {
|
516
|
+
graphFetchState.queryBuilderState.applicationStore.alertService.setActionAlertInfo(
|
517
|
+
{
|
518
|
+
message:
|
519
|
+
'Current graph-fetch will be lost when switching to a different serialization mode. Do you still want to proceed?',
|
520
|
+
type: ActionAlertType.CAUTION,
|
521
|
+
actions: [
|
522
|
+
{
|
523
|
+
label: 'Proceed',
|
524
|
+
type: ActionAlertActionType.PROCEED_WITH_CAUTION,
|
525
|
+
handler:
|
526
|
+
graphFetchState.queryBuilderState.applicationStore.guardUnhandledError(
|
527
|
+
async () => {
|
528
|
+
switch (implementationType) {
|
529
|
+
case SERIALIZATION_TYPE.EXTERNAL_FORMAT:
|
530
|
+
if (
|
531
|
+
compatibleBindings.length > 0 &&
|
532
|
+
compatibleBindings[0]
|
533
|
+
) {
|
534
|
+
const externalizeState =
|
535
|
+
new GraphFetchExternalFormatSerializationState(
|
536
|
+
graphFetchState,
|
537
|
+
compatibleBindings[0],
|
538
|
+
undefined,
|
539
|
+
);
|
540
|
+
graphFetchState.setGraphFetchTree(treeData);
|
541
|
+
externalizeState.setGraphFetchTree(
|
542
|
+
deepClone(treeData),
|
543
|
+
);
|
544
|
+
graphFetchState.setSerializationState(
|
545
|
+
externalizeState,
|
546
|
+
);
|
547
|
+
} else {
|
548
|
+
graphFetchState.queryBuilderState.applicationStore.notificationService.notifyWarning(
|
549
|
+
`Can't switch to external format serialization: No compatible bindings found`,
|
550
|
+
);
|
551
|
+
}
|
552
|
+
break;
|
553
|
+
case SERIALIZATION_TYPE.PURE:
|
554
|
+
default:
|
555
|
+
graphFetchState.setSerializationState(
|
556
|
+
new GraphFetchPureSerializationState(
|
557
|
+
graphFetchState,
|
558
|
+
),
|
559
|
+
);
|
560
|
+
break;
|
561
|
+
}
|
562
|
+
},
|
563
|
+
),
|
564
|
+
},
|
565
|
+
{
|
566
|
+
label: 'Cancel',
|
567
|
+
type: ActionAlertActionType.PROCEED,
|
568
|
+
default: true,
|
569
|
+
},
|
570
|
+
],
|
571
|
+
},
|
572
|
+
);
|
573
|
+
}
|
574
|
+
};
|
575
|
+
|
332
576
|
return (
|
333
577
|
<div className="query-builder-graph-fetch-tree">
|
334
578
|
<div className="query-builder-graph-fetch-tree__toolbar">
|
579
|
+
<div className="query-builder__fetch__structure__modes">
|
580
|
+
{Object.values(SERIALIZATION_TYPE).map((type) => (
|
581
|
+
<button
|
582
|
+
onClick={onChangeSerializationType(type)}
|
583
|
+
className={clsx('query-builder__fetch__structure__mode', {
|
584
|
+
'query-builder__fetch__structure__mode--selected':
|
585
|
+
type === serializationState.getLabel(),
|
586
|
+
})}
|
587
|
+
key={type}
|
588
|
+
>
|
589
|
+
{prettyCONSTName(type)}
|
590
|
+
</button>
|
591
|
+
))}
|
592
|
+
</div>
|
335
593
|
<div className="query-builder-graph-fetch-tree__actions">
|
336
|
-
|
337
|
-
className="query-builder-graph-fetch-tree__actions__action
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
594
|
+
{serializationState instanceof GraphFetchPureSerializationState && (
|
595
|
+
<div className="query-builder-graph-fetch-tree__actions__action">
|
596
|
+
<button
|
597
|
+
className="query-builder-graph-fetch-tree__actions__action-btn__label"
|
598
|
+
onClick={openConfigModal}
|
599
|
+
title={`${
|
600
|
+
serializationState.config
|
601
|
+
? 'Edit pure serialization config'
|
602
|
+
: 'Add pure serialization config'
|
603
|
+
}`}
|
604
|
+
tabIndex={-1}
|
605
|
+
>
|
606
|
+
<SerializeIcon className="query-builder-graph-fetch-tree__actions__action-btn__label__icon" />
|
607
|
+
<div className="query-builder-graph-fetch-tree__actions__action-btn__label__title">
|
608
|
+
{serializationState.config ? 'Edit Config' : 'Add Config'}
|
609
|
+
</div>
|
610
|
+
</button>
|
349
611
|
</div>
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
onClick={toggleChecked}
|
355
|
-
>
|
356
|
-
<button
|
357
|
-
className={clsx('panel__content__form__section__toggler__btn', {
|
358
|
-
'panel__content__form__section__toggler__btn--toggled':
|
359
|
-
graphFetchState.isChecked,
|
360
|
-
})}
|
612
|
+
)}
|
613
|
+
<div
|
614
|
+
className={clsx('panel__content__form__section__toggler')}
|
615
|
+
onClick={toggleChecked}
|
361
616
|
>
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
617
|
+
<button
|
618
|
+
className={clsx('panel__content__form__section__toggler__btn', {
|
619
|
+
'panel__content__form__section__toggler__btn--toggled':
|
620
|
+
graphFetchState.isChecked,
|
621
|
+
})}
|
622
|
+
>
|
623
|
+
{graphFetchState.isChecked ? (
|
624
|
+
<CheckSquareIcon />
|
625
|
+
) : (
|
626
|
+
<SquareIcon />
|
627
|
+
)}
|
628
|
+
</button>
|
629
|
+
<div className="panel__content__form__section__toggler__prompt">
|
630
|
+
Check graph fetch
|
631
|
+
</div>
|
632
|
+
<div className="query-builder-graph-fetch-tree__toolbar__hint-icon">
|
633
|
+
<InfoCircleIcon title="With this enabled, while executing, violations of constraints will reported as part of the result, rather than causing a failure" />
|
634
|
+
</div>
|
369
635
|
</div>
|
370
636
|
</div>
|
371
637
|
</div>
|
372
638
|
<div className="query-builder-graph-fetch-tree__container">
|
373
|
-
{
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
639
|
+
{serializationState instanceof GraphFetchPureSerializationState &&
|
640
|
+
serializationState.configModal && (
|
641
|
+
<PureSerializationConfigModal
|
642
|
+
pureSerializationState={serializationState}
|
643
|
+
graphFetchState={graphFetchState}
|
644
|
+
config={
|
645
|
+
serializationState.config ?? new PureSerializationConfig()
|
646
|
+
}
|
647
|
+
/>
|
648
|
+
)}
|
649
|
+
<ResizablePanelGroup orientation="horizontal">
|
650
|
+
<ResizablePanel>
|
651
|
+
<div className="query-builder-graph-fetch-external-format__config-group">
|
652
|
+
<div className="query-builder-graph-fetch-external-format__config-group__header">
|
653
|
+
<div className="query-builder-graph-fetch-external-format__config-group__header__title">
|
654
|
+
Graph Fetch Tree
|
655
|
+
</div>
|
656
|
+
</div>
|
657
|
+
<div className="query-builder-graph-fetch-external-format__config-group__content">
|
658
|
+
<div className="query-builder-graph-fetch-external-format__config-group__item">
|
659
|
+
<TreeView
|
660
|
+
components={{
|
661
|
+
TreeNodeContainer:
|
662
|
+
QueryBuilderGraphFetchTreeNodeContainer,
|
663
|
+
}}
|
664
|
+
className="query-builder-graph-fetch-tree__container__tree"
|
665
|
+
treeData={treeData}
|
666
|
+
onNodeSelect={onNodeSelect}
|
667
|
+
getChildNodes={getChildNodes}
|
668
|
+
innerProps={{
|
669
|
+
isReadOnly,
|
670
|
+
removeNode,
|
671
|
+
}}
|
672
|
+
/>
|
673
|
+
</div>
|
674
|
+
</div>
|
675
|
+
</div>
|
676
|
+
</ResizablePanel>
|
677
|
+
<ResizablePanelSplitter />
|
678
|
+
{serializationState instanceof
|
679
|
+
GraphFetchExternalFormatSerializationState &&
|
680
|
+
serializationState.treeData && (
|
681
|
+
<ResizablePanel>
|
682
|
+
<div className="query-builder-graph-fetch-external-format__config-group">
|
683
|
+
<div className="query-builder-graph-fetch-external-format__config-group__header">
|
684
|
+
<div className="query-builder-graph-fetch-external-format__config-group__header__title">
|
685
|
+
Externalize
|
686
|
+
</div>
|
687
|
+
</div>
|
688
|
+
<div className="query-builder-graph-fetch-external-format__config-group__content">
|
689
|
+
<div className="query-builder-graph-fetch-external-format_config-group__item">
|
690
|
+
<QueryBuilderGraphFetchExternalConfig
|
691
|
+
graphFetchState={graphFetchState}
|
692
|
+
serializationState={serializationState}
|
693
|
+
serializationTreeData={serializationState.treeData}
|
694
|
+
bindings={compatibleBindings}
|
695
|
+
isReadOnly={false}
|
696
|
+
/>
|
697
|
+
</div>
|
698
|
+
</div>
|
699
|
+
</div>
|
700
|
+
</ResizablePanel>
|
701
|
+
)}
|
702
|
+
</ResizablePanelGroup>
|
394
703
|
</div>
|
395
704
|
</div>
|
396
705
|
);
|
@@ -400,10 +709,9 @@ export const QueryBuilderGraphFetchTreeExplorer = observer(
|
|
400
709
|
const QueryBuilderGraphFetchTreePanel = observer(
|
401
710
|
(props: {
|
402
711
|
graphFetchTreeState: QueryBuilderGraphFetchTreeState;
|
403
|
-
|
404
|
-
pureSerializationState: GraphFetchPureSerializationState;
|
712
|
+
serializationState: GraphFetchSerializationState;
|
405
713
|
}) => {
|
406
|
-
const { graphFetchTreeState,
|
714
|
+
const { graphFetchTreeState, serializationState } = props;
|
407
715
|
const treeData = graphFetchTreeState.treeData;
|
408
716
|
|
409
717
|
// Deep/Graph Fetch Tree
|
@@ -415,8 +723,18 @@ const QueryBuilderGraphFetchTreePanel = observer(
|
|
415
723
|
const handleDrop = useCallback(
|
416
724
|
(item: QueryBuilderExplorerTreeDragSource): void => {
|
417
725
|
graphFetchTreeState.addProperty(item.node, { refreshTreeData: true });
|
726
|
+
// If serializationState is GraphFetchExternalFormatSerializationState, we should add this node to
|
727
|
+
// the external format serialization tree as well
|
728
|
+
if (
|
729
|
+
serializationState instanceof
|
730
|
+
GraphFetchExternalFormatSerializationState
|
731
|
+
) {
|
732
|
+
serializationState.addProperty(deepClone(item.node), {
|
733
|
+
refreshTreeData: true,
|
734
|
+
});
|
735
|
+
}
|
418
736
|
},
|
419
|
-
[graphFetchTreeState],
|
737
|
+
[graphFetchTreeState, serializationState],
|
420
738
|
);
|
421
739
|
const [{ isDragOver }, dropTargetConnector] = useDrop<
|
422
740
|
QueryBuilderExplorerTreeDragSource,
|
@@ -458,7 +776,7 @@ const QueryBuilderGraphFetchTreePanel = observer(
|
|
458
776
|
{treeData && !isGraphFetchTreeDataEmpty(treeData) && (
|
459
777
|
<QueryBuilderGraphFetchTreeExplorer
|
460
778
|
graphFetchState={graphFetchTreeState}
|
461
|
-
|
779
|
+
serializationState={serializationState}
|
462
780
|
treeData={treeData}
|
463
781
|
isReadOnly={false}
|
464
782
|
updateTreeData={updateTreeData}
|
@@ -478,11 +796,14 @@ export const QueryBuilderGraphFetchPanel = observer(
|
|
478
796
|
graphFetchTreeState.queryBuilderState.textEditorState.openModal(
|
479
797
|
QueryBuilderTextEditorMode.TEXT,
|
480
798
|
);
|
481
|
-
if (
|
799
|
+
if (
|
800
|
+
serializationState instanceof GraphFetchPureSerializationState ||
|
801
|
+
serializationState instanceof GraphFetchExternalFormatSerializationState
|
802
|
+
) {
|
482
803
|
return (
|
483
804
|
<QueryBuilderGraphFetchTreePanel
|
484
805
|
graphFetchTreeState={graphFetchTreeState}
|
485
|
-
|
806
|
+
serializationState={serializationState}
|
486
807
|
/>
|
487
808
|
);
|
488
809
|
}
|
@@ -48,6 +48,7 @@ import {
|
|
48
48
|
import type { LambdaFunctionBuilderOption } from '../../QueryBuilderValueSpecificationBuilderHelper.js';
|
49
49
|
import { appendGraphFetch } from './QueryBuilderGraphFetchTreeValueSpecificationBuilder.js';
|
50
50
|
import {
|
51
|
+
deepClone,
|
51
52
|
guaranteeNonNullable,
|
52
53
|
hashArray,
|
53
54
|
type Hashable,
|
@@ -190,6 +191,7 @@ export class GraphFetchExternalFormatSerializationState extends GraphFetchSerial
|
|
190
191
|
targetBinding: observable,
|
191
192
|
treeData: observable.ref,
|
192
193
|
serializationContentType: computed,
|
194
|
+
setGraphFetchTree: action,
|
193
195
|
});
|
194
196
|
this.targetBinding = targetBinding;
|
195
197
|
this.treeData = treeData;
|
@@ -203,6 +205,30 @@ export class GraphFetchExternalFormatSerializationState extends GraphFetchSerial
|
|
203
205
|
this.treeData = val;
|
204
206
|
}
|
205
207
|
|
208
|
+
addProperty(
|
209
|
+
node: QueryBuilderExplorerTreePropertyNodeData,
|
210
|
+
options?: {
|
211
|
+
refreshTreeData?: boolean;
|
212
|
+
},
|
213
|
+
): void {
|
214
|
+
if (!this.treeData) {
|
215
|
+
this.queryBuilderGraphFetchTreeState.queryBuilderState.applicationStore.notificationService.notifyWarning(
|
216
|
+
`Can't add property: graph-fetch tree has not been properly initialized`,
|
217
|
+
);
|
218
|
+
return;
|
219
|
+
}
|
220
|
+
addQueryBuilderPropertyNode(
|
221
|
+
this.treeData,
|
222
|
+
this.queryBuilderGraphFetchTreeState.queryBuilderState.explorerState
|
223
|
+
.nonNullableTreeData,
|
224
|
+
node,
|
225
|
+
this.queryBuilderGraphFetchTreeState.queryBuilderState,
|
226
|
+
);
|
227
|
+
if (options?.refreshTreeData) {
|
228
|
+
this.setGraphFetchTree({ ...this.treeData });
|
229
|
+
}
|
230
|
+
}
|
231
|
+
|
206
232
|
override getLabel(): string {
|
207
233
|
return SERIALIZATION_TYPE.EXTERNAL_FORMAT;
|
208
234
|
}
|
@@ -409,6 +435,14 @@ export class QueryBuilderGraphFetchTreeState
|
|
409
435
|
|
410
436
|
fetchProperty(node: QueryBuilderExplorerTreePropertyNodeData): void {
|
411
437
|
this.addProperty(node, { refreshTreeData: true });
|
438
|
+
if (
|
439
|
+
this.serializationState instanceof
|
440
|
+
GraphFetchExternalFormatSerializationState
|
441
|
+
) {
|
442
|
+
this.serializationState.addProperty(deepClone(node), {
|
443
|
+
refreshTreeData: true,
|
444
|
+
});
|
445
|
+
}
|
412
446
|
}
|
413
447
|
|
414
448
|
fetchProperties(nodes: QueryBuilderExplorerTreePropertyNodeData[]): void {
|
@@ -175,8 +175,8 @@ export const appendGraphFetch = (
|
|
175
175
|
`Can't build graph-fetch tree expression: preceding expression is not defined`,
|
176
176
|
);
|
177
177
|
|
178
|
-
const
|
179
|
-
if (
|
178
|
+
const serializationState = graphFetchTreeState.serializationState;
|
179
|
+
if (serializationState instanceof GraphFetchPureSerializationState) {
|
180
180
|
// build graph-fetch tree
|
181
181
|
if (
|
182
182
|
graphFetchTreeState.treeData &&
|
@@ -201,9 +201,9 @@ export const appendGraphFetch = (
|
|
201
201
|
graphFetchInstance,
|
202
202
|
];
|
203
203
|
serializeFunction.parametersValues = [graphFetchFunc, graphFetchInstance];
|
204
|
-
if (
|
204
|
+
if (serializationState.config) {
|
205
205
|
const configFunction = buildPureSerializationConfig(
|
206
|
-
|
206
|
+
serializationState.config as unknown as Record<PropertyKey, boolean>,
|
207
207
|
graphFetchTreeState.queryBuilderState.graphManagerState.graph,
|
208
208
|
);
|
209
209
|
serializeFunction.parametersValues.push(configFunction);
|
@@ -211,18 +211,18 @@ export const appendGraphFetch = (
|
|
211
211
|
lambdaFunction.expressionSequence[0] = serializeFunction;
|
212
212
|
}
|
213
213
|
} else if (
|
214
|
-
|
214
|
+
serializationState instanceof GraphFetchExternalFormatSerializationState
|
215
215
|
) {
|
216
216
|
const externalizeFunction = new SimpleFunctionExpression(
|
217
217
|
extractElementNameFromPath(QUERY_BUILDER_SUPPORTED_FUNCTIONS.EXTERNALIZE),
|
218
218
|
);
|
219
219
|
const mainGraphTree = graphFetchTreeState.treeData;
|
220
|
-
const
|
220
|
+
const externalizeGraphFetchTreeData = serializationState.treeData;
|
221
221
|
if (
|
222
222
|
mainGraphTree &&
|
223
|
-
|
223
|
+
externalizeGraphFetchTreeData &&
|
224
224
|
!isGraphFetchTreeDataEmpty(mainGraphTree) &&
|
225
|
-
!isGraphFetchTreeDataEmpty(
|
225
|
+
!isGraphFetchTreeDataEmpty(externalizeGraphFetchTreeData)
|
226
226
|
) {
|
227
227
|
// 0th param
|
228
228
|
const graphFetchInstance = new GraphFetchTreeInstanceValue();
|
@@ -244,12 +244,12 @@ export const appendGraphFetch = (
|
|
244
244
|
const bindingInstance = new InstanceValue(Multiplicity.ONE, undefined);
|
245
245
|
bindingInstance.values = [
|
246
246
|
PackageableElementExplicitReference.create(
|
247
|
-
|
247
|
+
serializationState.targetBinding,
|
248
248
|
),
|
249
249
|
];
|
250
250
|
// 2nd parameter
|
251
251
|
const xtGraphFetchInstance = new GraphFetchTreeInstanceValue();
|
252
|
-
xtGraphFetchInstance.values = [
|
252
|
+
xtGraphFetchInstance.values = [externalizeGraphFetchTreeData.tree];
|
253
253
|
// build externalize
|
254
254
|
externalizeFunction.parametersValues = [
|
255
255
|
graphFetchFunc,
|
@@ -260,7 +260,7 @@ export const appendGraphFetch = (
|
|
260
260
|
}
|
261
261
|
} else {
|
262
262
|
throw new UnsupportedOperationError(
|
263
|
-
`Unsupported serialization state ${
|
263
|
+
`Unsupported serialization state ${serializationState.getLabel()}`,
|
264
264
|
);
|
265
265
|
}
|
266
266
|
// build result set modifier: i.e. preview limit
|