@finos/legend-query-builder 4.14.25 → 4.14.27
Sign up to get free protection for your applications and to get access to all the features.
- package/lib/components/QueryBuilderConstantExpressionPanel.d.ts.map +1 -1
- package/lib/components/QueryBuilderConstantExpressionPanel.js +20 -8
- package/lib/components/QueryBuilderConstantExpressionPanel.js.map +1 -1
- package/lib/components/QueryBuilderParametersPanel.d.ts.map +1 -1
- package/lib/components/QueryBuilderParametersPanel.js +18 -14
- package/lib/components/QueryBuilderParametersPanel.js.map +1 -1
- package/lib/components/result/tds/QueryBuilderTDSGridResult.d.ts +4 -0
- package/lib/components/result/tds/QueryBuilderTDSGridResult.d.ts.map +1 -1
- package/lib/components/result/tds/QueryBuilderTDSGridResult.js +126 -37
- package/lib/components/result/tds/QueryBuilderTDSGridResult.js.map +1 -1
- package/lib/components/shared/BasicValueSpecificationEditor.d.ts +2 -2
- package/lib/components/shared/BasicValueSpecificationEditor.d.ts.map +1 -1
- package/lib/components/shared/BasicValueSpecificationEditor.js +12 -11
- package/lib/components/shared/BasicValueSpecificationEditor.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/QueryBuilderResultState.d.ts +12 -0
- package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
- package/lib/stores/QueryBuilderResultState.js +68 -4
- package/lib/stores/QueryBuilderResultState.js.map +1 -1
- package/package.json +5 -5
- package/src/components/QueryBuilderConstantExpressionPanel.tsx +37 -21
- package/src/components/QueryBuilderParametersPanel.tsx +14 -9
- package/src/components/result/tds/QueryBuilderTDSGridResult.tsx +188 -11
- package/src/components/shared/BasicValueSpecificationEditor.tsx +69 -49
- 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
|
38
|
-
QueryBuilderResultState,
|
39
|
-
|
40
|
-
|
41
|
-
|
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 {
|
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 {
|
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
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
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
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
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
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
}
|
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
|
-
|
204
|
-
|
205
|
-
|
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
|
}
|