@finos/legend-query-builder 4.0.11 → 4.0.13
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 +14 -14
- package/lib/components/QueryBuilderResultPanel.js.map +1 -1
- package/lib/components/data-access/DataAccessOverview.d.ts.map +1 -1
- package/lib/components/data-access/DataAccessOverview.js +7 -3
- package/lib/components/data-access/DataAccessOverview.js.map +1 -1
- package/lib/components/execution-plan/SQLExecutionNodeViewer.d.ts.map +1 -1
- package/lib/components/execution-plan/SQLExecutionNodeViewer.js +2 -1
- package/lib/components/execution-plan/SQLExecutionNodeViewer.js.map +1 -1
- package/lib/components/explorer/QueryBuilderMilestoningEditor.d.ts.map +1 -1
- package/lib/components/explorer/QueryBuilderMilestoningEditor.js +1 -1
- package/lib/components/explorer/QueryBuilderMilestoningEditor.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js +1 -1
- package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js.map +1 -1
- package/lib/components/shared/BasicValueSpecificationEditor.d.ts.map +1 -1
- package/lib/components/shared/BasicValueSpecificationEditor.js +5 -4
- package/lib/components/shared/BasicValueSpecificationEditor.js.map +1 -1
- package/lib/index.css +17 -1
- package/lib/index.css.map +1 -1
- package/lib/package.json +6 -6
- package/lib/stores/QueryBuilderResultState.js +1 -1
- package/package.json +14 -14
- package/src/components/QueryBuilderResultPanel.tsx +69 -66
- package/src/components/data-access/DataAccessOverview.tsx +16 -2
- package/src/components/execution-plan/SQLExecutionNodeViewer.tsx +10 -3
- package/src/components/explorer/QueryBuilderMilestoningEditor.tsx +5 -3
- package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +1 -2
- package/src/components/fetch-structure/QueryBuilderTDSWindowPanel.tsx +2 -2
- package/src/components/shared/BasicValueSpecificationEditor.tsx +11 -7
- package/src/stores/QueryBuilderResultState.ts +1 -1
package/lib/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@finos/legend-query-builder",
|
3
|
-
"version": "4.0.
|
3
|
+
"version": "4.0.13",
|
4
4
|
"description": "Legend query builder core",
|
5
5
|
"keywords": [
|
6
6
|
"legend",
|
@@ -50,8 +50,8 @@
|
|
50
50
|
"@finos/legend-shared": "workspace:*",
|
51
51
|
"@finos/legend-storage": "workspace:*",
|
52
52
|
"@testing-library/react": "14.0.0",
|
53
|
-
"@types/react": "18.2.
|
54
|
-
"@types/react-dom": "18.2.
|
53
|
+
"@types/react": "18.2.13",
|
54
|
+
"@types/react-dom": "18.2.6",
|
55
55
|
"chart.js": "4.3.0",
|
56
56
|
"mathjs": "11.8.1",
|
57
57
|
"mobx": "6.9.0",
|
@@ -62,17 +62,17 @@
|
|
62
62
|
"react-dnd": "16.0.1",
|
63
63
|
"react-dom": "18.2.0",
|
64
64
|
"serializr": "3.0.2",
|
65
|
-
"sql-formatter": "12.2.
|
65
|
+
"sql-formatter": "12.2.3"
|
66
66
|
},
|
67
67
|
"devDependencies": {
|
68
68
|
"@finos/legend-dev-utils": "workspace:*",
|
69
69
|
"@jest/globals": "29.5.0",
|
70
70
|
"cross-env": "7.0.3",
|
71
|
-
"eslint": "8.
|
71
|
+
"eslint": "8.43.0",
|
72
72
|
"jest": "29.5.0",
|
73
73
|
"npm-run-all": "4.1.5",
|
74
74
|
"rimraf": "5.0.1",
|
75
|
-
"sass": "1.63.
|
75
|
+
"sass": "1.63.4",
|
76
76
|
"typescript": "5.1.3"
|
77
77
|
},
|
78
78
|
"peerDependencies": {
|
@@ -200,7 +200,7 @@ export class QueryBuilderResultState {
|
|
200
200
|
}
|
201
201
|
}
|
202
202
|
catch (error) {
|
203
|
-
// When user cancels the query by calling the cancelQuery api, it will throw an
|
203
|
+
// When user cancels the query by calling the cancelQuery api, it will throw an execution failure error.
|
204
204
|
// For now, we don't want to notify users about this failure. Therefore we check to ensure the promise is still the same one.
|
205
205
|
// When cancelled the query, we set the queryRunPromise as undefined.
|
206
206
|
if (this.queryRunPromise === promise) {
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@finos/legend-query-builder",
|
3
|
-
"version": "4.0.
|
3
|
+
"version": "4.0.13",
|
4
4
|
"description": "Legend query builder core",
|
5
5
|
"keywords": [
|
6
6
|
"legend",
|
@@ -42,16 +42,16 @@
|
|
42
42
|
"test:watch": "jest --watch"
|
43
43
|
},
|
44
44
|
"dependencies": {
|
45
|
-
"@finos/legend-application": "15.0.
|
46
|
-
"@finos/legend-art": "7.0.
|
47
|
-
"@finos/legend-graph": "30.0.
|
48
|
-
"@finos/legend-lego": "1.0
|
49
|
-
"@finos/legend-server-depot": "6.0.
|
50
|
-
"@finos/legend-shared": "10.0.
|
51
|
-
"@finos/legend-storage": "3.0.
|
45
|
+
"@finos/legend-application": "15.0.24",
|
46
|
+
"@finos/legend-art": "7.0.24",
|
47
|
+
"@finos/legend-graph": "30.0.9",
|
48
|
+
"@finos/legend-lego": "1.1.0",
|
49
|
+
"@finos/legend-server-depot": "6.0.16",
|
50
|
+
"@finos/legend-shared": "10.0.15",
|
51
|
+
"@finos/legend-storage": "3.0.65",
|
52
52
|
"@testing-library/react": "14.0.0",
|
53
|
-
"@types/react": "18.2.
|
54
|
-
"@types/react-dom": "18.2.
|
53
|
+
"@types/react": "18.2.13",
|
54
|
+
"@types/react-dom": "18.2.6",
|
55
55
|
"chart.js": "4.3.0",
|
56
56
|
"mathjs": "11.8.1",
|
57
57
|
"mobx": "6.9.0",
|
@@ -62,17 +62,17 @@
|
|
62
62
|
"react-dnd": "16.0.1",
|
63
63
|
"react-dom": "18.2.0",
|
64
64
|
"serializr": "3.0.2",
|
65
|
-
"sql-formatter": "12.2.
|
65
|
+
"sql-formatter": "12.2.3"
|
66
66
|
},
|
67
67
|
"devDependencies": {
|
68
|
-
"@finos/legend-dev-utils": "2.0.
|
68
|
+
"@finos/legend-dev-utils": "2.0.69",
|
69
69
|
"@jest/globals": "29.5.0",
|
70
70
|
"cross-env": "7.0.3",
|
71
|
-
"eslint": "8.
|
71
|
+
"eslint": "8.43.0",
|
72
72
|
"jest": "29.5.0",
|
73
73
|
"npm-run-all": "4.1.5",
|
74
74
|
"rimraf": "5.0.1",
|
75
|
-
"sass": "1.63.
|
75
|
+
"sass": "1.63.4",
|
76
76
|
"typescript": "5.1.3"
|
77
77
|
},
|
78
78
|
"peerDependencies": {
|
@@ -126,11 +126,11 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
126
126
|
forwardRef<
|
127
127
|
HTMLDivElement,
|
128
128
|
{
|
129
|
-
|
129
|
+
data: QueryBuilderTDSResultCellData | null;
|
130
130
|
tdsState: QueryBuilderTDSState;
|
131
131
|
}
|
132
132
|
>(function QueryBuilderResultContextMenu(props, ref) {
|
133
|
-
const {
|
133
|
+
const { data, tdsState } = props;
|
134
134
|
const applicationStore = useApplicationStore();
|
135
135
|
const postFilterEqualOperator = new QueryBuilderPostFilterOperator_Equal();
|
136
136
|
const postFilterInOperator = new QueryBuilderPostFilterOperator_In();
|
@@ -145,10 +145,10 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
145
145
|
const postFilterState = tdsState.postFilterState;
|
146
146
|
|
147
147
|
const projectionColumnState = tdsState.projectionColumns
|
148
|
-
.filter((c) => c.columnName ===
|
148
|
+
.filter((c) => c.columnName === data?.columnName)
|
149
149
|
.concat(
|
150
150
|
tdsState.aggregationState.columns
|
151
|
-
.filter((c) => c.columnName ===
|
151
|
+
.filter((c) => c.columnName === data?.columnName)
|
152
152
|
.map((ag) => ag.projectionColumnState),
|
153
153
|
)[0];
|
154
154
|
const getExistingPostFilterNode = (
|
@@ -319,7 +319,7 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
319
319
|
: (v as InstanceValue).values,
|
320
320
|
)
|
321
321
|
.flat()
|
322
|
-
.includes(cellData.value ??
|
322
|
+
.includes(cellData.value ?? data?.value);
|
323
323
|
|
324
324
|
if (!doesValueAlreadyExist) {
|
325
325
|
const newValueSpecification = (
|
@@ -399,7 +399,7 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
399
399
|
|
400
400
|
const handleCopyCellValue = applicationStore.guardUnhandledError(() =>
|
401
401
|
applicationStore.clipboardService.copyTextToClipboard(
|
402
|
-
|
402
|
+
data?.value?.toString() ?? '',
|
403
403
|
),
|
404
404
|
);
|
405
405
|
|
@@ -597,7 +597,7 @@ const QueryResultCellRenderer = observer(
|
|
597
597
|
// NOTE: we only support this functionality for grid result with a projection fetch-structure
|
598
598
|
fetchStructureImplementation instanceof QueryBuilderTDSState ? (
|
599
599
|
<QueryBuilderGridResultContextMenu
|
600
|
-
|
600
|
+
data={resultState.mousedOverCell}
|
601
601
|
tdsState={fetchStructureImplementation}
|
602
602
|
/>
|
603
603
|
) : null
|
@@ -960,70 +960,73 @@ export const QueryBuilderResultPanel = observer(
|
|
960
960
|
/>
|
961
961
|
</div>
|
962
962
|
)}
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
onClick={cancelQuery}
|
967
|
-
tabIndex={-1}
|
968
|
-
disabled={!isQueryValid}
|
969
|
-
>
|
970
|
-
<div className="btn--dark btn--caution query-builder__result__stop-btn__label">
|
971
|
-
<PauseCircleIcon className="query-builder__result__stop-btn__label__icon" />
|
972
|
-
<div className="query-builder__result__stop-btn__label__title">
|
973
|
-
Stop
|
974
|
-
</div>
|
975
|
-
</div>
|
976
|
-
</button>
|
977
|
-
) : (
|
978
|
-
<div className="query-builder__result__execute-btn">
|
963
|
+
|
964
|
+
<div className="query-builder__result__execute-btn btn__dropdown-combo btn__dropdown-combo--primary">
|
965
|
+
{resultState.isRunningQuery ? (
|
979
966
|
<button
|
980
|
-
className="
|
981
|
-
onClick={
|
967
|
+
className="btn__dropdown-combo__canceler"
|
968
|
+
onClick={cancelQuery}
|
982
969
|
tabIndex={-1}
|
983
|
-
|
984
|
-
allValidationIssues.length
|
985
|
-
? `Query is not valid:\n${allValidationIssues
|
986
|
-
.map((issue) => `\u2022 ${issue}`)
|
987
|
-
.join('\n')}`
|
988
|
-
: undefined
|
989
|
-
}
|
990
|
-
disabled={isRunQueryDisabled}
|
970
|
+
disabled={!isQueryValid}
|
991
971
|
>
|
992
|
-
<
|
993
|
-
|
994
|
-
|
972
|
+
<div className="btn--dark btn--caution btn__dropdown-combo__canceler__label">
|
973
|
+
<PauseCircleIcon className="btn__dropdown-combo__canceler__label__icon" />
|
974
|
+
<div className="btn__dropdown-combo__canceler__label__title">
|
975
|
+
Stop
|
976
|
+
</div>
|
995
977
|
</div>
|
996
978
|
</button>
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
979
|
+
) : (
|
980
|
+
<>
|
981
|
+
<button
|
982
|
+
className="btn__dropdown-combo__label"
|
983
|
+
onClick={runQuery}
|
984
|
+
tabIndex={-1}
|
985
|
+
title={
|
986
|
+
allValidationIssues.length
|
987
|
+
? `Query is not valid:\n${allValidationIssues
|
988
|
+
.map((issue) => `\u2022 ${issue}`)
|
989
|
+
.join('\n')}`
|
990
|
+
: undefined
|
991
|
+
}
|
992
|
+
disabled={isRunQueryDisabled}
|
993
|
+
>
|
994
|
+
<PlayIcon className="btn__dropdown-combo__label__icon" />
|
995
|
+
<div className="btn__dropdown-combo__label__title">
|
996
|
+
Run Query
|
997
|
+
</div>
|
998
|
+
</button>
|
999
|
+
<DropdownMenu
|
1000
|
+
className="btn__dropdown-combo__dropdown-btn"
|
1001
|
+
disabled={isRunQueryDisabled}
|
1002
|
+
content={
|
1003
|
+
<MenuContent>
|
1004
|
+
<MenuContentItem
|
1005
|
+
className="btn__dropdown-combo__option"
|
1006
|
+
onClick={generatePlan}
|
1007
|
+
disabled={isRunQueryDisabled}
|
1008
|
+
>
|
1009
|
+
Generate Plan
|
1010
|
+
</MenuContentItem>
|
1011
|
+
<MenuContentItem
|
1012
|
+
className="btn__dropdown-combo__option"
|
1013
|
+
onClick={debugPlanGeneration}
|
1014
|
+
disabled={isRunQueryDisabled}
|
1015
|
+
>
|
1016
|
+
Debug
|
1017
|
+
</MenuContentItem>
|
1018
|
+
</MenuContent>
|
1019
|
+
}
|
1020
|
+
menuProps={{
|
1021
|
+
anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
|
1022
|
+
transformOrigin: { vertical: 'top', horizontal: 'right' },
|
1023
|
+
}}
|
1024
|
+
>
|
1025
|
+
<CaretDownIcon />
|
1026
|
+
</DropdownMenu>
|
1027
|
+
</>
|
1028
|
+
)}
|
1029
|
+
</div>
|
1027
1030
|
<DropdownMenu
|
1028
1031
|
className="query-builder__result__export__dropdown"
|
1029
1032
|
title="Export"
|
@@ -72,6 +72,17 @@ const DataAccessOverviewChart = observer(
|
|
72
72
|
<RefreshIcon />
|
73
73
|
</button>
|
74
74
|
</div>
|
75
|
+
{Boolean(
|
76
|
+
dataAccessState.datasets.find(
|
77
|
+
(dataset) =>
|
78
|
+
dataset.entitlementReport instanceof
|
79
|
+
DatasetEntitlementUnsupportedReport,
|
80
|
+
),
|
81
|
+
) && (
|
82
|
+
<div className="data-access-overview__chart__warning">
|
83
|
+
Use case is not fully supported!
|
84
|
+
</div>
|
85
|
+
)}
|
75
86
|
<div className="data-access-overview__chart__container">
|
76
87
|
<Doughnut
|
77
88
|
data={{
|
@@ -109,7 +120,7 @@ const DataAccessOverviewChart = observer(
|
|
109
120
|
/>
|
110
121
|
<div className="data-access-overview__chart__stats">
|
111
122
|
<div className="data-access-overview__chart__stats__percentage">
|
112
|
-
{accessGrantedPercentage}%
|
123
|
+
{total === 0 ? 0 : accessGrantedPercentage}%
|
113
124
|
</div>
|
114
125
|
<div className="data-access-overview__chart__stats__tally">
|
115
126
|
{total === 0 ? 0 : accessGrantedCount}/{total}
|
@@ -285,7 +296,10 @@ export const DataAccessOverview = observer(
|
|
285
296
|
const applicationStore = useApplicationStore();
|
286
297
|
|
287
298
|
useEffect(() => {
|
288
|
-
|
299
|
+
// NOTE: @YannanGao-gs - force refresh for now, let's investigate why the data is empty
|
300
|
+
// when we fetched it from cache
|
301
|
+
dataAccessState.refresh().catch(applicationStore.alertUnhandledError);
|
302
|
+
// dataAccessState.intialize().catch(applicationStore.alertUnhandledError);
|
289
303
|
}, [applicationStore, dataAccessState]);
|
290
304
|
|
291
305
|
return (
|
@@ -28,6 +28,10 @@ import {
|
|
28
28
|
PanelContent,
|
29
29
|
} from '@finos/legend-art';
|
30
30
|
import { tryToFormatSql } from '../QueryBuilderResultPanel.js';
|
31
|
+
import {
|
32
|
+
CodeEditor,
|
33
|
+
CODE_EDITOR_LANGUAGE,
|
34
|
+
} from '@finos/legend-lego/code-editor';
|
31
35
|
|
32
36
|
/**
|
33
37
|
* TODO: Create a new `AbstractPlugin` for this, called `ExecutionPlanViewerPlugin`
|
@@ -81,9 +85,12 @@ export const SQLExecutionNodeViewer: React.FC<{
|
|
81
85
|
</div>
|
82
86
|
</PanelListItem>
|
83
87
|
</div>
|
84
|
-
<
|
85
|
-
<
|
86
|
-
|
88
|
+
<div className="query-builder__sql__container__code-editor">
|
89
|
+
<CodeEditor
|
90
|
+
inputValue={tryToFormatSql(query)}
|
91
|
+
language={CODE_EDITOR_LANGUAGE.SQL}
|
92
|
+
/>
|
93
|
+
</div>
|
87
94
|
<PanelDivider />
|
88
95
|
</div>
|
89
96
|
</div>
|
@@ -271,9 +271,11 @@ export const MilestoningParametersEditor = observer(
|
|
271
271
|
<ModalHeader title="Milestoning Parameters" />
|
272
272
|
<ModalBody className="query-builder__variables__modal__body">
|
273
273
|
<TemporalMilestoningEditor queryBuilderState={queryBuilderState} />
|
274
|
-
<
|
275
|
-
|
276
|
-
|
274
|
+
<PanelFormSection>
|
275
|
+
<div className="panel__content__form__section__header__label">
|
276
|
+
List of compatible milestoning parameters
|
277
|
+
</div>
|
278
|
+
</PanelFormSection>
|
277
279
|
<div className="panel__content__form__section__list__items">
|
278
280
|
<VariableSelector
|
279
281
|
queryBuilderState={queryBuilderState}
|
@@ -1075,8 +1075,7 @@ const QueryBuilderPostFilterPanelContent = observer(
|
|
1075
1075
|
<QueryBuilderPostFilterTree tdsState={tdsState} />
|
1076
1076
|
</>
|
1077
1077
|
)}
|
1078
|
-
|
1079
|
-
{showDroppableSuggestion && (
|
1078
|
+
{showDroppableSuggestion && !postFilterState.isEmpty && (
|
1080
1079
|
<div
|
1081
1080
|
ref={dropTargetConnector}
|
1082
1081
|
className={clsx(
|
@@ -1186,8 +1186,8 @@ export const QueryBuilderTDSWindowPanel = observer(
|
|
1186
1186
|
>
|
1187
1187
|
<PanelHeader>
|
1188
1188
|
<div className="panel__header__title">
|
1189
|
-
<div className="panel__header__title__label">
|
1190
|
-
{tdsWindowState.windowValidationIssues.length && (
|
1189
|
+
<div className="panel__header__title__label">window function</div>
|
1190
|
+
{tdsWindowState.windowValidationIssues.length > 0 && (
|
1191
1191
|
<QueryBuilderPanelIssueCountBadge
|
1192
1192
|
issues={tdsWindowState.windowValidationIssues}
|
1193
1193
|
/>
|
@@ -665,7 +665,8 @@ const CollectionValueInstanceValueEditor = observer(
|
|
665
665
|
setValueSpecification,
|
666
666
|
obseverContext,
|
667
667
|
} = props;
|
668
|
-
const inputRef = useRef<
|
668
|
+
const inputRef = useRef<HTMLTextAreaElement>(null);
|
669
|
+
|
669
670
|
const [text, setText] = useState(stringifyValue(valueSpecification.values));
|
670
671
|
const [editable, setEditable] = useState(false);
|
671
672
|
const [showAdvancedEditorPopover, setShowAdvancedEditorPopover] =
|
@@ -697,9 +698,7 @@ const CollectionValueInstanceValueEditor = observer(
|
|
697
698
|
setText(stringifyValue(valueSpecification.values));
|
698
699
|
setValueSpecification(valueSpecification);
|
699
700
|
};
|
700
|
-
|
701
|
-
setText(event.target.value);
|
702
|
-
};
|
701
|
+
|
703
702
|
const changeValueTextArea: React.ChangeEventHandler<HTMLTextAreaElement> = (
|
704
703
|
event,
|
705
704
|
) => {
|
@@ -742,15 +741,20 @@ const CollectionValueInstanceValueEditor = observer(
|
|
742
741
|
</BasePopover>
|
743
742
|
)}
|
744
743
|
<div className={clsx('value-spec-editor', className)}>
|
745
|
-
<
|
744
|
+
<textarea
|
746
745
|
ref={inputRef}
|
747
746
|
className={clsx(
|
748
|
-
'panel__content__form__section__input value-spec-editor__input',
|
747
|
+
'panel__content__form__section__input value-spec-editor__input value-spec-editor__textarea ',
|
749
748
|
)}
|
750
749
|
spellCheck={false}
|
751
750
|
value={text}
|
752
751
|
placeholder={text === '' ? '(empty)' : undefined}
|
753
|
-
onChange={
|
752
|
+
onChange={changeValueTextArea}
|
753
|
+
onKeyDown={(event): void => {
|
754
|
+
if (event.key === 'Enter' && !event.shiftKey) {
|
755
|
+
saveEdit();
|
756
|
+
}
|
757
|
+
}}
|
754
758
|
/>
|
755
759
|
<button
|
756
760
|
className="value-spec-editor__list-editor__expand-button btn--dark"
|
@@ -345,7 +345,7 @@ export class QueryBuilderResultState {
|
|
345
345
|
);
|
346
346
|
}
|
347
347
|
} catch (error) {
|
348
|
-
// When user cancels the query by calling the cancelQuery api, it will throw an
|
348
|
+
// When user cancels the query by calling the cancelQuery api, it will throw an execution failure error.
|
349
349
|
// For now, we don't want to notify users about this failure. Therefore we check to ensure the promise is still the same one.
|
350
350
|
// When cancelled the query, we set the queryRunPromise as undefined.
|
351
351
|
if (this.queryRunPromise === promise) {
|