@finos/legend-query-builder 4.14.27 → 4.14.29

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 (29) hide show
  1. package/lib/components/QueryBuilder.d.ts.map +1 -1
  2. package/lib/components/QueryBuilder.js +16 -32
  3. package/lib/components/QueryBuilder.js.map +1 -1
  4. package/lib/components/QueryBuilderPropertyExpressionEditor.d.ts.map +1 -1
  5. package/lib/components/QueryBuilderPropertyExpressionEditor.js +6 -2
  6. package/lib/components/QueryBuilderPropertyExpressionEditor.js.map +1 -1
  7. package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
  8. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +10 -2
  9. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
  10. package/lib/components/result/tds/QueryBuilderTDSGridResult.d.ts.map +1 -1
  11. package/lib/components/result/tds/QueryBuilderTDSGridResult.js +1 -0
  12. package/lib/components/result/tds/QueryBuilderTDSGridResult.js.map +1 -1
  13. package/lib/index.css +2 -2
  14. package/lib/index.css.map +1 -1
  15. package/lib/package.json +1 -1
  16. package/lib/stores/QueryBuilderState.d.ts +2 -1
  17. package/lib/stores/QueryBuilderState.d.ts.map +1 -1
  18. package/lib/stores/QueryBuilderState.js +10 -2
  19. package/lib/stores/QueryBuilderState.js.map +1 -1
  20. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts.map +1 -1
  21. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js +4 -0
  22. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js.map +1 -1
  23. package/package.json +3 -3
  24. package/src/components/QueryBuilder.tsx +86 -141
  25. package/src/components/QueryBuilderPropertyExpressionEditor.tsx +6 -2
  26. package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +10 -2
  27. package/src/components/result/tds/QueryBuilderTDSGridResult.tsx +1 -0
  28. package/src/stores/QueryBuilderState.ts +21 -0
  29. package/src/stores/fetch-structure/tds/QueryBuilderTDSState.ts +7 -0
@@ -16,7 +16,6 @@
16
16
 
17
17
  import { observer } from 'mobx-react-lite';
