@finos/legend-query-builder 4.1.8 → 4.1.10

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.
Files changed (47) hide show
  1. package/lib/components/QueryBuilder.d.ts.map +1 -1
  2. package/lib/components/QueryBuilder.js +4 -2
  3. package/lib/components/QueryBuilder.js.map +1 -1
  4. package/lib/components/QueryBuilderResultPanel.d.ts.map +1 -1
  5. package/lib/components/QueryBuilderResultPanel.js +2 -2
  6. package/lib/components/QueryBuilderResultPanel.js.map +1 -1
  7. package/lib/components/QueryChat.d.ts +22 -0
  8. package/lib/components/QueryChat.d.ts.map +1 -0
  9. package/lib/components/QueryChat.js +28 -0
  10. package/lib/components/QueryChat.js.map +1 -0
  11. package/lib/components/execution-plan/AllocationExecutionNodeViewer.d.ts.map +1 -1
  12. package/lib/components/execution-plan/AllocationExecutionNodeViewer.js +1 -1
  13. package/lib/components/execution-plan/AllocationExecutionNodeViewer.js.map +1 -1
  14. package/lib/components/execution-plan/ConstantExecutionNodeViewer.js +1 -1
  15. package/lib/components/execution-plan/ConstantExecutionNodeViewer.js.map +1 -1
  16. package/lib/components/execution-plan/ExecutionPlanViewer.d.ts +4 -0
  17. package/lib/components/execution-plan/ExecutionPlanViewer.d.ts.map +1 -1
  18. package/lib/components/execution-plan/ExecutionPlanViewer.js +43 -5
  19. package/lib/components/execution-plan/ExecutionPlanViewer.js.map +1 -1
  20. package/lib/components/execution-plan/FunctionParametersValidationNodeViewer.d.ts.map +1 -1
  21. package/lib/components/execution-plan/FunctionParametersValidationNodeViewer.js.map +1 -1
  22. package/lib/components/execution-plan/ResultTypeViewer.js +2 -2
  23. package/lib/components/execution-plan/ResultTypeViewer.js.map +1 -1
  24. package/lib/index.css +17 -1
  25. package/lib/index.css.map +1 -1
  26. package/lib/package.json +1 -1
  27. package/lib/stores/QueryBuilderState.d.ts +2 -0
  28. package/lib/stores/QueryBuilderState.d.ts.map +1 -1
  29. package/lib/stores/QueryBuilderState.js +6 -0
  30. package/lib/stores/QueryBuilderState.js.map +1 -1
  31. package/lib/stores/QueryBuilder_LegendApplicationPlugin_Extension.d.ts +5 -0
  32. package/lib/stores/QueryBuilder_LegendApplicationPlugin_Extension.d.ts.map +1 -1
  33. package/lib/stores/explorer/QueryBuilderExplorerState.js +2 -2
  34. package/lib/stores/explorer/QueryBuilderExplorerState.js.map +1 -1
  35. package/package.json +8 -8
  36. package/src/components/QueryBuilder.tsx +17 -0
  37. package/src/components/QueryBuilderResultPanel.tsx +8 -1
  38. package/src/components/QueryChat.tsx +73 -0
  39. package/src/components/execution-plan/AllocationExecutionNodeViewer.tsx +12 -10
  40. package/src/components/execution-plan/ConstantExecutionNodeViewer.tsx +1 -1
  41. package/src/components/execution-plan/ExecutionPlanViewer.tsx +171 -19
  42. package/src/components/execution-plan/FunctionParametersValidationNodeViewer.tsx +1 -2
  43. package/src/components/execution-plan/ResultTypeViewer.tsx +1 -1
  44. package/src/stores/QueryBuilderState.ts +7 -0
  45. package/src/stores/QueryBuilder_LegendApplicationPlugin_Extension.ts +9 -0
  46. package/src/stores/explorer/QueryBuilderExplorerState.ts +2 -2
  47. 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
- <BlankPanelContent>
409
- <div className="execution-plan-viewer__unsupported-view">
410
- <div className="execution-plan-viewer__unsupported-view__summary">
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
  )}
@@ -23,10 +23,9 @@ import {
23
23
  import {
24
24
  type VariableExpression,
25
25
  type ParameterValidationContext,
26
- Multiplicity,
27
26
  type ResultType,
27
+ Multiplicity,
28
28
  } from '@finos/legend-graph';
29
-
30
29
  import {
31
30
  PanelListItem,
32
31
  PanelDivider,
@@ -32,6 +32,6 @@ export const ResultTypeViewer: React.FC<{
32
32
  } else if (resultType instanceof TDSResultType) {
33
33
  return <TDSResultTypeViewer resultType={resultType} />;
34
34
  } else {
35
- return <></>;
35
+ return null;
36
36
  }
37
37
  });
@@ -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",