@adaptabletools/adaptable-cjs 20.0.7-canary.1 → 20.0.7-canary.3

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 (49) hide show
  1. package/agGrid.d.ts +37 -0
  2. package/agGrid.js +39 -1
  3. package/base.css +19 -3
  4. package/base.css.map +1 -1
  5. package/index.css +17 -3
  6. package/index.css.map +1 -1
  7. package/package.json +3 -3
  8. package/src/AdaptableOptions/LayoutOptions.d.ts +3 -6
  9. package/src/AdaptableState/Common/AdaptableColumn.d.ts +14 -5
  10. package/src/AdaptableState/Common/AdaptableColumn.js +28 -1
  11. package/src/AdaptableState/Common/AggregationColumns.d.ts +10 -0
  12. package/src/AdaptableState/Common/AggregationColumns.js +13 -1
  13. package/src/AdaptableState/LayoutState.d.ts +4 -4
  14. package/src/Api/Implementation/ColumnApiImpl.d.ts +2 -2
  15. package/src/Api/Implementation/ColumnApiImpl.js +36 -3
  16. package/src/Api/Implementation/LayoutHelpers.js +7 -0
  17. package/src/Api/Internal/ColumnInternalApi.js +3 -3
  18. package/src/View/Alert/Wizard/AlertButtonsEditor.js +9 -10
  19. package/src/View/Alert/Wizard/AlertNotificationWizardSection.js +26 -25
  20. package/src/View/Components/ColumnFilter/ColumnFilter.js +1 -1
  21. package/src/View/Components/FilterForm/ListBoxFilterForm.js +6 -3
  22. package/src/View/Components/NewScopeComponent.js +2 -1
  23. package/src/View/Layout/Wizard/LayoutWizard.js +1 -1
  24. package/src/View/Layout/Wizard/sections/AggregationsSection.js +16 -1
  25. package/src/View/Layout/Wizard/sections/PivotAggregationsSection.d.ts +2 -2
  26. package/src/View/Layout/Wizard/sections/PivotAggregationsSection.js +223 -47
  27. package/src/agGrid/AdaptableAgGrid.d.ts +1 -0
  28. package/src/agGrid/AdaptableAgGrid.js +9 -1
  29. package/src/agGrid/AgGridAdapter.d.ts +1 -0
  30. package/src/agGrid/AgGridAdapter.js +9 -0
  31. package/src/components/Select/Select.js +15 -3
  32. package/src/env.js +2 -2
  33. package/src/layout-manager/src/LayoutManagerModel.d.ts +4 -4
  34. package/src/layout-manager/src/index.d.ts +1 -1
  35. package/src/layout-manager/src/index.js +41 -21
  36. package/src/layout-manager/src/isPivotAggTotalColumn.d.ts +2 -0
  37. package/src/layout-manager/src/isPivotAggTotalColumn.js +7 -0
  38. package/src/layout-manager/src/isPivotGrandTotalColumn.d.ts +2 -0
  39. package/src/layout-manager/src/isPivotGrandTotalColumn.js +7 -0
  40. package/src/layout-manager/src/isPivotGroupTotalColumn.d.ts +1 -2
  41. package/src/layout-manager/src/isPivotGroupTotalColumn.js +2 -2
  42. package/src/layout-manager/src/normalizeLayoutModel.js +0 -3
  43. package/src/layout-manager/src/simplifyLayoutModel.js +3 -0
  44. package/src/metamodel/adaptable.metamodel.d.ts +13 -7
  45. package/src/metamodel/adaptable.metamodel.js +1 -1
  46. package/src/types.d.ts +1 -1
  47. package/tsconfig.cjs.tsbuildinfo +1 -1
  48. package/src/layout-manager/src/isPivotTotalColumn.d.ts +0 -2
  49. package/src/layout-manager/src/isPivotTotalColumn.js +0 -7
@@ -183,6 +183,7 @@ const tableLayoutToTableLayoutModel = (tableLayout) => {
183
183
  }
184
184
  : undefined,
185
185
  TableAggregationColumns: TableAggregationColumns,
186
+ GrandTotalRow: tableLayout.GrandTotalRow,
186
187
  });
