@finos/legend-query-builder 4.14.20 → 4.14.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. package/lib/__lib__/QueryBuilderTesting.d.ts +1 -0
  2. package/lib/__lib__/QueryBuilderTesting.d.ts.map +1 -1
  3. package/lib/__lib__/QueryBuilderTesting.js +1 -0
  4. package/lib/__lib__/QueryBuilderTesting.js.map +1 -1
  5. package/lib/components/fetch-structure/QueryBuilderFetchStructurePanel.d.ts.map +1 -1
  6. package/lib/components/fetch-structure/QueryBuilderFetchStructurePanel.js +2 -1
  7. package/lib/components/fetch-structure/QueryBuilderFetchStructurePanel.js.map +1 -1
  8. package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
  9. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +1 -1
  10. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
  11. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.d.ts.map +1 -1
  12. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js +132 -67
  13. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js.map +1 -1
  14. package/lib/components/result/QueryBuilderResultPanel.js +1 -0
  15. package/lib/components/result/QueryBuilderResultPanel.js.map +1 -1
  16. package/lib/components/result/tds/QueryBuilderTDSGridResult.d.ts.map +1 -1
  17. package/lib/components/result/tds/QueryBuilderTDSGridResult.js +4 -2
  18. package/lib/components/result/tds/QueryBuilderTDSGridResult.js.map +1 -1
  19. package/lib/index.css +1 -1
  20. package/lib/package.json +1 -1
  21. package/lib/stores/QueryBuilderResultState.d.ts +9 -4
  22. package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
  23. package/lib/stores/QueryBuilderResultState.js +27 -4
  24. package/lib/stores/QueryBuilderResultState.js.map +1 -1
  25. package/lib/stores/QueryBuilderState.d.ts +4 -2
  26. package/lib/stores/QueryBuilderState.d.ts.map +1 -1
  27. package/lib/stores/QueryBuilderState.js +13 -2
  28. package/lib/stores/QueryBuilderState.js.map +1 -1
  29. package/lib/stores/QueryBuilderStateHashUtils.d.ts +1 -1
  30. package/lib/stores/QueryBuilderStateHashUtils.d.ts.map +1 -1
  31. package/lib/stores/QueryBuilderStateHashUtils.js +1 -1
  32. package/lib/stores/QueryBuilderStateHashUtils.js.map +1 -1
  33. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts.map +1 -1
  34. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js +6 -3
  35. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js.map +1 -1
  36. package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowState.d.ts +7 -2
  37. package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowState.d.ts.map +1 -1
  38. package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowState.js +46 -29
  39. package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowState.js.map +1 -1
  40. package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowValueSpecificationBuilder.js +1 -1
  41. package/lib/stores/fetch-structure/tds/window/QueryBuilderWindowValueSpecificationBuilder.js.map +1 -1
  42. package/package.json +6 -6
  43. package/src/__lib__/QueryBuilderTesting.ts +1 -0
  44. package/src/components/fetch-structure/QueryBuilderFetchStructurePanel.tsx +2 -1
  45. package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +1 -0
  46. package/src/components/fetch-structure/QueryBuilderTDSWindowPanel.tsx +232 -140
  47. package/src/components/result/QueryBuilderResultPanel.tsx +1 -1
  48. package/src/components/result/tds/QueryBuilderTDSGridResult.tsx +4 -2
  49. package/src/stores/QueryBuilderResultState.ts +36 -7
  50. package/src/stores/QueryBuilderState.ts +19 -2
  51. package/src/stores/QueryBuilderStateHashUtils.ts +1 -1
  52. package/src/stores/fetch-structure/tds/QueryBuilderTDSState.ts +16 -3
  53. package/src/stores/fetch-structure/tds/window/QueryBuilderWindowState.ts +70 -38
  54. package/src/stores/fetch-structure/tds/window/QueryBuilderWindowValueSpecificationBuilder.ts +1 -1
@@ -908,6 +908,7 @@ const QueryBuilderProjectionColumnEditor = observer(
908
908
  "This column is used and can't be removed"
909
909
  : 'Remove'
910
910
  }
911
+ name="Remove"
911
912
  >
