@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.
- 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
|
}
|