From 831773b8070ea766dd13a37f1ff8a4b1c2018d08 Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Thu, 17 Jun 2021 16:23:13 -0400 Subject: [PATCH] fix(state): changeColumnsArrangement should work w/columnIndexPosition --- .../__tests__/gridState.service.spec.ts | 12 ++++- .../services/extension.service.ts | 12 ++--- .../services/gridState.service.ts | 51 ++++++++++++------- 3 files changed, 49 insertions(+), 26 deletions(-) diff --git a/src/app/modules/angular-slickgrid/services/__tests__/gridState.service.spec.ts b/src/app/modules/angular-slickgrid/services/__tests__/gridState.service.spec.ts index 394d86a72..a3decc2a0 100644 --- a/src/app/modules/angular-slickgrid/services/__tests__/gridState.service.spec.ts +++ b/src/app/modules/angular-slickgrid/services/__tests__/gridState.service.spec.ts @@ -9,6 +9,7 @@ import { SortService } from '../sort.service'; import { TreeDataService } from '../treeData.service'; import { BackendService, + CheckboxSelector, CurrentFilter, CurrentPagination, CurrentPinning, @@ -21,8 +22,11 @@ import { GridState, GridStateChange, GridStateType, + RowDetailView, + RowMoveManager, TreeToggleStateChange, } from '../../models'; +import { RowMoveManagerExtension } from '../../extensions'; declare const Slick: any; @@ -165,9 +169,9 @@ describe('GridStateService', () => { beforeEach(() => { allColumnsMock = [ - rowCheckboxColumnMock, rowDetailColumnMock, rowMoveColumnMock, + rowCheckboxColumnMock, { id: 'field1', field: 'field1', width: 100, cssClass: 'red' }, { id: 'field2', field: 'field2', width: 150, headerCssClass: 'blue' }, { id: 'field3', field: 'field3' }, @@ -196,6 +200,10 @@ describe('GridStateService', () => { gridOptionMock.enableCheckboxSelector = true; gridOptionMock.enableRowDetailView = true; gridOptionMock.enableRowMoveManager = true; + gridOptionMock.rowDetailView = { columnIndexPosition: 0 } as unknown as RowDetailView; + gridOptionMock.rowMoveManager = { columnIndexPosition: 1 } as unknown as RowMoveManager; + gridOptionMock.checkboxSelector = { columnIndexPosition: 2 } as unknown as CheckboxSelector; + jest.spyOn(SharedService.prototype, 'allColumns', 'get').mockReturnValue(allColumnsMock); const setColsSpy = jest.spyOn(gridStub, 'setColumns'); const autoSizeSpy = jest.spyOn(gridStub, 'autosizeColumns'); @@ -203,7 +211,7 @@ describe('GridStateService', () => { service.changeColumnsArrangement(presetColumnsMock); - expect(setColsSpy).toHaveBeenCalledWith([rowCheckboxColumnMock, rowDetailColumnMock, rowMoveColumnMock, ...columnsWithoutCheckboxMock]); + expect(setColsSpy).toHaveBeenCalledWith([rowDetailColumnMock, rowMoveColumnMock, rowCheckboxColumnMock, ...columnsWithoutCheckboxMock]); expect(autoSizeSpy).toHaveBeenCalled(); expect(resizeByContentSpy).not.toHaveBeenCalled(); }); diff --git a/src/app/modules/angular-slickgrid/services/extension.service.ts b/src/app/modules/angular-slickgrid/services/extension.service.ts index 639179607..90ab4a5bd 100644 --- a/src/app/modules/angular-slickgrid/services/extension.service.ts +++ b/src/app/modules/angular-slickgrid/services/extension.service.ts @@ -33,7 +33,7 @@ import { SharedService } from './shared.service'; interface ExtensionWithColumnIndexPosition { name: ExtensionName; - position: number; + columnIndexPosition: number; extension: CheckboxSelectorExtension | RowDetailViewExtension | RowMoveManagerExtension; } @@ -286,23 +286,23 @@ export class ExtensionService { * @param gridOptions */ createExtensionsBeforeGridCreation(columnDefinitions: Column[], gridOptions: GridOption) { - const featureWithColumnIndexPositions: { name: ExtensionName; position: number; extension: CheckboxSelectorExtension | RowDetailViewExtension | RowMoveManagerExtension; }[] = []; + const featureWithColumnIndexPositions: ExtensionWithColumnIndexPosition[] = []; // the following 3 features might have `columnIndexPosition` that we need to respect their column order, we will execute them by their sort order further down // we push them into a array and we'll process them by their position (if provided, else use same order that they were inserted) if (gridOptions.enableCheckboxSelector) { if (!this.getCreatedExtensionByName(ExtensionName.checkboxSelector)) { - featureWithColumnIndexPositions.push({ name: ExtensionName.checkboxSelector, extension: this.checkboxSelectorExtension, position: gridOptions?.checkboxSelector?.columnIndexPosition ?? featureWithColumnIndexPositions.length }); + featureWithColumnIndexPositions.push({ name: ExtensionName.checkboxSelector, extension: this.checkboxSelectorExtension, columnIndexPosition: gridOptions?.checkboxSelector?.columnIndexPosition ?? featureWithColumnIndexPositions.length }); } } if (gridOptions.enableRowMoveManager) { if (!this.getCreatedExtensionByName(ExtensionName.rowMoveManager)) { - featureWithColumnIndexPositions.push({ name: ExtensionName.rowMoveManager, extension: this.rowMoveManagerExtension, position: gridOptions?.rowMoveManager?.columnIndexPosition ?? featureWithColumnIndexPositions.length }); + featureWithColumnIndexPositions.push({ name: ExtensionName.rowMoveManager, extension: this.rowMoveManagerExtension, columnIndexPosition: gridOptions?.rowMoveManager?.columnIndexPosition ?? featureWithColumnIndexPositions.length }); } } if (gridOptions.enableRowDetailView) { if (!this.getCreatedExtensionByName(ExtensionName.rowDetailView)) { - featureWithColumnIndexPositions.push({ name: ExtensionName.rowDetailView, extension: this.rowDetailViewExtension, position: gridOptions?.rowDetailView?.columnIndexPosition ?? featureWithColumnIndexPositions.length }); + featureWithColumnIndexPositions.push({ name: ExtensionName.rowDetailView, extension: this.rowDetailViewExtension, columnIndexPosition: gridOptions?.rowDetailView?.columnIndexPosition ?? featureWithColumnIndexPositions.length }); } } @@ -462,7 +462,7 @@ export class ExtensionService { */ private createExtensionByTheirColumnIndex(featureWithIndexPositions: ExtensionWithColumnIndexPosition[], columnDefinitions: Column[], gridOptions: GridOption) { // 1- first step is to sort them by their index position - featureWithIndexPositions.sort((feat1, feat2) => feat1.position - feat2.position); + featureWithIndexPositions.sort((feat1, feat2) => feat1.columnIndexPosition - feat2.columnIndexPosition); // 2- second step, we can now proceed to create each extension/addon and that will position them accordingly in the column definitions list featureWithIndexPositions.forEach(feature => { diff --git a/src/app/modules/angular-slickgrid/services/gridState.service.ts b/src/app/modules/angular-slickgrid/services/gridState.service.ts index 6bc708ee0..5e0893f7d 100644 --- a/src/app/modules/angular-slickgrid/services/gridState.service.ts +++ b/src/app/modules/angular-slickgrid/services/gridState.service.ts @@ -183,15 +183,23 @@ export class GridStateService { if (newArrangedColumns && Array.isArray(newArrangedColumns) && newArrangedColumns.length > 0) { // make sure that the checkbox selector is still visible in the list when it is enabled if (Array.isArray(this.sharedService.allColumns)) { + const dynamicAddonColumnByIndexPositionList: { columnId: string; columnIndexPosition: number; }[] = []; + if (this._gridOptions.enableCheckboxSelector) { - this.addColumnDynamicWhenFeatureEnabled('_checkbox_selector', this.sharedService.allColumns, newArrangedColumns); + const columnIndexPosition = this._gridOptions?.checkboxSelector?.columnIndexPosition ?? 0; + dynamicAddonColumnByIndexPositionList.push({ columnId: '_checkbox_selector', columnIndexPosition }); } if (this._gridOptions.enableRowDetailView) { - this.addColumnDynamicWhenFeatureEnabled('_detail_selector', this.sharedService.allColumns, newArrangedColumns); + const columnIndexPosition = this._gridOptions?.rowDetailView?.columnIndexPosition ?? 0; + dynamicAddonColumnByIndexPositionList.push({ columnId: '_detail_selector', columnIndexPosition }); } if (this._gridOptions.enableRowMoveManager) { - this.addColumnDynamicWhenFeatureEnabled('_move', this.sharedService.allColumns, newArrangedColumns); + const columnIndexPosition = this._gridOptions?.rowMoveManager?.columnIndexPosition ?? 0; + dynamicAddonColumnByIndexPositionList.push({ columnId: '_move', columnIndexPosition }); } + + // since some features could have a `columnIndexPosition`, we need to make sure these indexes are respected in the column definitions + this.addColumnDynamicWhenFeatureEnabled(dynamicAddonColumnByIndexPositionList, this.sharedService.allColumns, newArrangedColumns); } // keep copy the original optional `width` properties optionally provided by the user. @@ -475,21 +483,28 @@ export class GridStateService { // ------------------ /** - * Add certain column(s), when the feature is/are enabled, to an output column definitions array (by reference). - * Basically some features (for example: Row Selection, Row Detail, Row Move) will be added as column(s) dynamically and internally by the lib, - * we just ask the developer to enable the feature, via flags, and internally the lib will create the necessary column. - * So specifically for these column(s) and feature(s), we need to re-add them internally when the user calls the `changeColumnsArrangement()` method. - * @param {String} dynamicColumnName - the column name that will be re-added (if it wasn't already found in the output array) dynamically - * @param {Array} fullColumnDefinitions - full column definitions array that includes every columns (including Row Selection, Row Detail, Row Move when enabled) - * @param {Array} newArrangedColumns - output array that will be use to show in the UI (it could have less columns than fullColumnDefinitions array since user might hide some columns) - */ - addColumnDynamicWhenFeatureEnabled(dynamicColumnName: string, fullColumnDefinitions: Column[], newArrangedColumns: Column[]) { - const checkboxColumnIdx = fullColumnDefinitions.findIndex(col => col.id === dynamicColumnName); - const associatedGridCheckboxColumnIdx = newArrangedColumns.findIndex(col => col.id === dynamicColumnName); - if (checkboxColumnIdx >= 0 && associatedGridCheckboxColumnIdx === -1) { - const checkboxColumn = fullColumnDefinitions[checkboxColumnIdx]; - checkboxColumnIdx === 0 ? newArrangedColumns.unshift(checkboxColumn) : newArrangedColumns.splice(checkboxColumnIdx, 0, checkboxColumn); - } + * Add certain column(s), when the feature is/are enabled, to an output column definitions array (by reference). + * Basically some features (for example: Row Selection, Row Detail, Row Move) will be added as column(s) dynamically and internally by the lib, + * we just ask the developer to enable the feature, via flags, and internally the lib will create the necessary column. + * So specifically for these column(s) and feature(s), we need to re-add them internally when the user calls the `changeColumnsArrangement()` method. + * @param {Array} dynamicAddonColumnByIndexPositionList - array of plugin columnId and columnIndexPosition that will be re-added (if it wasn't already found in the output array) dynamically + * @param {Array} fullColumnDefinitions - full column definitions array that includes every columns (including Row Selection, Row Detail, Row Move when enabled) + * @param {Array} newArrangedColumns - output array that will be use to show in the UI (it could have less columns than fullColumnDefinitions array since user might hide some columns) + */ + private addColumnDynamicWhenFeatureEnabled(dynamicAddonColumnByIndexPositionList: Array<{ columnId: string; columnIndexPosition: number; }>, fullColumnDefinitions: Column[], newArrangedColumns: Column[]) { + // 1- first step is to sort them by their index position + dynamicAddonColumnByIndexPositionList.sort((feat1, feat2) => feat1.columnIndexPosition - feat2.columnIndexPosition); + + // 2- second step, we can now proceed to create each extension/addon and that will position them accordingly in the column definitions list + dynamicAddonColumnByIndexPositionList.forEach(feature => { + const pluginColumnIdx = fullColumnDefinitions.findIndex(col => col.id === feature.columnId); + const associatedGridCheckboxColumnIdx = newArrangedColumns.findIndex(col => col.id === feature.columnId); + + if (pluginColumnIdx >= 0 && associatedGridCheckboxColumnIdx === -1) { + const pluginColumn = fullColumnDefinitions[pluginColumnIdx]; + pluginColumnIdx === 0 ? newArrangedColumns.unshift(pluginColumn) : newArrangedColumns.splice(pluginColumnIdx, 0, pluginColumn); + } + }); } /**