@finos/legend-query-builder 4.14.25 → 4.14.27

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 (27) hide show
  1. package/lib/components/QueryBuilderConstantExpressionPanel.d.ts.map +1 -1
  2. package/lib/components/QueryBuilderConstantExpressionPanel.js +20 -8
  3. package/lib/components/QueryBuilderConstantExpressionPanel.js.map +1 -1
  4. package/lib/components/QueryBuilderParametersPanel.d.ts.map +1 -1
  5. package/lib/components/QueryBuilderParametersPanel.js +18 -14
  6. package/lib/components/QueryBuilderParametersPanel.js.map +1 -1
  7. package/lib/components/result/tds/QueryBuilderTDSGridResult.d.ts +4 -0
  8. package/lib/components/result/tds/QueryBuilderTDSGridResult.d.ts.map +1 -1
  9. package/lib/components/result/tds/QueryBuilderTDSGridResult.js +126 -37
  10. package/lib/components/result/tds/QueryBuilderTDSGridResult.js.map +1 -1
  11. package/lib/components/shared/BasicValueSpecificationEditor.d.ts +2 -2
  12. package/lib/components/shared/BasicValueSpecificationEditor.d.ts.map +1 -1
  13. package/lib/components/shared/BasicValueSpecificationEditor.js +12 -11
  14. package/lib/components/shared/BasicValueSpecificationEditor.js.map +1 -1
  15. package/lib/index.css +2 -2
  16. package/lib/index.css.map +1 -1
  17. package/lib/package.json +1 -1
  18. package/lib/stores/QueryBuilderResultState.d.ts +12 -0
  19. package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
  20. package/lib/stores/QueryBuilderResultState.js +68 -4
  21. package/lib/stores/QueryBuilderResultState.js.map +1 -1
  22. package/package.json +5 -5
  23. package/src/components/QueryBuilderConstantExpressionPanel.tsx +37 -21
  24. package/src/components/QueryBuilderParametersPanel.tsx +14 -9
  25. package/src/components/result/tds/QueryBuilderTDSGridResult.tsx +188 -11
  26. package/src/components/shared/BasicValueSpecificationEditor.tsx +69 -49
  27. package/src/stores/QueryBuilderResultState.ts +82 -4
@@ -14,11 +14,10 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { clsx } from '@finos/legend-art';
18
17
  import { observer } from 'mobx-react-lite';
19
18
  import type { QueryBuilderState } from '../../../stores/QueryBuilderState.js';
20
19
  import { PRIMITIVE_TYPE, type TDSExecutionResult } from '@finos/legend-graph';