912
913
  <TimesIcon />
913
914
  </button>
@@ -49,7 +49,12 @@ import {
49
49
  PanelHeaderActions,
50
50
  Panel,
51
51
  } from '@finos/legend-art';
52
- import { assertErrorThrown, guaranteeNonNullable } from '@finos/legend-shared';
52
+ import {
53
+ assertErrorThrown,
54
+ clone,
55
+ deleteEntry,
56
+ guaranteeNonNullable,
57
+ } from '@finos/legend-shared';
53
58
  import { observer } from 'mobx-react-lite';
54
59
  import { forwardRef, useCallback, useRef, useState } from 'react';
55
60
  import { type DropTargetMonitor, useDrag, useDrop } from 'react-dnd';
@@ -62,6 +67,7 @@ import {
62
67
  QueryBuilderTDS_WindowRankOperatorState,
63
68
  QueryBuilderTDS_WindowAggreationOperatorState,
64
69
  QUERY_BUILDER_WINDOW_COLUMN_DND_TYPE,
70
+ WindowGroupByColumnSortByState,
65
71
  } from '../../stores/fetch-structure/tds/window/QueryBuilderWindowState.js';
66
72
  import { QUERY_BUILDER_PROJECTION_COLUMN_DND_TYPE } from '../../stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.js';
67
73
  import type { QueryBuilderTDSColumnState } from '../../stores/fetch-structure/tds/QueryBuilderTDSColumnState.js';
@@ -83,6 +89,13 @@ const createWindowColumnState = (
83
89
  const nonColoperator = guaranteeNonNullable(
84
90
  tdsState.windowState.operators.filter((o) => !o.isColumnAggregator())[0],
85
91
  );
92
+ const columnName = operator
93
+ ? operator.isColumnAggregator()
94
+ ? `${operator.getLabel()} of ${columnState.columnName}`
95
+ : columnState.columnName
96
+ : nonColoperator.isColumnAggregator()
97
+ ? `${nonColoperator.getLabel()} of ${columnState.columnName}`
98
+ : columnState.columnName;
86
99
  if (operator) {
87
100
  const opState = new QueryBuilderTDS_WindowAggreationOperatorState(
88
101
  tdsState.windowState,
@@ -94,7 +107,7 @@ const createWindowColumnState = (
94
107
  [],
95
108
  undefined,
96
109
  opState,
97
- `${operator.getLabel()} ${columnState.columnName}`,
110
+ columnName,
98
111
  );
99
112
  } else {
100
113
  return new QueryBuilderWindowColumnState(
@@ -105,7 +118,7 @@ const createWindowColumnState = (
105
118
  tdsState.windowState,
106
119
  nonColoperator,
107
120
  ),
108
- `${nonColoperator.getLabel()} ${columnState.columnName}`,
121
+ columnName,
109
122
  );
110
123
  }
111
124
  };
@@ -188,85 +201,177 @@ const QueryBuilderWindowColumnModalEditor = observer(
188
201
  windowState: QueryBuilderWindowState;
189
202
  windowColumnState: QueryBuilderWindowColumnState;
190
203
  }) => {
204
+ // Read state
191
205
  const { windowState, windowColumnState } = props;
192
- const createNewWindow =
206
+ const isNewWindowFunction =
193
207
  !windowState.windowColumns.includes(windowColumnState);
194
208
  const tdsState = windowState.tdsState;
195
209
  const applicationStore = useApplicationStore();
196
- const close = (): void => {
197
- windowState.setEditColumn(undefined);
198
- };
199
- const isDuplicatedColumnName = !windowState.windowColumns.includes(
200
- windowColumnState,
201
- )
202
- ? windowState.tdsState.tdsColumns
203
- .map((c) => c.columnName)
204
- .includes(windowColumnState.columnName)
205
- : windowState.tdsState.isDuplicateColumn(windowColumnState);
206
- const windowOptions = createNewWindow
207
- ? tdsState.tdsColumns
208
- : windowColumnState.possibleReferencedColumns;
209
- const windowOptionsLabels = windowOptions.map((w) => ({
210
- label: w.columnName,
211
- value: w,
212
- }));
213
- // column Name
210
+
211
+ // Column name
212
+ const [selectedColumnName, setSelectedColumnName] = useState(
213
+ windowColumnState.columnName,
214
+ );
214
215
  const changeColumnName: React.ChangeEventHandler<HTMLInputElement> = (
215
216
  event,
216
- ) => windowColumnState.setColumnName(event.target.value);
217
- // operator
217
+ ) => setSelectedColumnName(event.target.value);
218
+ const isDuplicatedColumnName = isNewWindowFunction
219
+ ? windowState.tdsState.tdsColumns
220
+ .map((c) => c.columnName)
221
+ .filter((name) => name === selectedColumnName).length > 0
222
+ : windowState.tdsState.tdsColumns
223
+ .map((c) => c.columnName)
224
+ .filter((name) => name === selectedColumnName).length > 0 &&
225
+ selectedColumnName !== windowColumnState.columnName;
226
+
227
+ // Window operator
218
228
  const operators = windowState.operators;
