@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.
Files changed (90) hide show
  1. package/base.css +7 -2
  2. package/base.css.map +1 -1
  3. package/index.css +9 -2
  4. package/index.css.map +1 -1
  5. package/package.json +2 -2
  6. package/src/AdaptableInterfaces/IAdaptable.d.ts +8 -1
  7. package/src/AdaptableOptions/AdaptableOptions.d.ts +1 -1
  8. package/src/Api/ConfigApi.d.ts +1 -1
  9. package/src/Api/GridApi.d.ts +4 -0
  10. package/src/Api/Implementation/CommentsApiImpl.d.ts +4 -0
  11. package/src/Api/Implementation/CommentsApiImpl.js +5 -0
  12. package/src/Api/Implementation/ConfigApiImpl.js +6 -3
  13. package/src/Api/Implementation/GridApiImpl.d.ts +1 -0
  14. package/src/Api/Implementation/GridApiImpl.js +13 -0
  15. package/src/Api/Implementation/LayoutApiImpl.d.ts +2 -4
  16. package/src/Api/Implementation/LayoutApiImpl.js +15 -14
  17. package/src/Api/Implementation/NotesApiImpl.d.ts +4 -0
  18. package/src/Api/Implementation/NotesApiImpl.js +5 -0
  19. package/src/Api/Implementation/ScopeApiImpl.d.ts +2 -0
  20. package/src/Api/Implementation/ScopeApiImpl.js +20 -7
  21. package/src/Api/Internal/CalculatedColumnInternalApi.js +1 -1
  22. package/src/Api/Internal/CommentsInternalApi.d.ts +4 -0
  23. package/src/Api/Internal/CommentsInternalApi.js +13 -0
  24. package/src/Api/Internal/FormatColumnInternalApi.js +3 -2
  25. package/src/Api/Internal/FreeTextColumnInternalApi.js +1 -1
  26. package/src/Api/Internal/NotesInternalApi.d.ts +4 -0
  27. package/src/Api/Internal/NotesInternalApi.js +13 -0
  28. package/src/Api/LayoutApi.d.ts +11 -8
  29. package/src/Api/ScopeApi.d.ts +10 -0
  30. package/src/PredefinedConfig/Common/AdaptableColumn.d.ts +4 -0
  31. package/src/PredefinedConfig/Common/AdaptableIcon.d.ts +1 -1
  32. package/src/PredefinedConfig/Common/AdaptableScope.d.ts +4 -1
  33. package/src/PredefinedConfig/Common/RowSummary.d.ts +7 -0
  34. package/src/PredefinedConfig/Common/RowSummary.js +1 -0
  35. package/src/PredefinedConfig/LayoutState.d.ts +5 -0
  36. package/src/PredefinedConfig/SystemState.d.ts +7 -0
  37. package/src/Redux/ActionsReducers/LayoutRedux.d.ts +9 -0
  38. package/src/Redux/ActionsReducers/LayoutRedux.js +20 -0
  39. package/src/Redux/ActionsReducers/SystemRedux.d.ts +5 -0
  40. package/src/Redux/ActionsReducers/SystemRedux.js +13 -1
  41. package/src/Redux/Store/AdaptableStore.js +11 -0
  42. package/src/Redux/Store/Interface/IAdaptableStore.d.ts +2 -2
  43. package/src/Strategy/CellSummaryModule.d.ts +1 -0
  44. package/src/Strategy/CellSummaryModule.js +50 -21
  45. package/src/Strategy/CommentsModule.js +3 -0
  46. package/src/Strategy/LayoutModule.d.ts +7 -0
  47. package/src/Strategy/LayoutModule.js +102 -3
  48. package/src/Strategy/NotesModule.js +3 -4
  49. package/src/Utilities/ExpressionFunctions/aggregatedScalarExpressionFunctions.d.ts +2 -1
  50. package/src/Utilities/ExpressionFunctions/aggregatedScalarExpressionFunctions.js +294 -0
  51. package/src/Utilities/ExpressionFunctions/scalarAggregationHelper.js +1 -1
  52. package/src/Utilities/Extensions/ArrayExtensions.d.ts +2 -0
  53. package/src/Utilities/Extensions/ArrayExtensions.js +4 -0
  54. package/src/Utilities/ObjectFactory.js +6 -6
  55. package/src/Utilities/Services/AggregatedScalarLiveValue.d.ts +3 -2
  56. package/src/Utilities/Services/AggregatedScalarLiveValue.js +11 -8
  57. package/src/Utilities/Services/Interface/IQueryLanguageService.d.ts +1 -1
  58. package/src/Utilities/Services/LicenseService/index.js +10 -5
  59. package/src/Utilities/Services/QueryLanguageService.d.ts +1 -1
  60. package/src/Utilities/Services/QueryLanguageService.js +2 -1
  61. package/src/Utilities/Services/SummaryService.d.ts +19 -0
  62. package/src/Utilities/Services/SummaryService.js +29 -0
  63. package/src/View/AdaptableView.js +1 -1
  64. package/src/View/Components/AdaptableDateInput/index.d.ts +1 -1
  65. package/src/View/Components/NewScopeComponent.js +32 -1
  66. package/src/View/Components/Popups/AdaptableToaster.js +1 -1
  67. package/src/View/DataChangeHistory/DataChangeHistoryGrid.js +7 -7
  68. package/src/View/Layout/TransposedPopup.js +7 -6
  69. package/src/agGrid/ActionColumnRenderer.js +3 -2
  70. package/src/agGrid/AdaptableAgGrid.d.ts +16 -2
  71. package/src/agGrid/AdaptableAgGrid.js +201 -91
  72. package/src/agGrid/AgGridAdapter.d.ts +1 -0
  73. package/src/agGrid/AgGridAdapter.js +8 -0
  74. package/src/agGrid/AgGridColumnAdapter.js +14 -3
  75. package/src/components/ColorPicker/ColorPicker.d.ts +1 -1
  76. package/src/components/Datepicker/index.d.ts +1 -1
  77. package/src/components/Input/index.d.ts +1 -1
  78. package/src/components/List/ListGroupItem/index.d.ts +1 -1
  79. package/src/components/icons/index.js +2 -0
  80. package/src/components/icons/rows.d.ts +3 -0
  81. package/src/components/icons/rows.js +4 -0
  82. package/src/env.js +2 -2
  83. package/src/metamodel/adaptable.metamodel.d.ts +8 -0
  84. package/src/metamodel/adaptable.metamodel.js +18 -0
  85. package/src/parser/src/types.d.ts +5 -0
  86. package/tsconfig.esm.tsbuildinfo +1 -1
  87. package/src/View/Components/ScopeComponent.d.ts +0 -24
  88. package/src/View/Components/ScopeComponent.js +0 -133
  89. package/src/View/Export/Wizard/ReportScopeWizard.d.ts +0 -17
  90. 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 JSON.parse(JSON.stringify(initReducers(reducers)));
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: false,
32
- Resizable: false,
31
+ Filterable: true,
32
+ Resizable: true,
33
33
  Groupable: false,
34
- Sortable: false,
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: false,
258
- Resizable: false,
257
+ Filterable: true,
258
+ Resizable: true,
259
259
  Groupable: false,
260
- Sortable: false,
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
- private getGlobalAggregatedValue;
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 = this.adaptableApi.gridApi.getAllRowNodes({
74
- filterFn: expressionEvaluation.rowFilterFn,
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
- return aggregate(expressionEvaluation.aggregationParams, aggregatedRowNodes);
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 origin = typeof window !== 'undefined' ? window.location.origin : '';
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(origin) || []);
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(origin) || []);
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(origin) || []);
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
- this.init();
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, limit: adaptableOptions.notificationsOptions.maxNotifications, closeButton: false, icon: false, theme: "colored" }),
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),