@adaptabletools/adaptable 20.0.7-canary.1 → 20.0.7-canary.2
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/agGrid.d.ts +37 -0
- package/agGrid.js +38 -0
- package/base.css +19 -3
- package/base.css.map +1 -1
- package/index.css +17 -3
- package/index.css.map +1 -1
- package/package.json +3 -3
- package/src/AdaptableOptions/LayoutOptions.d.ts +3 -6
- package/src/AdaptableState/Common/AdaptableColumn.d.ts +10 -5
- package/src/AdaptableState/Common/AdaptableColumn.js +26 -0
- package/src/AdaptableState/Common/AggregationColumns.d.ts +10 -0
- package/src/AdaptableState/Common/AggregationColumns.js +11 -0
- package/src/Api/Implementation/ColumnApiImpl.d.ts +2 -2
- package/src/Api/Implementation/ColumnApiImpl.js +30 -2
- package/src/Api/Internal/ColumnInternalApi.js +3 -3
- package/src/View/Alert/Wizard/AlertButtonsEditor.js +9 -10
- package/src/View/Alert/Wizard/AlertNotificationWizardSection.js +26 -25
- package/src/View/Components/ColumnFilter/ColumnFilter.js +1 -1
- package/src/View/Components/FilterForm/ListBoxFilterForm.js +6 -3
- package/src/View/Components/NewScopeComponent.js +2 -1
- package/src/View/Layout/Wizard/LayoutWizard.js +2 -2
- package/src/View/Layout/Wizard/sections/AggregationsSection.js +1 -1
- package/src/View/Layout/Wizard/sections/PivotAggregationsSection.d.ts +2 -2
- package/src/View/Layout/Wizard/sections/PivotAggregationsSection.js +219 -43
- package/src/components/Select/Select.js +15 -3
- package/src/env.js +2 -2
- package/src/layout-manager/src/index.d.ts +1 -1
- package/src/layout-manager/src/index.js +26 -6
- package/src/layout-manager/src/isPivotAggTotalColumn.d.ts +2 -0
- package/src/layout-manager/src/{isPivotTotalColumn.js → isPivotAggTotalColumn.js} +1 -1
- package/src/layout-manager/src/isPivotGrandTotalColumn.d.ts +2 -0
- package/src/layout-manager/src/isPivotGrandTotalColumn.js +3 -0
- package/src/layout-manager/src/isPivotGroupTotalColumn.d.ts +1 -2
- package/src/layout-manager/src/isPivotGroupTotalColumn.js +2 -2
- package/src/metamodel/adaptable.metamodel.d.ts +8 -2
- package/src/metamodel/adaptable.metamodel.js +1 -1
- package/src/types.d.ts +1 -1
- package/tsconfig.esm.tsbuildinfo +1 -1
- package/src/layout-manager/src/isPivotTotalColumn.d.ts +0 -2
|
@@ -64,31 +64,32 @@ export const AlertNotificationWizardSection = (props) => {
|
|
|
64
64
|
React.createElement(Tabs, { "data-name": "display-options", mt: 2, mb: 3, autoFocus: false },
|
|
65
65
|
React.createElement(Tabs.Tab, null, "Notification Options"),
|
|
66
66
|
React.createElement(Tabs.Content, null,
|
|
67
|
-
React.createElement(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
newAlertDefinition.AlertForm
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
(
|
|
85
|
-
newAlertDefinition.AlertForm?.Buttons
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
67
|
+
React.createElement("div", null,
|
|
68
|
+
React.createElement(CheckBox, { checked: data.AlertProperties?.DisplayNotification, onChange: (DisplayNotification) => {
|
|
69
|
+
const newAlertDefinition = {
|
|
70
|
+
...data,
|
|
71
|
+
AlertProperties: {
|
|
72
|
+
...data.AlertProperties,
|
|
73
|
+
DisplayNotification,
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
if (!DisplayNotification && typeof newAlertDefinition.AlertForm === 'object') {
|
|
77
|
+
delete newAlertDefinition.AlertForm.Buttons;
|
|
78
|
+
}
|
|
79
|
+
if (DisplayNotification && newAlertDefinition.AlertForm == undefined) {
|
|
80
|
+
newAlertDefinition.AlertForm =
|
|
81
|
+
api.alertApi.internalApi.getDefaultAlertNotificationForm();
|
|
82
|
+
}
|
|
83
|
+
// make sure we have at least one button
|
|
84
|
+
if (typeof newAlertDefinition.AlertForm === 'object' &&
|
|
85
|
+
(!newAlertDefinition.AlertForm?.Buttons ||
|
|
86
|
+
newAlertDefinition.AlertForm?.Buttons?.length === 0)) {
|
|
87
|
+
newAlertDefinition.AlertForm.Buttons = [
|
|
88
|
+
api.alertApi.internalApi.getDefaultButton(),
|
|
89
|
+
];
|
|
90
|
+
}
|
|
91
|
+
props.onChange(newAlertDefinition);
|
|
92
|
+
} }, "Display a Notification when Alert is triggered (with action buttons)")),
|
|
92
93
|
data.AlertProperties?.DisplayNotification ? (typeof data.AlertForm === 'string' ? (React.createElement(Text, { fontSize: 2 }, "Alert buttons cannot be customized because form is dynamically driven")) : (React.createElement(AlertButtonsEditor, { alertType: props.alertType, AlertButtons: data.AlertForm?.Buttons, api: api, adaptableAlert: adaptableAlert, onChange: (buttons) => {
|
|
93
94
|
props.onChange({
|
|
94
95
|
...data,
|
|
@@ -18,7 +18,7 @@ const ColumnFilterPredicateDropdown = (props) => {
|
|
|
18
18
|
});
|
|
19
19
|
const operator = props.predicate?.operator;
|
|
20
20
|
const isAndOr = operator === 'AND' || operator === 'OR';
|
|
21
|
-
return (React.createElement(Box, { display: 'flex', alignItems: "center", style: {
|
|
21
|
+
return (React.createElement(Box, { display: 'flex', alignItems: "center", className: "ab-ColumnFilterPredicateDropdown", style: {
|
|
22
22
|
//@ts-ignore ignore
|
|
23
23
|
'--ab-cmp-input__background': 'var(--ab-color-primary)',
|
|
24
24
|
} },
|
|
@@ -24,9 +24,12 @@ export const ColumnValuesSelect = (props) => {
|
|
|
24
24
|
}
|
|
25
25
|
return true;
|
|
26
26
|
});
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
const menuStyle = React.useMemo(() => {
|
|
28
|
+
return {
|
|
29
|
+
minWidth: `var(--ab-cmp-select-column-menu-${column.columnId}__min-width, var(--ab-cmp-select-column-menu__min-width, 160px))`,
|
|
30
|
+
};
|
|
31
|
+
}, [column.columnId]);
|
|
32
|
+
const component = (React.createElement(Select, { isMulti: true, showHeaderSelectionCheckbox: true, searchable: true, closeMenuOnSelect: false, menuStyle: menuStyle, ...props.selectProps, options: options, value: value, isLoading: props.isLoading, onChange: props.onChange }));
|
|
30
33
|
return (React.createElement("div", { className: join(baseClassName, props.isLoading && `${baseClassName}--loading`, !value.length && `${baseClassName}--empty`), onKeyDownCapture: (e) => {
|
|
31
34
|
const event = e.nativeEvent || e;
|
|
32
35
|
event.stopPropagation = () => {
|
|
@@ -9,6 +9,7 @@ import { NewColumnSelector } from './ColumnSelector';
|
|
|
9
9
|
import { AdaptableFormControlTextClear } from './Forms/AdaptableFormControlTextClear';
|
|
10
10
|
import { useAdaptable } from '../AdaptableContext';
|
|
11
11
|
import { ValueOptionsTags } from './ValueSelector';
|
|
12
|
+
import { getColumnTypeFriendlyName } from '../../AdaptableState/Common/AdaptableColumn';
|
|
12
13
|
export const isScopeValid = ({ Scope }) => {
|
|
13
14
|
const result = [];
|
|
14
15
|
if (!Scope) {
|
|
@@ -175,5 +176,5 @@ export const NewScopeComponent = (props) => {
|
|
|
175
176
|
ColumnTypes: columnTypes,
|
|
176
177
|
};
|
|
177
178
|
props.updateScope(newScope);
|
|
178
|
-
} }, columnType)))))))));
|
|
179
|
+
} }, getColumnTypeFriendlyName(columnType))))))))));
|
|
179
180
|
};
|
|
@@ -18,7 +18,7 @@ import { areSummaryRowsValid, RowSummarySection, RowSummarySectionSummary, } fro
|
|
|
18
18
|
import { WEIGHTED_AVERAGE_AGGREGATED_FUNCTION } from '../../../AdaptableState/Common/RowSummary';
|
|
19
19
|
import { isPivotLayout } from '../../../Utilities/isPivotLayout';
|
|
20
20
|
import { PivotRowGroupingSection, PivotRowGroupingSectionSummary, } from './sections/PivotRowGroupingSection';
|
|
21
|
-
import { PivotAggregationsSection, PivotAggregationsSectionSummary, } from './sections/PivotAggregationsSection';
|
|
21
|
+
import { isPivotAggregationsSectionValid, PivotAggregationsSection, PivotAggregationsSectionSummary, } from './sections/PivotAggregationsSection';
|
|
22
22
|
export const LayoutWizard = (props) => {
|
|
23
23
|
const dispatch = useDispatch();
|
|
24
24
|
const adaptable = useAdaptable();
|
|
@@ -113,7 +113,7 @@ export const LayoutWizard = (props) => {
|
|
|
113
113
|
isVisible: () => layoutSupportedFeatures.PivotAggregationColumns && layoutSupportedFeatures.PivotColumns,
|
|
114
114
|
details: 'Select Pivot Column Aggregations',
|
|
115
115
|
renderSummary: () => React.createElement(PivotAggregationsSectionSummary, null),
|
|
116
|
-
isValid: (data) =>
|
|
116
|
+
isValid: (data) => isPivotAggregationsSectionValid(data),
|
|
117
117
|
render: () => (React.createElement(Box, { p: 2, style: { height: '100%' } },
|
|
118
118
|
React.createElement(PivotAggregationsSection, { onChange: (layout) => {
|
|
119
119
|
let newLayout = cloneObject(layout);
|
|
@@ -190,7 +190,7 @@ export const AggregationsSection = (props) => {
|
|
|
190
190
|
React.createElement(Tabs.Content, null,
|
|
191
191
|
React.createElement(Flex, null,
|
|
192
192
|
React.createElement(FormLayout, null,
|
|
193
|
-
React.createElement(CheckBox, { checked: layout.SuppressAggFuncInHeader, onChange: handleSuppressAggFuncInHeader }, "
|
|
193
|
+
React.createElement(CheckBox, { checked: layout.SuppressAggFuncInHeader, onChange: handleSuppressAggFuncInHeader }, "Omit Aggregation Function from Header"))),
|
|
194
194
|
React.createElement(ValueSelector, { showFilterInput: true, showSelectedOnlyPosition: "top", filter: 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: () => {
|
|
195
195
|
return `Active aggregations:`;
|
|
196
196
|
}, onChange: handleColumnsSelectionChange }))));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
export declare const
|
|
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;
|
|
@@ -5,11 +5,14 @@ import DropdownButton from '../../../../components/DropdownButton';
|
|
|
5
5
|
import FormLayout, { FormRow } from '../../../../components/FormLayout';
|
|
6
6
|
import { Tabs } from '../../../../components/Tabs';
|
|
7
7
|
import { Tag } from '../../../../components/Tag';
|
|
8
|
+
import { getAggFuncName, WEIGHTED_AVERAGE_AGG_FN_NAME, } from '../../../../AdaptableState/Common/AggregationColumns';
|
|
8
9
|
import { useAdaptable } from '../../../AdaptableContext';
|
|
9
10
|
import { ValueSelector } from '../../../Components/ValueSelector';
|
|
10
11
|
import { useOnePageAdaptableWizardContext } from '../../../Wizard/OnePageAdaptableWizard';
|
|
11
12
|
import { columnFilter } from './Utilities';
|
|
12
13
|
import ArrayExtensions from '../../../../Utilities/Extensions/ArrayExtensions';
|
|
14
|
+
import StringExtensions from '../../../../Utilities/Extensions/StringExtensions';
|
|
15
|
+
import { Select } from '../../../../components/Select';
|
|
13
16
|
const PivotColumnRow = (props) => {
|
|
14
17
|
const adaptable = useAdaptable();
|
|
15
18
|
const aggValue = (props.layout.PivotAggregationColumns || []).find((x) => x.ColumnId === props.column.columnId)?.AggFunc;
|
|
@@ -21,31 +24,31 @@ const PivotColumnRow = (props) => {
|
|
|
21
24
|
return {
|
|
22
25
|
label: fnName,
|
|
23
26
|
onClick: () => {
|
|
24
|
-
let aggCols = props.layout.PivotAggregationColumns;
|
|
27
|
+
let aggCols = props.layout.PivotAggregationColumns || [];
|
|
25
28
|
if (!aggCols) {
|
|
26
29
|
return;
|
|
27
30
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
31
|
+
const AggFuncValue = fnName === WEIGHTED_AVERAGE_AGG_FN_NAME
|
|
32
|
+
? {
|
|
33
|
+
type: 'weightedAverage',
|
|
34
|
+
weightedColumnId: null,
|
|
35
|
+
}
|
|
36
|
+
: fnName;
|
|
37
|
+
let found = false;
|
|
38
|
+
aggCols = aggCols.map(({ ColumnId, AggFunc }) => {
|
|
39
|
+
if (ColumnId === props.column.columnId) {
|
|
40
|
+
found = true;
|
|
41
|
+
return {
|
|
42
|
+
ColumnId,
|
|
43
|
+
AggFunc: AggFuncValue,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return { ColumnId, AggFunc };
|
|
47
|
+
});
|
|
48
|
+
if (!found) {
|
|
49
|
+
aggCols.push({
|
|
50
|
+
ColumnId: props.column.columnId,
|
|
51
|
+
AggFunc: AggFuncValue,
|
|
49
52
|
});
|
|
50
53
|
}
|
|
51
54
|
props.onChangeAggFunction(aggCols);
|
|
@@ -62,16 +65,27 @@ const PivotColumnRow = (props) => {
|
|
|
62
65
|
if (!aggCols) {
|
|
63
66
|
return;
|
|
64
67
|
}
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
const AggFuncValue = {
|
|
69
|
+
type: 'weightedAverage',
|
|
70
|
+
weightedColumnId: col.columnId,
|
|
71
|
+
};
|
|
72
|
+
let found = false;
|
|
73
|
+
aggCols = aggCols.map(({ ColumnId, AggFunc }) => {
|
|
74
|
+
if (ColumnId === props.column.columnId) {
|
|
75
|
+
found = true;
|
|
67
76
|
return {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
weightedColumnId: col.columnId,
|
|
77
|
+
ColumnId,
|
|
78
|
+
AggFunc: AggFuncValue,
|
|
71
79
|
};
|
|
72
80
|
}
|
|
73
|
-
return
|
|
81
|
+
return { ColumnId, AggFunc };
|
|
74
82
|
});
|
|
83
|
+
if (!found) {
|
|
84
|
+
aggCols.push({
|
|
85
|
+
ColumnId: props.column.columnId,
|
|
86
|
+
AggFunc: AggFuncValue,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
75
89
|
props.onChangeAggFunction(aggCols);
|
|
76
90
|
},
|
|
77
91
|
};
|
|
@@ -83,18 +97,122 @@ const PivotColumnRow = (props) => {
|
|
|
83
97
|
? adaptable.api.columnApi.getFriendlyNameForColumnId(aggValue.weightedColumnId)
|
|
84
98
|
: 'Select Weight';
|
|
85
99
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
100
|
+
const totalOptions = ['Off', 'Before', 'After', 'Pivot Specific'].map((totalVariant) => {
|
|
101
|
+
return {
|
|
102
|
+
label: totalVariant,
|
|
103
|
+
onClick: () => {
|
|
104
|
+
let aggCols = props.layout.PivotAggregationColumns;
|
|
105
|
+
if (!aggCols) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
aggCols = aggCols.map((aggCol) => {
|
|
109
|
+
if (aggCol.ColumnId === props.column.columnId) {
|
|
110
|
+
let updatedTotalColumn = false;
|
|
111
|
+
if (totalVariant === 'Before') {
|
|
112
|
+
updatedTotalColumn = 'before';
|
|
113
|
+
}
|
|
114
|
+
if (totalVariant === 'After') {
|
|
115
|
+
updatedTotalColumn = 'after';
|
|
116
|
+
}
|
|
117
|
+
if (totalVariant === 'Pivot Specific') {
|
|
118
|
+
updatedTotalColumn = props.layout.PivotColumns.map((pivotColId) => {
|
|
119
|
+
return {
|
|
120
|
+
PivotColumnId: pivotColId,
|
|
121
|
+
ShowTotal: true,
|
|
122
|
+
};
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
...aggCol,
|
|
127
|
+
TotalColumn: updatedTotalColumn,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
return aggCol;
|
|
131
|
+
});
|
|
132
|
+
props.onChangeAggFunction(aggCols);
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
});
|
|
136
|
+
const currentAggCol = props.layout.PivotAggregationColumns?.find((aggCol) => aggCol.ColumnId === props.column.columnId);
|
|
137
|
+
const currentTotal = currentAggCol?.TotalColumn
|
|
138
|
+
? currentAggCol.TotalColumn === true || currentAggCol.TotalColumn === 'before'
|
|
139
|
+
? 'Before'
|
|
140
|
+
: currentAggCol.TotalColumn === 'after'
|
|
141
|
+
? 'After'
|
|
142
|
+
: Array.isArray(currentAggCol.TotalColumn)
|
|
143
|
+
? 'Pivot Specific'
|
|
144
|
+
: 'Off'
|
|
145
|
+
: 'Off';
|
|
146
|
+
const hasPivotSpecificTotals = Array.isArray(currentAggCol?.TotalColumn);
|
|
147
|
+
const pivotSpecificTotals = Array.isArray(currentAggCol?.TotalColumn)
|
|
148
|
+
? currentAggCol.TotalColumn
|
|
149
|
+
: props.layout.PivotColumns?.map((pivotColId) => ({
|
|
150
|
+
PivotColumnId: pivotColId,
|
|
151
|
+
ShowTotal: false,
|
|
152
|
+
}));
|
|
153
|
+
const handleTotalChange = (pivotColId, value) => {
|
|
154
|
+
const updatedAggCols = (props.layout.PivotAggregationColumns || []).map((aggCol) => {
|
|
155
|
+
if (aggCol.ColumnId === props.column.columnId) {
|
|
156
|
+
const updatedTotals = pivotSpecificTotals.map((total) => {
|
|
157
|
+
if (total.PivotColumnId === pivotColId) {
|
|
158
|
+
return { ...total, ShowTotal: value };
|
|
159
|
+
}
|
|
160
|
+
return total;
|
|
161
|
+
});
|
|
162
|
+
return { ...aggCol, TotalColumn: updatedTotals };
|
|
163
|
+
}
|
|
164
|
+
return aggCol;
|
|
165
|
+
});
|
|
166
|
+
props.onChangeAggFunction(updatedAggCols);
|
|
167
|
+
};
|
|
168
|
+
const pivotTotalOptions = ['Off', 'Before', 'After'].map((option) => ({
|
|
169
|
+
label: option,
|
|
170
|
+
value: option === 'Off' ? false : option.toLowerCase(),
|
|
171
|
+
}));
|
|
172
|
+
return (React.createElement(Box, { "data-name": props.column.columnId, className: "ab-Layout-Wizard__ColumnRow" },
|
|
173
|
+
React.createElement(Flex, { alignItems: "flex-start" },
|
|
174
|
+
React.createElement(Flex, { flex: "0 0 auto", alignItems: "center" },
|
|
175
|
+
React.createElement(Flex, { minWidth: 80 }, props.column.friendlyName),
|
|
176
|
+
aggValue && (React.createElement(DropdownButton, { columns: ['label'], items: aggOptions, ml: 2 }, currentAggFnName)),
|
|
177
|
+
currentAggFnName === WEIGHTED_AVERAGE_AGG_FN_NAME && (React.createElement(Flex, { backgroundColor: "primary", ml: 3, alignItems: "center" },
|
|
178
|
+
React.createElement(Text, null, "Weight"),
|
|
179
|
+
' ',
|
|
180
|
+
React.createElement(DropdownButton, { columns: ['label'], items: numericColumnsOptions, ml: 2 }, weightName))),
|
|
181
|
+
aggValue && (React.createElement(Flex, { backgroundColor: "primary", ml: 3, alignItems: "center" },
|
|
182
|
+
React.createElement(Text, null, "Total Column"),
|
|
183
|
+
' ',
|
|
184
|
+
React.createElement(DropdownButton, { columns: ['label'], items: totalOptions, ml: 2 }, currentTotal)))),
|
|
185
|
+
hasPivotSpecificTotals && (React.createElement(Flex, { ml: 2, pl: 2, flexWrap: "wrap", flex: "1 1 auto", alignItems: "center", style: {
|
|
186
|
+
minWidth: '200px',
|
|
187
|
+
borderLeft: '1px solid var(--ab-color-text-on-primary)',
|
|
188
|
+
rowGap: '8px',
|
|
189
|
+
columnGap: '12px',
|
|
190
|
+
} }, props.layout.PivotColumns.map((pivotColId) => {
|
|
191
|
+
const pivotTotalSetting = pivotSpecificTotals.find((t) => t.PivotColumnId === pivotColId);
|
|
192
|
+
const currentValue = pivotTotalSetting == undefined
|
|
193
|
+
? 'Off'
|
|
194
|
+
: pivotTotalSetting.ShowTotal === false
|
|
195
|
+
? 'Off'
|
|
196
|
+
: pivotTotalSetting.ShowTotal === 'before' ||
|
|
197
|
+
pivotTotalSetting.ShowTotal === true ||
|
|
198
|
+
pivotTotalSetting.ShowTotal == undefined
|
|
199
|
+
? 'Before'
|
|
200
|
+
: pivotTotalSetting.ShowTotal === 'after'
|
|
201
|
+
? 'After'
|
|
202
|
+
: 'Off';
|
|
203
|
+
return (React.createElement(Flex, { key: pivotColId, alignItems: "center" },
|
|
204
|
+
React.createElement(Text, { mr: 1 },
|
|
205
|
+
adaptable.api.columnApi.getFriendlyNameForColumnId(pivotColId),
|
|
206
|
+
":"),
|
|
207
|
+
React.createElement(DropdownButton, { columns: ['label'], items: pivotTotalOptions.map((opt) => ({
|
|
208
|
+
label: opt.label,
|
|
209
|
+
onClick: () => handleTotalChange(pivotColId, opt.value),
|
|
210
|
+
})) }, currentValue)));
|
|
211
|
+
}))))));
|
|
93
212
|
};
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
? (data.TableAggregationColumns || [])
|
|
213
|
+
export const isPivotAggregationsSectionValid = (data) => {
|
|
214
|
+
const weightedAvg = data.PivotAggregationColumns
|
|
215
|
+
? (data.PivotAggregationColumns || [])
|
|
98
216
|
.map((agg) => agg.AggFunc)
|
|
99
217
|
.find((agg) => typeof agg === 'object' && agg.type === 'weightedAverage')
|
|
100
218
|
: null;
|
|
@@ -126,7 +244,6 @@ export const PivotAggregationsSection = (props) => {
|
|
|
126
244
|
const sortedAggregableColumns = React.useMemo(() => {
|
|
127
245
|
return ArrayExtensions.sortArrayWithOrder(allAggregableColumns.map((col) => col.columnId), (layout.PivotAggregationColumns ?? []).map((col) => col.ColumnId), { sortUnorderedItems: false }).map((colId) => adaptable.api.columnApi.getColumnWithColumnId(colId));
|
|
128
246
|
}, [layout, allAggregableColumns]);
|
|
129
|
-
globalThis.layout = layout;
|
|
130
247
|
const handleColumnsSelectionChange = React.useCallback((columnIds) => {
|
|
131
248
|
const currentAggColumns = layout.PivotAggregationColumns ?? [];
|
|
132
249
|
const PivotAggregationColumns = columnIds.map((colId) => {
|
|
@@ -134,6 +251,7 @@ export const PivotAggregationsSection = (props) => {
|
|
|
134
251
|
ColumnId: colId,
|
|
135
252
|
AggFunc: currentAggColumns.find((x) => x.ColumnId === colId)?.AggFunc ??
|
|
136
253
|
adaptable.api.columnApi.getDefaultAggFunc(colId),
|
|
254
|
+
TotalColumn: currentAggColumns.find((x) => x.ColumnId === colId)?.TotalColumn,
|
|
137
255
|
};
|
|
138
256
|
});
|
|
139
257
|
props.onChange({
|
|
@@ -141,10 +259,14 @@ export const PivotAggregationsSection = (props) => {
|
|
|
141
259
|
PivotAggregationColumns,
|
|
142
260
|
});
|
|
143
261
|
}, [layout]);
|
|
144
|
-
const handleAggregationChange = React.useCallback((
|
|
262
|
+
const handleAggregationChange = React.useCallback((pivotAggregationColumns) => {
|
|
263
|
+
if (pivotAggregationColumns.some((aggCol) => aggCol.TotalColumn !== false || aggCol.TotalColumn !== null)) {
|
|
264
|
+
// if any Aggregation Column has a Total Column, we need to disable the Pivot Group Total Column
|
|
265
|
+
delete layout['PivotGroupTotalColumn'];
|
|
266
|
+
}
|
|
145
267
|
props.onChange({
|
|
146
268
|
...layout,
|
|
147
|
-
PivotAggregationColumns,
|
|
269
|
+
PivotAggregationColumns: pivotAggregationColumns,
|
|
148
270
|
});
|
|
149
271
|
}, [layout]);
|
|
150
272
|
const aggregationColumnsMap = React.useMemo(() => {
|
|
@@ -174,12 +296,66 @@ export const PivotAggregationsSection = (props) => {
|
|
|
174
296
|
SuppressAggFuncInHeader: checked,
|
|
175
297
|
});
|
|
176
298
|
};
|
|
299
|
+
const checkIfPivotGroupTotalColumnEnabled = () => {
|
|
300
|
+
// check that all AggregationColumns have identical AggFuncs
|
|
301
|
+
const aggregationColumns = layout.PivotAggregationColumns;
|
|
302
|
+
if (!aggregationColumns || aggregationColumns.length === 0) {
|
|
303
|
+
return true;
|
|
304
|
+
}
|
|
305
|
+
const firstAggFuncName = getAggFuncName(aggregationColumns[0].AggFunc);
|
|
306
|
+
if (layout.PivotAggregationColumns?.some((aggCol) => getAggFuncName(aggCol.AggFunc) !== firstAggFuncName)) {
|
|
307
|
+
return 'Requires identical aggregation on all columns';
|
|
308
|
+
}
|
|
309
|
+
// check that no Aggregation Total Column is enabled
|
|
310
|
+
const hasAggregationTotalColumn = aggregationColumns.some((aggCol) => aggCol.TotalColumn !== false && aggCol.TotalColumn != null);
|
|
311
|
+
if (hasAggregationTotalColumn) {
|
|
312
|
+
return 'Can only be enabled when no Aggregation Total Column is present';
|
|
313
|
+
}
|
|
314
|
+
return true;
|
|
315
|
+
};
|
|
316
|
+
const isPivotGroupTotalColumnEnabled = checkIfPivotGroupTotalColumnEnabled();
|
|
177
317
|
return (React.createElement(Tabs, { style: { height: '100%' } },
|
|
178
318
|
React.createElement(Tabs.Tab, null, "Column Aggregations"),
|
|
179
319
|
React.createElement(Tabs.Content, null,
|
|
180
320
|
React.createElement(Flex, null,
|
|
181
321
|
React.createElement(FormLayout, null,
|
|
182
|
-
React.createElement(
|
|
322
|
+
React.createElement(FormRow, { label: 'Omit Aggregation from Header' },
|
|
323
|
+
React.createElement(CheckBox, { checked: layout.SuppressAggFuncInHeader, onChange: handleSuppressAggFuncInHeader })),
|
|
324
|
+
React.createElement(FormRow, { label: 'Grand Total Row' },
|
|
325
|
+
React.createElement(Select, { style: { width: 120 }, options: ['top', 'bottom'].map((position) => {
|
|
326
|
+
return {
|
|
327
|
+
label: StringExtensions.CapitaliseFirstLetter(position),
|
|
328
|
+
value: position,
|
|
329
|
+
};
|
|
330
|
+
}), placeholder: "Off", value: layout.GrandTotalRow, onChange: (value) => {
|
|
331
|
+
props.onChange({
|
|
332
|
+
...layout,
|
|
333
|
+
GrandTotalRow: value,
|
|
334
|
+
});
|
|
335
|
+
}, isClearable: true })),
|
|
336
|
+
React.createElement(FormRow, { label: 'Grand Total Column' },
|
|
337
|
+
React.createElement(Select, { style: { width: 120 }, options: ['before', 'after'].map((position) => {
|
|
338
|
+
return {
|
|
339
|
+
label: StringExtensions.CapitaliseFirstLetter(position),
|
|
340
|
+
value: position,
|
|
341
|
+
};
|
|
342
|
+
}), placeholder: "Off", value: layout.GrandTotalColumn, onChange: (value) => {
|
|
343
|
+
props.onChange({
|
|
344
|
+
...layout,
|
|
345
|
+
GrandTotalColumn: value,
|
|
346
|
+
});
|
|
347
|
+
}, isClearable: true })),
|
|
348
|
+
React.createElement(FormRow, { label: 'Pivot Group Total Column' }, isPivotGroupTotalColumnEnabled === true ? (React.createElement(Select, { style: { width: 120 }, options: ['before', 'after'].map((position) => {
|
|
349
|
+
return {
|
|
350
|
+
label: StringExtensions.CapitaliseFirstLetter(position),
|
|
351
|
+
value: position,
|
|
352
|
+
};
|
|
353
|
+
}), placeholder: "Off", value: layout.PivotGroupTotalColumn, onChange: (value) => {
|
|
354
|
+
props.onChange({
|
|
355
|
+
...layout,
|
|
356
|
+
PivotGroupTotalColumn: value,
|
|
357
|
+
});
|
|
358
|
+
}, isClearable: true })) : (React.createElement(Text, { marginLeft: 1, style: { fontStyle: 'italic' } }, isPivotGroupTotalColumnEnabled))))),
|
|
183
359
|
React.createElement(ValueSelector, { showFilterInput: true, showSelectedOnlyPosition: "top", filter: 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: () => {
|
|
184
360
|
return `Active aggregations:`;
|
|
185
361
|
}, onChange: handleColumnsSelectionChange }))));
|
|
@@ -28,8 +28,10 @@ const INFINITE_COLUMNS_WITH_CHECKBOX = {
|
|
|
28
28
|
},
|
|
29
29
|
resizable: false,
|
|
30
30
|
defaultSortable: false,
|
|
31
|
-
renderSelectionCheckBox:
|
|
32
|
-
|
|
31
|
+
renderSelectionCheckBox: true,
|
|
32
|
+
className: 'ab-Select-CheckboxColumn',
|
|
33
|
+
renderValue: ({ renderBag }) => {
|
|
34
|
+
return React.createElement("div", { className: "InfiniteCell_content_value" }, renderBag.value);
|
|
33
35
|
},
|
|
34
36
|
renderHeader: (headerParams) => {
|
|
35
37
|
return (React.createElement(React.Fragment, null,
|
|
@@ -74,8 +76,15 @@ const doesOptionMatchValue = function (value) {
|
|
|
74
76
|
};
|
|
75
77
|
};
|
|
76
78
|
export const Select = function (props) {
|
|
79
|
+
let maxLabelLength = 0;
|
|
77
80
|
const ref = React.useRef(null);
|
|
78
|
-
const valueToOptionMap = new Map((props.options || []).map((opt) =>
|
|
81
|
+
const valueToOptionMap = new Map((props.options || []).map((opt) => {
|
|
82
|
+
let label = opt.label;
|
|
83
|
+
if (typeof label === 'string' || typeof label === 'number' || typeof label === 'boolean') {
|
|
84
|
+
maxLabelLength = Math.max(maxLabelLength, `${label}`.length);
|
|
85
|
+
}
|
|
86
|
+
return [opt.value, opt];
|
|
87
|
+
}));
|
|
79
88
|
const findOptionByValue = (value) => {
|
|
80
89
|
const option = valueToOptionMap.get(value);
|
|
81
90
|
if (option) {
|
|
@@ -416,7 +425,10 @@ export const Select = function (props) {
|
|
|
416
425
|
zIndex: 999999,
|
|
417
426
|
boxShadow: 'var(--ab-cmp-select-menu__box-shadow)',
|
|
418
427
|
minWidth: `var(--ab-cmp-select-menu__min-width)`,
|
|
428
|
+
width: `${Math.max(maxLabelLength, 10)}ch`,
|
|
419
429
|
'--ab-cmp-select-menu__min-height': `min(${(props.options || []).length + (showHeaderSelectionCheckbox ? 1 : 0)} * var(--ab-grid-row-height), 20rem)`,
|
|
430
|
+
maxHeight: 'var(--ab-cmp-select-menu__max-height)',
|
|
431
|
+
maxWidth: 'var(--ab-cmp-select-menu__max-width)',
|
|
420
432
|
...commonStyles(state),
|
|
421
433
|
...props.menuStyle,
|
|
422
434
|
};
|
package/src/env.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
NEXT_PUBLIC_INFINITE_TABLE_LICENSE_KEY: "StartDate=2021-06-29|EndDate=2030-01-01|Owner=Adaptable|Type=distribution|TS=1624971462479|C=137829811,1004007071,2756196225,1839832928,3994409405,636616862" || '',
|
|
3
|
-
PUBLISH_TIMESTAMP:
|
|
4
|
-
VERSION: "20.0.7-canary.
|
|
3
|
+
PUBLISH_TIMESTAMP: 1745834803008 || Date.now(),
|
|
4
|
+
VERSION: "20.0.7-canary.2" || '--current-version--',
|
|
5
5
|
};
|
|
@@ -72,8 +72,8 @@ export declare class LayoutManager<DATA_TYPE = any> extends LMEmitter {
|
|
|
72
72
|
applyPivotTotals(layout: PivotLayoutModel): void;
|
|
73
73
|
applyPivotExpandLevel(layout: PivotLayoutModel): void;
|
|
74
74
|
private withSuppressColumnAnimation;
|
|
75
|
+
private patchColDefType;
|
|
75
76
|
private setupPivotTotals;
|
|
76
|
-
private isPivotRowTotalColDef;
|
|
77
77
|
private patchPivotTotalColumn;
|
|
78
78
|
private getPivotTotalColumnConfig;
|
|
79
79
|
}
|
|
@@ -6,7 +6,9 @@ import { isLayoutEqual } from './isLayoutEqual';
|
|
|
6
6
|
import { simplifyLayoutModel, simplifyPivotLayoutModel, simplifyTableLayoutModel, } from './simplifyLayoutModel';
|
|
7
7
|
import { sortColumnIdsByOrder } from './sortColumnIdsByOrder';
|
|
8
8
|
import { destructurePivotColumnId } from './destructurePivotColumnId';
|
|
9
|
-
import {
|
|
9
|
+
import { isPivotAggTotalColumn } from './isPivotAggTotalColumn';
|
|
10
|
+
import { isPivotGrandTotalColumn } from './isPivotGrandTotalColumn';
|
|
11
|
+
import { isPivotGroupTotalColumn } from './isPivotGroupTotalColumn';
|
|
10
12
|
function flattenColDefs(colDefs) {
|
|
11
13
|
const res = [];
|
|
12
14
|
const iteration = (c) => {
|
|
@@ -1108,8 +1110,28 @@ export class LayoutManager extends LMEmitter {
|
|
|
1108
1110
|
}
|
|
1109
1111
|
return res;
|
|
1110
1112
|
}
|
|
1113
|
+
patchColDefType(colDef, colTypes) {
|
|
1114
|
+
const originalTypes = colDef.type == undefined ? [] : Array.isArray(colDef.type) ? colDef.type : [colDef.type];
|
|
1115
|
+
const columnTypes = new Set(originalTypes);
|
|
1116
|
+
colTypes.forEach((colType) => {
|
|
1117
|
+
columnTypes.add(colType);
|
|
1118
|
+
});
|
|
1119
|
+
colDef.type = Array.from(columnTypes);
|
|
1120
|
+
}
|
|
1111
1121
|
setupPivotTotals() {
|
|
1112
1122
|
const _original_processPivotResultColDef = this.gridApi.getGridOption('processPivotResultColDef');
|
|
1123
|
+
this.gridApi.setGridOption('processPivotResultColDef', (colDef) => {
|
|
1124
|
+
_original_processPivotResultColDef?.(colDef);
|
|
1125
|
+
if (!isPivotLayoutModel(this.currentLayout)) {
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
if (isPivotGrandTotalColumn(colDef)) {
|
|
1129
|
+
this.patchColDefType(colDef, ['pivotTotalColumn', 'pivotGrandTotalColumn']);
|
|
1130
|
+
}
|
|
1131
|
+
if (isPivotGroupTotalColumn(colDef.colId)) {
|
|
1132
|
+
this.patchColDefType(colDef, ['pivotTotalColumn', 'pivotGroupTotalColumn']);
|
|
1133
|
+
}
|
|
1134
|
+
});
|
|
1113
1135
|
const _original_processPivotResultColGroupDef = this.gridApi.getGridOption('processPivotResultColGroupDef');
|
|
1114
1136
|
this.gridApi.setGridOption('processPivotResultColGroupDef', (colGroupDef) => {
|
|
1115
1137
|
_original_processPivotResultColGroupDef?.(colGroupDef);
|
|
@@ -1119,9 +1141,6 @@ export class LayoutManager extends LMEmitter {
|
|
|
1119
1141
|
this.patchPivotTotalColumn(colGroupDef);
|
|
1120
1142
|
});
|
|
1121
1143
|
}
|
|
1122
|
-
isPivotRowTotalColDef(colDef) {
|
|
1123
|
-
return colDef.colId?.startsWith('PivotRowTotal_');
|
|
1124
|
-
}
|
|
1125
1144
|
patchPivotTotalColumn(colGroupDef) {
|
|
1126
1145
|
const hasPivotTotalCols = (pivotLayout) => {
|
|
1127
1146
|
return pivotLayout.PivotAggregationColumns?.some((aggCol) => !!aggCol.TotalColumn);
|
|
@@ -1135,7 +1154,7 @@ export class LayoutManager extends LMEmitter {
|
|
|
1135
1154
|
const pivotTotalColDefsAfter = [];
|
|
1136
1155
|
const normalColDefs = [];
|
|
1137
1156
|
colGroupDef.children.forEach((colDef) => {
|
|
1138
|
-
if (
|
|
1157
|
+
if (isPivotGrandTotalColumn(colDef)) {
|
|
1139
1158
|
if (this.gridApi.getGridOption('pivotRowTotals') === 'after') {
|
|
1140
1159
|
pivotRowTotalColDefsAfter.push(colDef);
|
|
1141
1160
|
}
|
|
@@ -1144,11 +1163,12 @@ export class LayoutManager extends LMEmitter {
|
|
|
1144
1163
|
}
|
|
1145
1164
|
return;
|
|
1146
1165
|
}
|
|
1147
|
-
if (
|
|
1166
|
+
if (isPivotAggTotalColumn(colDef)) {
|
|
1148
1167
|
if (!colDef.colId.startsWith('pivot_')) {
|
|
1149
1168
|
this.warn(`Pivot total column ${colDef.colId} is not prefixed with 'pivot_', skipping...`);
|
|
1150
1169
|
return;
|
|
1151
1170
|
}
|
|
1171
|
+
this.patchColDefType(colDef, ['pivotTotalColumn', 'pivotAggregationTotalColumn']);
|
|
1152
1172
|
// we do this for all total cols, but we will hide the ones that are not visible
|
|
1153
1173
|
colDef.columnGroupShow = undefined;
|
|
1154
1174
|
const totalColConfig = this.getPivotTotalColumnConfig(colDef, this.currentLayout);
|