187
188
  if (tableLayout.RowGroupDisplayType) {
188
189
  result.RowGroupDisplayType = tableLayout.RowGroupDisplayType;
@@ -294,6 +295,12 @@ const tableLayoutModelToTableLayout = (layoutModel, defaults) => {
294
295
  else {
295
296
  delete tableLayout.TableAggregationColumns;
296
297
  }
298
+ if (layoutModel.GrandTotalRow) {
299
+ tableLayout.GrandTotalRow = layoutModel.GrandTotalRow;
300
+ }
301
+ else {
302
+ delete tableLayout.GrandTotalRow;
303
+ }
297
304
  if (layoutModel.ColumnFilters) {
298
305
  tableLayout.ColumnFilters = layoutModel.ColumnFilters;
299
306
  }
@@ -9,7 +9,7 @@ const StringExtensions_1 = tslib_1.__importDefault(require("../../Utilities/Exte
9
9
  const ColumnApiImpl_1 = require("../Implementation/ColumnApiImpl");
10
10
  const destructurePivotColumnId_1 = require("../../layout-manager/src/destructurePivotColumnId");
11
11
  const isPivotGroupTotalColumn_1 = require("../../layout-manager/src/isPivotGroupTotalColumn");
12
- const isPivotTotalColumn_1 = require("../../layout-manager/src/isPivotTotalColumn");
12
+ const isPivotAggTotalColumn_1 = require("../../layout-manager/src/isPivotAggTotalColumn");
13
13
  function getAutoRowGroupColumnIdFor(columnId) {
14
14
  return `${GeneralConstants_1.AG_GRID_GROUPED_COLUMN}-${columnId}`;
15
15
  }
@@ -226,7 +226,7 @@ class ColumnInternalApi extends ApiBase_1.ApiBase {
226
226
  aggregation: pivotValueCol.getAggFunc(),
227
227
  };
228
228
  }
229
- if ((0, isPivotGroupTotalColumn_1.isPivotGroupTotalColumn)(params.colDef)) {
229
+ if ((0, isPivotGroupTotalColumn_1.isPivotGroupTotalColumn)(params.colDef?.colId)) {
230
230
  const columnType = 'pivotGroupTotal';
231
231
  const pivotColInfo = (0, destructurePivotColumnId_1.destructurePivotColumnId)(params.colDef, {
232
232
  pivotColIds: currentPivotLayout.PivotColumns,
@@ -244,7 +244,7 @@ class ColumnInternalApi extends ApiBase_1.ApiBase {
244
244
  aggregation: params.colDef?.pivotValueColumn?.getAggFunc(),
245
245
  };
246
246
  }
247
- if ((0, isPivotTotalColumn_1.isPivotTotalColumn)(params.colDef)) {
247
+ if ((0, isPivotAggTotalColumn_1.isPivotAggTotalColumn)(params.colDef)) {
248
248
  const columnType = 'pivotAggregationTotal';
249
249
  const pivotValueCol = params.colDef.pivotValueColumn;
250
250
  const pivotColInfo = (0, destructurePivotColumnId_1.destructurePivotColumnId)(params.colDef, {
@@ -183,16 +183,15 @@ const AlertButtonsEditor = (props) => {
183
183
  return btn;
184
184
  }));
185
185
  } }),
186
- React.createElement(rebass_1.Box, { mr: 2 },
187
- React.createElement(Select_1.Select, { options: ['text', 'outlined', 'raised'].map((variant) => {
188
- return {
189
- label: StringExtensions_1.default.CapitaliseFirstLetter(variant),
190
- value: variant,
191
- };
192
- }), renderSingleValue: (option) => `Variant: ${option.label}`, value: buttonStyle?.variant, onChange: (value) => {
193
- setVariant(value);
194
- } })),
195
- React.createElement(Select_1.Select, { options: TONE_OPTIONS, onChange: (value) => {
186
+ React.createElement(Select_1.Select, { options: ['text', 'outlined', 'raised'].map((variant) => {
187
+ return {
188
+ label: StringExtensions_1.default.CapitaliseFirstLetter(variant),
189
+ value: variant,
190
+ };
191
+ }), renderSingleValue: (option) => `Variant: ${option.label}`, value: buttonStyle?.variant, onChange: (value) => {
192
+ setVariant(value);
193
+ } }),
194
+ React.createElement(Select_1.Select, { style: { marginLeft: 'var(--ab-space-2)' }, options: TONE_OPTIONS, onChange: (value) => {
196
195
  if (value === 'text') {
197
196
  setTone(null);
198
197
  return;
@@ -70,31 +70,32 @@ const AlertNotificationWizardSection = (props) => {
70
70
  React.createElement(Tabs_1.Tabs, { "data-name": "display-options", mt: 2, mb: 3, autoFocus: false },
71
71
  React.createElement(Tabs_1.Tabs.Tab, null, "Notification Options"),
72
72
  React.createElement(Tabs_1.Tabs.Content, null,
73
- React.createElement(CheckBox_1.CheckBox, { checked: data.AlertProperties?.DisplayNotification, onChange: (DisplayNotification) => {
74
- const newAlertDefinition = {
75
- ...data,
76
- AlertProperties: {
77
- ...data.AlertProperties,
78
- DisplayNotification,
79
- },
80
- };
81
- if (!DisplayNotification && typeof newAlertDefinition.AlertForm === 'object') {
82
- delete newAlertDefinition.AlertForm.Buttons;
83
- }
84
- if (DisplayNotification && newAlertDefinition.AlertForm == undefined) {
85
- newAlertDefinition.AlertForm =
86
- api.alertApi.internalApi.getDefaultAlertNotificationForm();
87
- }
88
- // make sure we have at least one button
89
- if (typeof newAlertDefinition.AlertForm === 'object' &&
90
- (!newAlertDefinition.AlertForm?.Buttons ||
91
- newAlertDefinition.AlertForm?.Buttons?.length === 0)) {
92
- newAlertDefinition.AlertForm.Buttons = [
93
- api.alertApi.internalApi.getDefaultButton(),
94
- ];
95
- }
96
- props.onChange(newAlertDefinition);
97
- } }, "Display a Notification when Alert is triggered (with action buttons)"),
73
+ React.createElement("div", null,
74
+ React.createElement(CheckBox_1.CheckBox, { checked: data.AlertProperties?.DisplayNotification, onChange: (DisplayNotification) => {
75
+ const newAlertDefinition = {
76
+ ...data,
77
+ AlertProperties: {
78
+ ...data.AlertProperties,
79
+ DisplayNotification,
80
+ },
81
+ };
82
+ if (!DisplayNotification && typeof newAlertDefinition.AlertForm === 'object') {
83
+ delete newAlertDefinition.AlertForm.Buttons;
84
+ }
85
+ if (DisplayNotification && newAlertDefinition.AlertForm == undefined) {
86
+ newAlertDefinition.AlertForm =
87
+ api.alertApi.internalApi.getDefaultAlertNotificationForm();
88
+ }
89
+ // make sure we have at least one button
90
+ if (typeof newAlertDefinition.AlertForm === 'object' &&
91
+ (!newAlertDefinition.AlertForm?.Buttons ||
92
+ newAlertDefinition.AlertForm?.Buttons?.length === 0)) {
93
+ newAlertDefinition.AlertForm.Buttons = [
94
+ api.alertApi.internalApi.getDefaultButton(),
95
+ ];
96
+ }
97
+ props.onChange(newAlertDefinition);
98
+ } }, "Display a Notification when Alert is triggered (with action buttons)")),
98
99
  data.AlertProperties?.DisplayNotification ? (typeof data.AlertForm === 'string' ? (React.createElement(rebass_1.Text, { fontSize: 2 }, "Alert buttons cannot be customized because form is dynamically driven")) : (React.createElement(AlertButtonsEditor_1.AlertButtonsEditor, { alertType: props.alertType, AlertButtons: data.AlertForm?.Buttons, api: api, adaptableAlert: adaptableAlert, onChange: (buttons) => {
99
100
  props.onChange({
100
101
  ...data,
@@ -22,7 +22,7 @@ const ColumnFilterPredicateDropdown = (props) => {
22
22
  });
23
23
  const operator = props.predicate?.operator;
24
24
  const isAndOr = operator === 'AND' || operator === 'OR';
25
- return (React.createElement(rebass_1.Box, { display: 'flex', alignItems: "center", style: {
25
+ return (React.createElement(rebass_1.Box, { display: 'flex', alignItems: "center", className: "ab-ColumnFilterPredicateDropdown", style: {
26
26
  //@ts-ignore ignore
27
27
  '--ab-cmp-input__background': 'var(--ab-color-primary)',
28
28
  } },
@@ -28,9 +28,12 @@ const ColumnValuesSelect = (props) => {
28
28
  }
29
29
  return true;
30
30
  });
31
- const component = (React.createElement(Select_1.Select, { isMulti: true, showHeaderSelectionCheckbox: true, searchable: true, closeMenuOnSelect: false, menuStyle: {
32
- minWidth: `var(--ab-cmp-select-column-menu-${column.columnId}__min-width, var(--ab-cmp-select-column-menu__min-width, 260px))`,
33
- }, ...props.selectProps, options: options, value: value, isLoading: props.isLoading, onChange: props.onChange }));
31
+ const menuStyle = React.useMemo(() => {
32
+ return {
33
+ minWidth: `var(--ab-cmp-select-column-menu-${column.columnId}__min-width, var(--ab-cmp-select-column-menu__min-width, 160px))`,
34
+ };
35
+ }, [column.columnId]);
36
+ const component = (React.createElement(Select_1.Select, { isMulti: true, showHeaderSelectionCheckbox: true, searchable: true, closeMenuOnSelect: false, menuStyle: menuStyle, ...props.selectProps, options: options, value: value, isLoading: props.isLoading, onChange: props.onChange }));
34
37
  return (React.createElement("div", { className: (0, join_1.default)(baseClassName, props.isLoading && `${baseClassName}--loading`, !value.length && `${baseClassName}--empty`), onKeyDownCapture: (e) => {
35
38
  const event = e.nativeEvent || e;
36
39
  event.stopPropagation = () => {
@@ -13,6 +13,7 @@ const ColumnSelector_1 = require("./ColumnSelector");
13
13
  const AdaptableFormControlTextClear_1 = require("./Forms/AdaptableFormControlTextClear");
14
14
  const AdaptableContext_1 = require("../AdaptableContext");
15
15
  const ValueSelector_1 = require("./ValueSelector");
16
+ const AdaptableColumn_1 = require("../../AdaptableState/Common/AdaptableColumn");
16
17
  const isScopeValid = ({ Scope }) => {
17
18
  const result = [];
18
19
  if (!Scope) {
@@ -181,6 +182,6 @@ const NewScopeComponent = (props) => {
181
182
  ColumnTypes: columnTypes,
182
183
  };
183
184
  props.updateScope(newScope);
184
- } }, columnType)))))))));
185
+ } }, (0, AdaptableColumn_1.getColumnTypeFriendlyName)(columnType))))))))));
185
186
  };
186
187
  exports.NewScopeComponent = NewScopeComponent;
@@ -117,7 +117,7 @@ const LayoutWizard = (props) => {
117
117
  isVisible: () => layoutSupportedFeatures.PivotAggregationColumns && layoutSupportedFeatures.PivotColumns,
118
118
  details: 'Select Pivot Column Aggregations',
119
119
  renderSummary: () => React.createElement(PivotAggregationsSection_1.PivotAggregationsSectionSummary, null),
120
- isValid: (data) => (0, AggregationsSection_1.isAggregationsSectionValid)(data),
120
+ isValid: (data) => (0, PivotAggregationsSection_1.isPivotAggregationsSectionValid)(data),
121
121
  render: () => (React.createElement(rebass_1.Box, { p: 2, style: { height: '100%' } },
122
122
  React.createElement(PivotAggregationsSection_1.PivotAggregationsSection, { onChange: (layout) => {
123
123
  let newLayout = (0, Helper_1.cloneObject)(layout);
@@ -14,6 +14,8 @@ const ValueSelector_1 = require("../../../Components/ValueSelector");
14
14
  const OnePageAdaptableWizard_1 = require("../../../Wizard/OnePageAdaptableWizard");
15
15
  const Utilities_1 = require("./Utilities");
16
16
  const ArrayExtensions_1 = tslib_1.__importDefault(require("../../../../Utilities/Extensions/ArrayExtensions"));
17
+ const Select_1 = require("../../../../components/Select");
18
+ const StringExtensions_1 = tslib_1.__importDefault(require("../../../../Utilities/Extensions/StringExtensions"));
17
19
  const WEIGHTED_AVERAGE_AGG_FN_NAME = 'weightedAvg';
18
20
  const isAggregationsSectionValid = (data) => {
19
21
  const weightedAvg = data.TableAggregationColumns
@@ -196,7 +198,20 @@ const AggregationsSection = (props) => {
196
198
  React.createElement(Tabs_1.Tabs.Content, null,
197
199
  React.createElement(rebass_1.Flex, null,
198
200
  React.createElement(FormLayout_1.default, null,
199
- React.createElement(CheckBox_1.CheckBox, { checked: layout.SuppressAggFuncInHeader, onChange: handleSuppressAggFuncInHeader }, "Suppress Aggregation Function Text in Column Header"))),
201
+ React.createElement(FormLayout_1.FormRow, { label: 'Omit Aggregation from Header' },
202
+ React.createElement(CheckBox_1.CheckBox, { checked: layout.SuppressAggFuncInHeader, onChange: handleSuppressAggFuncInHeader })),
203
+ React.createElement(FormLayout_1.FormRow, { label: 'Grand Total Row' },
204
+ React.createElement(Select_1.Select, { style: { width: 120 }, options: ['top', 'bottom'].map((position) => {
205
+ return {
206
+ label: StringExtensions_1.default.CapitaliseFirstLetter(position),
207
+ value: position,
208
+ };
209
+ }), placeholder: "Off", value: layout.GrandTotalRow, onChange: (value) => {
210
+ props.onChange({
211
+ ...layout,
212
+ GrandTotalRow: value,
213
+ });
214
+ }, isClearable: true })))),
200
215
  React.createElement(ValueSelector_1.ValueSelector, { showFilterInput: true, showSelectedOnlyPosition: "top", filter: Utilities_1.columnFilter, toIdentifier: (option) => `${option.columnId}`, toLabel: (option) => option.friendlyName ?? option.columnId, toListLabel: (column) => (React.createElement(ColumnRow, { onChangeAggFunction: handleAggregationChange, layout: layout, column: column, aggregationColumnsMap: aggregationColumnsMap, numberColumns: numberColumns })), options: sortedAggregableColumns, value: (layout.TableAggregationColumns || []).map((agg) => agg.ColumnId), allowReorder: () => true, xSelectedLabel: () => {
201
216
  return `Active aggregations:`;
202
217
  }, onChange: handleColumnsSelectionChange }))));
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
- import { Layout, PivotLayout } from '../../../../../types';
3
- export declare const isAggregationsSectionValid: (data: Layout) => true | string;
2
+ import { PivotLayout } from '../../../../../types';
3
+ export declare const isPivotAggregationsSectionValid: (data: PivotLayout) => true | string;
4
4
  export declare const PivotAggregationsSectionSummary: React.FunctionComponent;
5
5
  interface PivotAggregationsSectionProps {
6
6
  onChange: (data: PivotLayout) => void;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PivotAggregationsSection = exports.PivotAggregationsSectionSummary = exports.isAggregationsSectionValid = void 0;
3
+ exports.PivotAggregationsSection = exports.PivotAggregationsSectionSummary = exports.isPivotAggregationsSectionValid = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const React = tslib_1.__importStar(require("react"));
6
6
  const rebass_1 = require("rebass");
@@ -9,47 +9,50 @@ const DropdownButton_1 = tslib_1.__importDefault(require("../../../../components
9
9
  const FormLayout_1 = tslib_1.__importStar(require("../../../../components/FormLayout"));
10
10
  const Tabs_1 = require("../../../../components/Tabs");
11
11
  const Tag_1 = require("../../../../components/Tag");
12
+ const AggregationColumns_1 = require("../../../../AdaptableState/Common/AggregationColumns");
12
13
  const AdaptableContext_1 = require("../../../AdaptableContext");
13
14
  const ValueSelector_1 = require("../../../Components/ValueSelector");
14
15
  const OnePageAdaptableWizard_1 = require("../../../Wizard/OnePageAdaptableWizard");
15
16
  const Utilities_1 = require("./Utilities");
16
17
  const ArrayExtensions_1 = tslib_1.__importDefault(require("../../../../Utilities/Extensions/ArrayExtensions"));
18
+ const StringExtensions_1 = tslib_1.__importDefault(require("../../../../Utilities/Extensions/StringExtensions"));
19
+ const Select_1 = require("../../../../components/Select");
17
20
  const PivotColumnRow = (props) => {
18
21
  const adaptable = (0, AdaptableContext_1.useAdaptable)();
19
22
  const aggValue = (props.layout.PivotAggregationColumns || []).find((x) => x.ColumnId === props.column.columnId)?.AggFunc;
20
23
  const adaptableAggFunctions = [];
21
24
  if (props.column.dataType === 'number') {
22
- adaptableAggFunctions.push(WEIGHTED_AVERAGE_AGG_FN_NAME);
25
+ adaptableAggFunctions.push(AggregationColumns_1.WEIGHTED_AVERAGE_AGG_FN_NAME);
23
26
  }
24
27
  const aggOptions = [...props.column.availableAggregationFunctions, ...adaptableAggFunctions].map((fnName) => {
25
28
  return {
26
29
  label: fnName,
27
30
  onClick: () => {
28
- let aggCols = props.layout.PivotAggregationColumns;
31
+ let aggCols = props.layout.PivotAggregationColumns || [];
29
32
  if (!aggCols) {
30
33
  return;
31
34
  }
32
- if (fnName === WEIGHTED_AVERAGE_AGG_FN_NAME) {
33
- aggCols = aggCols.map((x) => {
34
- if (x.ColumnId === props.column.columnId) {
35
- return {
36
- ...x,
37
- type: 'weightedAverage',
38
- weightedColumnId: null,
39
- };
40
- }
41
- return x;
42
- });
43
- }
44
- else {
45
- aggCols = aggCols.map((x) => {
46
- if (x.ColumnId === props.column.columnId) {
47
- return {
48
- ...x,
49
- AggFunc: fnName,
50
- };
51
- }
52
- return x;
35
+ const AggFuncValue = fnName === AggregationColumns_1.WEIGHTED_AVERAGE_AGG_FN_NAME
36
+ ? {
37
+ type: 'weightedAverage',
38
+ weightedColumnId: null,
39
+ }
40
+ : fnName;
41
+ let found = false;
42
+ aggCols = aggCols.map(({ ColumnId, AggFunc }) => {
43
+ if (ColumnId === props.column.columnId) {
44
+ found = true;
45
+ return {
46
+ ColumnId,
47
+ AggFunc: AggFuncValue,
48
+ };
49
+ }
50
+ return { ColumnId, AggFunc };
51
+ });
52
+ if (!found) {
53
+ aggCols.push({
54
+ ColumnId: props.column.columnId,
55
+ AggFunc: AggFuncValue,
53
56
  });
54
57
  }
55
58
  props.onChangeAggFunction(aggCols);
@@ -66,16 +69,27 @@ const PivotColumnRow = (props) => {
66
69
  if (!aggCols) {
67
70
  return;
68
71
  }
69
- aggCols = aggCols.map((x) => {
70
- if (x.ColumnId === props.column.columnId) {
72
+ const AggFuncValue = {
73
+ type: 'weightedAverage',
74
+ weightedColumnId: col.columnId,
75
+ };
76
+ let found = false;
77
+ aggCols = aggCols.map(({ ColumnId, AggFunc }) => {
78
+ if (ColumnId === props.column.columnId) {
79
+ found = true;
71
80
  return {
72
- ...x,
73
- type: 'weightedAverage',
74
- weightedColumnId: col.columnId,
81
+ ColumnId,
82
+ AggFunc: AggFuncValue,
75
83
  };
76
84
  }
77
- return x;
85
+ return { ColumnId, AggFunc };
78
86
  });
87
+ if (!found) {
88
+ aggCols.push({
89
+ ColumnId: props.column.columnId,
90
+ AggFunc: AggFuncValue,
91
+ });
92
+ }
79
93
  props.onChangeAggFunction(aggCols);
80
94
  },
81
95
  };
@@ -87,18 +101,122 @@ const PivotColumnRow = (props) => {
87
101
  ? adaptable.api.columnApi.getFriendlyNameForColumnId(aggValue.weightedColumnId)
88
102
  : 'Select Weight';
89
103
  }
90
- return (React.createElement(rebass_1.Flex, { alignItems: "center" },
91
- props.column.friendlyName,
92
- aggValue && (React.createElement(DropdownButton_1.default, { columns: ['label'], items: aggOptions, ml: 2 }, currentAggFnName)),
93
- currentAggFnName === WEIGHTED_AVERAGE_AGG_FN_NAME && (React.createElement(rebass_1.Flex, { backgroundColor: "primary", ml: 3, alignItems: "center" },
94
- React.createElement(rebass_1.Text, null, "Weight"),
95
- ' ',
96
- React.createElement(DropdownButton_1.default, { columns: ['label'], items: numericColumnsOptions, ml: 2 }, weightName)))));
104
+ const totalOptions = ['Off', 'Before', 'After', 'Pivot Specific'].map((totalVariant) => {
105
+ return {
106
+ label: totalVariant,
107
+ onClick: () => {
108
+ let aggCols = props.layout.PivotAggregationColumns;
109
+ if (!aggCols) {
110
+ return;
111
+ }
112
+ aggCols = aggCols.map((aggCol) => {
113
+ if (aggCol.ColumnId === props.column.columnId) {
114
+ let updatedTotalColumn = false;
115
+ if (totalVariant === 'Before') {
116
+ updatedTotalColumn = 'before';
117
+ }
118
+ if (totalVariant === 'After') {
119
+ updatedTotalColumn = 'after';
120
+ }
121
+ if (totalVariant === 'Pivot Specific') {
122
+ updatedTotalColumn = props.layout.PivotColumns.map((pivotColId) => {
123
+ return {
124
+ PivotColumnId: pivotColId,
125
+ ShowTotal: true,
126
+ };
127
+ });
128
+ }
129
+ return {
130
+ ...aggCol,
131
+ TotalColumn: updatedTotalColumn,
132
+ };
133
+ }
134
+ return aggCol;
135
+ });
136
+ props.onChangeAggFunction(aggCols);
137
+ },
138
+ };
139
+ });
140
+ const currentAggCol = props.layout.PivotAggregationColumns?.find((aggCol) => aggCol.ColumnId === props.column.columnId);
141
+ const currentTotal = currentAggCol?.TotalColumn
142
+ ? currentAggCol.TotalColumn === true || currentAggCol.TotalColumn === 'before'
143
+ ? 'Before'
144
+ : currentAggCol.TotalColumn === 'after'
145
+ ? 'After'
146
+ : Array.isArray(currentAggCol.TotalColumn)
147
+ ? 'Pivot Specific'
148
+ : 'Off'
149
+ : 'Off';
150
+ const hasPivotSpecificTotals = Array.isArray(currentAggCol?.TotalColumn);
151
+ const pivotSpecificTotals = Array.isArray(currentAggCol?.TotalColumn)
152
+ ? currentAggCol.TotalColumn
153
+ : props.layout.PivotColumns?.map((pivotColId) => ({
154
+ PivotColumnId: pivotColId,
155
+ ShowTotal: false,
156
+ }));
157
+ const handleTotalChange = (pivotColId, value) => {
158
+ const updatedAggCols = (props.layout.PivotAggregationColumns || []).map((aggCol) => {
159
+ if (aggCol.ColumnId === props.column.columnId) {
160
+ const updatedTotals = pivotSpecificTotals.map((total) => {
161
+ if (total.PivotColumnId === pivotColId) {
162
+ return { ...total, ShowTotal: value };
163
+ }
164
+ return total;
165
+ });
166
+ return { ...aggCol, TotalColumn: updatedTotals };
167
+ }
168
+ return aggCol;
169
+ });
170
+ props.onChangeAggFunction(updatedAggCols);
171
+ };
172
+ const pivotTotalOptions = ['Off', 'Before', 'After'].map((option) => ({
173
+ label: option,
174
+ value: option === 'Off' ? false : option.toLowerCase(),
175
+ }));
176
+ return (React.createElement(rebass_1.Box, { "data-name": props.column.columnId, className: "ab-Layout-Wizard__ColumnRow" },
177
+ React.createElement(rebass_1.Flex, { alignItems: "flex-start" },
178
+ React.createElement(rebass_1.Flex, { flex: "0 0 auto", alignItems: "center" },
179
+ React.createElement(rebass_1.Flex, { minWidth: 80 }, props.column.friendlyName),
180
+ aggValue && (React.createElement(DropdownButton_1.default, { columns: ['label'], items: aggOptions, ml: 2 }, currentAggFnName)),
181
+ currentAggFnName === AggregationColumns_1.WEIGHTED_AVERAGE_AGG_FN_NAME && (React.createElement(rebass_1.Flex, { backgroundColor: "primary", ml: 3, alignItems: "center" },
182
+ React.createElement(rebass_1.Text, null, "Weight"),
183
+ ' ',
184
+ React.createElement(DropdownButton_1.default, { columns: ['label'], items: numericColumnsOptions, ml: 2 }, weightName))),
185
+ aggValue && (React.createElement(rebass_1.Flex, { backgroundColor: "primary", ml: 3, alignItems: "center" },
186
+ React.createElement(rebass_1.Text, null, "Total Column"),
187
+ ' ',
188
+ React.createElement(DropdownButton_1.default, { columns: ['label'], items: totalOptions, ml: 2 }, currentTotal)))),
189
+ hasPivotSpecificTotals && (React.createElement(rebass_1.Flex, { ml: 2, pl: 2, flexWrap: "wrap", flex: "1 1 auto", alignItems: "center", style: {
190
+ minWidth: '200px',
191
+ borderLeft: '1px solid var(--ab-color-text-on-primary)',
192
+ rowGap: '8px',
193
+ columnGap: '12px',
194
+ } }, props.layout.PivotColumns.map((pivotColId) => {
195
+ const pivotTotalSetting = pivotSpecificTotals.find((t) => t.PivotColumnId === pivotColId);
196
+ const currentValue = pivotTotalSetting == undefined
197
+ ? 'Off'
198
+ : pivotTotalSetting.ShowTotal === false
199
+ ? 'Off'
200
+ : pivotTotalSetting.ShowTotal === 'before' ||
201
+ pivotTotalSetting.ShowTotal === true ||
202
+ pivotTotalSetting.ShowTotal == undefined
203
+ ? 'Before'
204
+ : pivotTotalSetting.ShowTotal === 'after'
205
+ ? 'After'
206
+ : 'Off';
207
+ return (React.createElement(rebass_1.Flex, { key: pivotColId, alignItems: "center" },
208
+ React.createElement(rebass_1.Text, { mr: 1 },
209
+ adaptable.api.columnApi.getFriendlyNameForColumnId(pivotColId),
210
+ ":"),
211
+ React.createElement(DropdownButton_1.default, { columns: ['label'], items: pivotTotalOptions.map((opt) => ({
212
+ label: opt.label,
213
+ onClick: () => handleTotalChange(pivotColId, opt.value),
214
+ })) }, currentValue)));
215
+ }))))));
97
216
  };
98
- const WEIGHTED_AVERAGE_AGG_FN_NAME = 'weightedAvg';
99
- const isAggregationsSectionValid = (data) => {
100
- const weightedAvg = data.TableAggregationColumns
101
- ? (data.TableAggregationColumns || [])
217
+ const isPivotAggregationsSectionValid = (data) => {
218
+ const weightedAvg = data.PivotAggregationColumns
219
+ ? (data.PivotAggregationColumns || [])
102
220
  .map((agg) => agg.AggFunc)
103
221
  .find((agg) => typeof agg === 'object' && agg.type === 'weightedAverage')
104
222
  : null;
@@ -107,7 +225,7 @@ const isAggregationsSectionValid = (data) => {
107
225
  }
108
226
  return true;
109
227
  };
110
- exports.isAggregationsSectionValid = isAggregationsSectionValid;
228
+ exports.isPivotAggregationsSectionValid = isPivotAggregationsSectionValid;
111
229
  const PivotAggregationsSectionSummary = () => {
112
230
  const adaptable = (0, AdaptableContext_1.useAdaptable)();
113
231
  const { data: layout } = (0, OnePageAdaptableWizard_1.useOnePageAdaptableWizardContext)();
@@ -132,7 +250,6 @@ const PivotAggregationsSection = (props) => {
132
250
  const sortedAggregableColumns = React.useMemo(() => {
133
251
  return ArrayExtensions_1.default.sortArrayWithOrder(allAggregableColumns.map((col) => col.columnId), (layout.PivotAggregationColumns ?? []).map((col) => col.ColumnId), { sortUnorderedItems: false }).map((colId) => adaptable.api.columnApi.getColumnWithColumnId(colId));
134
252
  }, [layout, allAggregableColumns]);
135
- globalThis.layout = layout;
136
253
  const handleColumnsSelectionChange = React.useCallback((columnIds) => {
137
254
  const currentAggColumns = layout.PivotAggregationColumns ?? [];
138
255
  const PivotAggregationColumns = columnIds.map((colId) => {
@@ -140,6 +257,7 @@ const PivotAggregationsSection = (props) => {
140
257
  ColumnId: colId,
141
258
  AggFunc: currentAggColumns.find((x) => x.ColumnId === colId)?.AggFunc ??
142
259
  adaptable.api.columnApi.getDefaultAggFunc(colId),
260
+ TotalColumn: currentAggColumns.find((x) => x.ColumnId === colId)?.TotalColumn,
143
261
  };
144
262
  });
145
263
  props.onChange({
@@ -147,10 +265,14 @@ const PivotAggregationsSection = (props) => {
147
265
  PivotAggregationColumns,
148
266
  });
149
267
  }, [layout]);
150
- const handleAggregationChange = React.useCallback((PivotAggregationColumns) => {
268
+ const handleAggregationChange = React.useCallback((pivotAggregationColumns) => {
269
+ if (pivotAggregationColumns.some((aggCol) => aggCol.TotalColumn !== false || aggCol.TotalColumn !== null)) {
270
+ // if any Aggregation Column has a Total Column, we need to disable the Pivot Group Total Column
271
+ delete layout['PivotGroupTotalColumn'];
272
+ }
151
273
  props.onChange({
152
274
  ...layout,
153
- PivotAggregationColumns,
275
+ PivotAggregationColumns: pivotAggregationColumns,
154
276
  });
155
277
  }, [layout]);
156
278
  const aggregationColumnsMap = React.useMemo(() => {
@@ -165,7 +287,7 @@ const PivotAggregationsSection = (props) => {
165
287
  fnName = allColumnsMap[colId].aggregationFunction;
166
288
  }
167
289
  if (typeof fn === 'object' && fn.type === 'weightedAverage') {
168
- fnName = WEIGHTED_AVERAGE_AGG_FN_NAME;
290
+ fnName = AggregationColumns_1.WEIGHTED_AVERAGE_AGG_FN_NAME;
169
291
  }
170
292
  else if (typeof fn === 'string') {
171
293
  fnName = fn;
@@ -180,12 +302,66 @@ const PivotAggregationsSection = (props) => {
180
302
  SuppressAggFuncInHeader: checked,
181
303
  });
182
304
  };
305
+ const checkIfPivotGroupTotalColumnEnabled = () => {
306
+ // check that all AggregationColumns have identical AggFuncs
307
+ const aggregationColumns = layout.PivotAggregationColumns;
308
+ if (!aggregationColumns || aggregationColumns.length === 0) {
309
+ return true;
310
+ }
311
+ const firstAggFuncName = (0, AggregationColumns_1.getAggFuncName)(aggregationColumns[0].AggFunc);
312
+ if (layout.PivotAggregationColumns?.some((aggCol) => (0, AggregationColumns_1.getAggFuncName)(aggCol.AggFunc) !== firstAggFuncName)) {
313
+ return 'Requires identical aggregation on all columns';
314
+ }
315
+ // check that no Aggregation Total Column is enabled
316
+ const hasAggregationTotalColumn = aggregationColumns.some((aggCol) => aggCol.TotalColumn !== false && aggCol.TotalColumn != null);
317
+ if (hasAggregationTotalColumn) {
318
+ return 'Can only be enabled when no Aggregation Total Column is present';
319
+ }
320
+ return true;
321
+ };
322
+ const isPivotGroupTotalColumnEnabled = checkIfPivotGroupTotalColumnEnabled();
183
323
  return (React.createElement(Tabs_1.Tabs, { style: { height: '100%' } },
184
324
  React.createElement(Tabs_1.Tabs.Tab, null, "Column Aggregations"),
185
325
  React.createElement(Tabs_1.Tabs.Content, null,
186
326
  React.createElement(rebass_1.Flex, null,
187
327
  React.createElement(FormLayout_1.default, null,
188
- React.createElement(CheckBox_1.CheckBox, { checked: layout.SuppressAggFuncInHeader, onChange: handleSuppressAggFuncInHeader }, "Suppress Aggregation Function Text in Column Header"))),
328
+ React.createElement(FormLayout_1.FormRow, { label: 'Omit Aggregation from Header' },
329
+ React.createElement(CheckBox_1.CheckBox, { checked: layout.SuppressAggFuncInHeader, onChange: handleSuppressAggFuncInHeader })),
330
+ React.createElement(FormLayout_1.FormRow, { label: 'Grand Total Row' },
331
+ React.createElement(Select_1.Select, { style: { width: 120 }, options: ['top', 'bottom'].map((position) => {
332
+ return {
333
+ label: StringExtensions_1.default.CapitaliseFirstLetter(position),
334
+ value: position,
335
+ };
336
+ }), placeholder: "Off", value: layout.GrandTotalRow, onChange: (value) => {
337
+ props.onChange({
338
+ ...layout,
339
+ GrandTotalRow: value,
340
+ });
341
+ }, isClearable: true })),
342
+ React.createElement(FormLayout_1.FormRow, { label: 'Grand Total Column' },
343
+ React.createElement(Select_1.Select, { style: { width: 120 }, options: ['before', 'after'].map((position) => {
344
+ return {
345
+ label: StringExtensions_1.default.CapitaliseFirstLetter(position),
346
+ value: position,
347
+ };
348
+ }), placeholder: "Off", value: layout.GrandTotalColumn, onChange: (value) => {
349
+ props.onChange({
350
+ ...layout,
351
+ GrandTotalColumn: value,
352
+ });
353
+ }, isClearable: true })),
354
+ React.createElement(FormLayout_1.FormRow, { label: 'Pivot Group Total Column' }, isPivotGroupTotalColumnEnabled === true ? (React.createElement(Select_1.Select, { style: { width: 120 }, options: ['before', 'after'].map((position) => {
355
+ return {
356
+ label: StringExtensions_1.default.CapitaliseFirstLetter(position),
357
+ value: position,
358
+ };
359
+ }), placeholder: "Off", value: layout.PivotGroupTotalColumn, onChange: (value) => {
360
+ props.onChange({
361
+ ...layout,
362
+ PivotGroupTotalColumn: value,
363
+ });
364
+ }, isClearable: true })) : (React.createElement(rebass_1.Text, { marginLeft: 1, style: { fontStyle: 'italic' } }, isPivotGroupTotalColumnEnabled))))),
189
365
  React.createElement(ValueSelector_1.ValueSelector, { showFilterInput: true, showSelectedOnlyPosition: "top", filter: Utilities_1.columnFilter, toIdentifier: (option) => `${option.columnId}`, toLabel: (option) => option.friendlyName ?? option.columnId, toListLabel: (column) => (React.createElement(PivotColumnRow, { onChangeAggFunction: handleAggregationChange, layout: layout, column: column, aggregationColumnsMap: aggregationColumnsMap, numberColumns: numberColumns })), options: sortedAggregableColumns, value: (layout.PivotAggregationColumns || []).map((col) => col.ColumnId), allowReorder: true, xSelectedLabel: () => {
190
366
  return `Active aggregations:`;
191
367
  }, onChange: handleColumnsSelectionChange }))));
@@ -332,6 +332,7 @@ export declare class AdaptableAgGrid implements IAdaptable {
332
332
  private filterOnDataChange;
333
333
  refreshLayout(): void;
334
334
  private isRowGroupDifferentInLayout;
335
+ private hasPivotTotalsInLayout;
335
336
  private onLayoutChange;
336
337
  private validateColumnDefTypes;
337
338
  }