@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.
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",