@finos/legend-query-builder 4.14.8 → 4.14.9
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/QueryBuilderPropertyExpressionEditor.d.ts +2 -0
- package/lib/components/QueryBuilderPropertyExpressionEditor.d.ts.map +1 -1
- package/lib/components/QueryBuilderPropertyExpressionEditor.js +6 -3
- package/lib/components/QueryBuilderPropertyExpressionEditor.js.map +1 -1
- package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts.map +1 -1
- package/lib/components/explorer/QueryBuilderExplorerPanel.js +12 -9
- package/lib/components/explorer/QueryBuilderExplorerPanel.js.map +1 -1
- package/lib/components/explorer/QueryBuilderPropertySearchPanel.d.ts.map +1 -1
- package/lib/components/explorer/QueryBuilderPropertySearchPanel.js +6 -5
- package/lib/components/explorer/QueryBuilderPropertySearchPanel.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +19 -5
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
- package/lib/components/shared/QueryBuilderPropertyInfoTooltip.d.ts +3 -0
- package/lib/components/shared/QueryBuilderPropertyInfoTooltip.d.ts.map +1 -1
- package/lib/components/shared/QueryBuilderPropertyInfoTooltip.js +3 -3
- package/lib/components/shared/QueryBuilderPropertyInfoTooltip.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/explorer/QueryBuilderExplorerState.d.ts +5 -0
- package/lib/stores/explorer/QueryBuilderExplorerState.d.ts.map +1 -1
- package/lib/stores/explorer/QueryBuilderExplorerState.js +32 -0
- package/lib/stores/explorer/QueryBuilderExplorerState.js.map +1 -1
- package/package.json +5 -5
- package/src/components/QueryBuilderPropertyExpressionEditor.tsx +16 -2
- package/src/components/explorer/QueryBuilderExplorerPanel.tsx +18 -8
- package/src/components/explorer/QueryBuilderPropertySearchPanel.tsx +8 -5
- package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +65 -24
- package/src/components/shared/QueryBuilderPropertyInfoTooltip.tsx +29 -2
- package/src/stores/explorer/QueryBuilderExplorerState.ts +35 -0
@@ -144,8 +144,9 @@ const QueryBuilderProjectionColumnContextMenu = observer(
|
|
144
144
|
const QueryBuilderSimpleProjectionColumnEditor = observer(
|
145
145
|
(props: {
|
146
146
|
projectionColumnState: QueryBuilderSimpleProjectionColumnState;
|
147
|
+
setIsEditingColumnName: (isEditing: boolean) => void;
|
147
148
|
}) => {
|
148
|
-
const { projectionColumnState } = props;
|
149
|
+
const { projectionColumnState, setIsEditingColumnName } = props;
|
149
150
|
const onPropertyExpressionChange = (
|
150
151
|
node: QueryBuilderExplorerTreePropertyNodeData,
|
151
152
|
): void =>
|
@@ -158,10 +159,12 @@ const QueryBuilderSimpleProjectionColumnEditor = observer(
|
|
158
159
|
return (
|
159
160
|
<div className="query-builder__projection__column__value__property">
|
160
161
|
<QueryBuilderPropertyExpressionBadge
|
162
|
+
columnName={projectionColumnState.columnName}
|
161
163
|
propertyExpressionState={
|
162
164
|
projectionColumnState.propertyExpressionState
|
163
165
|
}
|
164
166
|
onPropertyExpressionChange={onPropertyExpressionChange}
|
167
|
+
setIsEditingColumnName={setIsEditingColumnName}
|
165
168
|
/>
|
166
169
|
</div>
|
167
170
|
);
|
@@ -378,6 +381,13 @@ const QueryBuilderProjectionColumnEditor = observer(
|
|
378
381
|
) => projectionColumnState.setColumnName(event.target.value);
|
379
382
|
const isDuplicatedColumnName =
|
380
383
|
projectionColumnState.tdsState.isDuplicateColumn(projectionColumnState);
|
384
|
+
const [isEditingColumnName, setIsEditingColumnName] = useState(false);
|
385
|
+
const columnNameInputRef = useRef<HTMLInputElement>(null);
|
386
|
+
useEffect(() => {
|
387
|
+
if (isEditingColumnName) {
|
388
|
+
columnNameInputRef.current?.focus();
|
389
|
+
}
|
390
|
+
}, [isEditingColumnName, columnNameInputRef]);
|
381
391
|
|
382
392
|
// aggregation
|
383
393
|
const aggregateColumnState = tdsState.aggregationState.columns.find(
|
@@ -742,29 +752,60 @@ const QueryBuilderProjectionColumnEditor = observer(
|
|
742
752
|
dragSourceConnector={dragHandleRef}
|
743
753
|
className="query-builder__projection__column__drag-handle__container"
|
744
754
|
/>
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
755
|
+
{projectionColumnState instanceof
|
756
|
+
QueryBuilderSimpleProjectionColumnState &&
|
757
|
+
(isEditingColumnName ? (
|
758
|
+
<div className="query-builder__projection__column__name">
|
759
|
+
<InputWithInlineValidation
|
760
|
+
className="query-builder__projection__column__name__input input-group__input"
|
761
|
+
spellCheck={false}
|
762
|
+
value={projectionColumnState.columnName}
|
763
|
+
onChange={changeColumnName}
|
764
|
+
onKeyDown={(
|
765
|
+
event: React.KeyboardEvent<HTMLInputElement>,
|
766
|
+
) => {
|
767
|
+
if (event.key === 'Enter') {
|
768
|
+
setIsEditingColumnName(false);
|
769
|
+
}
|
770
|
+
}}
|
771
|
+
onBlur={() => {
|
772
|
+
setIsEditingColumnName(false);
|
773
|
+
}}
|
774
|
+
error={
|
775
|
+
isDuplicatedColumnName ? 'Duplicated column' : undefined
|
776
|
+
}
|
777
|
+
ref={columnNameInputRef}
|
778
|
+
/>
|
779
|
+
</div>
|
780
|
+
) : (
|
781
|
+
<div className="query-builder__projection__column__value">
|
782
|
+
<QueryBuilderSimpleProjectionColumnEditor
|
783
|
+
projectionColumnState={projectionColumnState}
|
784
|
+
setIsEditingColumnName={setIsEditingColumnName}
|
785
|
+
/>
|
786
|
+
</div>
|
787
|
+
))}
|
788
|
+
{projectionColumnState instanceof
|
789
|
+
QueryBuilderDerivationProjectionColumnState && (
|
790
|
+
<>
|
791
|
+
<div className="query-builder__projection__column__name query-builder__projection__column__name__derivation">
|
792
|
+
<InputWithInlineValidation
|
793
|
+
className="query-builder__projection__column__name__input input-group__input"
|
794
|
+
spellCheck={false}
|
795
|
+
value={projectionColumnState.columnName}
|
796
|
+
onChange={changeColumnName}
|
797
|
+
error={
|
798
|
+
isDuplicatedColumnName ? 'Duplicated column' : undefined
|
799
|
+
}
|
800
|
+
/>
|
801
|
+
</div>
|
802
|
+
<div className="query-builder__projection__column__value">
|
803
|
+
<QueryBuilderDerivationProjectionColumnEditor
|
804
|
+
projectionColumnState={projectionColumnState}
|
805
|
+
/>
|
806
|
+
</div>
|
807
|
+
</>
|
808
|
+
)}
|
768
809
|
<div className="query-builder__projection__column__aggregate">
|
769
810
|
<div className="query-builder__projection__column__aggregate__operator">
|
770
811
|
{aggregateColumnState && (
|
@@ -14,7 +14,11 @@
|
|
14
14
|
* limitations under the License.
|
15
15
|
*/
|
16
16
|
|
17
|
-
import {
|
17
|
+
import {
|
18
|
+
ShareBoxIcon,
|
19
|
+
type TooltipPlacement,
|
20
|
+
Tooltip,
|
21
|
+
} from '@finos/legend-art';
|
18
22
|
import {
|
19
23
|
type AbstractProperty,
|
20
24
|
type Type,
|
@@ -25,6 +29,7 @@ import {
|
|
25
29
|
PURE_DOC_TAG,
|
26
30
|
} from '@finos/legend-graph';
|
27
31
|
import { useState } from 'react';
|
32
|
+
import type { QueryBuilderExplorerState } from '../../stores/explorer/QueryBuilderExplorerState.js';
|
28
33
|
|
29
34
|
export const QueryBuilderTaggedValueInfoTooltip: React.FC<{
|
30
35
|
taggedValues: TaggedValue[];
|
@@ -112,14 +117,25 @@ export const QueryBuilderTaggedValueInfoTooltip: React.FC<{
|
|
112
117
|
};
|
113
118
|
|
114
119
|
export const QueryBuilderPropertyInfoTooltip: React.FC<{
|
120
|
+
title: string;
|
115
121
|
property: AbstractProperty;
|
116
122
|
path: string;
|
117
123
|
isMapped: boolean;
|
118
124
|
children: React.ReactElement;
|
119
125
|
placement?: TooltipPlacement | undefined;
|
120
126
|
type?: Type | undefined;
|
127
|
+
explorerState?: QueryBuilderExplorerState | undefined;
|
121
128
|
}> = (props) => {
|
122
|
-
const {
|
129
|
+
const {
|
130
|
+
title,
|
131
|
+
property,
|
132
|
+
path,
|
133
|
+
isMapped,
|
134
|
+
children,
|
135
|
+
placement,
|
136
|
+
type,
|
137
|
+
explorerState,
|
138
|
+
} = props;
|
123
139
|
|
124
140
|
return (
|
125
141
|
<Tooltip
|
@@ -138,6 +154,7 @@ export const QueryBuilderPropertyInfoTooltip: React.FC<{
|
|
138
154
|
}}
|
139
155
|
title={
|
140
156
|
<div className="query-builder__tooltip__content">
|
157
|
+
<div className="query-builder__tooltip__header">{title}</div>
|
141
158
|
<div className="query-builder__tooltip__item">
|
142
159
|
<div className="query-builder__tooltip__item__label">Type</div>
|
143
160
|
<div className="query-builder__tooltip__item__value">
|
@@ -147,6 +164,16 @@ export const QueryBuilderPropertyInfoTooltip: React.FC<{
|
|
147
164
|
<div className="query-builder__tooltip__item">
|
148
165
|
<div className="query-builder__tooltip__item__label">Path</div>
|
149
166
|
<div className="query-builder__tooltip__item__value">{path}</div>
|
167
|
+
{explorerState && (
|
168
|
+
<div className="query-builder__tooltip__item__action">
|
169
|
+
<button
|
170
|
+
onClick={() => explorerState.highlightTreeNode(path)}
|
171
|
+
title="Show in tree"
|
172
|
+
>
|
173
|
+
<ShareBoxIcon color="white" />
|
174
|
+
</button>
|
175
|
+
</div>
|
176
|
+
)}
|
150
177
|
</div>
|
151
178
|
<div className="query-builder__tooltip__item">
|
152
179
|
<div className="query-builder__tooltip__item__label">
|
@@ -72,6 +72,7 @@ import { QueryBuilderPropertySearchState } from './QueryBuilderPropertySearchSta
|
|
72
72
|
import { QUERY_BUILDER_SUPPORTED_FUNCTIONS } from '../../graph/QueryBuilderMetaModelConst.js';
|
73
73
|
import { propertyExpression_setFunc } from '../shared/ValueSpecificationModifierHelper.js';
|
74
74
|
import { QueryBuilderTelemetryHelper } from '../../__lib__/QueryBuilderTelemetryHelper.js';
|
75
|
+
import { createRef } from 'react';
|
75
76
|
|
76
77
|
export enum QUERY_BUILDER_EXPLORER_TREE_DND_TYPE {
|
77
78
|
ROOT = 'ROOT',
|
@@ -97,6 +98,7 @@ export interface QueryBuilderExplorerTreeDragSource {
|
|
97
98
|
export abstract class QueryBuilderExplorerTreeNodeData implements TreeNodeData {
|
98
99
|
isSelected?: boolean | undefined;
|
99
100
|
isOpen?: boolean | undefined;
|
101
|
+
isHighlighting?: boolean | undefined;
|
100
102
|
id: string;
|
101
103
|
label: string;
|
102
104
|
dndText: string;
|
@@ -104,6 +106,7 @@ export abstract class QueryBuilderExplorerTreeNodeData implements TreeNodeData {
|
|
104
106
|
isPartOfDerivedPropertyBranch: boolean;
|
105
107
|
type: Type;
|
106
108
|
mappingData: QueryBuilderExplorerTreeNodeMappingData;
|
109
|
+
elementRef: React.RefObject<HTMLDivElement>;
|
107
110
|
|
108
111
|
constructor(
|
109
112
|
id: string,
|
@@ -114,7 +117,9 @@ export abstract class QueryBuilderExplorerTreeNodeData implements TreeNodeData {
|
|
114
117
|
mappingData: QueryBuilderExplorerTreeNodeMappingData,
|
115
118
|
) {
|
116
119
|
makeObservable(this, {
|
120
|
+
isHighlighting: observable,
|
117
121
|
isSelected: observable,
|
122
|
+
setIsHighlighting: action,
|
118
123
|
setIsSelected: action,
|
119
124
|
});
|
120
125
|
|
@@ -124,11 +129,16 @@ export abstract class QueryBuilderExplorerTreeNodeData implements TreeNodeData {
|
|
124
129
|
this.isPartOfDerivedPropertyBranch = isPartOfDerivedPropertyBranch;
|
125
130
|
this.type = type;
|
126
131
|
this.mappingData = mappingData;
|
132
|
+
this.elementRef = createRef();
|
127
133
|
}
|
128
134
|
|
129
135
|
setIsSelected(val: boolean | undefined): void {
|
130
136
|
this.isSelected = val;
|
131
137
|
}
|
138
|
+
|
139
|
+
setIsHighlighting(val: boolean | undefined): void {
|
140
|
+
this.isHighlighting = val;
|
141
|
+
}
|
132
142
|
}
|
133
143
|
|
134
144
|
export type QueryBuilderExplorerTreeNodeMappingData = {
|
@@ -663,6 +673,7 @@ export class QueryBuilderExplorerState {
|
|
663
673
|
setHumanizePropertyName: action,
|
664
674
|
setShowUnmappedProperties: action,
|
665
675
|
setHighlightUsedProperties: action,
|
676
|
+
highlightTreeNode: action,
|
666
677
|
analyzeMappingModelCoverage: flow,
|
667
678
|
previewData: flow,
|
668
679
|
});
|
@@ -717,6 +728,30 @@ export class QueryBuilderExplorerState {
|
|
717
728
|
);
|
718
729
|
}
|
719
730
|
|
731
|
+
highlightTreeNode(key: string): void {
|
732
|
+
const nodeToHighlight = this.treeData?.nodes.get(key);
|
733
|
+
if (nodeToHighlight instanceof QueryBuilderExplorerTreePropertyNodeData) {
|
734
|
+
let nodeToOpen: QueryBuilderExplorerTreeNodeData | null =
|
735
|
+
this.treeData?.nodes.get(nodeToHighlight.parentId) ?? null;
|
736
|
+
while (nodeToOpen !== null) {
|
737
|
+
if (!nodeToOpen.isOpen) {
|
738
|
+
nodeToOpen.isOpen = true;
|
739
|
+
}
|
740
|
+
nodeToOpen =
|
741
|
+
nodeToOpen instanceof QueryBuilderExplorerTreePropertyNodeData
|
742
|
+
? this.treeData?.nodes.get(nodeToOpen.parentId) ?? null
|
743
|
+
: null;
|
744
|
+
}
|
745
|
+
this.refreshTree();
|
746
|
+
nodeToHighlight.setIsHighlighting(true);
|
747
|
+
// scrollIntoView must be called in a setTimeout because it must happen after
|
748
|
+
// the tree nodes are recursively opened and the tree is refreshed.
|
749
|
+
setTimeout(() => {
|
750
|
+
nodeToHighlight.elementRef.current?.scrollIntoView();
|
751
|
+
}, 0);
|
752
|
+
}
|
753
|
+
}
|
754
|
+
|
720
755
|
*analyzeMappingModelCoverage(): GeneratorFn<void> {
|
721
756
|
// We will only refetch if the analysis result's mapping has changed.
|
722
757
|
// This makes the assumption that the mapping has not been edited, which is a valid assumption since query is not for editing mappings
|