219
- const operationState = windowColumnState.operationState;
220
- const windowOpColumn =
221
- operationState instanceof QueryBuilderTDS_WindowAggreationOperatorState
222
- ? operationState.columnState
229
+ const operatorState = windowColumnState.operatorState;
230
+ const [selectedOperatorState, setSelectedOperatorState] = useState(() => {
231
+ if (
232
+ operatorState instanceof QueryBuilderTDS_WindowAggreationOperatorState
233
+ ) {
234
+ return new QueryBuilderTDS_WindowAggreationOperatorState(
235
+ operatorState.windowState,
236
+ operatorState.operator,
237
+ operatorState.columnState,
238
+ );
239
+ }
240
+ return new QueryBuilderTDS_WindowRankOperatorState(
241
+ operatorState.windowState,
242
+ operatorState.operator,
243
+ );
244
+ });
245
+ const windowOperatorColumn =
246
+ selectedOperatorState instanceof
247
+ QueryBuilderTDS_WindowAggreationOperatorState
248
+ ? selectedOperatorState.columnState
223
249
  : undefined;
224
- const changeOperatorCol = (
250
+ const changeWindowOperatorColumn = (
225
251
  val: { label: string; value: QueryBuilderTDSColumnState } | null,
226
252
  ): void => {
227
253
  if (
228
- operationState instanceof QueryBuilderTDS_WindowAggreationOperatorState
254
+ selectedOperatorState instanceof
255
+ QueryBuilderTDS_WindowAggreationOperatorState &&
256
+ val !== null
229
257
  ) {
230
- if (val !== null) {
231
- operationState.setColumnState(val.value);
232
- }
258
+ const newOpertorState = clone(selectedOperatorState);
259
+ const newColumnName = newOpertorState.operator.isColumnAggregator()
260
+ ? `${newOpertorState.operator.getLabel()} of ${val.value.columnName}`
261
+ : val.value.columnName;
262
+ newOpertorState.setColumnState(val.value);
263
+ setSelectedOperatorState(newOpertorState);
264
+ setSelectedColumnName(newColumnName);
233
265
  }
234
266
  };
235
267
  const changeOperator =
236
- (olapOp: QueryBuilderTDS_WindowOperator) => (): void => {
237
- windowColumnState.changeOperator(olapOp);
268
+ (newOperator: QueryBuilderTDS_WindowOperator) => (): void => {
269
+ const stateAndName =
270
+ windowColumnState.getChangeOperatorStateAndColumnName(
271
+ selectedOperatorState.operator,
272
+ windowOperatorColumn,
273
+ newOperator,
274
+ );
275
+ if (stateAndName) {
276
+ setSelectedOperatorState(stateAndName.operatorState);
277
+ setSelectedColumnName(stateAndName.columnName);
278
+ }
238
279
  };
239
- // window
240
- const addOptions = windowOptions.filter(
241
- (e) => !windowColumnState.windowColumns.includes(e),
280
+ const allColumns = isNewWindowFunction
281
+ ? tdsState.tdsColumns
282
+ : windowColumnState.possibleReferencedColumns;
283
+ const allColumnsOptions = allColumns.map((w) => ({
284
+ label: w.columnName,
285
+ value: w,
286
+ }));
287
+
288
+ // Window columns
289
+ const [selectedWindowColumns, setSelectedWindowColumns] = useState([
290
+ ...windowColumnState.windowColumns,
291
+ ]);
292
+ const availableColumns = allColumns.filter(
293
+ (e) => !selectedWindowColumns.includes(e),
242
294
  );
243
- const create = (): void => {
244
- windowState.addWindowColumn(windowColumnState);
245
- close();
246
- };
247
- const addWindowValue = (): void => {
248
- if (addOptions.length > 0) {
249
- windowColumnState.addWindow(guaranteeNonNullable(addOptions[0]));
295
+ const addWindowColumn = (): void => {
296
+ if (availableColumns.length > 0) {
297
+ setSelectedWindowColumns([
298
+ ...selectedWindowColumns,
299
+ guaranteeNonNullable(availableColumns[0]),
300
+ ]);
250
301
  }
251
302
  };
252
- // sortby
253
- const sortByState = windowColumnState.sortByState;
303
+ const updateWindowColumn = (
304
+ idx: number,
305
+ column: QueryBuilderTDSColumnState,
306
+ ): void => {
307
+ const newWindowColumns = clone(selectedWindowColumns);
308
+ newWindowColumns[idx] = column;
309
+ setSelectedWindowColumns(newWindowColumns);
310
+ };
311
+ const deleteWindowColumn = (column: QueryBuilderTDSColumnState): void => {
312
+ const newWindowColumns = clone(selectedWindowColumns);
313
+ deleteEntry(newWindowColumns, column);
314
+ setSelectedWindowColumns(newWindowColumns);
315
+ };
316
+
317
+ // Sort by
318
+ const [selectedSortBy, setSelectedSortBy] = useState(() => {
319
+ const sortBy = windowColumnState.sortByState;
320
+ if (sortBy) {
321
+ return new WindowGroupByColumnSortByState(
322
+ sortBy.columnState,
323
+ sortBy.sortType,
324
+ );
325
+ }
326
+ return undefined;
327
+ });
254
328
  const changeSortBy = (sortOp: COLUMN_SORT_TYPE | undefined) => (): void => {
255
- windowColumnState.changeSortBy(sortOp);
329
+ if (selectedSortBy?.sortType !== sortOp) {
330
+ if (sortOp) {
331
+ const newSortByState = new WindowGroupByColumnSortByState(
332
+ selectedSortBy?.columnState
333
+ ? selectedSortBy.columnState
334
+ : guaranteeNonNullable(
335
+ windowColumnState.possibleReferencedColumns[0],
336
+ ),
337
+ sortOp,
338
+ );
339
+ setSelectedSortBy(newSortByState);
340
+ } else {
341
+ setSelectedSortBy(undefined);
342
+ }
343
+ }
256
344
  };
257
345
  const changeSortCol = (
258
346
  val: { label: string; value: QueryBuilderTDSColumnState } | null,
259
347
  ): void => {
260
- if (sortByState) {
261
- if (val !== null) {
262
- sortByState.setColumnState(val.value);
263
- }
348
+ if (selectedSortBy && val !== null) {
349
+ const newSortByState = new WindowGroupByColumnSortByState(
350
+ val.value,
351
+ selectedSortBy.sortType,
352
+ );
353
+ setSelectedSortBy(newSortByState);
264
354
  }
265
355
  };
356
+
357
+ // Modal lifecycle actions
358
+ const handleCancel = (): void => {
359
+ windowState.setEditColumn(undefined);
360
+ };
361
+
362
+ const handleApply = (): void => {
363
+ windowColumnState.setColumnName(selectedColumnName);
364
+ windowColumnState.setOperatorState(selectedOperatorState);
365
+ windowColumnState.setWindows(selectedWindowColumns);
366
+ windowColumnState.setSortBy(selectedSortBy);
367
+ windowState.addWindowColumn(windowColumnState);
368
+ handleCancel();
369
+ };
370
+
266
371
  return (
267
372
  <Dialog
268
373
  open={Boolean(windowState.editColumn)}
269
- onClose={close}
374
+ onClose={handleCancel}
270
375
  classes={{
271
376
  root: 'editor-modal__root-container',
272
377
  container: 'editor-modal__container',
@@ -288,7 +393,7 @@ const QueryBuilderWindowColumnModalEditor = observer(
288
393
  >
289
394
  <ModalHeader
290
395
  title={
291
- createNewWindow
396
+ isNewWindowFunction
292
397
  ? 'Create Window Function Column'
293
398
  : 'Update Window Function Column'
294
399
  }
@@ -305,27 +410,16 @@ const QueryBuilderWindowColumnModalEditor = observer(
305
410
  <div className="panel__content__form__section__list">
306
411
  <div className="panel__content__form__section__list__items">
307
412
  <div className="query-builder__olap__column__operation__operator">
308
- <div
309
- className={clsx(
310
- 'query-builder__olap__column__operation__operator__label',
311
- {
312
- 'query-builder__olap__column__operation__operator__label__agg':
313
- !windowOpColumn,
314
- },
315
- )}
316
- >
317
- {operationState.operator.getLabel()}
318
- </div>
319
- {windowOpColumn && (
413
+ {windowOperatorColumn && (
320
414
  <div className="panel__content__form__section__list__item query-builder__olap__tds__column__options">
321
415
  <CustomSelectorInput
322
416
  className="query-builder__olap__tds__column__dropdown"
323
- options={windowOptionsLabels}
324
- disabled={windowOptionsLabels.length < 1}
325
- onChange={changeOperatorCol}
417
+ options={allColumnsOptions}
418
+ disabled={allColumnsOptions.length < 1}
419
+ onChange={changeWindowOperatorColumn}
326
420
  value={{
327
- value: windowOpColumn,
328
- label: windowOpColumn.columnName,
421
+ value: windowOperatorColumn,
422
+ label: windowOperatorColumn.columnName,
329
423
  }}
330
424
  darkMode={
331
425
  !applicationStore.layoutService
@@ -334,8 +428,20 @@ const QueryBuilderWindowColumnModalEditor = observer(
334
428
  />
335
429
  </div>
336
430
  )}
431
+ <div
432
+ className={clsx(
433
+ 'query-builder__olap__column__operation__operator__label',
434
+ {
435
+ 'query-builder__olap__column__operation__operator__label__agg':
436
+ !windowOperatorColumn,
437
+ },
438
+ )}
439
+ >
440
+ {selectedOperatorState.operator.getLabel()}
441
+ </div>
337
442
  <DropdownMenu
338
443
  className="query-builder__olap__column__operation__operator__dropdown"
444
+ title="Choose Window Function Operator..."
339
445
  disabled={!operators.length}
340
446
  content={
341
447
  <MenuContent>
@@ -362,16 +468,10 @@ const QueryBuilderWindowColumnModalEditor = observer(
362
468
  elevation: 7,
363
469
  }}
364
470
  >
365
- <div
366
- className="query-builder__olap__column__operation__operator__badge"
367
- title="Choose Window Function Operator..."
368
- >
471
+ <div className="query-builder__olap__column__operation__operator__badge">
369
472
  <SigmaIcon />
370
473
  </div>
371
- <div
372
- className="query-builder__olap__column__operation__operator__dropdown__trigger"
373
- title="Choose Window Function Operator..."
374
- >
474
+ <div className="query-builder__olap__column__operation__operator__dropdown__trigger">
375
475
  <CaretDownIcon />
376
476
  </div>
377
477
  </DropdownMenu>
@@ -385,29 +485,29 @@ const QueryBuilderWindowColumnModalEditor = observer(
385
485
  </div>
386
486
  <div className="panel__content__form__section__header__prompt">
387
487
  Represents the window of columns that will partition the rows
388
- for which to apply the aggragte function
488
+ for which to apply the aggregate function
389
489
  </div>
390
490
  <div className="panel__content__form__section__list">
391
491
  <div className="panel__content__form__section__list__items">
392
- {windowColumnState.windowColumns.map((value, idx) => (
492
+ {selectedWindowColumns.map((value, idx) => (
393
493
  <TDSColumnSelectorEditor
394
494
  key={value.uuid}
395
495
  colValue={value}
396
496
  setColumn={(v: QueryBuilderTDSColumnState) =>
397
- windowColumnState.changeWindow(v, idx)
497
+ updateWindowColumn(idx, v)
398
498
  }
399
- deleteColumn={(v: QueryBuilderTDSColumnState): void =>
400
- windowColumnState.deleteWindow(v)
499
+ deleteColumn={(v: QueryBuilderTDSColumnState) =>
500
+ deleteWindowColumn(v)
401
501
  }
402
- tdsColOptions={windowOptions}
502
+ tdsColOptions={availableColumns}
403
503
  />
404
504
  ))}
405
505
  </div>
406
506
  <div className="panel__content__form__section__list__new-item__add">
407
507
  <button
408
508
  className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
409
- disabled={!addOptions.length}
410
- onClick={addWindowValue}
509
+ disabled={!availableColumns.length}
510
+ onClick={addWindowColumn}
411
511
  tabIndex={-1}
412
512
  >
413
513
  Add Value
@@ -425,21 +525,16 @@ const QueryBuilderWindowColumnModalEditor = observer(
425
525
  <div className="panel__content__form__section__header__prompt"></div>
426
526
  <div className="panel__content__form__section__list">
427
527
  <div className="query-builder__olap__column__sortby__operator">
428
- {sortByState && (
429
- <div className="query-builder__olap__column__sortby__operator__label">
430
- {sortByState.sortType.toLowerCase()}
431
- </div>
432
- )}
433
- {sortByState && (
528
+ {selectedSortBy && (
434
529
  <div className="panel__content__form__section__list__item query-builder__olap__tds__column__options">
435
530
  <CustomSelectorInput
436
531
  className="query-builder__olap__tds__column__dropdown"
437
- options={windowOptionsLabels}
438
- disabled={windowOptionsLabels.length < 1}
532
+ options={allColumnsOptions}
533
+ disabled={allColumnsOptions.length < 1}
439
534
  onChange={changeSortCol}
440
535
  value={{
441
- value: sortByState.columnState,
442
- label: sortByState.columnState.columnName,
536
+ value: selectedSortBy.columnState,
537
+ label: selectedSortBy.columnState.columnName,
443
538
  }}
444
539
  darkMode={
445
540
  !applicationStore.layoutService
@@ -448,13 +543,19 @@ const QueryBuilderWindowColumnModalEditor = observer(
448
543
  />
449
544
  </div>
450
545
  )}
451
- {!sortByState && (
546
+ {!selectedSortBy && (
452
547
  <div className="query-builder__olap__column__sortby__none">
453
548
  (none)
454
549
  </div>
455
550
  )}
551
+ {selectedSortBy && (
552
+ <div className="query-builder__olap__column__sortby__operator__label">
553
+ {selectedSortBy.sortType.toLowerCase()}
554
+ </div>
555
+ )}
456
556
  <DropdownMenu
457
557
  className="query-builder__olap__column__sortby__operator__dropdown"
558
+ title="Choose Window Function SortBy Operator..."
458
559
  content={
459
560
  <MenuContent>
460
561
  <MenuContentItem
@@ -487,18 +588,16 @@ const QueryBuilderWindowColumnModalEditor = observer(
487
588
  'query-builder__olap__column__sortby__operator__badge',
488
589
  {
489
590
  'query-builder__olap__column__sortby__operator__badge--activated':
490
- Boolean(sortByState),
591
+ Boolean(selectedSortBy),
491
592
  },
492
593
  )}
493
594
  tabIndex={-1}
494
- title="Choose Window Function SortBy Operator..."
495
595
  >
496
596
  <SortIcon />
497
597
  </div>
498
598
  <div
499
599
  className="query-builder__olap__column__sortby__operator__dropdown__trigger"
500
600
  tabIndex={-1}
501
- title="Choose Window Function SortBy Operator..."
502
601
  >
503
602
  <CaretDownIcon />
504
603
  </div>
@@ -517,22 +616,23 @@ const QueryBuilderWindowColumnModalEditor = observer(
517
616
  <InputWithInlineValidation
518
617
  className="query-builder__olap__column__name__input input-group__input"
519
618
  spellCheck={false}
520
- value={windowColumnState.columnName}
619
+ value={selectedColumnName}
521
620
  onChange={changeColumnName}
522
621
  error={isDuplicatedColumnName ? 'Duplicated column' : undefined}
523
622
  />
524
623
  </PanelFormSection>
525
624
  </div>
526
625
  <ModalFooter>
527
- {createNewWindow ? (
528
- <ModalFooterButton text="Create" onClick={create} />
529
- ) : (
530
- <ModalFooterButton
531
- text="Close"
532
- onClick={close}
533
- type="secondary"
534
- />
535
- )}
626
+ <ModalFooterButton
627
+ text={isNewWindowFunction ? 'Create' : 'Apply'}
628
+ onClick={handleApply}
629
+ disabled={isDuplicatedColumnName}
630
+ />
631
+ <ModalFooterButton
632
+ text="Cancel"
633
+ onClick={handleCancel}
634
+ type="secondary"
635
+ />
536
636
  </ModalFooter>
537
637
  </Modal>
538
638
  </Dialog>
@@ -718,7 +818,7 @@ const QueryBuilderWindowColumnEditor = observer(
718
818
  };
719
819
 
720
820
  // operator
721
- const operationState = windowColumnState.operationState;
821
+ const operationState = windowColumnState.operatorState;
722
822
  const aggregateColumn =
723
823
  operationState instanceof QueryBuilderTDS_WindowAggreationOperatorState
724
824
  ? operationState.columnState
@@ -887,6 +987,15 @@ const QueryBuilderWindowColumnEditor = observer(
887
987
  />
888
988
  <div className="query-builder__olap__column__operation">
889
989
  <div className="query-builder__olap__column__operation__operator">
990
+ {aggregateColumn && (
991
+ <TDSColumnReferenceEditor
992
+ tdsColumn={aggregateColumn}
993
+ handleChange={handleOpDrop}
994
+ selectionEditor={{
995
+ options: windowColumnState.possibleReferencedColumns,
996
+ }}
997
+ />
998
+ )}
890
999
  <div
891
1000
  className={clsx(
892
1001
  'query-builder__olap__column__operation__operator__label',
@@ -898,18 +1007,10 @@ const QueryBuilderWindowColumnEditor = observer(
898
1007
  >
899
1008
  {operationState.operator.getLabel()}
900
1009
  </div>
901
- {aggregateColumn && (
902
- <TDSColumnReferenceEditor
903
- tdsColumn={aggregateColumn}
904
- handleChange={handleOpDrop}
905
- selectionEditor={{
906
- options: windowColumnState.possibleReferencedColumns,
907
- }}
908
- />
909
- )}
910
1010
  <DropdownMenu
911
1011
  className="query-builder__olap__column__operation__operator__dropdown"
912
1012
  disabled={!operators.length}
1013
+ title="Choose Window Function Operator..."
913
1014
  content={
914
1015
  <MenuContent>
915
1016
  {operators.map((op) => (
@@ -929,16 +1030,10 @@ const QueryBuilderWindowColumnEditor = observer(
929
1030
  elevation: 7,
930
1031
  }}
931
1032
  >
932
- <div
933
- className="query-builder__olap__column__operation__operator__badge"
934
- title="Choose Window Function Operator..."
935
- >
1033
+ <div className="query-builder__olap__column__operation__operator__badge">
936
1034
  <SigmaIcon />
937
1035
  </div>
938
- <div
939
- className="query-builder__olap__column__operation__operator__dropdown__trigger"
940
- title="Choose Window Function Operator..."
941
- >
1036
+ <div className="query-builder__olap__column__operation__operator__dropdown__trigger">
942
1037
  <CaretDownIcon />
943
1038
  </div>
944
1039
  </DropdownMenu>
@@ -998,7 +1093,7 @@ const QueryBuilderWindowColumnEditor = observer(
998
1093
  deleteColumn={(v: QueryBuilderTDSColumnState): void =>
999
1094
  windowColumnState.deleteWindow(v)
1000
1095
  }
1001
- tdsColOptions={windowOptions}
1096
+ tdsColOptions={addWindowOptions}
1002
1097
  />
1003
1098
  ))}
1004
1099
  </div>
@@ -1018,11 +1113,6 @@ const QueryBuilderWindowColumnEditor = observer(
1018
1113
  </div>
1019
1114
  <div className="query-builder__olap__column__sortby">
1020
1115
  <div className="query-builder__olap__column__sortby__operator">
1021
- {sortByState && (
1022
- <div className="query-builder__olap__column__sortby__operator__label">
1023
- {sortByState.sortType.toLowerCase()}
1024
- </div>
1025
- )}
1026
1116
  {sortByState && (
1027
1117
  <TDSColumnReferenceEditor
1028
1118
  tdsColumn={sortByState.columnState}
@@ -1037,8 +1127,14 @@ const QueryBuilderWindowColumnEditor = observer(
1037
1127
  (none)
1038
1128
  </div>
1039
1129
  )}
1130
+ {sortByState && (
1131
+ <div className="query-builder__olap__column__sortby__operator__label">
1132
+ {sortByState.sortType.toLowerCase()}
1133
+ </div>
1134
+ )}
1040
1135
  <DropdownMenu
1041
1136
  className="query-builder__olap__column__sortby__operator__dropdown"
1137
+ title="Choose Window Function SortBy Operator..."
1042
1138
  content={
1043
1139
  <MenuContent>
1044
1140
  <MenuContentItem
@@ -1074,14 +1170,10 @@ const QueryBuilderWindowColumnEditor = observer(
1074
1170
  Boolean(sortByState),
1075
1171
  },
1076
1172
  )}
1077
- title="Choose Window Function SortBy Operator..."
1078
1173
  >
1079
1174
  <SortIcon />
1080
1175
  </div>
1081
- <div
1082
- className="query-builder__olap__column__sortby__operator__dropdown__trigger"
1083
- title="Choose Window Function SortBy Operator..."
1084
- >
1176
+ <div className="query-builder__olap__column__sortby__operator__dropdown__trigger">
1085
1177
  <CaretDownIcon />
1086
1178
  </div>
1087
1179
  </DropdownMenu>
@@ -288,6 +288,7 @@ export const QueryBuilderResultPanel = observer(
288
288
  } else {
289
289
  queryBuilderState.resultState.setPreviewLimit(previewLimitValue);
290
290
  }
291
+ queryBuilderState.resultState.updatePreviewLimitInConfig();
291
292
  };
292
293
 
293
294
  const onKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (event) => {
@@ -305,7 +306,6 @@ export const QueryBuilderResultPanel = observer(
305
306
  !queryBuilderState.isLocalModeEnabled,
306
307
  );
307
308
  };
308
-
309
309
  return (
310
310
  <div
311
311
  data-testid={QUERY_BUILDER_TEST_ID.QUERY_BUILDER_RESULT_PANEL}
@@ -99,7 +99,7 @@ const getLocalColDefs = (
99
99
  enableValue: true,
100
100
  ...getAggregationTDSColumnCustomizations(executionResult, colName),
101
101
  } as DataGridColumnDefinition;
102
- const persistedColumn = resultState.gridConfig.columns.find(
102
+ const persistedColumn = resultState.gridConfig?.columns.find(
103
103
  (c) => c.colId === colName,
104
104
  );
105
105
  if (persistedColumn) {
@@ -240,6 +240,8 @@ export const QueryBuilderTDSGridResult = observer(
240
240
  resultState.setGridConfig({
241
241
  columns: columnAPi.getColumnState(),
242
242
  isPivotModeEnabled: columnAPi.isPivotMode(),
243
+ isLocalModeEnabled: true,
244
+ previewLimit: resultState.previewLimit,
243
245
  });
244
246
  };
245
247
 
@@ -351,7 +353,7 @@ export const QueryBuilderTDSGridResult = observer(
351
353
  onGridReady={(params): void => {
352
354
  setColumnApi(params.columnApi);
353
355
  params.columnApi.setPivotMode(
354
- resultState.gridConfig.isPivotModeEnabled,
356
+ Boolean(resultState.gridConfig?.isPivotModeEnabled),
355
357
  );
356
358
  }}
357
359
  gridOptions={{