@finos/legend-application-repl 0.0.49 → 0.0.51

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 (78) hide show
  1. package/lib/components/dataCube/DataCube.d.ts.map +1 -1
  2. package/lib/components/dataCube/DataCube.js +1 -3
  3. package/lib/components/dataCube/DataCube.js.map +1 -1
  4. package/lib/components/dataCube/editor/DataCubeEditor.d.ts.map +1 -1
  5. package/lib/components/dataCube/editor/DataCubeEditor.js +3 -7
  6. package/lib/components/dataCube/editor/DataCubeEditor.js.map +1 -1
  7. package/lib/components/dataCube/editor/DataCubeEditorColumnsPanel.js +6 -6
  8. package/lib/components/dataCube/editor/DataCubeEditorColumnsPanel.js.map +1 -1
  9. package/lib/components/dataCube/editor/DataCubeEditorColumnsSelector.js +5 -5
  10. package/lib/components/dataCube/editor/DataCubeEditorColumnsSelector.js.map +1 -1
  11. package/lib/components/dataCube/{editor/DataCubeEditorFilterPanel.d.ts → filter/DataCubeEditorFilter.d.ts} +2 -2
  12. package/lib/components/dataCube/filter/DataCubeEditorFilter.d.ts.map +1 -0
  13. package/lib/components/dataCube/{editor/DataCubeEditorFilterPanel.js → filter/DataCubeEditorFilter.js} +44 -39
  14. package/lib/components/dataCube/filter/DataCubeEditorFilter.js.map +1 -0
  15. package/lib/index.css +2 -2
  16. package/lib/index.css.map +1 -1
  17. package/lib/package.json +3 -3
  18. package/lib/stores/dataCube/DataCubeState.d.ts +2 -0
  19. package/lib/stores/dataCube/DataCubeState.d.ts.map +1 -1
  20. package/lib/stores/dataCube/DataCubeState.js +4 -1
  21. package/lib/stores/dataCube/DataCubeState.js.map +1 -1
  22. package/lib/stores/dataCube/core/DataCubeQueryBuilderUtils.d.ts +1 -1
  23. package/lib/stores/dataCube/core/DataCubeQueryBuilderUtils.d.ts.map +1 -1
  24. package/lib/stores/dataCube/core/DataCubeQueryBuilderUtils.js +3 -2
  25. package/lib/stores/dataCube/core/DataCubeQueryBuilderUtils.js.map +1 -1
  26. package/lib/stores/dataCube/core/filter/DataCubeQueryFilterEditorState.d.ts.map +1 -1
  27. package/lib/stores/dataCube/core/filter/DataCubeQueryFilterEditorState.js +4 -2
  28. package/lib/stores/dataCube/core/filter/DataCubeQueryFilterEditorState.js.map +1 -1
  29. package/lib/stores/dataCube/editor/DataCubeEditorColumnsPanelState.d.ts.map +1 -1
  30. package/lib/stores/dataCube/editor/DataCubeEditorColumnsPanelState.js +6 -2
  31. package/lib/stores/dataCube/editor/DataCubeEditorColumnsPanelState.js.map +1 -1
  32. package/lib/stores/dataCube/editor/DataCubeEditorColumnsSelectorState.d.ts +5 -5
  33. package/lib/stores/dataCube/editor/DataCubeEditorColumnsSelectorState.d.ts.map +1 -1
  34. package/lib/stores/dataCube/editor/DataCubeEditorColumnsSelectorState.js +22 -18
  35. package/lib/stores/dataCube/editor/DataCubeEditorColumnsSelectorState.js.map +1 -1
  36. package/lib/stores/dataCube/editor/DataCubeEditorState.d.ts +1 -5
  37. package/lib/stores/dataCube/editor/DataCubeEditorState.d.ts.map +1 -1
  38. package/lib/stores/dataCube/editor/DataCubeEditorState.js +3 -10
  39. package/lib/stores/dataCube/editor/DataCubeEditorState.js.map +1 -1
  40. package/lib/stores/dataCube/{editor/DataCubeEditorFilterPanelState.d.ts → filter/DataCubeFilterEditorState.d.ts} +10 -11
  41. package/lib/stores/dataCube/filter/DataCubeFilterEditorState.d.ts.map +1 -0
  42. package/lib/stores/dataCube/{editor/DataCubeEditorFilterPanelState.js → filter/DataCubeFilterEditorState.js} +27 -15
  43. package/lib/stores/dataCube/filter/DataCubeFilterEditorState.js.map +1 -0
  44. package/lib/stores/dataCube/grid/DataCubeGridConfigurationBuilder.d.ts.map +1 -1
  45. package/lib/stores/dataCube/grid/DataCubeGridConfigurationBuilder.js +39 -13
  46. package/lib/stores/dataCube/grid/DataCubeGridConfigurationBuilder.js.map +1 -1
  47. package/lib/stores/dataCube/grid/DataCubeGridControllerState.d.ts +1 -1
  48. package/lib/stores/dataCube/grid/DataCubeGridControllerState.d.ts.map +1 -1
  49. package/lib/stores/dataCube/grid/DataCubeGridControllerState.js.map +1 -1
  50. package/lib/stores/dataCube/grid/DataCubeGridMenuBuilder.d.ts +1 -1
  51. package/lib/stores/dataCube/grid/DataCubeGridMenuBuilder.d.ts.map +1 -1
  52. package/lib/stores/dataCube/grid/DataCubeGridMenuBuilder.js +25 -13
  53. package/lib/stores/dataCube/grid/DataCubeGridMenuBuilder.js.map +1 -1
  54. package/lib/stores/dataCube/grid/DataCubeGridQuerySnapshotBuilder.d.ts.map +1 -1
  55. package/lib/stores/dataCube/grid/DataCubeGridQuerySnapshotBuilder.js +9 -2
  56. package/lib/stores/dataCube/grid/DataCubeGridQuerySnapshotBuilder.js.map +1 -1
  57. package/package.json +7 -7
  58. package/src/components/dataCube/DataCube.tsx +1 -3
  59. package/src/components/dataCube/editor/DataCubeEditor.tsx +11 -21
  60. package/src/components/dataCube/editor/DataCubeEditorColumnsPanel.tsx +8 -8
  61. package/src/components/dataCube/editor/DataCubeEditorColumnsSelector.tsx +5 -5
  62. package/src/components/dataCube/{editor/DataCubeEditorFilterPanel.tsx → filter/DataCubeEditorFilter.tsx} +100 -79
  63. package/src/stores/dataCube/DataCubeState.ts +4 -1
  64. package/src/stores/dataCube/core/DataCubeQueryBuilderUtils.ts +4 -3
  65. package/src/stores/dataCube/core/filter/DataCubeQueryFilterEditorState.ts +6 -2
  66. package/src/stores/dataCube/editor/DataCubeEditorColumnsPanelState.ts +7 -3
  67. package/src/stores/dataCube/editor/DataCubeEditorColumnsSelectorState.ts +21 -17
  68. package/src/stores/dataCube/editor/DataCubeEditorState.tsx +7 -11
  69. package/src/stores/dataCube/{editor/DataCubeEditorFilterPanelState.ts → filter/DataCubeFilterEditorState.tsx} +48 -28
  70. package/src/stores/dataCube/grid/DataCubeGridConfigurationBuilder.tsx +41 -13
  71. package/src/stores/dataCube/grid/DataCubeGridControllerState.ts +1 -0
  72. package/src/stores/dataCube/grid/DataCubeGridMenuBuilder.tsx +37 -16
  73. package/src/stores/dataCube/grid/DataCubeGridQuerySnapshotBuilder.ts +18 -8
  74. package/tsconfig.json +2 -2
  75. package/lib/components/dataCube/editor/DataCubeEditorFilterPanel.d.ts.map +0 -1
  76. package/lib/components/dataCube/editor/DataCubeEditorFilterPanel.js.map +0 -1
  77. package/lib/stores/dataCube/editor/DataCubeEditorFilterPanelState.d.ts.map +0 -1
  78. package/lib/stores/dataCube/editor/DataCubeEditorFilterPanelState.js.map +0 -1
