@adaptabletools/adaptable 18.0.0-canary.7 → 18.0.0-canary.9
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/base.css +7 -2
- package/base.css.map +1 -1
- package/index.css +9 -2
- package/index.css.map +1 -1
- package/package.json +2 -2
- package/src/AdaptableInterfaces/IAdaptable.d.ts +8 -1
- package/src/AdaptableOptions/AdaptableOptions.d.ts +1 -1
- package/src/Api/ConfigApi.d.ts +1 -1
- package/src/Api/GridApi.d.ts +4 -0
- package/src/Api/Implementation/CommentsApiImpl.d.ts +4 -0
- package/src/Api/Implementation/CommentsApiImpl.js +5 -0
- package/src/Api/Implementation/ConfigApiImpl.js +6 -3
- package/src/Api/Implementation/GridApiImpl.d.ts +1 -0
- package/src/Api/Implementation/GridApiImpl.js +13 -0
- package/src/Api/Implementation/LayoutApiImpl.d.ts +2 -4
- package/src/Api/Implementation/LayoutApiImpl.js +15 -14
- package/src/Api/Implementation/NotesApiImpl.d.ts +4 -0
- package/src/Api/Implementation/NotesApiImpl.js +5 -0
- package/src/Api/Implementation/ScopeApiImpl.d.ts +2 -0
- package/src/Api/Implementation/ScopeApiImpl.js +20 -7
- package/src/Api/Internal/CalculatedColumnInternalApi.js +1 -1
- package/src/Api/Internal/CommentsInternalApi.d.ts +4 -0
- package/src/Api/Internal/CommentsInternalApi.js +13 -0
- package/src/Api/Internal/FormatColumnInternalApi.js +3 -2
- package/src/Api/Internal/FreeTextColumnInternalApi.js +1 -1
- package/src/Api/Internal/NotesInternalApi.d.ts +4 -0
- package/src/Api/Internal/NotesInternalApi.js +13 -0
- package/src/Api/LayoutApi.d.ts +11 -8
- package/src/Api/ScopeApi.d.ts +10 -0
- package/src/PredefinedConfig/Common/AdaptableColumn.d.ts +4 -0
- package/src/PredefinedConfig/Common/AdaptableIcon.d.ts +1 -1
- package/src/PredefinedConfig/Common/AdaptableScope.d.ts +4 -1
- package/src/PredefinedConfig/Common/RowSummary.d.ts +7 -0
- package/src/PredefinedConfig/Common/RowSummary.js +1 -0
- package/src/PredefinedConfig/LayoutState.d.ts +5 -0
- package/src/PredefinedConfig/SystemState.d.ts +7 -0
- package/src/Redux/ActionsReducers/LayoutRedux.d.ts +9 -0
- package/src/Redux/ActionsReducers/LayoutRedux.js +20 -0
- package/src/Redux/ActionsReducers/SystemRedux.d.ts +5 -0
- package/src/Redux/ActionsReducers/SystemRedux.js +13 -1
- package/src/Redux/Store/AdaptableStore.js +11 -0
- package/src/Redux/Store/Interface/IAdaptableStore.d.ts +2 -2
- package/src/Strategy/CellSummaryModule.d.ts +1 -0
- package/src/Strategy/CellSummaryModule.js +50 -21
- package/src/Strategy/CommentsModule.js +3 -0
- package/src/Strategy/LayoutModule.d.ts +7 -0
- package/src/Strategy/LayoutModule.js +102 -3
- package/src/Strategy/NotesModule.js +3 -4
- package/src/Utilities/ExpressionFunctions/aggregatedScalarExpressionFunctions.d.ts +2 -1
- package/src/Utilities/ExpressionFunctions/aggregatedScalarExpressionFunctions.js +294 -0
- package/src/Utilities/ExpressionFunctions/scalarAggregationHelper.js +1 -1
- package/src/Utilities/Extensions/ArrayExtensions.d.ts +2 -0
- package/src/Utilities/Extensions/ArrayExtensions.js +4 -0
- package/src/Utilities/ObjectFactory.js +6 -6
- package/src/Utilities/Services/AggregatedScalarLiveValue.d.ts +3 -2
- package/src/Utilities/Services/AggregatedScalarLiveValue.js +11 -8
- package/src/Utilities/Services/Interface/IQueryLanguageService.d.ts +1 -1
- package/src/Utilities/Services/LicenseService/index.js +10 -5
- package/src/Utilities/Services/QueryLanguageService.d.ts +1 -1
- package/src/Utilities/Services/QueryLanguageService.js +2 -1
- package/src/Utilities/Services/SummaryService.d.ts +19 -0
- package/src/Utilities/Services/SummaryService.js +29 -0
- package/src/View/AdaptableView.js +1 -1
- package/src/View/Components/AdaptableDateInput/index.d.ts +1 -1
- package/src/View/Components/NewScopeComponent.js +32 -1
- package/src/View/Components/Popups/AdaptableToaster.js +1 -1
- package/src/View/DataChangeHistory/DataChangeHistoryGrid.js +7 -7
- package/src/View/Layout/TransposedPopup.js +7 -6
- package/src/agGrid/ActionColumnRenderer.js +3 -2
- package/src/agGrid/AdaptableAgGrid.d.ts +16 -2
- package/src/agGrid/AdaptableAgGrid.js +201 -91
- package/src/agGrid/AgGridAdapter.d.ts +1 -0
- package/src/agGrid/AgGridAdapter.js +8 -0
- package/src/agGrid/AgGridColumnAdapter.js +14 -3
- package/src/components/ColorPicker/ColorPicker.d.ts +1 -1
- package/src/components/Datepicker/index.d.ts +1 -1
- package/src/components/Input/index.d.ts +1 -1
- package/src/components/List/ListGroupItem/index.d.ts +1 -1
- package/src/components/icons/index.js +2 -0
- package/src/components/icons/rows.d.ts +3 -0
- package/src/components/icons/rows.js +4 -0
- package/src/env.js +2 -2
- package/src/metamodel/adaptable.metamodel.d.ts +8 -0
- package/src/metamodel/adaptable.metamodel.js +18 -0
- package/src/parser/src/types.d.ts +5 -0
- package/tsconfig.esm.tsbuildinfo +1 -1
- package/src/View/Components/ScopeComponent.d.ts +0 -24
- package/src/View/Components/ScopeComponent.js +0 -133
- package/src/View/Export/Wizard/ReportScopeWizard.d.ts +0 -17
- package/src/View/Export/Wizard/ReportScopeWizard.js +0 -47
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { extractColumnParameter, extractColumnParameters, extractParameter, getNumericValue, handleColumnFunction, validateColumnType, } from './expressionFunctionUtils';
|
|
2
2
|
import { ExpressionEvaluationError } from '../../parser/src/ExpressionEvaluationError';
|
|
3
3
|
import { getTypedKeys } from '../Extensions/TypeExtensions';
|
|
4
|
+
import { SumArray } from '../Extensions/ArrayExtensions';
|
|
4
5
|
export const aggregatedExpressionFunctions = [
|
|
5
6
|
'SUM',
|
|
6
7
|
'PERCENTAGE',
|
|
@@ -11,6 +12,11 @@ export const aggregatedExpressionFunctions = [
|
|
|
11
12
|
'WEIGHT',
|
|
12
13
|
'COL',
|
|
13
14
|
'GROUP_BY',
|
|
15
|
+
'MEDIAN',
|
|
16
|
+
'MODE',
|
|
17
|
+
'DISTINCT',
|
|
18
|
+
'ONLY',
|
|
19
|
+
'STD_DEVIATION',
|
|
14
20
|
];
|
|
15
21
|
export const cumulativeAggregatedExpressionFunctions = [
|
|
16
22
|
'CUMUL',
|
|
@@ -77,6 +83,8 @@ export const aggregatedScalarExpressionFunctions = {
|
|
|
77
83
|
field: sumColumnName,
|
|
78
84
|
initialValue: 0,
|
|
79
85
|
reducer: (totalSum, rowValue) => {
|
|
86
|
+
// TODO: see why error are not concole logged
|
|
87
|
+
// debuger = 'Adaptable:*'
|
|
80
88
|
if (isUndefinedValue(rowValue)) {
|
|
81
89
|
return totalSum;
|
|
82
90
|
}
|
|
@@ -86,6 +94,7 @@ export const aggregatedScalarExpressionFunctions = {
|
|
|
86
94
|
},
|
|
87
95
|
},
|
|
88
96
|
rowFilterFn: context.filterFn,
|
|
97
|
+
getRowNodes: context.getRowNodes,
|
|
89
98
|
};
|
|
90
99
|
addGroupByParams(groupByParameter === null || groupByParameter === void 0 ? void 0 : groupByParameter.value, aggregationExpressionEvaluation);
|
|
91
100
|
const result = {
|
|
@@ -148,6 +157,7 @@ export const aggregatedScalarExpressionFunctions = {
|
|
|
148
157
|
100);
|
|
149
158
|
},
|
|
150
159
|
rowFilterFn: context.filterFn,
|
|
160
|
+
getRowNodes: context.getRowNodes,
|
|
151
161
|
};
|
|
152
162
|
addGroupByParams(groupByColumnNames, aggregationExpressionEvaluation);
|
|
153
163
|
const result = {
|
|
@@ -222,6 +232,7 @@ export const aggregatedScalarExpressionFunctions = {
|
|
|
222
232
|
},
|
|
223
233
|
},
|
|
224
234
|
rowFilterFn: context.filterFn,
|
|
235
|
+
getRowNodes: context.getRowNodes,
|
|
225
236
|
};
|
|
226
237
|
addGroupByParams(groupByParameter === null || groupByParameter === void 0 ? void 0 : groupByParameter.value, aggregationExpressionEvaluation);
|
|
227
238
|
if (weightParameter) {
|
|
@@ -246,6 +257,284 @@ export const aggregatedScalarExpressionFunctions = {
|
|
|
246
257
|
examples: ['AVG([colA])', 'AVG([colA], GROUP_BY([colB]))', 'AVG([colA], WEIGHT([colB]))'],
|
|
247
258
|
category: 'aggregation',
|
|
248
259
|
},
|
|
260
|
+
MEDIAN: {
|
|
261
|
+
handler(args, context) {
|
|
262
|
+
const medianColumnParameter = extractColumnParameter('MEDIAN', args);
|
|
263
|
+
const medianColumnName = medianColumnParameter.value;
|
|
264
|
+
validateColumnType(medianColumnName, ['Number'], 'MEDIAN', context.adaptableApi);
|
|
265
|
+
const groupByParameter = extractParameter('MEDIAN', 'operand', ['GROUP_BY'], args, {
|
|
266
|
+
isOptional: true,
|
|
267
|
+
});
|
|
268
|
+
const getCellValue = (rowNode) => {
|
|
269
|
+
return context.adaptableApi.gridApi.getNormalisedValueFromRowNode(rowNode, medianColumnName);
|
|
270
|
+
};
|
|
271
|
+
const aggregationExpressionEvaluation = {
|
|
272
|
+
aggregationParams: {
|
|
273
|
+
reducers: {
|
|
274
|
+
MEDIAN: {
|
|
275
|
+
name: 'MEDIAN',
|
|
276
|
+
field: medianColumnName,
|
|
277
|
+
initialValue: [],
|
|
278
|
+
reducer: (aggregatedValue, value, rowNode) => {
|
|
279
|
+
aggregatedValue.push(rowNode);
|
|
280
|
+
return aggregatedValue;
|
|
281
|
+
},
|
|
282
|
+
done: (aggregatedValue) => {
|
|
283
|
+
if (aggregatedValue.length === 0) {
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
if (aggregatedValue.length === 1) {
|
|
287
|
+
return getCellValue(aggregatedValue[0]);
|
|
288
|
+
}
|
|
289
|
+
const lenght = aggregatedValue.length;
|
|
290
|
+
const middle = Math.floor((lenght - 1) / 2);
|
|
291
|
+
if (lenght % 2) {
|
|
292
|
+
return getCellValue(aggregatedValue[middle]);
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
return ((getCellValue(aggregatedValue[middle]) +
|
|
296
|
+
getCellValue(aggregatedValue[middle + 1])) /
|
|
297
|
+
2.0);
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
rowFilterFn: context.filterFn,
|
|
304
|
+
getRowNodes: context.getRowNodes,
|
|
305
|
+
};
|
|
306
|
+
addGroupByParams(groupByParameter === null || groupByParameter === void 0 ? void 0 : groupByParameter.value, aggregationExpressionEvaluation);
|
|
307
|
+
const result = {
|
|
308
|
+
name: 'MEDIAN',
|
|
309
|
+
type: 'aggregationScalar',
|
|
310
|
+
value: aggregationExpressionEvaluation,
|
|
311
|
+
};
|
|
312
|
+
return result;
|
|
313
|
+
},
|
|
314
|
+
description: 'Aggregates a column over multiple rows by computing the median of the column values\nOptionally the aggregation may be grouped.',
|
|
315
|
+
signatures: [
|
|
316
|
+
'MEDIAN( [colName] )',
|
|
317
|
+
'MEDIAN( COL(name: string))',
|
|
318
|
+
'MEDIAN( [colNameA], GROUP_BY( [colNameB] ))',
|
|
319
|
+
'MEDIAN( COL(nameA: string), GROUP_BY( COL(nameB: string)))',
|
|
320
|
+
],
|
|
321
|
+
examples: ['MEDIAN([colA])', 'MEDIAN([colA], GROUP_BY([colB]))'],
|
|
322
|
+
category: 'aggregation',
|
|
323
|
+
},
|
|
324
|
+
MODE: {
|
|
325
|
+
handler(args, context) {
|
|
326
|
+
const modeColumnParameter = extractColumnParameter('mode', args);
|
|
327
|
+
const modeColumnName = modeColumnParameter.value;
|
|
328
|
+
validateColumnType(modeColumnName, ['Number'], 'mode', context.adaptableApi);
|
|
329
|
+
const groupByParameter = extractParameter('MODE', 'operand', ['GROUP_BY'], args, {
|
|
330
|
+
isOptional: true,
|
|
331
|
+
});
|
|
332
|
+
const aggregationExpressionEvaluation = {
|
|
333
|
+
aggregationParams: {
|
|
334
|
+
reducers: {
|
|
335
|
+
MODE: {
|
|
336
|
+
name: 'MODE',
|
|
337
|
+
field: modeColumnName,
|
|
338
|
+
initialValue: new Map(),
|
|
339
|
+
reducer: (aggregatedValue, rowValue, rowNode) => {
|
|
340
|
+
var _a;
|
|
341
|
+
if (typeof rowValue !== 'number' && typeof rowValue !== 'string') {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
aggregatedValue.set(rowValue, ((_a = aggregatedValue.get(rowValue)) !== null && _a !== void 0 ? _a : 0) + 1);
|
|
345
|
+
return aggregatedValue;
|
|
346
|
+
},
|
|
347
|
+
done: (aggregatedValue) => {
|
|
348
|
+
const sorted = [...aggregatedValue.entries()].sort(([aVal, aFreq], [bVal, bFreq]) => {
|
|
349
|
+
if (aFreq < bFreq) {
|
|
350
|
+
return 1;
|
|
351
|
+
}
|
|
352
|
+
else if (aFreq > bFreq || aVal < bVal) {
|
|
353
|
+
return -1;
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
return aVal === bVal ? 0 : 1;
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
return sorted[0][0];
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
rowFilterFn: context.filterFn,
|
|
365
|
+
getRowNodes: context.getRowNodes,
|
|
366
|
+
};
|
|
367
|
+
addGroupByParams(groupByParameter === null || groupByParameter === void 0 ? void 0 : groupByParameter.value, aggregationExpressionEvaluation);
|
|
368
|
+
const result = {
|
|
369
|
+
name: 'MODE',
|
|
370
|
+
type: 'aggregationScalar',
|
|
371
|
+
value: aggregationExpressionEvaluation,
|
|
372
|
+
};
|
|
373
|
+
return result;
|
|
374
|
+
},
|
|
375
|
+
description: 'Aggregates a column over multiple rows by computing the mode of the column values\nOptionally the aggregation may be grouped.',
|
|
376
|
+
signatures: [
|
|
377
|
+
'MODE( [colName] )',
|
|
378
|
+
'MODE( COL(name: string))',
|
|
379
|
+
'MODE( [colNameA], GROUP_BY( [colNameB] ))',
|
|
380
|
+
'MODE( COL(nameA: string), GROUP_BY( COL(nameB: string)))',
|
|
381
|
+
],
|
|
382
|
+
examples: ['MODE([colA])', 'MODE([colA], GROUP_BY([colB]))'],
|
|
383
|
+
category: 'aggregation',
|
|
384
|
+
},
|
|
385
|
+
DISTINCT: {
|
|
386
|
+
handler(args, context) {
|
|
387
|
+
const distinctColumnParameter = extractColumnParameter('DISTINCT', args);
|
|
388
|
+
const distinctColumnName = distinctColumnParameter.value;
|
|
389
|
+
const groupByParameter = extractParameter('MODE', 'operand', ['GROUP_BY'], args, {
|
|
390
|
+
isOptional: true,
|
|
391
|
+
});
|
|
392
|
+
const aggregationExpressionEvaluation = {
|
|
393
|
+
aggregationParams: {
|
|
394
|
+
reducers: {
|
|
395
|
+
DISTINCT: {
|
|
396
|
+
name: 'DISTINCT',
|
|
397
|
+
field: distinctColumnName,
|
|
398
|
+
initialValue: new Set(),
|
|
399
|
+
reducer: (aggregatedValue, rowValue, rowNode) => {
|
|
400
|
+
if (typeof rowValue !== 'number' && typeof rowValue !== 'string') {
|
|
401
|
+
return aggregatedValue;
|
|
402
|
+
}
|
|
403
|
+
aggregatedValue.add(rowValue);
|
|
404
|
+
return aggregatedValue;
|
|
405
|
+
},
|
|
406
|
+
done: (aggregatedValue) => {
|
|
407
|
+
return aggregatedValue.size;
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
},
|
|
411
|
+
},
|
|
412
|
+
getRowNodes: context.getRowNodes,
|
|
413
|
+
};
|
|
414
|
+
addGroupByParams(groupByParameter === null || groupByParameter === void 0 ? void 0 : groupByParameter.value, aggregationExpressionEvaluation);
|
|
415
|
+
const result = {
|
|
416
|
+
name: 'DISTINCT',
|
|
417
|
+
type: 'aggregationScalar',
|
|
418
|
+
value: aggregationExpressionEvaluation,
|
|
419
|
+
};
|
|
420
|
+
return result;
|
|
421
|
+
},
|
|
422
|
+
description: 'Aggregates a column over multiple rows by computing the distinct number of the column values\nOptionally the aggregation may be grouped.',
|
|
423
|
+
signatures: [
|
|
424
|
+
'DISTINCT( [colName] )',
|
|
425
|
+
'DISTINCT( COL(name: string))',
|
|
426
|
+
'DISTINCT( [colNameA], GROUP_BY( [colNameB] ))',
|
|
427
|
+
'DISTINCT( COL(nameA: string), GROUP_BY( COL(nameB: string)))',
|
|
428
|
+
],
|
|
429
|
+
examples: ['DISTINCT([colA])', 'DISTINCT([colA], GROUP_BY([colB]))'],
|
|
430
|
+
category: 'aggregation',
|
|
431
|
+
},
|
|
432
|
+
ONLY: {
|
|
433
|
+
handler(args, context) {
|
|
434
|
+
const distinctColumnParameter = extractColumnParameter('ONLY', args);
|
|
435
|
+
const onlyColumnName = distinctColumnParameter.value;
|
|
436
|
+
validateColumnType(onlyColumnName, ['Number'], 'ONLY', context.adaptableApi);
|
|
437
|
+
const groupByParameter = extractParameter('ONLY', 'operand', ['GROUP_BY'], args, {
|
|
438
|
+
isOptional: true,
|
|
439
|
+
});
|
|
440
|
+
const aggregationExpressionEvaluation = {
|
|
441
|
+
aggregationParams: {
|
|
442
|
+
reducers: {
|
|
443
|
+
ONLY: {
|
|
444
|
+
name: 'ONLY',
|
|
445
|
+
field: onlyColumnName,
|
|
446
|
+
initialValue: new Set(),
|
|
447
|
+
reducer: (aggregatedValue, rowValue, rowNode) => {
|
|
448
|
+
if (typeof rowValue !== 'number' && typeof rowValue !== 'string') {
|
|
449
|
+
return aggregatedValue;
|
|
450
|
+
}
|
|
451
|
+
aggregatedValue.add(rowValue);
|
|
452
|
+
return aggregatedValue;
|
|
453
|
+
},
|
|
454
|
+
done: (aggregatedValue) => {
|
|
455
|
+
return aggregatedValue.size === 1 ? aggregatedValue.values().next().value : null;
|
|
456
|
+
},
|
|
457
|
+
},
|
|
458
|
+
},
|
|
459
|
+
},
|
|
460
|
+
rowFilterFn: context.filterFn,
|
|
461
|
+
getRowNodes: context.getRowNodes,
|
|
462
|
+
};
|
|
463
|
+
addGroupByParams(groupByParameter === null || groupByParameter === void 0 ? void 0 : groupByParameter.value, aggregationExpressionEvaluation);
|
|
464
|
+
const result = {
|
|
465
|
+
name: 'ONLY',
|
|
466
|
+
type: 'aggregationScalar',
|
|
467
|
+
value: aggregationExpressionEvaluation,
|
|
468
|
+
};
|
|
469
|
+
return result;
|
|
470
|
+
},
|
|
471
|
+
description: 'Aggregates a column over multiple rows by computing to a value that is common to all rows. \nOptionally the aggregation may be grouped.',
|
|
472
|
+
signatures: [
|
|
473
|
+
'ONLY( [colName] )',
|
|
474
|
+
'ONLY( COL(name: string))',
|
|
475
|
+
'ONLY( [colNameA], GROUP_BY( [colNameB] ))',
|
|
476
|
+
'ONLY( COL(nameA: string), GROUP_BY( COL(nameB: string)))',
|
|
477
|
+
],
|
|
478
|
+
examples: ['ONLY([colA])', 'ONLY([colA], GROUP_BY([colB]))'],
|
|
479
|
+
category: 'aggregation',
|
|
480
|
+
},
|
|
481
|
+
STD_DEVIATION: {
|
|
482
|
+
handler(args, context) {
|
|
483
|
+
const columnParameter = extractColumnParameter('STD_DEVIATION', args);
|
|
484
|
+
const columnName = columnParameter.value;
|
|
485
|
+
validateColumnType(columnName, ['Number'], 'STD_DEVIATION', context.adaptableApi);
|
|
486
|
+
const groupByParameter = extractParameter('STD_DEVIATION', 'operand', ['GROUP_BY'], args, {
|
|
487
|
+
isOptional: true,
|
|
488
|
+
});
|
|
489
|
+
const aggregationExpressionEvaluation = {
|
|
490
|
+
aggregationParams: {
|
|
491
|
+
reducers: {
|
|
492
|
+
STD_DEVIATION: {
|
|
493
|
+
name: 'STD_DEVIATION',
|
|
494
|
+
field: columnName,
|
|
495
|
+
initialValue: { sumOfValues: 0, values: [] },
|
|
496
|
+
reducer: (aggregatedValue, rowValue, rowNode) => {
|
|
497
|
+
// TODO: getNumericValue; allow numeric strings
|
|
498
|
+
if (typeof rowValue !== 'number' || isNaN(rowValue)) {
|
|
499
|
+
return aggregatedValue;
|
|
500
|
+
}
|
|
501
|
+
aggregatedValue.sumOfValues = aggregatedValue.sumOfValues + rowValue;
|
|
502
|
+
aggregatedValue.values.push(rowValue);
|
|
503
|
+
return aggregatedValue;
|
|
504
|
+
},
|
|
505
|
+
done: (aggregatedValue) => {
|
|
506
|
+
const { sumOfValues, values } = aggregatedValue;
|
|
507
|
+
if (values.length === 0) {
|
|
508
|
+
return 0;
|
|
509
|
+
}
|
|
510
|
+
const mean = sumOfValues / values.length;
|
|
511
|
+
const variance = SumArray(values.map((value) => Math.pow(value - mean, 2))) / values.length;
|
|
512
|
+
return Math.sqrt(variance);
|
|
513
|
+
},
|
|
514
|
+
},
|
|
515
|
+
},
|
|
516
|
+
},
|
|
517
|
+
rowFilterFn: context.filterFn,
|
|
518
|
+
getRowNodes: context.getRowNodes,
|
|
519
|
+
};
|
|
520
|
+
addGroupByParams(groupByParameter === null || groupByParameter === void 0 ? void 0 : groupByParameter.value, aggregationExpressionEvaluation);
|
|
521
|
+
const result = {
|
|
522
|
+
name: 'STD_DEVIATION',
|
|
523
|
+
type: 'aggregationScalar',
|
|
524
|
+
value: aggregationExpressionEvaluation,
|
|
525
|
+
};
|
|
526
|
+
return result;
|
|
527
|
+
},
|
|
528
|
+
description: 'Aggregates a column over multiple rows by computing to a value that is common to all rows. \nOptionally the aggregation may be grouped.',
|
|
529
|
+
signatures: [
|
|
530
|
+
'ONLY( [colName] )',
|
|
531
|
+
'ONLY( COL(name: string))',
|
|
532
|
+
'ONLY( [colNameA], GROUP_BY( [colNameB] ))',
|
|
533
|
+
'ONLY( COL(nameA: string), GROUP_BY( COL(nameB: string)))',
|
|
534
|
+
],
|
|
535
|
+
examples: ['ONLY([colA])', 'ONLY([colA], GROUP_BY([colB]))'],
|
|
536
|
+
category: 'aggregation',
|
|
537
|
+
},
|
|
249
538
|
MIN: {
|
|
250
539
|
handler(args, context) {
|
|
251
540
|
const minColumnParameter = extractColumnParameter('MIN', args);
|
|
@@ -277,6 +566,7 @@ export const aggregatedScalarExpressionFunctions = {
|
|
|
277
566
|
},
|
|
278
567
|
},
|
|
279
568
|
rowFilterFn: context.filterFn,
|
|
569
|
+
getRowNodes: context.getRowNodes,
|
|
280
570
|
};
|
|
281
571
|
addGroupByParams(groupByParameter === null || groupByParameter === void 0 ? void 0 : groupByParameter.value, aggregationExpressionEvaluation);
|
|
282
572
|
const result = {
|
|
@@ -327,6 +617,7 @@ export const aggregatedScalarExpressionFunctions = {
|
|
|
327
617
|
},
|
|
328
618
|
},
|
|
329
619
|
rowFilterFn: context.filterFn,
|
|
620
|
+
getRowNodes: context.getRowNodes,
|
|
330
621
|
};
|
|
331
622
|
addGroupByParams(groupByParameter === null || groupByParameter === void 0 ? void 0 : groupByParameter.value, aggregationExpressionEvaluation);
|
|
332
623
|
const result = {
|
|
@@ -445,6 +736,7 @@ export const aggregatedScalarExpressionFunctions = {
|
|
|
445
736
|
const rowValue = context.adaptableApi.gridApi.getRawValueFromRowNode(rowNode, quantileColumnName);
|
|
446
737
|
return isDefinedValue(rowValue);
|
|
447
738
|
},
|
|
739
|
+
getRowNodes: context.getRowNodes,
|
|
448
740
|
aggregationParams: {
|
|
449
741
|
reducers: {
|
|
450
742
|
QUANT: Object.assign({ name: 'QUANT', field: quantileColumnName }, quantReducer),
|
|
@@ -523,6 +815,7 @@ export const aggregatedScalarExpressionFunctions = {
|
|
|
523
815
|
},
|
|
524
816
|
},
|
|
525
817
|
rowFilterFn: context.filterFn,
|
|
818
|
+
getRowNodes: context.getRowNodes,
|
|
526
819
|
};
|
|
527
820
|
addGroupByParams(groupByParameter === null || groupByParameter === void 0 ? void 0 : groupByParameter.value, aggregationExpressionEvaluation);
|
|
528
821
|
const result = {
|
|
@@ -745,6 +1038,7 @@ const mapAggregationToCumulation = (aggregationParameter, overColumnParameter, c
|
|
|
745
1038
|
},
|
|
746
1039
|
rowValueGetter,
|
|
747
1040
|
rowFilterFn: aggregationEvaluation.rowFilterFn,
|
|
1041
|
+
getRowNodes: context.getRowNodes,
|
|
748
1042
|
};
|
|
749
1043
|
return cumulationExpressionEvaluation;
|
|
750
1044
|
};
|
|
@@ -8,7 +8,7 @@ export function aggregate(aggregateParams, data) {
|
|
|
8
8
|
const deepMap = new DeepMap();
|
|
9
9
|
let currentGroupKeys = [];
|
|
10
10
|
const getInitialReducerValue = () => {
|
|
11
|
-
return
|
|
11
|
+
return structuredClone(initReducers(reducers));
|
|
12
12
|
};
|
|
13
13
|
const globalReducerResults = getInitialReducerValue();
|
|
14
14
|
for (let i = 0, len = data.length; i < len; i++) {
|
|
@@ -32,6 +32,7 @@ export declare function sortCellValueArrayNumeric(cellValues: GridCell[], sortOr
|
|
|
32
32
|
export declare function sortCellValueArrayDates(cellValues: GridCell[], sortOrder?: SortOrder): GridCell[];
|
|
33
33
|
export declare function groupArrayBy(array: Array<any>, prop: string): Array<any>;
|
|
34
34
|
export declare function createCommaSeparatedString(values: any[]): string;
|
|
35
|
+
export declare function SumArray(array: (number | undefined)[]): number;
|
|
35
36
|
export declare const ArrayExtensions: {
|
|
36
37
|
GetLength: typeof GetLength;
|
|
37
38
|
CorrectLength: typeof CorrectLength;
|
|
@@ -65,5 +66,6 @@ export declare const ArrayExtensions: {
|
|
|
65
66
|
sortCellValueArrayDates: typeof sortCellValueArrayDates;
|
|
66
67
|
sortArrayWithProperty: typeof sortArrayWithProperty;
|
|
67
68
|
createCommaSeparatedString: typeof createCommaSeparatedString;
|
|
69
|
+
SumArray: typeof SumArray;
|
|
68
70
|
};
|
|
69
71
|
export default ArrayExtensions;
|
|
@@ -254,6 +254,9 @@ export function groupArrayBy(array, prop) {
|
|
|
254
254
|
export function createCommaSeparatedString(values) {
|
|
255
255
|
return values.join(', ');
|
|
256
256
|
}
|
|
257
|
+
export function SumArray(array) {
|
|
258
|
+
return array.filter((num) => typeof num === 'number' && !isNaN(num)).reduce((a, b) => a + b, 0);
|
|
259
|
+
}
|
|
257
260
|
export const ArrayExtensions = {
|
|
258
261
|
GetLength,
|
|
259
262
|
CorrectLength,
|
|
@@ -287,5 +290,6 @@ export const ArrayExtensions = {
|
|
|
287
290
|
sortCellValueArrayDates,
|
|
288
291
|
sortArrayWithProperty,
|
|
289
292
|
createCommaSeparatedString,
|
|
293
|
+
SumArray,
|
|
290
294
|
};
|
|
291
295
|
export default ArrayExtensions;
|
|
@@ -28,10 +28,10 @@ export function CreateEmptyCalculatedColumn() {
|
|
|
28
28
|
// need to create some defaults - which we will change later
|
|
29
29
|
CalculatedColumnSettings: {
|
|
30
30
|
DataType: undefined,
|
|
31
|
-
Filterable:
|
|
32
|
-
Resizable:
|
|
31
|
+
Filterable: true,
|
|
32
|
+
Resizable: true,
|
|
33
33
|
Groupable: false,
|
|
34
|
-
Sortable:
|
|
34
|
+
Sortable: true,
|
|
35
35
|
Pivotable: false,
|
|
36
36
|
Aggregatable: false,
|
|
37
37
|
SuppressMenu: false,
|
|
@@ -254,10 +254,10 @@ export function CreateEmptyFreeTextColumn() {
|
|
|
254
254
|
TextEditor: 'Inline',
|
|
255
255
|
FreeTextColumnSettings: {
|
|
256
256
|
DataType: 'String',
|
|
257
|
-
Filterable:
|
|
258
|
-
Resizable:
|
|
257
|
+
Filterable: true,
|
|
258
|
+
Resizable: true,
|
|
259
259
|
Groupable: false,
|
|
260
|
-
Sortable:
|
|
260
|
+
Sortable: true,
|
|
261
261
|
Pivotable: false,
|
|
262
262
|
Aggregatable: false,
|
|
263
263
|
SuppressMenu: false,
|
|
@@ -7,6 +7,7 @@ export declare class AggregatedScalarLiveValue {
|
|
|
7
7
|
private source;
|
|
8
8
|
private requestingModule;
|
|
9
9
|
private adaptableApi;
|
|
10
|
+
private getRowNodes?;
|
|
10
11
|
private aggregationReducerName;
|
|
11
12
|
private aggregatedScalarExpression;
|
|
12
13
|
private expressionEvaluation;
|
|
@@ -15,11 +16,11 @@ export declare class AggregatedScalarLiveValue {
|
|
|
15
16
|
aggregatedScalarExpression: string;
|
|
16
17
|
}, {
|
|
17
18
|
aggregatedScalarExpressionEvaluation: AggregatedScalarExpressionEvaluation;
|
|
18
|
-
}>, requestingModule: ModuleConstants, adaptableApi: AdaptableApi);
|
|
19
|
+
}>, requestingModule: ModuleConstants, adaptableApi: AdaptableApi, getRowNodes?: () => IRowNode[]);
|
|
19
20
|
refresh(): void;
|
|
20
21
|
getAggregatedValueForRow(rowNode: IRowNode): any;
|
|
21
22
|
getAllAggregationValues(): number[];
|
|
22
23
|
private getAggregationValue;
|
|
23
|
-
|
|
24
|
+
getGlobalAggregatedValue(): any;
|
|
24
25
|
private computeAggregatedValue;
|
|
25
26
|
}
|
|
@@ -8,18 +8,18 @@ const logOnce = (message, loggingFn) => {
|
|
|
8
8
|
doOnceFlags[message] = true;
|
|
9
9
|
};
|
|
10
10
|
export class AggregatedScalarLiveValue {
|
|
11
|
-
constructor(source, requestingModule, adaptableApi) {
|
|
11
|
+
constructor(source, requestingModule, adaptableApi, getRowNodes) {
|
|
12
12
|
this.source = source;
|
|
13
13
|
this.requestingModule = requestingModule;
|
|
14
14
|
this.adaptableApi = adaptableApi;
|
|
15
|
+
this.getRowNodes = getRowNodes;
|
|
15
16
|
if (source.aggregatedScalarExpression) {
|
|
16
17
|
this.aggregatedScalarExpression = source.aggregatedScalarExpression;
|
|
17
18
|
}
|
|
18
19
|
this.expressionEvaluation = source.aggregatedScalarExpression
|
|
19
20
|
? this.adaptableApi.internalApi
|
|
20
21
|
.getQueryLanguageService()
|
|
21
|
-
.evaluateAggregatedScalarExpression(source.aggregatedScalarExpression, requestingModule)
|
|
22
|
-
.value
|
|
22
|
+
.evaluateAggregatedScalarExpression(source.aggregatedScalarExpression, requestingModule, getRowNodes).value
|
|
23
23
|
: source.aggregatedScalarExpressionEvaluation;
|
|
24
24
|
// currently we support only one reducer
|
|
25
25
|
this.aggregationReducerName = Object.keys(this.expressionEvaluation.aggregationParams.reducers)[0];
|
|
@@ -29,7 +29,7 @@ export class AggregatedScalarLiveValue {
|
|
|
29
29
|
if (this.aggregatedScalarExpression) {
|
|
30
30
|
this.expressionEvaluation = this.adaptableApi.internalApi
|
|
31
31
|
.getQueryLanguageService()
|
|
32
|
-
.evaluateAggregatedScalarExpression(this.aggregatedScalarExpression, this.requestingModule).value;
|
|
32
|
+
.evaluateAggregatedScalarExpression(this.aggregatedScalarExpression, this.requestingModule, this.getRowNodes).value;
|
|
33
33
|
}
|
|
34
34
|
// currently we support only one reducer
|
|
35
35
|
this.aggregationReducerName = Object.keys(this.expressionEvaluation.aggregationParams.reducers)[0];
|
|
@@ -70,9 +70,11 @@ export class AggregatedScalarLiveValue {
|
|
|
70
70
|
}
|
|
71
71
|
computeAggregatedValue(expressionEvaluation) {
|
|
72
72
|
var _a;
|
|
73
|
-
const gridRowNodes =
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
const gridRowNodes = expressionEvaluation.getRowNodes
|
|
74
|
+
? expressionEvaluation.getRowNodes()
|
|
75
|
+
: this.adaptableApi.gridApi.getAllRowNodes({
|
|
76
|
+
filterFn: expressionEvaluation.rowFilterFn,
|
|
77
|
+
});
|
|
76
78
|
// we iterate over the RowNode list (we need this to handle complex column values (nested values, valueGetters etc)
|
|
77
79
|
// so we will map the fieldNames to RowNode.data
|
|
78
80
|
const mapReducerValueGetter = (fieldName) => {
|
|
@@ -108,6 +110,7 @@ export class AggregatedScalarLiveValue {
|
|
|
108
110
|
return 0;
|
|
109
111
|
});
|
|
110
112
|
}
|
|
111
|
-
|
|
113
|
+
const result = aggregate(expressionEvaluation.aggregationParams, aggregatedRowNodes);
|
|
114
|
+
return result;
|
|
112
115
|
}
|
|
113
116
|
}
|
|
@@ -15,7 +15,7 @@ export interface IQueryLanguageService extends IAdaptableService {
|
|
|
15
15
|
evaluateScalarExpression(expression: string, module: AdaptableModule, rowNode: IRowNode): any;
|
|
16
16
|
evaluateObservableExpression(expression: string, module: AdaptableModule): Observable<CellDataChangedInfo | GridDataChangedInfo>;
|
|
17
17
|
evaluateAggregatedBooleanExpression(expression: string, module: AdaptableModule): BooleanAggregationParameter;
|
|
18
|
-
evaluateAggregatedScalarExpression(expression: string, module: AdaptableModule): ScalarAggregationParameter;
|
|
18
|
+
evaluateAggregatedScalarExpression(expression: string, module: AdaptableModule, getRowNodes?: () => IRowNode[]): ScalarAggregationParameter;
|
|
19
19
|
validateBoolean(expression: string, module: AdaptableModule, config?: {
|
|
20
20
|
force?: boolean;
|
|
21
21
|
}): {
|
|
@@ -22,17 +22,19 @@ export var LicenseValidityType;
|
|
|
22
22
|
const SANDPACK_REGEX = /(https):\/\/\d+\-\d+\-\d+\-(sandpack\.codesandbox\.io)/g;
|
|
23
23
|
const SANDBOX_REGEX = /(https):\/\/\S+(\.csb\.app)/g;
|
|
24
24
|
const DEMO_REGEX = /(https):\/\/\S+(\.adaptabletools\.com)/g;
|
|
25
|
-
const
|
|
25
|
+
const getOrigin = () => {
|
|
26
|
+
return typeof window !== 'undefined' ? window.location.origin : '';
|
|
27
|
+
};
|
|
26
28
|
const isInsideSandpack = () => {
|
|
27
|
-
const [_fullUrl, protocol, sandpackUrl] = Array.from(SANDPACK_REGEX.exec(
|
|
29
|
+
const [_fullUrl, protocol, sandpackUrl] = Array.from(SANDPACK_REGEX.exec(getOrigin()) || []);
|
|
28
30
|
return protocol === 'https' && sandpackUrl === 'sandpack.codesandbox.io';
|
|
29
31
|
};
|
|
30
32
|
const isInsideSandbox = () => {
|
|
31
|
-
const [_fullUrl, protocol, sandboxUrl] = Array.from(SANDBOX_REGEX.exec(
|
|
33
|
+
const [_fullUrl, protocol, sandboxUrl] = Array.from(SANDBOX_REGEX.exec(getOrigin()) || []);
|
|
32
34
|
return protocol === 'https' && sandboxUrl === '.csb.app';
|
|
33
35
|
};
|
|
34
36
|
const isDemoApp = () => {
|
|
35
|
-
const [_fullUrl, protocol, demoAppUrl] = Array.from(DEMO_REGEX.exec(
|
|
37
|
+
const [_fullUrl, protocol, demoAppUrl] = Array.from(DEMO_REGEX.exec(getOrigin()) || []);
|
|
36
38
|
return protocol === 'https' && demoAppUrl === '.adaptabletools.com';
|
|
37
39
|
};
|
|
38
40
|
export class LicenseService {
|
|
@@ -42,7 +44,10 @@ export class LicenseService {
|
|
|
42
44
|
this.packageDetails = packageDetails;
|
|
43
45
|
this.adaptable = adaptable;
|
|
44
46
|
this.adaptable.api.eventApi.on('AdaptableReady', () => {
|
|
45
|
-
|
|
47
|
+
requestAnimationFrame(() => {
|
|
48
|
+
// using a rAF because we want to make sure that the window.location.origin is available (Master/Detail is fidgity sometimes)
|
|
49
|
+
this.init();
|
|
50
|
+
});
|
|
46
51
|
});
|
|
47
52
|
}
|
|
48
53
|
init() {
|
|
@@ -16,7 +16,7 @@ export declare class QueryLanguageService implements IQueryLanguageService {
|
|
|
16
16
|
constructor(adaptableApi: AdaptableApi);
|
|
17
17
|
evaluateBooleanExpression(expression: string, module: AdaptableModule, rowNode: any): any;
|
|
18
18
|
evaluateScalarExpression(expression: string, module: AdaptableModule, rowNode: IRowNode): any;
|
|
19
|
-
evaluateAggregatedScalarExpression(expression: string, module: AdaptableModule): ScalarAggregationParameter;
|
|
19
|
+
evaluateAggregatedScalarExpression(expression: string, module: AdaptableModule, getRowNodes?: () => IRowNode[]): ScalarAggregationParameter;
|
|
20
20
|
evaluateObservableExpression(reactiveExpression: string, module: AdaptableModule): Observable<CellDataChangedInfo | GridDataChangedInfo>;
|
|
21
21
|
evaluateAggregatedBooleanExpression(aggregationExpression: string, module: AdaptableModule): BooleanAggregationParameter;
|
|
22
22
|
validateBoolean(expressionInput: string, module: AdaptableModule, config?: {
|
|
@@ -32,7 +32,7 @@ export class QueryLanguageService {
|
|
|
32
32
|
// currently scalar and boolean expressions are evaluated the same
|
|
33
33
|
return this.evaluateBooleanExpression(expression, module, rowNode);
|
|
34
34
|
}
|
|
35
|
-
evaluateAggregatedScalarExpression(expression, module) {
|
|
35
|
+
evaluateAggregatedScalarExpression(expression, module, getRowNodes) {
|
|
36
36
|
const aggregatedScalarFunctions = this.getModuleExpressionFunctionsMap(module).aggregatedScalarFunctions;
|
|
37
37
|
return parser.evaluate(expression, {
|
|
38
38
|
node: null,
|
|
@@ -41,6 +41,7 @@ export class QueryLanguageService {
|
|
|
41
41
|
adaptableId: this.adaptableApi.optionsApi.getAdaptableId(),
|
|
42
42
|
functions: aggregatedScalarFunctions,
|
|
43
43
|
evaluateCustomQueryVariable: this.evaluateCustomQueryVariable,
|
|
44
|
+
getRowNodes,
|
|
44
45
|
});
|
|
45
46
|
}
|
|
46
47
|
evaluateObservableExpression(reactiveExpression, module) {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { IRowNode } from '@ag-grid-community/core';
|
|
2
|
+
import { AggregatedScalarLiveValue } from './AggregatedScalarLiveValue';
|
|
3
|
+
import { AdaptableApi, AdaptableModule } from '../../types';
|
|
4
|
+
export declare const summarySupportedExpressions: readonly ["SUM", "AVG", "MIN", "MAX", "COUNT", "MEDIAN", "MODE", "DISTINCT", "ONLY", "STD_DEVIATION"];
|
|
5
|
+
export type SummarySupportedExpression = (typeof summarySupportedExpressions)[number];
|
|
6
|
+
export type SumaryConfig = {
|
|
7
|
+
expression: {
|
|
8
|
+
function: SummarySupportedExpression;
|
|
9
|
+
};
|
|
10
|
+
columnId: string;
|
|
11
|
+
getRowNodes?: () => IRowNode[];
|
|
12
|
+
};
|
|
13
|
+
export declare class SummaryService {
|
|
14
|
+
private adaptableApi;
|
|
15
|
+
constructor(adaptableApi: AdaptableApi);
|
|
16
|
+
evaluateExpressionValue(config: SumaryConfig, moduleId: AdaptableModule): any;
|
|
17
|
+
evaluateScalarLiveValue(config: SumaryConfig, moduleId: AdaptableModule): AggregatedScalarLiveValue;
|
|
18
|
+
destroy(): void;
|
|
19
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { AggregatedScalarLiveValue } from './AggregatedScalarLiveValue';
|
|
2
|
+
export const summarySupportedExpressions = [
|
|
3
|
+
'SUM',
|
|
4
|
+
'AVG',
|
|
5
|
+
'MIN',
|
|
6
|
+
'MAX',
|
|
7
|
+
'COUNT',
|
|
8
|
+
'MEDIAN',
|
|
9
|
+
'MODE',
|
|
10
|
+
'DISTINCT',
|
|
11
|
+
'ONLY',
|
|
12
|
+
'STD_DEVIATION',
|
|
13
|
+
];
|
|
14
|
+
export class SummaryService {
|
|
15
|
+
constructor(adaptableApi) {
|
|
16
|
+
this.adaptableApi = adaptableApi;
|
|
17
|
+
}
|
|
18
|
+
evaluateExpressionValue(config, moduleId) {
|
|
19
|
+
return this.evaluateScalarLiveValue(config, moduleId).getGlobalAggregatedValue();
|
|
20
|
+
}
|
|
21
|
+
evaluateScalarLiveValue(config, moduleId) {
|
|
22
|
+
return new AggregatedScalarLiveValue({
|
|
23
|
+
aggregatedScalarExpression: `${config.expression.function}([${config.columnId}])`,
|
|
24
|
+
}, moduleId, this.adaptableApi, config.getRowNodes);
|
|
25
|
+
}
|
|
26
|
+
destroy() {
|
|
27
|
+
this.adaptableApi = null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -31,7 +31,7 @@ class AdaptableView extends React.Component {
|
|
|
31
31
|
, {
|
|
32
32
|
// we NEEEEED!!!! this containerId, otherwise, toastify will have memory leaks when the adaptable
|
|
33
33
|
// instance is destroyed and re-created many times
|
|
34
|
-
containerId: adaptableOptions.adaptableId
|
|
34
|
+
containerId: `Toastify-${adaptableOptions.adaptableId}`, limit: adaptableOptions.notificationsOptions.maxNotifications, closeButton: false, icon: false, theme: "colored" }),
|
|
35
35
|
(watermark === null || watermark === void 0 ? void 0 : watermark.show) && React.createElement(LicenseWatermark, null, watermark === null || watermark === void 0 ? void 0 : watermark.text),
|
|
36
36
|
React.createElement(WindowPopups, null),
|
|
37
37
|
React.createElement(FormPopups, null),
|