@adaptabletools/adaptable 21.0.6 → 21.0.8
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/package.json +2 -1
- package/src/AdaptableOptions/DateInputOptions.d.ts +1 -1
- package/src/Api/Internal/AdaptableInternalApi.d.ts +1 -0
- package/src/Api/Internal/AdaptableInternalApi.js +9 -0
- package/src/Api/Internal/ColumnInternalApi.d.ts +1 -4
- package/src/Api/Internal/ColumnInternalApi.js +0 -12
- package/src/Api/Internal/ExportInternalApi.d.ts +1 -0
- package/src/Api/Internal/ExportInternalApi.js +3 -0
- package/src/Redux/Store/AdaptableStore.d.ts +0 -2
- package/src/Redux/Store/AdaptableStore.js +2 -2
- package/src/Utilities/Helpers/DateHelper.d.ts +0 -1
- package/src/Utilities/Helpers/DateHelper.js +28 -16
- package/src/View/Filter/FilterViewPanel.js +1 -1
- package/src/agGrid/AdaptableAgGrid.js +18 -5
- package/src/agGrid/AgGridColumnAdapter.js +61 -8
- package/src/agGrid/AgGridExportAdapter.js +21 -0
- package/src/env.js +2 -2
- package/src/layout-manager/src/index.js +16 -1
- package/src/layout-manager/src/normalizeLayoutModel.js +8 -3
- package/tsconfig.esm.tsbuildinfo +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adaptabletools/adaptable",
|
|
3
|
-
"version": "21.0.
|
|
3
|
+
"version": "21.0.8",
|
|
4
4
|
"description": "Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"web-components",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"react-select": "5.10.1",
|
|
54
54
|
"react-toastify": "9.1.3",
|
|
55
55
|
"rebass": "^3.2.2",
|
|
56
|
+
"@types/rebass": "^4.0.10",
|
|
56
57
|
"redux": "^5.0.1",
|
|
57
58
|
"rxjs": "^7.4.0",
|
|
58
59
|
"sentence-case": "^3.0.4",
|
|
@@ -123,4 +123,5 @@ export declare class AdaptableInternalApi extends ApiBase {
|
|
|
123
123
|
findAdaptableObjectsByLookupCriteria<T extends AdaptableObjectWithScope>({ scope, tag, ids }: AdaptableObjectLookupCriteria, specificAdaptableObjects: T[]): T[];
|
|
124
124
|
buildBaseContext(): BaseContext;
|
|
125
125
|
setCellSummaryInfo(cellSummaryInfo: CellSummmaryInfo): void;
|
|
126
|
+
parseDateValue(dateValue: string | Date | number): Date | undefined;
|
|
126
127
|
}
|
|
@@ -5,6 +5,7 @@ import StringExtensions from '../../Utilities/Extensions/StringExtensions';
|
|
|
5
5
|
import { ADAPTABLE_ID } from '../../Utilities/Constants/GeneralConstants';
|
|
6
6
|
import { waitForCondition } from '../../Utilities/waitForCondition';
|
|
7
7
|
import { isAdaptableCustomIcon, isAdaptableSystemIcon } from '../../components/Icon';
|
|
8
|
+
import { parseDateValue } from '../../Utilities/Helpers/DateHelper';
|
|
8
9
|
export class AdaptableInternalApi extends ApiBase {
|
|
9
10
|
getInternalState() {
|
|
10
11
|
return this.getAdaptableState().Internal;
|
|
@@ -439,4 +440,12 @@ export class AdaptableInternalApi extends ApiBase {
|
|
|
439
440
|
setCellSummaryInfo(cellSummaryInfo) {
|
|
440
441
|
this.dispatchAction(InternalRedux.SetCellSummaryInfo(cellSummaryInfo));
|
|
441
442
|
}
|
|
443
|
+
parseDateValue(dateValue) {
|
|
444
|
+
const dateFormat = this.getUserInterfaceOptions().dateInputOptions.dateFormat;
|
|
445
|
+
if (dateFormat === 'yyyy-MM-dd') {
|
|
446
|
+
// if the format is ISO, we don't pass it so that we use the date-fns `parseISO` which is more robust
|
|
447
|
+
return parseDateValue(dateValue);
|
|
448
|
+
}
|
|
449
|
+
return parseDateValue(dateValue, dateFormat);
|
|
450
|
+
}
|
|
442
451
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { ApiBase } from '../Implementation/ApiBase';
|
|
2
|
-
import { ColDef, Column, HeaderValueGetterParams
|
|
3
|
-
import { CustomSort } from '../../AdaptableState/CustomSortState';
|
|
4
|
-
import { ColumnValuesComparer } from '../../AdaptableOptions/CustomSortOptions';
|
|
2
|
+
import { ColDef, Column, HeaderValueGetterParams } from 'ag-grid-enterprise';
|
|
5
3
|
import { AdaptableColumn, AdaptableColumnDataType } from '../../types';
|
|
6
4
|
export declare function getAutoRowGroupColumnIdFor(columnId: string): string;
|
|
7
5
|
export declare class ColumnInternalApi extends ApiBase {
|
|
@@ -29,7 +27,6 @@ export declare class ColumnInternalApi extends ApiBase {
|
|
|
29
27
|
* @param columnId columnId to look up
|
|
30
28
|
*/
|
|
31
29
|
getAgGridColumnForAdaptableColumn(columnId: string): Column;
|
|
32
|
-
getActiveColumnComparator(columnId: string, customSort?: CustomSort, customSortComparer?: ColumnValuesComparer): (valueA: any, valueB: any, nodeA?: IRowNode, nodeB?: IRowNode, isInverted?: boolean) => number | undefined;
|
|
33
30
|
isSpecialColumn(columnId: string, column?: AdaptableColumn): boolean;
|
|
34
31
|
getColumnHeaderName(params: HeaderValueGetterParams): string;
|
|
35
32
|
private buildColumnHeaderContext;
|
|
@@ -64,18 +64,6 @@ export class ColumnInternalApi extends ApiBase {
|
|
|
64
64
|
getAgGridColumnForAdaptableColumn(columnId) {
|
|
65
65
|
return this._adaptable.getAgGridColumnForColumnId(columnId);
|
|
66
66
|
}
|
|
67
|
-
getActiveColumnComparator(columnId, customSort, customSortComparer) {
|
|
68
|
-
if ((!customSort || customSort?.IsSuspended) && !customSortComparer) {
|
|
69
|
-
// defaults to AG-Grid column definition comparator if no CustomSort is defined&active
|
|
70
|
-
const colDefComparator = this._adaptable.agGridColumnAdapter.getUserColDefProperty(columnId, 'comparator');
|
|
71
|
-
return colDefComparator;
|
|
72
|
-
}
|
|
73
|
-
// CustomSort Comparer function takes precedence over CustomSort SortedValues
|
|
74
|
-
const comparerFunction = customSortComparer
|
|
75
|
-
? customSortComparer.comparer
|
|
76
|
-
: this.getCustomSortApi().internalApi.getDefaultCustomSortComparer(customSort.ColumnId, customSort.SortedValues);
|
|
77
|
-
return comparerFunction;
|
|
78
|
-
}
|
|
79
67
|
isSpecialColumn(columnId, column = null) {
|
|
80
68
|
if (column) {
|
|
81
69
|
return column.isCalculatedColumn || column.isFreeTextColumn || column.isActionColumn;
|
|
@@ -14,6 +14,7 @@ export declare class ExportInternalApi extends ApiBase {
|
|
|
14
14
|
setExportInProgress(reportName: ReportNameType, reportFormat: ReportFormatType, exportDestination: ExportDestinationType): void;
|
|
15
15
|
setExportComplete(): void;
|
|
16
16
|
isVisualDataExportInProgress(): boolean;
|
|
17
|
+
isExcelExportInProgress(): boolean;
|
|
17
18
|
createSystemReport(systemReportName: SystemReportName): Report;
|
|
18
19
|
isSystemReport(reportName: ReportNameType): boolean;
|
|
19
20
|
isSystemDestination(destination: ExportDestinationType): boolean;
|
|
@@ -82,6 +82,9 @@ export class ExportInternalApi extends ApiBase {
|
|
|
82
82
|
isVisualDataExportInProgress() {
|
|
83
83
|
return this.getAdaptableState().Internal.Export.inProgress?.reportFormat === 'VisualExcel';
|
|
84
84
|
}
|
|
85
|
+
isExcelExportInProgress() {
|
|
86
|
+
return this.getAdaptableState().Internal.Export.inProgress?.reportFormat === 'Excel';
|
|
87
|
+
}
|
|
85
88
|
createSystemReport(systemReportName) {
|
|
86
89
|
switch (systemReportName) {
|
|
87
90
|
case ALL_DATA_REPORT:
|
|
@@ -5,8 +5,6 @@ import { BaseState } from '../../AdaptableState/BaseState';
|
|
|
5
5
|
import { IAdaptableStore, LoadStoreConfig } from './Interface/IAdaptableStore';
|
|
6
6
|
type EmitterCallback = (data?: any) => any;
|
|
7
7
|
type EmitterAnyCallback = (eventName: string, data?: any) => any;
|
|
8
|
-
export declare const INIT_STATE = "INIT_STATE";
|
|
9
|
-
export declare const LOAD_STATE = "LOAD_STATE";
|
|
10
8
|
export interface ResetUserDataAction extends Redux.Action {
|
|
11
9
|
}
|
|
12
10
|
export interface InitStateAction extends Redux.Action {
|
|
@@ -40,8 +40,8 @@ import * as ThemeRedux from '../ActionsReducers/ThemeRedux';
|
|
|
40
40
|
import * as ToolPanelRedux from '../ActionsReducers/ToolPanelRedux';
|
|
41
41
|
import { isAdaptableSharedEntity, isCustomSharedEntity, } from '../../AdaptableState/TeamSharingState';
|
|
42
42
|
import { buildAdaptableStateFunctionConfig } from './buildAdaptableStateFunctionConfig';
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
const INIT_STATE = 'INIT_STATE';
|
|
44
|
+
const LOAD_STATE = 'LOAD_STATE';
|
|
45
45
|
const NON_PERSIST_ACTIONS = {
|
|
46
46
|
'@@INIT': true,
|
|
47
47
|
'@@redux/init': true,
|
|
@@ -8,4 +8,3 @@ export declare const isValueValidDate: (data: any) => boolean;
|
|
|
8
8
|
export declare const dateToISO: (date: Date | number | string) => string;
|
|
9
9
|
export declare const parseToISO: (date: string | Date | number, dateFormat?: string) => string;
|
|
10
10
|
export declare const parseDateValue: (dateValue: string | Date | number, dateFormat?: string) => Date | undefined;
|
|
11
|
-
export declare const parseFilterInputDate: (stringDate: string) => Date;
|
|
@@ -23,6 +23,9 @@ export const parseToISO = (date, dateFormat) => {
|
|
|
23
23
|
const dateInstance = parseDateValue(date, dateFormat);
|
|
24
24
|
return isValidDate(dateInstance) ? dateToISO(dateInstance) : '';
|
|
25
25
|
};
|
|
26
|
+
// !!!
|
|
27
|
+
// AFL: ideally we should NEVER call directly this method, but use the AdaptableInternalApi.parseDateValue() instead
|
|
28
|
+
// we should refactor this with the first opportunity
|
|
26
29
|
export const parseDateValue = (dateValue, dateFormat) => {
|
|
27
30
|
if (dateValue == undefined || (typeof dateValue === 'string' && dateValue.trim() === '')) {
|
|
28
31
|
return undefined;
|
|
@@ -30,27 +33,36 @@ export const parseDateValue = (dateValue, dateFormat) => {
|
|
|
30
33
|
if (dateValue instanceof Date) {
|
|
31
34
|
return !isNaN(dateValue.getTime()) ? dateValue : undefined;
|
|
32
35
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
else {
|
|
38
|
-
// typeof dateValue === 'string'
|
|
39
|
-
if (dateFormat) {
|
|
40
|
-
dateInstance = parse(dateValue, dateFormat, new Date());
|
|
36
|
+
try {
|
|
37
|
+
let dateInstance;
|
|
38
|
+
if (typeof dateValue === 'number') {
|
|
39
|
+
dateInstance = new Date(dateValue);
|
|
41
40
|
}
|
|
42
41
|
else {
|
|
43
|
-
|
|
42
|
+
// typeof dateValue === 'string'
|
|
43
|
+
if (dateFormat) {
|
|
44
|
+
dateInstance = parse(dateValue, dateFormat, new Date());
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
dateInstance = parseISO(dateValue);
|
|
48
|
+
}
|
|
49
|
+
if (!isValidDate(dateInstance)) {
|
|
50
|
+
// last chance: try to use the native Date.parse(), https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse
|
|
51
|
+
dateInstance = new Date(Date.parse(dateValue));
|
|
52
|
+
}
|
|
44
53
|
}
|
|
45
54
|
if (!isValidDate(dateInstance)) {
|
|
46
|
-
|
|
47
|
-
dateInstance =
|
|
55
|
+
AdaptableLogger.consoleWarnBase(`Invalid date value "${dateValue}" - cannot be converted to a Date instance. Please make sure you specify adaptableOptions.userInterfaceOptions.dateInputOptions.dateFormat correctly.`);
|
|
56
|
+
dateInstance = undefined;
|
|
48
57
|
}
|
|
58
|
+
return dateInstance;
|
|
49
59
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
60
|
+
catch (error) {
|
|
61
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
62
|
+
const errorStack = error instanceof Error ? error.stack : undefined;
|
|
63
|
+
AdaptableLogger.consoleErrorBase(`Error parsing date value "${dateValue}": ${errorMessage}`, {
|
|
64
|
+
stack: errorStack,
|
|
65
|
+
originalError: error,
|
|
66
|
+
});
|
|
53
67
|
}
|
|
54
|
-
return dateInstance;
|
|
55
68
|
};
|
|
56
|
-
export const parseFilterInputDate = (stringDate) => new Date(stringDate);
|
|
@@ -31,7 +31,7 @@ class FilterViewPanelComponent extends React.Component {
|
|
|
31
31
|
ArrayExtensions.IsNotNullOrEmpty(this.props.ColumnFilters) && (React.createElement(AdaptablePopover, { popupPadding: 0, className: `ab-${elementType}__Filter__info`, headerText: "", bodyText: [React.createElement(ActiveFiltersPanel, null)], useButton: true, showEvent: 'focus', hideEvent: "blur", popoverMinWidth: 400 })),
|
|
32
32
|
React.createElement(ButtonClear, { "aria-label": 'Clear Filters', className: `ab-${elementType}__Filter__clear`, marginLeft: 1, marginBottom: 0, marginRight: 1, onClick: () => this.onClearFilters(), tooltip: "Clear Filters", disabled: this.props.ColumnFilters.length == 0, showText: this.props.viewType === 'ToolPanel' }, this.props.viewType === 'ToolPanel' && 'Clear'),
|
|
33
33
|
React.createElement(SimpleButton, { "aria-label": isAtLeastOneFilterActive ? 'Suspend All Filters' : 'Resume All Filters', className: join(`ab-${elementType}__Filter__suspend-button`, isAtLeastOneFilterActive && `ab-${elementType}__Filter__suspend-all`, !isAtLeastOneFilterActive && `ab-${elementType}__Filter__un-suspend-all`), disabled: !isAtLeastOneFilter, onClick: handleSuspendUnsuspendAll, tone: isAtLeastOneFilterActive ? 'neutral' : 'success', variant: "text", icon: isAtLeastOneFilterActive ? 'pause' : 'play', accessLevel: this.props.accessLevel })),
|
|
34
|
-
React.createElement(Flex, { alignItems: "center" }, this.props.api.filterApi.columnFilterApi.isQuickFilterAvailable() && (React.createElement(CheckBox, { className: `ab-${elementType}__Filter__active-check`, disabled: this.props.accessLevel === 'ReadOnly' ||
|
|
34
|
+
React.createElement(Flex, { alignItems: "center" }, this.props.api.filterApi.columnFilterApi.isQuickFilterAvailable() && (React.createElement(CheckBox, { "data-name": "quick-filter-toggle", className: `ab-${elementType}__Filter__active-check`, disabled: this.props.accessLevel === 'ReadOnly' ||
|
|
35
35
|
this.props.api.layoutApi.isCurrentLayoutPivot(), marginTop: 0, marginBottom: 0, fontSize: 2, padding: 1, checked: this.props.IsQuickFilterVisible, onChange: (checked) => {
|
|
36
36
|
checked ? this.props.onShowQuickFilterBar() : this.props.onHideQuickFilterBar();
|
|
37
37
|
} }, "Filter Bar")))));
|
|
@@ -1085,6 +1085,24 @@ You need to define at least one Layout!`);
|
|
|
1085
1085
|
color: '#aaaaaa',
|
|
1086
1086
|
pattern: 'Solid',
|
|
1087
1087
|
},
|
|
1088
|
+
},
|
|
1089
|
+
// see #EXCEL_EXPORT_DATA_TYPES
|
|
1090
|
+
{
|
|
1091
|
+
id: 'stringExcelType',
|
|
1092
|
+
dataType: 'String',
|
|
1093
|
+
}, {
|
|
1094
|
+
id: 'booleanExcelType',
|
|
1095
|
+
dataType: 'Boolean',
|
|
1096
|
+
}, {
|
|
1097
|
+
id: 'dateExcelType',
|
|
1098
|
+
dataType: 'DateTime',
|
|
1099
|
+
}, {
|
|
1100
|
+
id: 'numberExcelType',
|
|
1101
|
+
// dataType: 'Number',
|
|
1102
|
+
// AG Grid requires either dataType or numberFormat to be set for Numbers
|
|
1103
|
+
numberFormat: {
|
|
1104
|
+
format: '0.###############',
|
|
1105
|
+
},
|
|
1088
1106
|
});
|
|
1089
1107
|
this.agGridExportAdapter.originalExcelStyles = excelStyles;
|
|
1090
1108
|
this.agGridExportAdapter.DANGER_excelStyles = this.agGridExportAdapter.originalExcelStyles;
|
|
@@ -3195,11 +3213,6 @@ You need to define at least one Layout!`);
|
|
|
3195
3213
|
return this.agGridModulesAdapter.isAgGridModuleRegistered('CsvExportModule');
|
|
3196
3214
|
}
|
|
3197
3215
|
isQuickFilterAvailable() {
|
|
3198
|
-
if (this.api.layoutApi.isCurrentLayoutPivot() &&
|
|
3199
|
-
this.adaptableOptions.filterOptions.useAdaptableFiltering) {
|
|
3200
|
-
// hide completely the quick filter if pivot is enabled
|
|
3201
|
-
return false;
|
|
3202
|
-
}
|
|
3203
3216
|
return this.hasFloatingFilterOnAtLeastOneColumn(this.agGridAdapter.getAgGridApi().getColumnDefs());
|
|
3204
3217
|
}
|
|
3205
3218
|
hasFloatingFilterOnAtLeastOneColumn(columnDefs) {
|
|
@@ -169,11 +169,27 @@ export class AgGridColumnAdapter {
|
|
|
169
169
|
if (!gridCell.column) {
|
|
170
170
|
return null;
|
|
171
171
|
}
|
|
172
|
-
|
|
173
|
-
|
|
172
|
+
const isExcelExport = this.adaptableApi.exportApi.internalApi.isExcelExportInProgress();
|
|
173
|
+
const isVisualDataExport = this.adaptableApi.exportApi.internalApi.isVisualDataExportInProgress();
|
|
174
|
+
if (isExcelExport || isVisualDataExport) {
|
|
175
|
+
const excelStyleClasses = [];
|
|
174
176
|
const userDefinedCellClass = typeof userCellClass === 'function' ? userCellClass(params) : userCellClass;
|
|
175
|
-
|
|
176
|
-
|
|
177
|
+
if (userDefinedCellClass) {
|
|
178
|
+
if (Array.isArray(userDefinedCellClass)) {
|
|
179
|
+
excelStyleClasses.push(...userDefinedCellClass.filter(Boolean));
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
excelStyleClasses.push(userDefinedCellClass);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (isVisualDataExport) {
|
|
186
|
+
const cellClassKey = AgGridExportAdapter.getExcelClassNameForCell(colId, gridCell.primaryKeyValue, userDefinedCellClass);
|
|
187
|
+
const customCellClass = this.adaptableInstance.agGridExportAdapter.getExcelStyleIdForCellClassKey(cellClassKey);
|
|
188
|
+
if (customCellClass) {
|
|
189
|
+
excelStyleClasses.push(customCellClass);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return excelStyleClasses.length ? excelStyleClasses : null;
|
|
177
193
|
}
|
|
178
194
|
const isQuickSearchActive = this.isQuickSearchActive(gridCell);
|
|
179
195
|
const editableClassName = this.getEditableCellClass(gridCell, params);
|
|
@@ -612,7 +628,7 @@ export class AgGridColumnAdapter {
|
|
|
612
628
|
const isFloatingFilterDisabled = !colDef.filter ||
|
|
613
629
|
!colDef.floatingFilter ||
|
|
614
630
|
!this.adaptableOptions.filterOptions.useAdaptableFiltering ||
|
|
615
|
-
!this.
|
|
631
|
+
!this.adaptableApi.filterApi.columnFilterApi.isQuickFilterVisible();
|
|
616
632
|
if (this.adaptableApi.columnApi.isAutoRowGroupColumn(col.getColId())) {
|
|
617
633
|
this.setColDefProperty(col, 'floatingFilter', (original_floatingFilter) => {
|
|
618
634
|
// the floating filter for the group column is "inherited" from the base column
|
|
@@ -803,10 +819,47 @@ export class AgGridColumnAdapter {
|
|
|
803
819
|
}
|
|
804
820
|
setupColumnComparator({ col, colId, abColumn }) {
|
|
805
821
|
const customSort = this.adaptableApi.customSortApi.getCustomSortForColumn(colId);
|
|
806
|
-
const
|
|
822
|
+
const customSortComparer = this.adaptableApi.customSortApi.internalApi.getCustomSortComparer(abColumn.columnId);
|
|
823
|
+
const memoizedDateValues = new Map();
|
|
824
|
+
const getDateValue = (rawDateValue) => {
|
|
825
|
+
if (memoizedDateValues.has(rawDateValue)) {
|
|
826
|
+
return memoizedDateValues.get(rawDateValue);
|
|
827
|
+
}
|
|
828
|
+
const dateValue = this.adaptableApi.internalApi.parseDateValue(rawDateValue);
|
|
829
|
+
memoizedDateValues.set(rawDateValue, dateValue);
|
|
830
|
+
return dateValue;
|
|
831
|
+
};
|
|
807
832
|
const comparatorGetter = (propName) => {
|
|
808
|
-
return () => {
|
|
809
|
-
|
|
833
|
+
return (userPropertyValue) => {
|
|
834
|
+
// CustomSort Comparer function takes precedence over CustomSort SortedValues
|
|
835
|
+
if (customSortComparer) {
|
|
836
|
+
return customSortComparer.comparer;
|
|
837
|
+
}
|
|
838
|
+
if (customSort && !customSort.IsSuspended) {
|
|
839
|
+
return this.adaptableApi.customSortApi.internalApi.getDefaultCustomSortComparer(customSort.ColumnId, customSort.SortedValues);
|
|
840
|
+
}
|
|
841
|
+
if (userPropertyValue) {
|
|
842
|
+
return userPropertyValue;
|
|
843
|
+
}
|
|
844
|
+
// for DATE columns we have to use the normalised values (Date objects) to compare
|
|
845
|
+
if (abColumn.dataType === 'date') {
|
|
846
|
+
return (valueA, valueB) => {
|
|
847
|
+
const dateA = getDateValue(valueA);
|
|
848
|
+
const dateB = getDateValue(valueB);
|
|
849
|
+
if (dateA && dateB) {
|
|
850
|
+
return dateA.getTime() - dateB.getTime();
|
|
851
|
+
}
|
|
852
|
+
else if (dateA) {
|
|
853
|
+
return 1; // consider non-null dates as greater than null/undefined
|
|
854
|
+
}
|
|
855
|
+
else if (dateB) {
|
|
856
|
+
return -1; // consider non-null dates as greater than null/undefined
|
|
857
|
+
}
|
|
858
|
+
else {
|
|
859
|
+
return 0; // both are null/undefined, considered equal
|
|
860
|
+
}
|
|
861
|
+
};
|
|
862
|
+
}
|
|
810
863
|
};
|
|
811
864
|
};
|
|
812
865
|
this.setColDefProperty(col, 'comparator', comparatorGetter('comparator'));
|
|
@@ -602,6 +602,27 @@ export class AgGridExportAdapter {
|
|
|
602
602
|
this.registerExcelStyle(finalCellExcelStyle, cellClassId);
|
|
603
603
|
});
|
|
604
604
|
}, forAllVisibleRowNodesDoConfig);
|
|
605
|
+
// see #EXCEL_EXPORT_DATA_TYPES
|
|
606
|
+
this.excelStylesCache['stringExcelType'] = {
|
|
607
|
+
id: 'stringExcelType',
|
|
608
|
+
dataType: 'String',
|
|
609
|
+
};
|
|
610
|
+
this.excelStylesCache['booleanExcelType'] = {
|
|
611
|
+
id: 'booleanExcelType',
|
|
612
|
+
dataType: 'Boolean',
|
|
613
|
+
};
|
|
614
|
+
this.excelStylesCache['dateExcelType'] = {
|
|
615
|
+
id: 'dateExcelType',
|
|
616
|
+
dataType: 'DateTime',
|
|
617
|
+
};
|
|
618
|
+
this.excelStylesCache['numberExcelType'] = {
|
|
619
|
+
id: 'numberExcelType',
|
|
620
|
+
// dataType: 'Number',
|
|
621
|
+
// AG Grid requires either dataType or numberFormat to be set for Numbers
|
|
622
|
+
numberFormat: {
|
|
623
|
+
format: '0.###############',
|
|
624
|
+
},
|
|
625
|
+
};
|
|
605
626
|
return Object.values(this.excelStylesCache);
|
|
606
627
|
}
|
|
607
628
|
registerExcelStyle(excelStyle, cellClassKey) {
|
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: "21.0.
|
|
3
|
+
PUBLISH_TIMESTAMP: 1761108086778 || Date.now(),
|
|
4
|
+
VERSION: "21.0.8" || '--current-version--',
|
|
5
5
|
};
|
|
@@ -333,6 +333,8 @@ export class LayoutManager extends LMEmitter {
|
|
|
333
333
|
getPivotLayoutModelFromGrid() {
|
|
334
334
|
const pivotResultColumns = this.gridApi.getPivotResultColumns() || [];
|
|
335
335
|
const pivotResultColumnsSet = new Set(pivotResultColumns.map((col) => col.getColId()));
|
|
336
|
+
const rowGroupColumns = this.gridApi.getRowGroupColumns() || [];
|
|
337
|
+
const rowGroupColumnsSet = new Set(rowGroupColumns.map((col) => col.getColId()));
|
|
336
338
|
const prevLayout = this.currentLayout;
|
|
337
339
|
const columnState = this.gridApi
|
|
338
340
|
.getColumnState()
|
|
@@ -340,6 +342,7 @@ export class LayoutManager extends LMEmitter {
|
|
|
340
342
|
let PivotColumns = this.gridApi.getPivotColumns().map((col) => col.getColId());
|
|
341
343
|
const layout = this.getUndecidedLayoutModelFromGrid(columnState);
|
|
342
344
|
let ColumnSizing = layout.ColumnSizing || {};
|
|
345
|
+
let ColumnVisibility = { ...layout.ColumnVisibility };
|
|
343
346
|
//let's also include the column widths of the pivotResult columns
|
|
344
347
|
pivotResultColumns.forEach((col) => {
|
|
345
348
|
const colId = col.getColId();
|
|
@@ -355,6 +358,18 @@ export class LayoutManager extends LMEmitter {
|
|
|
355
358
|
if (!Object.keys(ColumnSizing).length) {
|
|
356
359
|
ColumnSizing = undefined;
|
|
357
360
|
}
|
|
361
|
+
// from column visibility, let's remove all columns that are not actually in the pivot layout
|
|
362
|
+
// since having normal table columns here will break the equality check
|
|
363
|
+
// so we only want to keep the group columns and the pivot result columns
|
|
364
|
+
Object.keys(ColumnVisibility).forEach((colId) => {
|
|
365
|
+
const isInLayout = pivotResultColumnsSet.has(colId) || rowGroupColumnsSet.has(colId);
|
|
366
|
+
if (!isInLayout) {
|
|
367
|
+
delete ColumnVisibility[colId];
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
if (!Object.keys(ColumnVisibility).length) {
|
|
371
|
+
ColumnVisibility = undefined;
|
|
372
|
+
}
|
|
358
373
|
delete layout.TableColumns;
|
|
359
374
|
const pivotLayout = {
|
|
360
375
|
Name: layout.Name,
|
|
@@ -372,7 +387,7 @@ export class LayoutManager extends LMEmitter {
|
|
|
372
387
|
ColumnPinning: layout.ColumnPinning,
|
|
373
388
|
ColumnSorts: layout.ColumnSorts,
|
|
374
389
|
ColumnSizing,
|
|
375
|
-
ColumnVisibility
|
|
390
|
+
ColumnVisibility,
|
|
376
391
|
RowGroupValues: layout.RowGroupValues,
|
|
377
392
|
ColumnGroupValues: layout.ColumnGroupValues,
|
|
378
393
|
PivotGroupedColumns: layout.RowGroupedColumns,
|
|
@@ -102,6 +102,11 @@ export function normalizeTableLayoutModel(layout, options) {
|
|
|
102
102
|
};
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
|
+
// there might be a case where there are we have an RowGroupedColumns array, but it's empty (or it's inexistent altogether)
|
|
106
|
+
// and there is no display type specified - so default it to single
|
|
107
|
+
if (!layout.RowGroupDisplayType && layout.TableColumns) {
|
|
108
|
+
layout.RowGroupDisplayType = 'single';
|
|
109
|
+
}
|
|
105
110
|
if (options?.isTree && !layout.TableColumns.includes(AUTO_GROUP_COLUMN_ID__SINGLE)) {
|
|
106
111
|
layout.TableColumns.unshift(AUTO_GROUP_COLUMN_ID__SINGLE);
|
|
107
112
|
}
|
|
@@ -157,9 +162,9 @@ export function normalizePivotLayoutModel(layout) {
|
|
|
157
162
|
// make it an own property
|
|
158
163
|
layout.PivotColumnTotal = undefined;
|
|
159
164
|
}
|
|
160
|
-
if (layout.PivotGroupedColumns && layout.PivotGroupedColumns.length) {
|
|
161
|
-
|
|
162
|
-
}
|
|
165
|
+
// if (layout.PivotGroupedColumns && layout.PivotGroupedColumns.length) {
|
|
166
|
+
layout.RowGroupDisplayType = layout.RowGroupDisplayType || 'single';
|
|
167
|
+
// }
|
|
163
168
|
return layout;
|
|
164
169
|
}
|
|
165
170
|
export function normalizeLayoutModel(layout, options) {
|