@finos/legend-query-builder 4.14.27 → 4.14.29

Sign up to get free protection for your applications and to get access to all the features.
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) =>