18
18
  import {
19
- clsx,
20
19
  HammerIcon,
21
20
  ResizablePanelGroup,
22
21
  ResizablePanel,
@@ -31,7 +30,6 @@ import {
31
30
  CaretDownIcon,
32
31
  DiffIcon,
33
32
  WaterDropIcon,
34
- AssistantIcon,
35
33
  MenuContentDivider,
36
34
  Dialog,
37
35
  Modal,
@@ -43,6 +41,9 @@ import {
43
41
  CalendarClockIcon,
44
42
  ChatIcon,
45
43
  PanelLoadingIndicator,
44
+ SerializeIcon,
45
+ DataAccessIcon,
46
+ AssistantIcon,
46
47
  } from '@finos/legend-art';
47
48
  import { QueryBuilderFilterPanel } from './filter/QueryBuilderFilterPanel.js';
48
49
  import { QueryBuilderExplorerPanel } from './explorer/QueryBuilderExplorerPanel.js';
@@ -57,7 +58,6 @@ import { flowResult } from 'mobx';
57
58
  import { QueryBuilderUnsupportedQueryEditor } from './QueryBuilderUnsupportedQueryEditor.js';
58
59
  import {
59
60
  BackdropContainer,
60
- useApplicationStore,
61
61
  useCommands,
62
62
  ActionAlertActionType,
63
63
  ActionAlertType,
@@ -78,138 +78,6 @@ import { QueryChat } from './QueryChat.js';
78
78
  import { useEffect, useRef } from 'react';
79
79
  import { RedoButton, UndoButton } from '@finos/legend-lego/application';
80
80
 
81
- const QueryBuilderStatusBar = observer(
82
- (props: { queryBuilderState: QueryBuilderState }) => {
83
- const { queryBuilderState } = props;
84
- const applicationStore = useApplicationStore();
85
- const showDiff = (): void =>
86
- queryBuilderState.changeDetectionState.showDiffViewPanel();
87
- const openLambdaEditor = (mode: QueryBuilderTextEditorMode): void =>
88
- queryBuilderState.textEditorState.openModal(mode);
89
- const compile = applicationStore.guardUnhandledError(() =>
90
- flowResult(queryBuilderState.compileQuery()),
91
- );
92
- const toggleAssistant = (): void =>
93
- applicationStore.assistantService.toggleAssistant();
94
- const openQueryChat = (): void =>
95
- queryBuilderState.setIsQueryChatOpened(true);
96
-
97
- return (
98
- <div className="query-builder__status-bar">
99
- <div className="query-builder__status-bar__left"></div>
100
- <div className="query-builder__status-bar__right">
101
- {queryBuilderState.changeDetectionState.initState.hasCompleted && (
102
- <>
103
- <button
104
- className={clsx(
105
- 'query-builder__status-bar__action query-builder__status-bar__view-diff-btn',
106
- )}
107
- disabled={!queryBuilderState.changeDetectionState.hasChanged}
108
- onClick={showDiff}
109
- tabIndex={-1}
110
- title={
111
- queryBuilderState.changeDetectionState.hasChanged
112
- ? 'Show changes'
113
- : 'Query has not been changed'
114
- }
115
- >
116
- <DiffIcon />
117
- </button>
118
- {queryBuilderState.changeDetectionState.diffViewState && (
119
- <QueryBuilderDiffViewPanelDiaglog
120
- diffViewState={
121
- queryBuilderState.changeDetectionState.diffViewState
122
- }
123
- />
124
- )}
125
- </>
126
- )}
127
- {queryBuilderState.isQueryChatOpened && (
128
- <QueryChat queryBuilderState={queryBuilderState} />
129
- )}
130
- {!queryBuilderState.config?.TEMPORARY__disableQueryBuilderChat && (
131
- <button
132
- className={clsx(
133
- 'query-builder__status-bar__action query-builder__status-bar__action__toggler',
134
- {
135
- 'query-builder__status-bar__action__toggler--toggled':
136
- queryBuilderState.isQueryChatOpened === true,
137
- },
138
- )}
139
- onClick={openQueryChat}
140
- tabIndex={-1}
141
- title="Open Query Chat"
142
- >
143
- <ChatIcon />
144
- </button>
145
- )}
146
- <button
147
- className={clsx(
148
- 'query-builder__status-bar__action query-builder__status-bar__compile-btn',
149
- {
150
- 'query-builder__status-bar__compile-btn--wiggling':
151
- queryBuilderState.queryCompileState.isInProgress,
152
- },
153
- )}
154
- disabled={queryBuilderState.queryCompileState.isInProgress}
155
- onClick={compile}
156
- tabIndex={-1}
157
- title="Compile (F9)"
158
- >
159
- <HammerIcon />
160
- </button>
161
- <button
162
- className={clsx(
163
- 'query-builder__status-bar__action query-builder__status-bar__action__toggler',
164
- {
165
- 'query-builder__status-bar__action__toggler--toggled':
166
- queryBuilderState.textEditorState.mode ===
167
- QueryBuilderTextEditorMode.JSON,
168
- },
169
- )}
170
- onClick={(): void =>
171
- openLambdaEditor(QueryBuilderTextEditorMode.JSON)
172
- }
173
- tabIndex={-1}
174
- title="View Query Protocol"
175
- >{`{ }`}</button>
176
- <button
177
- className={clsx(
178
- 'query-builder__status-bar__action query-builder__status-bar__action__toggler',
179
- {
180
- 'query-builder__status-bar__action__toggler--toggled':
181
- queryBuilderState.textEditorState.mode ===
182
- QueryBuilderTextEditorMode.TEXT,
183
- },
184
- )}
185
- onClick={(): void =>
186
- openLambdaEditor(QueryBuilderTextEditorMode.TEXT)
187
- }
188
- tabIndex={-1}
189
- title="View Query in Pure"
190
- >
191
- <HackerIcon />
192
- </button>
193
- <button
194
- className={clsx(
195
- 'query-builder__status-bar__action query-builder__status-bar__action__toggler',
196
- {
197
- 'query-builder__status-bar__action__toggler--toggled':
198
- !applicationStore.assistantService.isHidden,
199
- },
200
- )}
201
- onClick={toggleAssistant}
202
- tabIndex={-1}
203
- title="Toggle assistant"
204
- >
205
- <AssistantIcon />
206
- </button>
207
- </div>
208
- </div>
209
- );
210
- },
211
- );
212
-
213
81
  const QueryBuilderPostGraphFetchPanel = observer(
214
82
  (props: { graphFetchState: QueryBuilderGraphFetchTreeState }) => {
215
83
  const { graphFetchState } = props;
@@ -381,6 +249,16 @@ export const QueryBuilder = observer(
381
249
  queryBuilderState.changeHistoryState.redo();
382
250
  };
383
251
 
252
+ const toggleAssistant = (): void =>
253
+ applicationStore.assistantService.toggleAssistant();
254
+ const compileQuery = applicationStore.guardUnhandledError(() =>
255
+ flowResult(queryBuilderState.compileQuery()),
256
+ );
257
+ const showDiff = (): void =>
258
+ queryBuilderState.changeDetectionState.showDiffViewPanel();
259
+ const openQueryChat = (): void =>
260
+ queryBuilderState.setIsQueryChatOpened(true);
261
+
384
262
  useEffect(() => {
385
263
  // this condition is for passing all exisitng tests because when we initialize a queryBuilderState for a test,
386
264
  // we use an empty RawLambda with an empty class and this useEffect is called earlier than initializeWithQuery()
@@ -576,7 +454,9 @@ export const QueryBuilder = observer(
576
454
  </MenuContentItemLabel>
577
455
  </MenuContentItem>
578
456
  <MenuContentItem onClick={openWatermark}>
579
- <MenuContentItemIcon>{null}</MenuContentItemIcon>
457
+ <MenuContentItemIcon>
458
+ <WaterDropIcon />
459
+ </MenuContentItemIcon>
580
460
  <MenuContentItemLabel>
581
461
  Show Watermark
582
462
  </MenuContentItemLabel>
@@ -594,7 +474,9 @@ export const QueryBuilder = observer(
594
474
  <MenuContentItemIcon>
595
475
  {queryBuilderState.isCalendarEnabled ? (
596
476
  <CheckIcon />
597
- ) : null}
477
+ ) : (
478
+ <CalendarClockIcon />
479
+ )}
598
480
  </MenuContentItemIcon>
599
481
  <MenuContentItemLabel>
600
482
  Enable Calendar
@@ -611,23 +493,77 @@ export const QueryBuilder = observer(
611
493
  .projectionColumns.length === 0
612
494
  }
613
495
  >
614
- <MenuContentItemIcon />
496
+ <MenuContentItemIcon>
497
+ <DataAccessIcon />
498
+ </MenuContentItemIcon>
615
499
  <MenuContentItemLabel>
616
500
  Check Entitlements
617
501
  </MenuContentItemLabel>
618
502
  </MenuContentItem>
619
503
  <MenuContentItem onClick={editQueryInPure}>
620
- <MenuContentItemIcon />
504
+ <MenuContentItemIcon>
505
+ <HackerIcon />
506
+ </MenuContentItemIcon>
621
507
  <MenuContentItemLabel>
622
508
  Edit Query in Pure
623
509
  </MenuContentItemLabel>
624
510
  </MenuContentItem>
625
511
  <MenuContentItem onClick={showQueryProtocol}>
626
- <MenuContentItemIcon />
512
+ <MenuContentItemIcon>
513
+ <SerializeIcon />
514
+ </MenuContentItemIcon>
627
515
  <MenuContentItemLabel>
628
516
  Show Query Protocol
629
517
  </MenuContentItemLabel>
630
518
  </MenuContentItem>
519
+ <MenuContentItem onClick={compileQuery}>
520
+ <MenuContentItemIcon>
521
+ <HammerIcon />
522
+ </MenuContentItemIcon>
523
+ <MenuContentItemLabel>
524
+ Compile Query (F9)
525
+ </MenuContentItemLabel>
526
+ </MenuContentItem>
527
+ {queryBuilderState.changeDetectionState.initState
528
+ .hasCompleted && (
529
+ <MenuContentItem
530
+ disabled={
531
+ !queryBuilderState.changeDetectionState.hasChanged
532
+ }
533
+ onClick={showDiff}
534
+ title={
535
+ queryBuilderState.changeDetectionState.hasChanged
536
+ ? 'Show changes'
537
+ : 'Query has not been changed'
538
+ }
539
+ >
540
+ <MenuContentItemIcon>
541
+ <DiffIcon />
542
+ </MenuContentItemIcon>
543
+ <MenuContentItemLabel>
544
+ Show Query Diff
545
+ </MenuContentItemLabel>
546
+ </MenuContentItem>
547
+ )}
548
+ {!queryBuilderState.config
549
+ ?.TEMPORARY__disableQueryBuilderChat && (
550
+ <MenuContentItem onClick={openQueryChat}>
551
+ <MenuContentItemIcon>
552
+ <ChatIcon />
553
+ </MenuContentItemIcon>
554
+ <MenuContentItemLabel>
555
+ Open Query Chat
556
+ </MenuContentItemLabel>
557
+ </MenuContentItem>
558
+ )}
559
+ <MenuContentItem onClick={toggleAssistant}>
560
+ <MenuContentItemIcon>
561
+ <AssistantIcon />
562
+ </MenuContentItemIcon>
563
+ <MenuContentItemLabel>
564
+ Open Assistant
565
+ </MenuContentItemLabel>
566
+ </MenuContentItem>
631
567
  </MenuContent>
632
568
  }
633
569
  menuProps={{
@@ -736,9 +672,19 @@ export const QueryBuilder = observer(
736
672
  </ResizablePanelGroup>
737
673
  </div>
738
674
  </div>
675
+ {queryBuilderState.isQueryChatOpened && (
676
+ <QueryChat queryBuilderState={queryBuilderState} />
677
+ )}
739
678
  {queryBuilderState.textEditorState.mode && (
740
679
  <QueryBuilderTextEditor queryBuilderState={queryBuilderState} />
741
680
  )}
681
+ {queryBuilderState.changeDetectionState.diffViewState && (
682
+ <QueryBuilderDiffViewPanelDiaglog
683
+ diffViewState={
684
+ queryBuilderState.changeDetectionState.diffViewState
685
+ }
686
+ />
687
+ )}
742
688
  {queryBuilderState.checkEntitlementsState
743
689
  .showCheckEntitlementsViewer && (
744
690
  <Dialog
@@ -789,7 +735,6 @@ export const QueryBuilder = observer(
789
735
  </Dialog>
790
736
  )}
791
737
  </div>
792
- <QueryBuilderStatusBar queryBuilderState={queryBuilderState} />
793
738
  </div>
794
739
  );
795
740
  },
@@ -408,11 +408,15 @@ export const QueryBuilderEditablePropertyName = observer(
408
408
  onChange={changeColumnName}
409
409
  onKeyDown={(event: React.KeyboardEvent<HTMLInputElement>) => {
410
410
  if (event.key === 'Enter') {
411
- setIsEditingColumnName(false);
411
+ if (columnName.length > 0) {
412
+ setIsEditingColumnName(false);
413
+ }
412
414
  }
413
415
  }}
414
416
  onBlur={() => {
415
- setIsEditingColumnName(false);
417
+ if (columnName.length > 0) {
418
+ setIsEditingColumnName(false);
419
+ }
416
420
  }}
417
421
  error={error}
418
422
  ref={columnNameInputRef}
@@ -789,7 +789,11 @@ const QueryBuilderProjectionColumnEditor = observer(
789
789
  projectionColumnState={projectionColumnState}
790
790
  changeColumnName={changeColumnName}
791
791
  error={
792
- isDuplicatedColumnName ? 'Duplicated column' : undefined
792
+ isDuplicatedColumnName
793
+ ? 'Duplicated column'
794
+ : projectionColumnState.columnName.length === 0
795
+ ? 'Empty column name'
796
+ : undefined
793
797
  }
794
798
  />
795
799
  </div>
@@ -812,7 +816,11 @@ const QueryBuilderProjectionColumnEditor = observer(
812
816
  columnName={projectionColumnState.columnName}
813
817
  changeColumnName={changeColumnName}
814
818
  error={
815
- isDuplicatedColumnName ? 'Duplicated column' : undefined
819
+ isDuplicatedColumnName
820
+ ? 'Duplicated column'
821
+ : projectionColumnState.columnName.length === 0
822
+ ? 'Empty column name'
823
+ : undefined
816
824
  }
817
825
  title={projectionColumnState.columnName}
818
826
  />
@@ -88,6 +88,7 @@ const getAggregationTDSColumnCustomizations = (
88
88
  allowedAggFuncs: ['count'],
89
89
  };
90
90
  case PRIMITIVE_TYPE.DECIMAL:
91
+ case PRIMITIVE_TYPE.NUMBER:
91
92
  case PRIMITIVE_TYPE.INTEGER:
92
93
  case PRIMITIVE_TYPE.FLOAT:
93
94
  return {
@@ -32,6 +32,7 @@ import {
32
32
  ActionState,
33
33
  hashArray,
34
34
  assertTrue,
35
+ assertNonNullable,
35
36
  } from '@finos/legend-shared';
36
37
  import { QueryBuilderFilterState } from './filter/QueryBuilderFilterState.js';
37
38
  import { QueryBuilderFetchStructureState } from './fetch-structure/QueryBuilderFetchStructureState.js';
@@ -54,6 +55,7 @@ import {
54
55
  type ValueSpecification,
55
56
  type Type,
56
57
  type QueryGridConfig,
58
+ type QueryExecutionContext,
57
59
  GRAPH_MANAGER_EVENT,
58
60
  CompilationError,
59
61
  extractSourceInformationCoordinates,
@@ -73,6 +75,7 @@ import {
73
75
  InstanceValue,
74
76
  Multiplicity,
75
77
  RuntimePointer,
78
+ QueryExplicitExecutionContext,
76
79
  } from '@finos/legend-graph';
77
80
  import { buildLambdaFunction } from './QueryBuilderValueSpecificationBuilder.js';
78
81
  import type {
@@ -287,6 +290,24 @@ export abstract class QueryBuilderState implements CommandRegistrar {
287
290
  return this.allVariables.map((e) => e.name);
288
291
  }
289
292
 
293
+ getQueryExecutionContext(): QueryExecutionContext {
294
+ const queryExeContext = new QueryExplicitExecutionContext();
295
+ const runtimeValue = guaranteeType(
296
+ this.executionContextState.runtimeValue,
297
+ RuntimePointer,
298
+ 'Query runtime must be of type runtime pointer',
299
+ );
300
+ assertNonNullable(
301
+ this.executionContextState.mapping,
302
+ 'Query required mapping to update',
303
+ );
304
+ queryExeContext.mapping = PackageableElementExplicitReference.create(
305
+ this.executionContextState.mapping,
306
+ );
307
+ queryExeContext.runtime = runtimeValue.packageableRuntime;
308
+ return queryExeContext;
309
+ }
310
+
290
311
  /**
291
312
  * Gets information about the current queryBuilderState.
292
313
  * This information can be used as a part of analytics
@@ -279,6 +279,13 @@ export class QueryBuilderTDSState
279
279
  get fetchStructureValidationIssues(): string[] {
280
280
  const validationIssues: string[] = [];
281
281
 
282
+ const hasEmptyProjectionColumnName = this.projectionColumns.some(
283
+ (column) => column.columnName.length === 0,
284
+ );
285
+ if (hasEmptyProjectionColumnName) {
286
+ validationIssues.push('Query has projection column with no name');
287
+ }
288
+
282
289
  const hasInValidCalendarAggregateColumns =
283
290
  this.aggregationState.columns.some(
284
291
  (column) =>