@@ -23,7 +23,7 @@ import {
23
23
  import type { DataCubeQueryEditorPanelState } from './DataCubeEditorPanelState.js';
24
24
  import {
25
25
  DataCubeEditorColumnsSelectorColumnState,
26
- DataCubeEditorColumnsSelectorColumnsVisibility,
26
+ DataCubeEditorColumnsSelectorHiddenColumnsVisibility,
27
27
  DataCubeEditorColumnsSelectorState,
28
28
  } from './DataCubeEditorColumnsSelectorState.js';
29
29
  import type { DataCubeEditorState } from './DataCubeEditorState.js';
@@ -66,8 +66,8 @@ export class DataCubeEditorColumnsPanelState
66
66
  this.editor = editor;
67
67
  this.dataCube = editor.dataCube;
68
68
  this.selector = new DataCubeEditorBasicColumnsSelectorState(editor, {
69
- initialColumnsVisibility:
70
- DataCubeEditorColumnsSelectorColumnsVisibility.HIDDEN,
69
+ initialHiddenColumnsVisibility:
70
+ DataCubeEditorColumnsSelectorHiddenColumnsVisibility.HIDDEN,
71
71
  onChange: (selector) => {
72
72
  // populate a default configuration for the newly selected columns
73
73
  selector.selectedColumns
@@ -135,6 +135,9 @@ export class DataCubeEditorColumnsPanelState
135
135
  this.selector.setSelectedColumns(
136
136
  // extract selected columns from the configuration since the configuration specifies the order
137
137
  // taking into account the group extended columns
138
+ // NOTE: since select() is applied before grouping/aggregation, it's technicaly not possible to
139
+ // unselect the group extended columns, so we will take advantage of the `hidden` property to show
140
+ // group extended columns that are not hidden as selected
138
141
  configuration.columns.map((col) => {
139
142
  const column = this.selector.getColumn(col.name);
140
143
  return new DataCubeEditorColumnsSelectorColumnState(
@@ -152,6 +155,7 @@ export class DataCubeEditorColumnsPanelState
152
155
  this.propagateColumnSelectionChanges();
153
156
  newSnapshot.data.selectColumns = this.selector.selectedColumns
154
157
  // TODO: filter by group extended columns
158
+ // and translate unselection to hidden columns in column configuration
155
159
  .map((col) => ({
156
160
  name: col.name,
157
161
  type: col.type,
@@ -29,7 +29,7 @@ export class DataCubeEditorColumnsSelectorColumnState {
29
29
  }
30
30
  }
31
31
 
32
- export enum DataCubeEditorColumnsSelectorColumnsVisibility {
32
+ export enum DataCubeEditorColumnsSelectorHiddenColumnsVisibility {
33
33
  VISIBLE = 'visible',
34
34
  VISIBLE_WITH_WARNING = 'visible-with-warning',
35
35
  HIDDEN = 'hidden',
@@ -49,13 +49,13 @@ export abstract class DataCubeEditorColumnsSelectorState<
49
49
  readonly onChange?:
50
50
  | ((selector: DataCubeEditorColumnsSelectorState<T>) => void)
51
51
  | undefined;
52
- columnsVisibility!: DataCubeEditorColumnsSelectorColumnsVisibility;
52
+ hiddenColumnsVisibility!: DataCubeEditorColumnsSelectorHiddenColumnsVisibility;
53
53
 
54
54
  constructor(
55
55
  editor: DataCubeEditorState,
56
56
  options?: {
57
- initialColumnsVisibility?:
58
- | DataCubeEditorColumnsSelectorColumnsVisibility
57
+ initialHiddenColumnsVisibility?:
58
+ | DataCubeEditorColumnsSelectorHiddenColumnsVisibility
59
59
  | undefined;
60
60
  onChange?:
61
61
  | ((select: DataCubeEditorColumnsSelectorState<T>) => void)
@@ -76,22 +76,23 @@ export abstract class DataCubeEditorColumnsSelectorState<
76
76
  selectedColumnsSearchText: observable,
77
77
  setSelectedColumnsSearchText: action,
78
78
 
79
- columnsVisibility: observable,
80
- setColumnsVisibility: action,
79
+ hiddenColumnsVisibility: observable,
80
+ setHiddenColumnsVisibility: action,
81
81
  });
82
82
 
83
83
  this.editor = editor;
84
84
  this.dataCube = editor.dataCube;
85
85
  this.onChange = options?.onChange;
86
- this.columnsVisibility =
87
- options?.initialColumnsVisibility ??
88
- DataCubeEditorColumnsSelectorColumnsVisibility.VISIBLE;
86
+ this.hiddenColumnsVisibility =
87
+ options?.initialHiddenColumnsVisibility ??
88
+ // default to show hidden columns
89
+ DataCubeEditorColumnsSelectorHiddenColumnsVisibility.VISIBLE;
89
90
  }
90
91
 
91
- setColumnsVisibility(
92
- visibility: DataCubeEditorColumnsSelectorColumnsVisibility,
92
+ setHiddenColumnsVisibility(
93
+ val: DataCubeEditorColumnsSelectorHiddenColumnsVisibility,
93
94
  ) {
94
- this.columnsVisibility = visibility;
95
+ this.hiddenColumnsVisibility = val;
95
96
  }
96
97
 
97
98
  abstract get availableColumns(): T[];
@@ -105,8 +106,8 @@ export abstract class DataCubeEditorColumnsSelectorState<
105
106
  .sort((a, b) => a.name.localeCompare(b.name))
106
107
  .filter(
107
108
  (column) =>
108
- this.columnsVisibility !==
109
- DataCubeEditorColumnsSelectorColumnsVisibility.HIDDEN ||
109
+ this.hiddenColumnsVisibility !==
110
+ DataCubeEditorColumnsSelectorHiddenColumnsVisibility.HIDDEN ||
110
111
  !this.editor.columnProperties.columns.find(
111
112
  (col) => col.name === column.name,
112
113
  )?.hideFromView,
@@ -116,8 +117,8 @@ export abstract class DataCubeEditorColumnsSelectorState<
116
117
  get selectedColumnsForDisplay(): T[] {
117
118
  return this.selectedColumns.filter(
118
119
  (column) =>
119
- this.columnsVisibility !==
120
- DataCubeEditorColumnsSelectorColumnsVisibility.HIDDEN ||
120
+ this.hiddenColumnsVisibility !==
121
+ DataCubeEditorColumnsSelectorHiddenColumnsVisibility.HIDDEN ||
121
122
  !this.editor.columnProperties.columns.find(
122
123
  (col) => col.name === column.name,
123
124
  )?.hideFromView,
@@ -125,6 +126,9 @@ export abstract class DataCubeEditorColumnsSelectorState<
125
126
  }
126
127
 
127
128
  setSelectedColumns(val: T[]) {
129
+ // NOTE: since we have a list of columns available which we treat as
130
+ // "templates" to select from, we need to clone these columns in order
131
+ // to avoid modifying the original available columns
128
132
  this.selectedColumns = val.map((col) => this.cloneColumn(col));
129
133
  this.onChange?.(this);
130
134
  }
@@ -144,5 +148,5 @@ export abstract class DataCubeEditorColumnsSelectorState<
144
148
  );
145
149
  }
146
150
 
147
- abstract cloneColumn(column: T): T;
151
+ protected abstract cloneColumn(column: T): T;
148
152
  }
@@ -28,13 +28,10 @@ import { DataCubeConfiguration } from '../core/DataCubeConfiguration.js';
28
28
  import { DataCubeEditorVerticalPivotsPanelState } from './DataCubeEditorVerticalPivotsPanelState.js';
29
29
  import { SingletonModeDisplayState } from '../../LayoutManagerState.js';
30
30
  import { DataCubeEditor } from '../../../components/dataCube/editor/DataCubeEditor.js';
31
- import { DataCubeEditorFilterPanelState } from './DataCubeEditorFilterPanelState.js';
32
31
 
33
32
  export enum DataCubeEditorTab {
34
33
  GENERAL_PROPERTIES = 'General Properties',
35
34
  COLUMN_PROPERTIES = 'Column Properties',
36
- EXTENDED_COLUMNS = 'Extended Columns',
37
- FILTER = 'Filter',
38
35
  COLUMNS = 'Columns',
39
36
  VERTICAL_PIVOTS = 'Vertical Pivots',
40
37
  HORIZONTAL_PIVOTS = 'Horizontal Pivots',
@@ -44,13 +41,15 @@ export enum DataCubeEditorTab {
44
41
 
45
42
  export class DataCubeEditorState extends DataCubeQuerySnapshotController {
46
43
  readonly display: SingletonModeDisplayState;
44
+
45
+ readonly code: DataCubeEditorCodePanelState;
46
+
47
47
  readonly generalProperties: DataCubeEditorGeneralPropertiesPanelState;
48
48
  readonly columnProperties: DataCubeEditorColumnPropertiesPanelState;
49
- readonly filter: DataCubeEditorFilterPanelState;
49
+
50
50
  readonly columns: DataCubeEditorColumnsPanelState;
51
51
  readonly verticalPivots: DataCubeEditorVerticalPivotsPanelState;
52
52
  readonly sorts: DataCubeEditorSortsPanelState;
53
- readonly code: DataCubeEditorCodePanelState;
54
53
 
55
54
  currentTab = DataCubeEditorTab.GENERAL_PROPERTIES;
56
55
 
@@ -58,10 +57,10 @@ export class DataCubeEditorState extends DataCubeQuerySnapshotController {
58
57
  super(dataCube);
59
58
 
60
59
  makeObservable(this, {
61
- applyChanges: action,
62
-
63
60
  currentTab: observable,
64
61
  setCurrentTab: action,
62
+
63
+ applyChanges: action,
65
64
  });
66
65
 
67
66
  this.display = new SingletonModeDisplayState(
@@ -73,7 +72,6 @@ export class DataCubeEditorState extends DataCubeQuerySnapshotController {
73
72
  this,
74
73
  );
75
74
  this.columnProperties = new DataCubeEditorColumnPropertiesPanelState(this);
76
- this.filter = new DataCubeEditorFilterPanelState(this);
77
75
  this.columns = new DataCubeEditorColumnsPanelState(this);
78
76
  this.verticalPivots = new DataCubeEditorVerticalPivotsPanelState(this);
79
77
  this.sorts = new DataCubeEditorSortsPanelState(this);
@@ -88,13 +86,12 @@ export class DataCubeEditorState extends DataCubeQuerySnapshotController {
88
86
  const baseSnapshot = guaranteeNonNullable(this.getLatestSnapshot());
89
87
  const snapshot = baseSnapshot.clone();
90
88
 
91
- // NOTE: column selection must be processed first so necassary
89
+ // NOTE: column selection must be processed first so necessary
92
90
  // prunings can be done to make sure other panel stats are in sync
93
91
  // with the current column selection
94
92
  this.columns.buildSnapshot(snapshot, baseSnapshot);
95
93
  this.verticalPivots.buildSnapshot(snapshot, baseSnapshot);
96
94
  this.sorts.buildSnapshot(snapshot, baseSnapshot);
97
- this.filter.buildSnapshot(snapshot, baseSnapshot);
98
95
 
99
96
  // grid configuration must be processed before processing columns' configuration
100
97
  // to properly generate the container configuration
@@ -118,7 +115,6 @@ export class DataCubeEditorState extends DataCubeQuerySnapshotController {
118
115
  this.columns.applySnaphot(snapshot, configuration);
119
116
  this.verticalPivots.applySnaphot(snapshot, configuration);
120
117
  this.sorts.applySnaphot(snapshot, configuration);
121
- this.filter.applySnaphot(snapshot, configuration);
122
118
 
123
119
  this.generalProperties.applySnaphot(snapshot, configuration);
124
120
  this.columnProperties.applySnaphot(snapshot, configuration);
@@ -25,10 +25,7 @@ import {
25
25
  getNonNullableEntry,
26
26
  guaranteeNonNullable,
27
27
  } from '@finos/legend-shared';
28
- import type { DataCubeEditorState } from './DataCubeEditorState.js';
29
28
  import type { DataCubeState } from '../DataCubeState.js';
30
- import type { DataCubeQueryEditorPanelState } from './DataCubeEditorPanelState.js';
31
- import type { DataCubeConfiguration } from '../core/DataCubeConfiguration.js';
32
29
  import {
33
30
  type DataCubeFilterEditorTree,
34
31
  type DataCubeFilterEditorTreeNode,
@@ -37,22 +34,33 @@ import {
37
34
  buildFilterEditorTree,
38
35
  buildFilterQuerySnapshot,
39
36
  } from '../core/filter/DataCubeQueryFilterEditorState.js';
37
+ import { DataCubeQuerySnapshotController } from '../core/DataCubeQuerySnapshotManager.js';
38
+ import {
39
+ DataCubeConfiguration,
40
+ type DataCubeColumnConfiguration,
41
+ } from '../core/DataCubeConfiguration.js';
42
+ import { SingletonModeDisplayState } from '../../LayoutManagerState.js';
43
+ import { DataCubeFilterEditor } from '../../../components/dataCube/filter/DataCubeEditorFilter.js';
40
44
 
41
- export class DataCubeEditorFilterPanelState
42
- implements DataCubeQueryEditorPanelState
43
- {
44
- readonly dataCube!: DataCubeState;
45
- readonly editor!: DataCubeEditorState;
45
+ export class DataCubeFilterEditorState extends DataCubeQuerySnapshotController {
46
+ readonly display: SingletonModeDisplayState;
46
47
 
47
48
  tree: DataCubeFilterEditorTree;
48
49
  selectedNode?: DataCubeFilterEditorTreeNode | undefined;
50
+ columns: DataCubeColumnConfiguration[] = [];
51
+
52
+ constructor(dataCube: DataCubeState) {
53
+ super(dataCube);
49
54
 
50
- constructor(editor: DataCubeEditorState) {
51
55
  makeObservable(this, {
52
56
  tree: observable.ref,
53
57
  initializeTree: action,
54
58
  refreshTree: action,
55
59
 
60
+ columns: observable,
61
+
62
+ applySnapshot: action,
63
+
56
64
  selectedNode: observable,
57
65
  selectedGroupNode: computed,
58
66
  setSelectedNode: action,
@@ -61,18 +69,17 @@ export class DataCubeEditorFilterPanelState
61
69
  layerFilterNode: action,
62
70
  });
63
71
 
64
- this.dataCube = editor.dataCube;
65
- this.editor = editor;
72
+ this.display = new SingletonModeDisplayState(
73
+ this.dataCube.repl.layout,
74
+ 'Filter',
75
+ () => <DataCubeFilterEditor dataCube={this.dataCube} />,
76
+ );
77
+
66
78
  this.tree = {
67
79
  nodes: new Map<string, DataCubeFilterEditorTreeNode>(),
68
80
  };
69
81
  }
70
82
 
71
- get columns() {
72
- // TODO: include leaf-extended columns
73
- return this.editor.columns.sourceColumns;
74
- }
75
-
76
83
  initializeTree() {
77
84
  if (this.tree.root === undefined && this.tree.nodes.size === 0) {
78
85
  const root = new DataCubeFilterEditorConditionGroupTreeNode(
@@ -118,11 +125,8 @@ export class DataCubeEditorFilterPanelState
118
125
  baseNode.not,
119
126
  );
120
127
  } else if (baseNode instanceof DataCubeFilterEditorConditionGroupTreeNode) {
121
- if (this.editor.columnProperties.columns.length !== 0) {
122
- const columnConfig = getNonNullableEntry(
123
- this.editor.columnProperties.columns,
124
- 0,
125
- );
128
+ if (this.columns.length !== 0) {
129
+ const columnConfig = getNonNullableEntry(this.columns, 0);
126
130
  const column = {
127
131
  name: columnConfig.name,
128
132
  type: columnConfig.type,
@@ -267,10 +271,21 @@ export class DataCubeEditorFilterPanelState
267
271
  }
268
272
  }
269
273
 
270
- applySnaphot(
274
+ override async applySnapshot(
271
275
  snapshot: DataCubeQuerySnapshot,
272
- configuration: DataCubeConfiguration,
273
- ): void {
276
+ previousSnapshot: DataCubeQuerySnapshot | undefined,
277
+ ): Promise<void> {
278
+ const configuration = DataCubeConfiguration.serialization.fromJson(
279
+ snapshot.data.configuration,
280
+ );
281
+ // NOTE: filtering group extended columns is not supported
282
+ this.columns = configuration.columns.filter(
283
+ (column) =>
284
+ !snapshot.data.groupExtendedColumns.find(
285
+ (col) => col.name === column.name,
286
+ ),
287
+ );
288
+
274
289
  this.tree.nodes = new Map<string, DataCubeFilterEditorTreeNode>();
275
290
  this.tree.root = snapshot.data.filter
276
291
  ? buildFilterEditorTree(
@@ -284,12 +299,17 @@ export class DataCubeEditorFilterPanelState
284
299
  this.refreshTree();
285
300
  }
286
301
 
287
- buildSnapshot(
288
- newSnapshot: DataCubeQuerySnapshot,
289
- baseSnapshot: DataCubeQuerySnapshot,
290
- ): void {
302
+ applyChanges() {
303
+ const baseSnapshot = guaranteeNonNullable(this.getLatestSnapshot());
304
+ const newSnapshot = baseSnapshot.clone();
305
+
291
306
  newSnapshot.data.filter = this.tree.root
292
307
  ? buildFilterQuerySnapshot(this.tree.root)
293
308
  : undefined;
309
+
310
+ newSnapshot.finalize();
311
+ if (newSnapshot.hashCode !== baseSnapshot.hashCode) {
312
+ this.publishSnapshot(newSnapshot);
313
+ }
294
314
  }
295
315
  }
@@ -345,13 +345,19 @@ function _sizeSpec(columnData: ColumnData) {
345
345
  //
346
346
  // TODO: if we support column resize to fit content, should we disable this behavior?
347
347
  resizable: column.fixedWidth === undefined,
348
- // suppressAutoSize: columnConfiguration.fixedWidth !== undefined,
348
+ suppressAutoSize: column.fixedWidth !== undefined,
349
+ suppressSizeToFit: column.fixedWidth !== undefined,
349
350
  width: column.fixedWidth,
350
351
  minWidth: Math.max(
351
352
  column.minWidth ?? INTERNAL__GRID_CLIENT_COLUMN_MIN_WIDTH,
352
353
  INTERNAL__GRID_CLIENT_COLUMN_MIN_WIDTH,
353
354
  ),
354
355
  maxWidth: column.maxWidth,
356
+ // Make sure the column spans the width if possible so when total width
357
+ // is less than grid width, removing/adding one column will cause the other
358
+ // columns to take/give up space
359
+ flex:
360
+ column.fixedWidth === undefined ? 1 : (undefined as unknown as number),
355
361
  } as ColDef;
356
362
  }
357
363
 
@@ -360,7 +366,7 @@ function _sortSpec(columnData: ColumnData) {
360
366
  const sortColumns = snapshot.data.sortColumns;
361
367
  const sortCol = _findCol(sortColumns, column.name);
362
368
  return {
363
- sortable: true, // if this is pivot column, no sorting is allowed
369
+ sortable: true, // if this is pivot column, no sorting is supported yet
364
370
  sort: sortCol
365
371
  ? sortCol.operation === DataCubeQuerySortOperator.ASCENDING
366
372
  ? GridClientSortDirection.ASCENDING
@@ -374,10 +380,10 @@ function _rowGroupSpec(columnData: ColumnData) {
374
380
  const { snapshot, column } = columnData;
375
381
  const data = snapshot.data;
376
382
  const groupByCol = _findCol(data.groupBy?.columns, column.name);
377
- const aggCol = _findCol(data.groupBy?.aggColumns, column.name);
378
383
  return {
379
384
  enableRowGroup: column.kind === DataCubeColumnKind.DIMENSION,
380
- enableValue: column.kind === DataCubeColumnKind.MEASURE,
385
+ enableValue: false, // disable GUI interactions to modify this column's aggregate function
386
+ allowedAggFuncs: [], // disable GUI for options of the agg functions
381
387
  rowGroup: Boolean(groupByCol),
382
388
  rowGroupIndex: groupByCol
383
389
  ? (data.groupBy?.columns.indexOf(groupByCol) ?? null)
@@ -385,9 +391,10 @@ function _rowGroupSpec(columnData: ColumnData) {
385
391
  // NOTE: we don't quite care about populating these accurately
386
392
  // since ag-grid aggregation does not support parameters, so
387
393
  // its set of supported aggregators will never match that specified
388
- // in the editor, so we just assign dummy values here
389
- aggFunc: aggCol ? aggCol.operation : null,
390
- allowedAggFuncs: [],
394
+ // in the editor.
395
+ // But we need to set this to make sure sorting works when row grouping
396
+ // is used, so we use a dummy value here.
397
+ aggFunc: () => 0,
391
398
  } satisfies ColDef;
392
399
  }
393
400
 
@@ -455,18 +462,35 @@ export function generateBaseGridOptions(dataCube: DataCubeState): GridOptions {
455
462
  },
456
463
  onBodyScrollEnd: () => grid.setScrollHintText(undefined),
457
464
  scrollbarWidth: 10,
465
+ alwaysShowVerticalScroll: true, // this is needed to ensure
458
466
  // -------------------------------------- CONTEXT MENU --------------------------------------
459
467
  preventDefaultOnContextMenu: true, // prevent showing the browser's context menu
460
468
  columnMenu: 'new', // ensure context menu works on header
461
469
  // NOTE: dynamically generate the content of the context menu to make sure the items are not stale
462
470
  getContextMenuItems: (params) =>
463
- grid.controller.menuBuilder?.(params) ?? [],
464
- getMainMenuItems: (params) => grid.controller.menuBuilder?.(params) ?? [],
471
+ grid.controller.menuBuilder?.(params, false) ?? [],
472
+ getMainMenuItems: (params) =>
473
+ grid.controller.menuBuilder?.(params, true) ?? [],
474
+ // NOTE: when right-clicking empty space in the header, a menu will show up
475
+ // with 2 default options: 'Choose Columns` and `Reset Columns`, which is not
476
+ // a desired behavior, so we hide the popup menu immediately
477
+ onColumnMenuVisibleChanged: (event) => {
478
+ if (!event.column) {
479
+ event.api.hidePopupMenu();
480
+ }
481
+ },
465
482
  // -------------------------------------- COLUMN SIZING --------------------------------------
466
483
  autoSizePadding: INTERNAL__GRID_CLIENT_AUTO_RESIZE_PADDING,
484
+ // ensure columns are resized to fit the grid width initially and on window resize
485
+ // NOTE: this has to be used with `alwaysShowVerticalScroll` to ensure accurate sizing
486
+ // otherwise on initial load, the computation will be done when no data is rendered,
487
+ // so when data is rendered and the vertical scrollbar shows up, it will block a part of
488
+ // the last column.
467
489
  autoSizeStrategy: {
468
- // resize to fit content initially
469
- type: 'fitCellContents',
490
+ type: 'fitGridWidth',
491
+ },
492
+ onGridSizeChanged: (event) => {
493
+ event.api.sizeColumnsToFit();
470
494
  },
471
495
  // -------------------------------------- TOOLTIP --------------------------------------
472
496
  tooltipShowDelay: INTERNAL__GRID_CLIENT_TOOLTIP_SHOW_DELAY,
@@ -597,17 +621,21 @@ export function generateGridOptionsFromSnapshot(
597
621
  justifyContent: 'space-between',
598
622
  display: 'flex',
599
623
  },
624
+ cellDataType: 'text',
625
+ flex: 1,
600
626
  // TODO: display: coloring, text, etc.
601
627
  // TODO: pinning (should we pin this left by default?)
602
628
  // TODO: tooltip
603
629
  loadingCellRenderer: DataCubeGridLoadingCellRenderer,
604
- sortable: false, // TODO: @akphi - we can support this in the configuration
630
+ // TODO: @akphi - we can support this in the configuration (support sorting by tree-column?)
631
+ // sortable: false,
605
632
  } satisfies ColDef,
606
633
  // NOTE: Internal column used for programatically trigger data fetch when filter is modified
607
634
  {
608
635
  colId: INTERNAL__GRID_CLIENT_FILTER_TRIGGER_COLUMN_ID,
609
636
  hide: true,
610
- enableValue: false,
637
+ enableValue: false, // disable GUI interactions to modify this column's aggregate function
638
+ allowedAggFuncs: [], // disable GUI for options of the agg functions
611
639
  enablePivot: false,
612
640
  enableRowGroup: false,
613
641
  filter: 'agTextColumnFilter',
@@ -75,6 +75,7 @@ export class DataCubeGridControllerState extends DataCubeQuerySnapshotController
75
75
  params:
76
76
  | GetContextMenuItemsParams<unknown, { dataCube: DataCubeState }>
77
77
  | GetMainMenuItemsParams<unknown, { dataCube: DataCubeState }>,
78
+ fromHeader: boolean,
78
79
  ) => (string | MenuItemDef)[])
79
80
  | undefined;
80
81
 
@@ -38,10 +38,10 @@ import {
38
38
  DataCubeGridClientExportFormat,
39
39
  INTERNAL__GRID_CLIENT_MISSING_VALUE,
40
40
  } from './DataCubeGridClientEngine.js';
41
- import { DataCubeEditorTab } from '../editor/DataCubeEditorState.js';
42
41
  import { PRIMITIVE_TYPE } from '@finos/legend-graph';
43
42
  import type { DataCubeColumnConfiguration } from '../core/DataCubeConfiguration.js';
44
43
  import { DataCubeFilterEditorConditionTreeNode } from '../core/filter/DataCubeQueryFilterEditorState.js';
44
+ import { DataCubeEditorTab } from '../editor/DataCubeEditorState.js';
45
45
 
46
46
  function toFilterValue(
47
47
  value: unknown,
@@ -157,11 +157,15 @@ export function generateMenuBuilder(
157
157
  controller: DataCubeGridControllerState,
158
158
  ): (
159
159
  params: GetContextMenuItemsParams | GetMainMenuItemsParams,
160
+ fromHeader: boolean,
160
161
  ) => (string | MenuItemDef)[] {
161
162
  const dataCube = controller.dataCube;
162
163
  const editor = dataCube.editor;
163
164
 
164
- return (params: GetContextMenuItemsParams | GetMainMenuItemsParams) => {
165
+ return (
166
+ params: GetContextMenuItemsParams | GetMainMenuItemsParams,
167
+ fromHeader: boolean,
168
+ ) => {
165
169
  const column = params.column ?? undefined;
166
170
  const columnName = column?.getColId();
167
171
  const columnConfiguration = controller.getColumnConfiguration(columnName);
@@ -457,8 +461,7 @@ export function generateMenuBuilder(
457
461
  {
458
462
  name: 'Filters...',
459
463
  action: () => {
460
- editor.setCurrentTab(DataCubeEditorTab.FILTER);
461
- editor.display.open();
464
+ dataCube.filter.display.open();
462
465
  },
463
466
  },
464
467
  {
@@ -563,44 +566,55 @@ export function generateMenuBuilder(
563
566
  subMenu: [
564
567
  {
565
568
  name: `Auto-size to Fit Content`,
569
+ disabled:
570
+ !column ||
571
+ !columnConfiguration ||
572
+ columnConfiguration.fixedWidth !== undefined,
566
573
  action: () =>
567
574
  params.api.autoSizeColumns(
568
575
  [column?.getColId()].filter(isNonNullable),
569
576
  ),
570
- disabled: !column,
571
577
  },
572
578
  {
573
579
  name: `Minimize Column`,
580
+ disabled:
581
+ !column ||
582
+ !columnConfiguration ||
583
+ columnConfiguration.fixedWidth !== undefined,
574
584
  action: () => {
575
585
  if (column) {
576
586
  params.api.setColumnWidths([
577
587
  {
578
588
  key: column.getColId(),
579
589
  newWidth:
580
- controller.getColumnConfiguration(columnName)?.minWidth ??
581
- DEFAULT_COLUMN_MIN_WIDTH,
590
+ columnConfiguration?.minWidth ?? DEFAULT_COLUMN_MIN_WIDTH,
582
591
  },
583
592
  ]);
584
593
  }
585
594
  },
586
- disabled: !column,
587
595
  },
588
596
  'separator',
589
597
  {
590
598
  name: `Auto-size All Columns`,
591
- action: () => params.api.autoSizeAllColumns(),
599
+ action: () =>
600
+ params.api.autoSizeColumns(
601
+ controller.configuration.columns
602
+ .filter((col) => col.fixedWidth === undefined)
603
+ .map((col) => col.name),
604
+ ),
592
605
  },
593
606
  {
594
607
  name: `Minimize All Columns`,
595
608
  action: () => {
596
609
  params.api.setColumnWidths(
597
610
  // TODO: take care of pivot columns
598
- controller.configuration.columns.map((col) => ({
599
- key: col.name,
600
- newWidth:
601
- controller.getColumnConfiguration(columnName)?.minWidth ??
602
- DEFAULT_COLUMN_MIN_WIDTH,
603
- })),
611
+ controller.configuration.columns
612
+ .filter((col) => col.fixedWidth === undefined)
613
+ .map((col) => ({
614
+ key: col.name,
615
+ newWidth:
616
+ columnConfiguration?.minWidth ?? DEFAULT_COLUMN_MIN_WIDTH,
617
+ })),
604
618
  );
605
619
  },
606
620
  },
@@ -689,7 +703,14 @@ export function generateMenuBuilder(
689
703
  {
690
704
  name: 'Properties...',
691
705
  disabled: editor.display.isOpen,
692
- action: () => editor.display.open(),
706
+ action: () => {
707
+ // open the column property
708
+ if (column && fromHeader) {
709
+ editor.setCurrentTab(DataCubeEditorTab.COLUMN_PROPERTIES);
710
+ editor.columnProperties.setSelectedColumnName(column.getColId());
711
+ }
712
+ editor.display.open();
713
+ },
693
714
  },
694
715
  ];
695
716
  };
@@ -27,7 +27,10 @@ import {
27
27
  type DataCubeQuerySnapshotGroupBy,
28
28
  _getCol,
29
29
  } from '../core/DataCubeQuerySnapshot.js';
30
- import { GridClientSortDirection } from './DataCubeGridClientEngine.js';
30
+ import {
31
+ GridClientSortDirection,
32
+ INTERNAL__GRID_CLIENT_TREE_COLUMN_ID,
33
+ } from './DataCubeGridClientEngine.js';
31
34
  import {
32
35
  DataCubeColumnKind,
33
36
  DataCubeQuerySortOperator,
@@ -82,13 +85,20 @@ export function buildQuerySnapshot(
82
85
 
83
86
  // --------------------------------- SORT ---------------------------------
84
87
 
85
- snapshot.data.sortColumns = request.sortModel.map((item) => ({
86
- ..._getCol(baseSnapshot.stageCols('sort'), item.colId),
87
- operation:
88
- item.sort === GridClientSortDirection.ASCENDING
89
- ? DataCubeQuerySortOperator.ASCENDING
90
- : DataCubeQuerySortOperator.DESCENDING,
91
- }));
88
+ snapshot.data.sortColumns = request.sortModel
89
+ // Make sure the tree group is not being sorted since it's a synthetic column
90
+ // the sorting state of this special column is `synthesized` by ag-grid
91
+ // so when all group by columns are sorted in the same direction, the tree group
92
+ // column will be sorted in that direction, and vice versa, when user sorts
93
+ // the tree-group, all group-by columns will be sorted in that direction
94
+ .filter((item) => item.colId !== INTERNAL__GRID_CLIENT_TREE_COLUMN_ID)
95
+ .map((item) => ({
96
+ ..._getCol(baseSnapshot.stageCols('sort'), item.colId),
97
+ operation:
98
+ item.sort === GridClientSortDirection.ASCENDING
99
+ ? DataCubeQuerySortOperator.ASCENDING
100
+ : DataCubeQuerySortOperator.DESCENDING,
101
+ }));
92
102
 
93
103
  // --------------------------------- FINALIZE ---------------------------------
94
104
 
package/tsconfig.json CHANGED
@@ -77,7 +77,6 @@
77
77
  "./src/stores/dataCube/editor/DataCubeEditorColumnPropertiesPanelState.ts",
78
78
  "./src/stores/dataCube/editor/DataCubeEditorColumnsPanelState.ts",
79
79
  "./src/stores/dataCube/editor/DataCubeEditorColumnsSelectorState.ts",
80
- "./src/stores/dataCube/editor/DataCubeEditorFilterPanelState.ts",
81
80
  "./src/stores/dataCube/editor/DataCubeEditorGeneralPropertiesPanelState.ts",
82
81
  "./src/stores/dataCube/editor/DataCubeEditorPanelState.ts",
83
82
  "./src/stores/dataCube/editor/DataCubeEditorSortsPanelState.ts",
@@ -102,11 +101,11 @@
102
101
  "./src/components/dataCube/editor/DataCubeEditorColumnsPanel.tsx",
103
102
  "./src/components/dataCube/editor/DataCubeEditorColumnsSelector.tsx",
104
103
  "./src/components/dataCube/editor/DataCubeEditorExtendedColumnsPanel.tsx",
105
- "./src/components/dataCube/editor/DataCubeEditorFilterPanel.tsx",
106
104
  "./src/components/dataCube/editor/DataCubeEditorGeneralPropertiesPanel.tsx",
107
105
  "./src/components/dataCube/editor/DataCubeEditorHorizontalPivotsPanel.tsx",
108
106
  "./src/components/dataCube/editor/DataCubeEditorSortsPanel.tsx",
109
107
  "./src/components/dataCube/editor/DataCubeEditorVerticalPivotsPanel.tsx",
108
+ "./src/components/dataCube/filter/DataCubeEditorFilter.tsx",
110
109
  "./src/components/dataCube/grid/DataCubeGrid.tsx",
111
110
  "./src/components/dataCube/grid/DataCubeGridShared.tsx",
112
111
  "./src/components/repl/Alert.tsx",
@@ -143,6 +142,7 @@
143
142
  "./src/stores/dataCube/core/filter/DataCubeQueryFilterOperation__StartWith.tsx",
144
143
  "./src/stores/dataCube/core/filter/DataCubeQueryFilterOperation__StartWithCaseInsensitive.tsx",
145
144
  "./src/stores/dataCube/editor/DataCubeEditorState.tsx",
145
+ "./src/stores/dataCube/filter/DataCubeFilterEditorState.tsx",
146
146
  "./src/stores/dataCube/grid/DataCubeGridConfigurationBuilder.tsx",
147
147
  "./src/stores/dataCube/grid/DataCubeGridMenuBuilder.tsx"
148
148
  ],
@@ -1 +0,0 @@
1
- {"version":3,"file":"DataCubeEditorFilterPanel.d.ts","sourceRoot":"","sources":["../../../../src/components/dataCube/editor/DataCubeEditorFilterPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA6BH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2CAA2C,CAAC;AAywB/E,eAAO,MAAM,yBAAyB,WAC5B;IAAE,QAAQ,EAAE,aAAa,CAAA;CAAE;;CAgEpC,CAAC"}