21
- import { useState, useCallback } from 'react';
20
+ import { useState, useCallback, useEffect } from 'react';
22
21
  import {
23
22
  DataGrid,
24
23
  type DataGridApi,
@@ -28,23 +27,45 @@ import {
28
27
  type DataGridGetContextMenuItemsParams,
29
28
  type DataGridIRowNode,
30
29
  type DataGridMenuItemDef,
30
+ type DataGridIAggFuncParams,
31
31
  } from '@finos/legend-lego/data-grid';
32
32
  import {
33
33
  getRowDataFromExecutionResult,
34
34
  type IQueryRendererParamsWithGridType,
35
35
  filterByOrOutValues,
36
36
  } from './QueryBuilderTDSResultShared.js';
37
- import type {
38
- QueryBuilderResultState,
39
- QueryBuilderTDSResultCellData,
40
- QueryBuilderTDSResultCellDataType,
41
- QueryBuilderTDSRowDataType,
37
+ import {
38
+ type QueryBuilderResultState,
39
+ QueryBuilderResultWavgAggregationState,
40
+ type QueryBuilderTDSResultCellData,
41
+ type QueryBuilderTDSResultCellDataType,
42
+ type QueryBuilderTDSRowDataType,
42
43
  } from '../../../stores/QueryBuilderResultState.js';
43
44
  import { QueryBuilderTDSState } from '../../../stores/fetch-structure/tds/QueryBuilderTDSState.js';
44
45
  import { DEFAULT_LOCALE } from '../../../graph-manager/QueryBuilderConst.js';
45
- import { isNumber, isString, isValidURL } from '@finos/legend-shared';
46
+ import {
47
+ assertErrorThrown,
48
+ isNumber,
49
+ isString,
50
+ isValidURL,
51
+ } from '@finos/legend-shared';
46
52
  import { useApplicationStore } from '@finos/legend-application';
47
53
  import { QUERY_BUILDER_TEST_ID } from '../../../__lib__/QueryBuilderTesting.js';
54
+ import {
55
+ clsx,
56
+ Modal,
57
+ ModalBody,
58
+ ModalHeader,
59
+ ModalFooter,
60
+ ModalFooterButton,
61
+ Dialog,
62
+ CustomSelectorInput,
63
+ } from '@finos/legend-art';
64
+
65
+ export const enum QueryBuilderDataGridCustomAggregationFunction {
66
+ wavg = 'wavg',
67
+ WAVG = 'WAVG',
68
+ }
48
69
 
49
70
  const getAggregationTDSColumnCustomizations = (
50
71
  result: TDSExecutionResult,
@@ -71,7 +92,7 @@ const getAggregationTDSColumnCustomizations = (
71
92
  case PRIMITIVE_TYPE.FLOAT:
72
93
  return {
73
94
  filter: 'agNumberColumnFilter',
74
- allowedAggFuncs: ['count', 'sum', 'max', 'min', 'avg'],
95
+ allowedAggFuncs: ['count', 'sum', 'max', 'min', 'avg', 'wavg'],
75
96
  };
76
97
  default:
77
98
  return {
@@ -222,16 +243,19 @@ export const QueryBuilderTDSGridResult = observer(
222
243
  }) => {
223
244
  const { executionResult, queryBuilderState } = props;
224
245
  const applicationStore = useApplicationStore();
246
+ const darkMode =
247
+ !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled;
225
248
  const [columnAPi, setColumnApi] = useState<DataGridColumnApi | undefined>(
226
249
  undefined,
227
250
  );
251
+ const [aggFuncParams, setAggFuncParams] = useState<
252
+ DataGridIAggFuncParams | undefined
253
+ >(undefined);
228
254
  const resultState = queryBuilderState.resultState;
229
255
  const isLocalModeEnabled = queryBuilderState.isLocalModeEnabled;
230
256
  const colDefs = isLocalModeEnabled
231
257
  ? getLocalColDefs(executionResult, resultState)
232
258
  : getColDefs(executionResult, resultState);
233
- const darkMode =
234
- !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled;
235
259
 
236
260
  const onSaveGridColumnState = (): void => {
237
261
  if (!columnAPi) {
@@ -242,6 +266,10 @@ export const QueryBuilderTDSGridResult = observer(
242
266
  isPivotModeEnabled: columnAPi.isPivotMode(),
243
267
  isLocalModeEnabled: true,
244
268
  previewLimit: resultState.previewLimit,
269
+ ...(resultState.wavgAggregationState?.weightedColumnIdPairs && {
270
+ weightedColumnPairs:
271
+ resultState.wavgAggregationState.weightedColumnIdPairs,
272
+ }),
245
273
  });
246
274
  };
247
275
 
@@ -336,6 +364,103 @@ export const QueryBuilderTDSGridResult = observer(
336
364
  ],
337
365
  );
338
366
 
367
+ const weightedColumnOptions = columnAPi
368
+ ?.getColumns()
369
+ ?.filter((c) => c.getColDef().cellDataType === 'number')
370
+ .map((col) => ({
371
+ label: col.getColId(),
372
+ value: col.getColId(),
373
+ }));
374
+
375
+ const selectedWeightedColumn =
376
+ aggFuncParams?.colDef.field &&
377
+ resultState.wavgAggregationState?.weightedColumnIdPairs.get(
378
+ aggFuncParams.colDef.field,
379
+ )
380
+ ? {
381
+ label: resultState.wavgAggregationState.weightedColumnIdPairs.get(
382
+ aggFuncParams.colDef.field,
383
+ ),
384
+ value: resultState.wavgAggregationState.weightedColumnIdPairs.get(
385
+ aggFuncParams.colDef.field,
386
+ ),
387
+ }
388
+ : null;
389
+
390
+ const onWeightedColumnOptionChange = async (
391
+ option: { label: string; value: string } | null,
392
+ ): Promise<void> => {
393
+ if (aggFuncParams?.colDef.field && option?.value) {
394
+ resultState.wavgAggregationState?.addWeightedColumnIdPair(
395
+ aggFuncParams.colDef.field,
396
+ option.value,
397
+ );
398
+ }
399
+ };
400
+
401
+ const weightedAverage = (param: DataGridIAggFuncParams): void => {
402
+ if (param.colDef.field) {
403
+ if (!resultState.wavgAggregationState) {
404
+ resultState.setWavgAggregationState(
405
+ new QueryBuilderResultWavgAggregationState(),
406
+ );
407
+ }
408
+ resultState.wavgAggregationState?.addWeightedColumnIdPair(
409
+ param.colDef.field,
410
+ param.colDef.field,
411
+ );
412
+ resultState.wavgAggregationState?.setIsApplyingWavg(true);
413
+ setAggFuncParams(param);
414
+ } else {
415
+ applicationStore.notificationService.notifyError(
416
+ 'The id of this column can`t be retrieved to perform weighted average',
417
+ );
418
+ }
419
+ };
420
+
421
+ const weightedAverageHelper = (param: DataGridIAggFuncParams): number => {
422
+ try {
423
+ const column = param.colDef.field;
424
+ if (column) {
425
+ const weightedColumnId =
426
+ resultState.wavgAggregationState?.weightedColumnIdPairs.get(column);
427
+ if (weightedColumnId) {
428
+ const weightedColumnSum = param.rowNode.allLeafChildren
429
+ .map((node) => node.data[weightedColumnId])
430
+ .reduce((a, b) => a + b) as number;
431
+ const weightedColumnMultiply = param.rowNode.allLeafChildren
432
+ .map((node) => node.data[weightedColumnId] * node.data[column])
433
+ .reduce((a, b) => a + b);
434
+ if (weightedColumnSum !== 0) {
435
+ onSaveGridColumnState();
436
+ return weightedColumnMultiply / weightedColumnSum;
437
+ } else {
438
+ applicationStore.notificationService.notifyError(
439
+ 'The weighted column sum is 0',
440
+ );
441
+ }
442
+ } else {
443
+ applicationStore.notificationService.notifyError(
444
+ 'The weighted column Id is not defined',
445
+ );
446
+ }
447
+ }
448
+ } catch (error) {
449
+ assertErrorThrown(error);
450
+ applicationStore.notificationService.notifyError(error);
451
+ }
452
+ return -1;
453
+ };
454
+
455
+ useEffect(() => {
456
+ if (aggFuncParams) {
457
+ aggFuncParams.columnApi.setColumnAggFunc(
458
+ aggFuncParams.colDef.field!,
459
+ QueryBuilderDataGridCustomAggregationFunction.WAVG,
460
+ );
461
+ }
462
+ }, [resultState.wavgAggregationState, aggFuncParams]);
463
+
339
464
  return (
340
465
  <div
341
466
  data-testid={QUERY_BUILDER_TEST_ID.QUERY_BUILDER_RESULT_VALUES_TDS}
@@ -372,6 +497,10 @@ export const QueryBuilderTDSGridResult = observer(
372
497
  suppressFieldDotNotation={true}
373
498
  suppressContextMenu={false}
374
499
  columnDefs={colDefs}
500
+ aggFuncs={{
501
+ wavg: weightedAverage,
502
+ WAVG: weightedAverageHelper,
503
+ }}
375
504
  sideBar={['columns', 'filters']}
376
505
  onColumnVisible={onSaveGridColumnState}
377
506
  onColumnPinned={onSaveGridColumnState}
@@ -411,6 +540,54 @@ export const QueryBuilderTDSGridResult = observer(
411
540
  }
412
541
  />
413
542
  )}
543
+ {resultState.wavgAggregationState?.isApplyingWavg && (
544
+ <Dialog
545
+ open={resultState.wavgAggregationState.isApplyingWavg}
546
+ onClose={() =>
547
+ resultState.wavgAggregationState?.setIsApplyingWavg(false)
548
+ }
549
+ classes={{
550
+ root: 'editor-modal__root-container',
551
+ container: 'editor-modal__container',
552
+ paper: 'editor-modal__content',
553
+ }}
554
+ >
555
+ <Modal
556
+ darkMode={
557
+ !applicationStore.layoutService
558
+ .TEMPORARY__isLightColorThemeEnabled
559
+ }
560
+ className="query-editor__blocking-alert"
561
+ >
562
+ <ModalHeader title="Applying Weighted Average" />
563
+ <ModalBody>
564
+ <div className="query-builder__result__tds-grid__text">
565
+ choose a weighted column from dropdown
566
+ </div>
567
+ <CustomSelectorInput
568
+ options={weightedColumnOptions}
569
+ onChange={onWeightedColumnOptionChange}
570
+ value={selectedWeightedColumn}
571
+ placeholder={'Choose a weighted column'}
572
+ darkMode={
573
+ !applicationStore.layoutService
574
+ .TEMPORARY__isLightColorThemeEnabled
575
+ }
576
+ />
577
+ </ModalBody>
578
+ <ModalFooter>
579
+ <ModalFooterButton
580
+ onClick={() => {
581
+ resultState.wavgAggregationState?.setIsApplyingWavg(
582
+ false,
583
+ );
584
+ }}
585
+ text="Apply"
586
+ />
587
+ </ModalFooter>
588
+ </Modal>
589
+ </Dialog>
590
+ )}
414
591
  </div>
415
592
  </div>
416
593
  );
@@ -70,7 +70,13 @@ import {
70
70
  } from '@finos/legend-shared';
71
71
  import { flowResult } from 'mobx';
72
72
  import { observer } from 'mobx-react-lite';
73
- import { useEffect, useRef, useState } from 'react';
73
+ import {
74
+ forwardRef,
75
+ useEffect,
76
+ useImperativeHandle,
77
+ useRef,
78
+ useState,
79
+ } from 'react';
74
80
  import {
75
81
  instanceValue_setValue,
76
82
  instanceValue_setValues,
@@ -204,23 +210,26 @@ const VariableExpressionParameterEditor = observer(
204
210
  );
205
211
 
206
212
  const StringPrimitiveInstanceValueEditor = observer(
207
- (props: {
208
- valueSpecification: PrimitiveInstanceValue;
209
- className?: string | undefined;
210
- setValueSpecification: (val: ValueSpecification) => void;
211
- resetValue: () => void;
212
- selectorConfig?:
213
- | {
214
- values: string[] | undefined;
215
- isLoading: boolean;
216
- reloadValues:
217
- | DebouncedFunc<(inputValue: string) => GeneratorFn<void>>
218
- | undefined;
219
- cleanUpReloadValues?: () => void;
220
- }
221
- | undefined;
222
- obseverContext: ObserverContext;
223
- }) => {
213
+ forwardRef<
214
+ HTMLInputElement,
215
+ {
216
+ valueSpecification: PrimitiveInstanceValue;
217
+ className?: string | undefined;
218
+ setValueSpecification: (val: ValueSpecification) => void;
219
+ resetValue: () => void;
220
+ selectorConfig?:
221
+ | {
222
+ values: string[] | undefined;
223
+ isLoading: boolean;
224
+ reloadValues:
225
+ | DebouncedFunc<(inputValue: string) => GeneratorFn<void>>
226
+ | undefined;
227
+ cleanUpReloadValues?: () => void;
228
+ }
229
+ | undefined;
230
+ obseverContext: ObserverContext;
231
+ }
232
+ >(function StringPrimitiveInstanceValueEditor(props, ref) {
224
233
  const {
225
234
  valueSpecification,
226
235
  className,
@@ -307,6 +316,7 @@ const StringPrimitiveInstanceValueEditor = observer(
307
316
  value={value}
308
317
  placeholder={value === '' ? '(empty)' : undefined}
309
318
  onChange={changeInputValue}
319
+ ref={ref}
310
320
  />
311
321
  )}
312
322
  <button
@@ -319,7 +329,7 @@ const StringPrimitiveInstanceValueEditor = observer(
319
329
  </button>
320
330
  </div>
321
331
  );
322
- },
332
+ }),
323
333
  );
324
334
 
325
335
  const BooleanPrimitiveInstanceValueEditor = observer(
@@ -367,14 +377,17 @@ const BooleanPrimitiveInstanceValueEditor = observer(
367
377
  );
368
378
 
369
379
  const NumberPrimitiveInstanceValueEditor = observer(
370
- (props: {
371
- valueSpecification: PrimitiveInstanceValue;
372
- isInteger: boolean;
373
- className?: string | undefined;
374
- resetValue: () => void;
375
- setValueSpecification: (val: ValueSpecification) => void;
376
- obseverContext: ObserverContext;
377
- }) => {
380
+ forwardRef<
381
+ HTMLInputElement,
382
+ {
383
+ valueSpecification: PrimitiveInstanceValue;
384
+ isInteger: boolean;
385
+ className?: string | undefined;
386
+ resetValue: () => void;
387
+ setValueSpecification: (val: ValueSpecification) => void;
388
+ obseverContext: ObserverContext;
389
+ }
390
+ >(function NumberPrimitiveInstanceValueEditor(props, ref) {
378
391
  const {
379
392
  valueSpecification,
380
393
  isInteger,
@@ -387,6 +400,7 @@ const NumberPrimitiveInstanceValueEditor = observer(
387
400
  (valueSpecification.values[0] as number).toString(),
388
401
  );
389
402
  const inputRef = useRef<HTMLInputElement>(null);
403
+ useImperativeHandle(ref, () => inputRef.current as HTMLInputElement, []);
390
404
  const numericValue = isInteger
391
405
  ? Number.parseInt(Number(value).toString(), 10)
392
406
  : Number(value);
@@ -484,7 +498,7 @@ const NumberPrimitiveInstanceValueEditor = observer(
484
498
  </button>
485
499
  </div>
486
500
  );
487
- },
501
+ }),
488
502
  );
489
503
 
490
504
  const EnumValueInstanceValueEditor = observer(
@@ -947,26 +961,29 @@ const DateInstanceValueEditor = observer(
947
961
  *
948
962
  * See https://github.com/finos/legend-studio/pull/1021
949
963
  */
950
- export const BasicValueSpecificationEditor: React.FC<{
951
- valueSpecification: ValueSpecification;
952
- graph: PureModel;
953
- obseverContext: ObserverContext;
954
- typeCheckOption: TypeCheckOption;
955
- className?: string | undefined;
956
- setValueSpecification: (val: ValueSpecification) => void;
957
- resetValue: () => void;
958
- isConstant?: boolean;
959
- selectorConfig?:
960
- | {
961
- values: string[] | undefined;
962
- isLoading: boolean;
963
- reloadValues:
964
- | DebouncedFunc<(inputValue: string) => GeneratorFn<void>>
965
- | undefined;
966
- cleanUpReloadValues?: () => void;
967
- }
968
- | undefined;
969
- }> = (props) => {
964
+ export const BasicValueSpecificationEditor = forwardRef<
965
+ HTMLInputElement,
966
+ {
967
+ valueSpecification: ValueSpecification;
968
+ graph: PureModel;
969
+ obseverContext: ObserverContext;
970
+ typeCheckOption: TypeCheckOption;
971
+ className?: string | undefined;
972
+ setValueSpecification: (val: ValueSpecification) => void;
973
+ resetValue: () => void;
974
+ isConstant?: boolean;
975
+ selectorConfig?:
976
+ | {
977
+ values: string[] | undefined;
978
+ isLoading: boolean;
979
+ reloadValues:
980
+ | DebouncedFunc<(inputValue: string) => GeneratorFn<void>>
981
+ | undefined;
982
+ cleanUpReloadValues?: () => void;
983
+ }
984
+ | undefined;
985
+ }
986
+ >(function BasicValueSpecificationEditor(props, ref) {
970
987
  const {
971
988
  className,
972
989
  valueSpecification,
@@ -990,6 +1007,7 @@ export const BasicValueSpecificationEditor: React.FC<{
990
1007
  resetValue={resetValue}
991
1008
  selectorConfig={selectorConfig}
992
1009
  obseverContext={obseverContext}
1010
+ ref={ref}
993
1011
  />
994
1012
  );
995
1013
  case PRIMITIVE_TYPE.BOOLEAN:
@@ -1016,6 +1034,7 @@ export const BasicValueSpecificationEditor: React.FC<{
1016
1034
  className={className}
1017
1035
  resetValue={resetValue}
1018
1036
  obseverContext={obseverContext}
1037
+ ref={ref}
1019
1038
  />
1020
1039
  );
1021
1040
  case PRIMITIVE_TYPE.DATE:
@@ -1134,6 +1153,7 @@ export const BasicValueSpecificationEditor: React.FC<{
1134
1153
  className={className}
1135
1154
  resetValue={resetValue}
1136
1155
  obseverContext={obseverContext}
1156
+ ref={ref}
1137
1157
  />
1138
1158
  );
1139
1159
  }
@@ -1141,4 +1161,4 @@ export const BasicValueSpecificationEditor: React.FC<{
1141
1161
  }
1142
1162
 
1143
1163
  return <UnsupportedValueSpecificationEditor />;
1144
- };
1164
+ });
@@ -48,6 +48,7 @@ import { QUERY_BUILDER_EVENT } from '../__lib__/QueryBuilderEvent.js';
48
48
  import { ExecutionPlanState } from './execution-plan/ExecutionPlanState.js';
49
49
  import type { DataGridColumnState } from '@finos/legend-lego/data-grid';
50
50
  import { downloadStream } from '@finos/legend-application';
51
+ import { QueryBuilderDataGridCustomAggregationFunction } from '../components/result/tds/QueryBuilderTDSGridResult.js';
51
52
 
52
53
  export const DEFAULT_LIMIT = 1000;
53
54
 
@@ -83,8 +84,37 @@ type QueryBuilderDataGridConfig = {
83
84
  isPivotModeEnabled: boolean | undefined;
84
85
  isLocalModeEnabled: boolean | undefined;
85
86
  previewLimit?: number | undefined;
87
+ weightedColumnPairs?: Map<string, string> | undefined;
86
88
  };
87
89
 
90
+ export class QueryBuilderResultWavgAggregationState {
91
+ isApplyingWavg = false;
92
+ weightedColumnIdPairs: Map<string, string>;
93
+
94
+ constructor() {
95
+ makeObservable(this, {
96
+ isApplyingWavg: observable,
97
+ weightedColumnIdPairs: observable,
98
+ setIsApplyingWavg: action,
99
+ addWeightedColumnIdPair: action,
100
+ removeWeightedColumnIdPair: action,
101
+ });
102
+ this.weightedColumnIdPairs = new Map<string, string>();
103
+ }
104
+
105
+ setIsApplyingWavg(val: boolean): void {
106
+ this.isApplyingWavg = val;
107
+ }
108
+
109
+ addWeightedColumnIdPair(col: string, weightedColumnId: string): void {
110
+ this.weightedColumnIdPairs.set(col, weightedColumnId);
111
+ }
112
+
113
+ removeWeightedColumnIdPair(col: string): void {
114
+ this.weightedColumnIdPairs.delete(col);
115
+ }
116
+ }
117
+
88
118
  export class QueryBuilderResultState {
89
119
  readonly queryBuilderState: QueryBuilderState;
90
120
  readonly executionPlanState: ExecutionPlanState;
@@ -105,6 +135,7 @@ export class QueryBuilderResultState {
105
135
  isSelectingCells: boolean;
106
136
 
107
137
  gridConfig: QueryBuilderDataGridConfig | undefined;
138
+ wavgAggregationState: QueryBuilderResultWavgAggregationState | undefined;
108
139
 
109
140
  constructor(queryBuilderState: QueryBuilderState) {
110
141
  makeObservable(this, {
@@ -120,7 +151,9 @@ export class QueryBuilderResultState {
120
151
  isSelectingCells: observable,
121
152
  isQueryUsageViewerOpened: observable,
122
153
  gridConfig: observable,
154
+ wavgAggregationState: observable,
123
155
  setGridConfig: action,
156
+ setWavgAggregationState: action,
124
157
  setIsSelectingCells: action,
125
158
  setIsRunningQuery: action,
126
159
  setExecutionResult: action,
@@ -153,6 +186,12 @@ export class QueryBuilderResultState {
153
186
  this.gridConfig = val;
154
187
  }
155
188
 
189
+ setWavgAggregationState(
190
+ val: QueryBuilderResultWavgAggregationState | undefined,
191
+ ): void {
192
+ this.wavgAggregationState = val;
193
+ }
194
+
156
195
  setIsSelectingCells(val: boolean): void {
157
196
  this.isSelectingCells = val;
158
197
  }
@@ -199,11 +238,50 @@ export class QueryBuilderResultState {
199
238
  }
200
239
  }
201
240
 
241
+ processWeightedColumnPairsMap(
242
+ config: QueryGridConfig,
243
+ ): Map<string, string> | undefined {
244
+ if (config.weightedColumnPairs) {
245
+ const wavgColumns = config.columns
246
+ .filter(
247
+ (col) =>
248
+ (col as DataGridColumnState).aggFunc ===
249
+ QueryBuilderDataGridCustomAggregationFunction.WAVG,
250
+ )
251
+ .map((col) => (col as DataGridColumnState).colId);
252
+ const weightedColumnPairsMap = new Map<string, string>();
253
+ config.weightedColumnPairs.forEach((wc) => {
254
+ if (wc[0] && wc[1]) {
255
+ weightedColumnPairsMap.set(wc[0], wc[1]);
256
+ }
257
+ });
258
+ for (const wavgCol of weightedColumnPairsMap.keys()) {
259
+ if (!wavgColumns.includes(wavgCol)) {
260
+ weightedColumnPairsMap.delete(wavgCol);
261
+ }
262
+ }
263
+ return weightedColumnPairsMap;
264
+ }
265
+ return undefined;
266
+ }
267
+
202
268
  handlePreConfiguredGridConfig(config: QueryGridConfig): void {
203
- const newConfig = {
204
- ...config,
205
- columns: config.columns as DataGridColumnState[],
206
- };
269
+ let newConfig;
270
+ const weightedColumnPairsMap = this.processWeightedColumnPairsMap(config);
271
+ if (weightedColumnPairsMap) {
272
+ this.wavgAggregationState = new QueryBuilderResultWavgAggregationState();
273
+ this.wavgAggregationState.weightedColumnIdPairs = weightedColumnPairsMap;
274
+ newConfig = {
275
+ ...config,
276
+ weightedColumnPairs: weightedColumnPairsMap,
277
+ columns: config.columns as DataGridColumnState[],
278
+ };
279
+ } else {
280
+ newConfig = {
281
+ ...config,
282
+ columns: config.columns as DataGridColumnState[],
283
+ };
284
+ }
207
285
  if (config.previewLimit) {
208
286
  this.setPreviewLimit(config.previewLimit);
209
287
  }