@finos/legend-query-builder 4.1.8 → 4.1.10
Sign up to get free protection for your applications and to get access to all the features.
- package/lib/components/QueryBuilder.d.ts.map +1 -1
- package/lib/components/QueryBuilder.js +4 -2
- package/lib/components/QueryBuilder.js.map +1 -1
- package/lib/components/QueryBuilderResultPanel.d.ts.map +1 -1
- package/lib/components/QueryBuilderResultPanel.js +2 -2
- package/lib/components/QueryBuilderResultPanel.js.map +1 -1
- package/lib/components/QueryChat.d.ts +22 -0
- package/lib/components/QueryChat.d.ts.map +1 -0
- package/lib/components/QueryChat.js +28 -0
- package/lib/components/QueryChat.js.map +1 -0
- package/lib/components/execution-plan/AllocationExecutionNodeViewer.d.ts.map +1 -1
- package/lib/components/execution-plan/AllocationExecutionNodeViewer.js +1 -1
- package/lib/components/execution-plan/AllocationExecutionNodeViewer.js.map +1 -1
- package/lib/components/execution-plan/ConstantExecutionNodeViewer.js +1 -1
- package/lib/components/execution-plan/ConstantExecutionNodeViewer.js.map +1 -1
- package/lib/components/execution-plan/ExecutionPlanViewer.d.ts +4 -0
- package/lib/components/execution-plan/ExecutionPlanViewer.d.ts.map +1 -1
- package/lib/components/execution-plan/ExecutionPlanViewer.js +43 -5
- package/lib/components/execution-plan/ExecutionPlanViewer.js.map +1 -1
- package/lib/components/execution-plan/FunctionParametersValidationNodeViewer.d.ts.map +1 -1
- package/lib/components/execution-plan/FunctionParametersValidationNodeViewer.js.map +1 -1
- package/lib/components/execution-plan/ResultTypeViewer.js +2 -2
- package/lib/components/execution-plan/ResultTypeViewer.js.map +1 -1
- package/lib/index.css +17 -1
- package/lib/index.css.map +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/QueryBuilderState.d.ts +2 -0
- package/lib/stores/QueryBuilderState.d.ts.map +1 -1
- package/lib/stores/QueryBuilderState.js +6 -0
- package/lib/stores/QueryBuilderState.js.map +1 -1
- package/lib/stores/QueryBuilder_LegendApplicationPlugin_Extension.d.ts +5 -0
- package/lib/stores/QueryBuilder_LegendApplicationPlugin_Extension.d.ts.map +1 -1
- package/lib/stores/explorer/QueryBuilderExplorerState.js +2 -2
- package/lib/stores/explorer/QueryBuilderExplorerState.js.map +1 -1
- package/package.json +8 -8
- package/src/components/QueryBuilder.tsx +17 -0
- package/src/components/QueryBuilderResultPanel.tsx +8 -1
- package/src/components/QueryChat.tsx +73 -0
- package/src/components/execution-plan/AllocationExecutionNodeViewer.tsx +12 -10
- package/src/components/execution-plan/ConstantExecutionNodeViewer.tsx +1 -1
- package/src/components/execution-plan/ExecutionPlanViewer.tsx +171 -19
- package/src/components/execution-plan/FunctionParametersValidationNodeViewer.tsx +1 -2
- package/src/components/execution-plan/ResultTypeViewer.tsx +1 -1
- package/src/stores/QueryBuilderState.ts +7 -0
- package/src/stores/QueryBuilder_LegendApplicationPlugin_Extension.ts +9 -0
- package/src/stores/explorer/QueryBuilderExplorerState.ts +2 -2
- package/tsconfig.json +1 -0
@@ -14,7 +14,7 @@
|
|
14
14
|
* limitations under the License.
|
15
15
|
*/
|
16
16
|
|
17
|
-
import { useEffect } from 'react';
|
17
|
+
import { useEffect, useState } from 'react';
|
18
18
|
import {
|
19
19
|
type TreeNodeContainerProps,
|
20
20
|
Dialog,
|
@@ -39,8 +39,10 @@ import {
|
|
39
39
|
ModalFooterButton,
|
40
40
|
PanelHeader,
|
41
41
|
Panel,
|
42
|
+
PanelDivider,
|
43
|
+
Button,
|
42
44
|
} from '@finos/legend-art';
|
43
|
-
import { isNonNullable } from '@finos/legend-shared';
|
45
|
+
import { isNonNullable, prettyCONSTName } from '@finos/legend-shared';
|
44
46
|
import {
|
45
47
|
ExecutionNodeTreeNodeData,
|
46
48
|
ExecutionPlanViewTreeNodeData,
|
@@ -59,6 +61,7 @@ import {
|
|
59
61
|
ConstantExecutionNode,
|
60
62
|
SequenceExecutionNode,
|
61
63
|
type RawExecutionPlan,
|
64
|
+
JavaPlatformImplementation,
|
62
65
|
} from '@finos/legend-graph';
|
63
66
|
import { SQLExecutionNodeViewer } from './SQLExecutionNodeViewer.js';
|
64
67
|
import { FunctionParametersValidationNodeViewer } from './FunctionParametersValidationNodeViewer.js';
|
@@ -95,6 +98,169 @@ export const generateExecutionNodeLabel = (type: ExecutionNode): string => {
|
|
95
98
|
}
|
96
99
|
};
|
97
100
|
|
101
|
+
enum PLAN_TABS {
|
102
|
+
GENERAL = 'GENERAL',
|
103
|
+
GLOBAL_IMPLEMENTATION_SUPPORT = 'GLOBAL_IMPLEMENTATION_SUPPORT',
|
104
|
+
}
|
105
|
+
|
106
|
+
export const ExecutionPlanViewerPanelContent: React.FC<{
|
107
|
+
executionPlanState: ExecutionPlanState;
|
108
|
+
}> = observer((props) => {
|
109
|
+
const { executionPlanState } = props;
|
110
|
+
const applicationStore = executionPlanState.applicationStore;
|
111
|
+
const globalImplementationSupport =
|
112
|
+
executionPlanState.plan?.globalImplementationSupport;
|
113
|
+
const templateFunctions =
|
114
|
+
executionPlanState.plan?.processingTemplateFunctions ?? [];
|
115
|
+
const [selectedTab, setSelectedTab] = useState<PLAN_TABS>(PLAN_TABS.GENERAL);
|
116
|
+
const [selectedJavaClass, setSelectedJavaClass] = useState<
|
117
|
+
string | undefined
|
118
|
+
>(undefined);
|
119
|
+
|
120
|
+
if (
|
121
|
+
globalImplementationSupport &&
|
122
|
+
globalImplementationSupport instanceof JavaPlatformImplementation
|
123
|
+
) {
|
124
|
+
globalImplementationSupport.classes.sort((a, b) =>
|
125
|
+
(a.package + a.name).toLowerCase() > (b.package + b.name).toLowerCase()
|
126
|
+
? 1
|
127
|
+
: -1,
|
128
|
+
);
|
129
|
+
if (
|
130
|
+
globalImplementationSupport.classes.length > 0 &&
|
131
|
+
globalImplementationSupport.classes[0] &&
|
132
|
+
selectedJavaClass === undefined
|
133
|
+
) {
|
134
|
+
setSelectedJavaClass(
|
135
|
+
globalImplementationSupport.classes[0]?.package +
|
136
|
+
globalImplementationSupport.classes[0]?.name,
|
137
|
+
);
|
138
|
+
}
|
139
|
+
}
|
140
|
+
|
141
|
+
return (
|
142
|
+
<div className="query-builder__execution-plan-form--editor">
|
143
|
+
<div className="panel">
|
144
|
+
<div className="panel__header query-builder__execution-plan-form--editor__header--with-tabs">
|
145
|
+
<div className="uml-element-editor__tabs">
|
146
|
+
{Object.values(PLAN_TABS).map((tab) => (
|
147
|
+
<div
|
148
|
+
key={tab}
|
149
|
+
onClick={() => setSelectedTab(tab)}
|
150
|
+
className={clsx(
|
151
|
+
'query-builder__execution-plan-form--editor__tab',
|
152
|
+
{
|
153
|
+
'query-builder__execution-plan-form--editor__tab--active':
|
154
|
+
tab === selectedTab,
|
155
|
+
},
|
156
|
+
)}
|
157
|
+
>
|
158
|
+
{prettyCONSTName(tab)}
|
159
|
+
</div>
|
160
|
+
))}
|
161
|
+
</div>
|
162
|
+
</div>
|
163
|
+
{selectedTab === PLAN_TABS.GLOBAL_IMPLEMENTATION_SUPPORT &&
|
164
|
+
globalImplementationSupport &&
|
165
|
+
globalImplementationSupport instanceof JavaPlatformImplementation && (
|
166
|
+
<ResizablePanelGroup orientation="vertical">
|
167
|
+
<ResizablePanel minSize={30} size={250}>
|
168
|
+
<PanelContent
|
169
|
+
darkMode={
|
170
|
+
!applicationStore.layoutService
|
171
|
+
.TEMPORARY__isLightColorThemeEnabled
|
172
|
+
}
|
173
|
+
className="query-builder__java__container__panel"
|
174
|
+
>
|
175
|
+
<div className="query-builder__java__container">
|
176
|
+
<div>
|
177
|
+
{globalImplementationSupport.classes.map((cl) => (
|
178
|
+
<div
|
179
|
+
className={clsx(
|
180
|
+
'query-builder__java__container__item',
|
181
|
+
{
|
182
|
+
'query-builder__java__container__item--active':
|
183
|
+
`${cl.package}${cl.name}` === selectedJavaClass,
|
184
|
+
},
|
185
|
+
)}
|
186
|
+
key={cl.package + cl.name}
|
187
|
+
>
|
188
|
+
<button
|
189
|
+
className="query-builder__java__container__item__btn"
|
190
|
+
onClick={() =>
|
191
|
+
setSelectedJavaClass(cl.package + cl.name)
|
192
|
+
}
|
193
|
+
tabIndex={-1}
|
194
|
+
title={`Go to ${cl.package}.${cl.name}`}
|
195
|
+
>
|
196
|
+
{`${cl.package}.${cl.name}`}
|
197
|
+
</button>
|
198
|
+
</div>
|
199
|
+
))}
|
200
|
+
<PanelDivider />
|
201
|
+
</div>
|
202
|
+
</div>
|
203
|
+
</PanelContent>
|
204
|
+
</ResizablePanel>
|
205
|
+
<ResizablePanelSplitter>
|
206
|
+
<ResizablePanelSplitterLine color="var(--color-dark-grey-200)" />
|
207
|
+
</ResizablePanelSplitter>
|
208
|
+
<ResizablePanel>
|
209
|
+
{selectedJavaClass && (
|
210
|
+
<CodeEditor
|
211
|
+
inputValue={globalImplementationSupport.classes.reduce(
|
212
|
+
(value, cl) => {
|
213
|
+
if (selectedJavaClass === `${cl.package}${cl.name}`) {
|
214
|
+
return cl.source;
|
215
|
+
}
|
216
|
+
return value;
|
217
|
+
},
|
218
|
+
'',
|
219
|
+
)}
|
220
|
+
isReadOnly={true}
|
221
|
+
language={CODE_EDITOR_LANGUAGE.JAVA}
|
222
|
+
hideMinimap={true}
|
223
|
+
/>
|
224
|
+
)}
|
225
|
+
</ResizablePanel>
|
226
|
+
</ResizablePanelGroup>
|
227
|
+
)}
|
228
|
+
{selectedTab === PLAN_TABS.GENERAL && (
|
229
|
+
<>
|
230
|
+
<div className="query-builder__template--function--editor__header">
|
231
|
+
{`AuthDependent: ${executionPlanState.plan?.authDependent.toString()}`}
|
232
|
+
</div>
|
233
|
+
<div className="query-builder__template--function--editor__title">
|
234
|
+
Template Functions
|
235
|
+
</div>
|
236
|
+
<div className="query-builder__template--function--editor__code">
|
237
|
+
<CodeEditor
|
238
|
+
inputValue={templateFunctions.reduce(
|
239
|
+
(total, func) => (total += `${func}\n`),
|
240
|
+
'',
|
241
|
+
)}
|
242
|
+
isReadOnly={true}
|
243
|
+
language={CODE_EDITOR_LANGUAGE.XML}
|
244
|
+
hideMinimap={true}
|
245
|
+
hideActionBar={true}
|
246
|
+
/>
|
247
|
+
</div>
|
248
|
+
<div className="query-builder__template--function--editor__json">
|
249
|
+
<Button
|
250
|
+
className="btn--dark execution-node-viewer__unsupported-view__to-text-mode__btn"
|
251
|
+
onClick={(): void =>
|
252
|
+
executionPlanState.setViewMode(EXECUTION_PLAN_VIEW_MODE.JSON)
|
253
|
+
}
|
254
|
+
text="View JSON"
|
255
|
+
/>
|
256
|
+
</div>
|
257
|
+
</>
|
258
|
+
)}
|
259
|
+
</div>
|
260
|
+
</div>
|
261
|
+
);
|
262
|
+
});
|
263
|
+
|
98
264
|
const ExecutionNodeElementTreeNodeContainer = observer(
|
99
265
|
(
|
100
266
|
props: TreeNodeContainerProps<
|
@@ -405,23 +571,9 @@ const ExecutionPlanViewPanel = observer(
|
|
405
571
|
/>
|
406
572
|
)}
|
407
573
|
{currentElement instanceof ExecutionPlan && (
|
408
|
-
<
|
409
|
-
|
410
|
-
|
411
|
-
{`Can't display full execution plan`}
|
412
|
-
</div>
|
413
|
-
<button
|
414
|
-
className="btn--dark execution-plan-viewer__unsupported-view__to-text-mode__btn"
|
415
|
-
onClick={(): void =>
|
416
|
-
executionPlanState.setViewMode(
|
417
|
-
EXECUTION_PLAN_VIEW_MODE.JSON,
|
418
|
-
)
|
419
|
-
}
|
420
|
-
>
|
421
|
-
View JSON
|
422
|
-
</button>
|
423
|
-
</div>
|
424
|
-
</BlankPanelContent>
|
574
|
+
<ExecutionPlanViewerPanelContent
|
575
|
+
executionPlanState={executionPlanState}
|
576
|
+
/>
|
425
577
|
)}
|
426
578
|
</>
|
427
579
|
)}
|
@@ -122,6 +122,7 @@ export abstract class QueryBuilderState implements CommandRegistrar {
|
|
122
122
|
isEditingWatermark = false;
|
123
123
|
isCheckingEntitlments = false;
|
124
124
|
isCalendarEnabled = false;
|
125
|
+
isQueryChatOpened = false;
|
125
126
|
|
126
127
|
class?: Class | undefined;
|
127
128
|
mapping?: Mapping | undefined;
|
@@ -156,6 +157,7 @@ export abstract class QueryBuilderState implements CommandRegistrar {
|
|
156
157
|
class: observable,
|
157
158
|
mapping: observable,
|
158
159
|
runtimeValue: observable,
|
160
|
+
isQueryChatOpened: observable,
|
159
161
|
|
160
162
|
sideBarClassName: computed,
|
161
163
|
isQuerySupported: computed,
|
@@ -169,6 +171,7 @@ export abstract class QueryBuilderState implements CommandRegistrar {
|
|
169
171
|
setClass: action,
|
170
172
|
setMapping: action,
|
171
173
|
setRuntimeValue: action,
|
174
|
+
setIsQueryChatOpened: action,
|
172
175
|
|
173
176
|
resetQueryResult: action,
|
174
177
|
resetQueryContent: action,
|
@@ -243,6 +246,10 @@ export abstract class QueryBuilderState implements CommandRegistrar {
|
|
243
246
|
return this.allVariables.map((e) => e.name);
|
244
247
|
}
|
245
248
|
|
249
|
+
setIsQueryChatOpened(val: boolean): void {
|
250
|
+
this.isQueryChatOpened = val;
|
251
|
+
}
|
252
|
+
|
246
253
|
setShowFunctionsExplorerPanel(val: boolean): void {
|
247
254
|
this.showFunctionsExplorerPanel = val;
|
248
255
|
}
|
@@ -45,6 +45,10 @@ export type QueryExportUsageConfiguration = {
|
|
45
45
|
renderer(): React.ReactNode;
|
46
46
|
};
|
47
47
|
|
48
|
+
export type QueryChatRenderer = (
|
49
|
+
queryBuilderState: QueryBuilderState,
|
50
|
+
) => React.ReactNode;
|
51
|
+
|
48
52
|
export interface QueryBuilder_LegendApplicationPlugin_Extension
|
49
53
|
extends LegendApplicationPlugin {
|
50
54
|
/**
|
@@ -61,4 +65,9 @@ export interface QueryBuilder_LegendApplicationPlugin_Extension
|
|
61
65
|
* Get the list of query usage configurations
|
62
66
|
*/
|
63
67
|
getExtraQueryUsageConfigurations?(): QueryExportUsageConfiguration[];
|
68
|
+
|
69
|
+
/**
|
70
|
+
* Get the list of query chat configurations
|
71
|
+
*/
|
72
|
+
getExtraQueryChatRenderers?(): QueryChatRenderer[];
|
64
73
|
}
|
@@ -676,8 +676,8 @@ export class QueryBuilderExplorerState {
|
|
676
676
|
// This makes the assumption that the mapping has not been edited, which is a valid assumption since query is not for editing mappings
|
677
677
|
if (
|
678
678
|
this.queryBuilderState.mapping &&
|
679
|
-
this.queryBuilderState.mapping !==
|
680
|
-
this.mappingModelCoverageAnalysisResult?.mapping
|
679
|
+
this.queryBuilderState.mapping.path !==
|
680
|
+
this.mappingModelCoverageAnalysisResult?.mapping.path
|
681
681
|
) {
|
682
682
|
this.mappingModelCoverageAnalysisState.inProgress();
|
683
683
|
QueryBuilderTelemetryHelper.logEvent_QueryMappingModelCoverageAnalysisLaunched(
|
package/tsconfig.json
CHANGED
@@ -217,6 +217,7 @@
|
|
217
217
|
"./src/components/QueryBuilderSideBar.tsx",
|
218
218
|
"./src/components/QueryBuilderTextEditor.tsx",
|
219
219
|
"./src/components/QueryBuilderUnsupportedQueryEditor.tsx",
|
220
|
+
"./src/components/QueryChat.tsx",
|
220
221
|
"./src/components/QueryLoader.tsx",
|
221
222
|
"./src/components/QueryUsageViewer.tsx",
|
222
223
|
"./src/components/ServiceQuerySetupUtils.tsx",
|