From eab49e64c0481c6c0511abfa20da0a8bcfec467b Mon Sep 17 00:00:00 2001 From: kanandev2024 Date: Tue, 7 Dec 2021 11:18:47 +0900 Subject: [PATCH] Revert pseudo merging via rebasing of PR #154 Because the PR is not ready yet, and it should probably be squashed before merging. --- .../src/lib/classes/abstract-list.spec.ts | 64 +++++++++---------- .../natural/src/lib/classes/abstract-list.ts | 33 ++++++---- .../columns-picker.component.ts | 30 ++------- src/app/app-routing.module.ts | 2 +- src/app/home/home.component.html | 2 +- src/app/list/list.component.html | 15 ++--- src/app/list/list.component.spec.ts | 45 +++---------- .../navigable-list.component.html | 11 ++-- 8 files changed, 79 insertions(+), 123 deletions(-) diff --git a/projects/natural/src/lib/classes/abstract-list.spec.ts b/projects/natural/src/lib/classes/abstract-list.spec.ts index b414704..c4b1cd2 100644 --- a/projects/natural/src/lib/classes/abstract-list.spec.ts +++ b/projects/natural/src/lib/classes/abstract-list.spec.ts @@ -14,7 +14,7 @@ import {MaterialModule} from '../../../../../src/app/material.module'; import {ActivatedRoute, Data} from '@angular/router'; @Component({ - template: ` + template: ` column 1 column 2 column 3 @@ -82,7 +82,7 @@ describe('NaturalAbstractList', () => { fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(defaultColumns); + expect(component.selectedColumns).toEqual(defaultColumns); expect(persistSpy).toHaveBeenCalledOnceWith('col', null, mockedActivatedRoute, 'test-key'); // Selecting different columns will persist them @@ -90,7 +90,7 @@ describe('NaturalAbstractList', () => { fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(['col1', 'col2']); + expect(component.selectedColumns).toEqual(['col1', 'col2']); expect(persistSpy).toHaveBeenCalledWith('col', 'col1,col2', mockedActivatedRoute, 'test-key'); } @@ -103,7 +103,7 @@ describe('NaturalAbstractList', () => { fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(defaultColumns); + expect(component.selectedColumns).toEqual(defaultColumns); expect(persistSpy).not.toHaveBeenCalled(); // Selecting different columns will not persist them @@ -111,7 +111,7 @@ describe('NaturalAbstractList', () => { fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(['col1', 'col2']); + expect(component.selectedColumns).toEqual(['col1', 'col2']); expect(persistSpy).not.toHaveBeenCalled(); } @@ -130,17 +130,17 @@ describe('NaturalAbstractList', () => { fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(['col1', 'col3', 'col4', 'hidden']); + expect(component.selectedColumns).toEqual(['col1', 'col3', 'col4', 'hidden']); selectingDifferentColumnsWillPersistThem(['col1', 'col3', 'col4', 'hidden']); })); - it('should select all valid selectedColumns', fakeAsync(() => { - component.selectedColumns = ['col1', 'invalid-column']; + it('should select all valid initialColumns', fakeAsync(() => { + component.initialColumns = ['col1', 'invalid-column']; fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(['col1']); + expect(component.selectedColumns).toEqual(['col1']); selectingDifferentColumnsWillPersistThem(['col1']); })); @@ -150,16 +150,16 @@ describe('NaturalAbstractList', () => { fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(['col2', 'col4']); + expect(component.selectedColumns).toEqual(['col2', 'col4']); })); it('should reload selection from persistence even with @Input', fakeAsync(() => { mockColumnsInPersistence(); - component.selectedColumns = ['col1', 'invalid-column']; + component.initialColumns = ['col1', 'invalid-column']; fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(['col2', 'col4']); + expect(component.selectedColumns).toEqual(['col2', 'col4']); })); }); @@ -169,18 +169,18 @@ describe('NaturalAbstractList', () => { fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(['col1', 'col3', 'col4', 'hidden']); + expect(component.selectedColumns).toEqual(['col1', 'col3', 'col4', 'hidden']); selectingDifferentColumnsWillNotPersistThem(['col1', 'col3', 'col4', 'hidden']); })); - it('should select all valid selectedColumns', fakeAsync(() => { + it('should select all valid initialColumns', fakeAsync(() => { component.persistSearch = false; - component.selectedColumns = ['col1', 'invalid-column']; + component.initialColumns = ['col1', 'invalid-column']; fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(['col1']); + expect(component.selectedColumns).toEqual(['col1']); selectingDifferentColumnsWillNotPersistThem(['col1']); })); @@ -191,23 +191,23 @@ describe('NaturalAbstractList', () => { fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(['col1', 'col3', 'col4', 'hidden']); + expect(component.selectedColumns).toEqual(['col1', 'col3', 'col4', 'hidden']); })); it('should not reload selection from persistence even with @Input', fakeAsync(() => { component.persistSearch = false; mockColumnsInPersistence(); - component.selectedColumns = ['col1', 'invalid-column']; + component.initialColumns = ['col1', 'invalid-column']; fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(['col1']); + expect(component.selectedColumns).toEqual(['col1']); })); }); }); describe('with route data for col3', () => { - beforeEach(waitForAsync(() => createComponent({selectedColumns: ['col3', 'invalid-column']}))); + beforeEach(waitForAsync(() => createComponent({initialColumns: ['col3', 'invalid-column']}))); it('should create', () => { expect(component).toBeTruthy(); @@ -218,17 +218,17 @@ describe('NaturalAbstractList', () => { fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(['col3']); + expect(component.selectedColumns).toEqual(['col3']); selectingDifferentColumnsWillPersistThem(['col3']); })); it('should ignore direct @Input and select col3 via route data', fakeAsync(() => { - component.selectedColumns = ['col1', 'invalid-column']; + component.initialColumns = ['col1', 'invalid-column']; fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(['col3']); + expect(component.selectedColumns).toEqual(['col3']); selectingDifferentColumnsWillPersistThem(['col3']); })); @@ -238,16 +238,16 @@ describe('NaturalAbstractList', () => { fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(['col2', 'col4']); + expect(component.selectedColumns).toEqual(['col2', 'col4']); })); it('should reload selection from persistence even with @Input', fakeAsync(() => { mockColumnsInPersistence(); - component.selectedColumns = ['col1', 'invalid-column']; + component.initialColumns = ['col1', 'invalid-column']; fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(['col2', 'col4']); + expect(component.selectedColumns).toEqual(['col2', 'col4']); })); }); @@ -257,18 +257,18 @@ describe('NaturalAbstractList', () => { fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(['col3']); + expect(component.selectedColumns).toEqual(['col3']); selectingDifferentColumnsWillNotPersistThem(['col3']); })); it('should ignore direct @Input and select col3 via route data', fakeAsync(() => { component.persistSearch = false; - component.selectedColumns = ['col1', 'invalid-column']; + component.initialColumns = ['col1', 'invalid-column']; fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(['col3']); + expect(component.selectedColumns).toEqual(['col3']); selectingDifferentColumnsWillNotPersistThem(['col3']); })); @@ -279,17 +279,17 @@ describe('NaturalAbstractList', () => { fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(['col3']); + expect(component.selectedColumns).toEqual(['col3']); })); it('should not reload selection from persistence even with @Input', fakeAsync(() => { component.persistSearch = false; mockColumnsInPersistence(); - component.selectedColumns = ['col1', 'invalid-column']; + component.initialColumns = ['col1', 'invalid-column']; fixture.detectChanges(); tick(1000); - expect(component.columnsForTable).toEqual(['col3']); + expect(component.selectedColumns).toEqual(['col3']); })); }); }); diff --git a/projects/natural/src/lib/classes/abstract-list.ts b/projects/natural/src/lib/classes/abstract-list.ts index 87eb7f4..6cdc650 100644 --- a/projects/natural/src/lib/classes/abstract-list.ts +++ b/projects/natural/src/lib/classes/abstract-list.ts @@ -43,7 +43,7 @@ function unwrapNavigable(item: MaybeNavigable): Literal { * Components inheriting from this class can be used as standalone with input attributes. * * Usage : - * + * */ // @dynamic @@ -77,7 +77,7 @@ export class NaturalAbstractList< /** * Columns list after interaction with */ - public columnsForTable: string[] = []; + private _selectedColumns: string[] = []; /** * The default column selection that automatically happened after initialization @@ -89,7 +89,7 @@ export class NaturalAbstractList< * * Changing this value after initialization will have no effect at all */ - @Input() public selectedColumns?: string[]; + @Input() public initialColumns?: string[]; /** * Source of the list @@ -419,7 +419,7 @@ export class NaturalAbstractList< * Uses data provided by router such as: * * - `route.data.forcedVariables` - * - `route.data.selectedColumns` + * - `route.data.initialColumns` */ protected initFromRoute(): void { // Variables @@ -428,8 +428,8 @@ export class NaturalAbstractList< } // Columns - if (this.route.snapshot.data.selectedColumns) { - this.selectedColumns = this.route.snapshot.data.selectedColumns; + if (this.route.snapshot.data.initialColumns) { + this.initialColumns = this.route.snapshot.data.initialColumns; } } @@ -461,12 +461,6 @@ export class NaturalAbstractList< this.variablesManager.set('sorting', {sorting} as ExtractVall); } - // Columns - const persistedColumns = this.persistenceService.get('col', this.route, storageKey); - if (typeof persistedColumns === 'string') { - this.selectedColumns = persistedColumns.split(','); - } - // Natural search : ns this.naturalSearchSelections = fromUrl(this.persistenceService.get('ns', this.route, storageKey)); this.translateSearchAndRefreshList(this.naturalSearchSelections, true); @@ -541,8 +535,12 @@ export class NaturalAbstractList< } } - public selectColumns(columns: string[]): void { - this.columnsForTable = columns; + public get selectedColumns(): string[] { + return this._selectedColumns; + } + + public set selectedColumns(columns: string[]) { + this._selectedColumns = columns; if (!this.persistSearch || this.isPanel) { return; @@ -551,6 +549,13 @@ export class NaturalAbstractList< // The first selection we receive is the default one made by if (!this.defaultSelectedColumns) { this.defaultSelectedColumns = columns; + + // Now that we know the defaults, we can try to reload from persistence + const storageKey = this.getStorageKey(); + const persistedColumns = this.persistenceService.get('col', this.route, storageKey); + if (typeof persistedColumns === 'string') { + this.selectedColumns = persistedColumns.split(','); + } } else { // Persist only if wanted columns are different from default selection const value = isEqual(this.defaultSelectedColumns, columns) ? null : columns.join(','); diff --git a/projects/natural/src/lib/modules/columns-picker/columns-picker.component.ts b/projects/natural/src/lib/modules/columns-picker/columns-picker.component.ts index 16c0338..81104b9 100644 --- a/projects/natural/src/lib/modules/columns-picker/columns-picker.component.ts +++ b/projects/natural/src/lib/modules/columns-picker/columns-picker.component.ts @@ -28,35 +28,19 @@ export class NaturalColumnsPickerComponent implements AfterViewInit, OnDestroy { } /** - * Define preselected (checked) columns at start - */ - private _selections?: string[]; - @Input() - public set selections(columns: string[] | undefined) { - this._selections = columns; - - if (!columns || !this.availableColumns) { - return; - } - - this.selection = columns; - this.updateColumns(); - } - - /** - * Emit a list of column keys whenever the selection changes in the dropdown menu + * Emit a list of column keys whenever the selection changes */ @Output() public readonly selectionChange = new EventEmitter(); + @Output() public readonly defaultSelectionChange = new EventEmitter(); /** - * Available columns are defined by options in the template + * Filter available columns */ + @Input() public initialSelection?: string[]; + @ContentChildren(NaturalColumnsPickerColumnDirective) public availableColumns: QueryList | null = null; - /** - * Displayed options in the dropdown menu - */ public displayedColumns: NaturalColumnsPickerColumnDirective[] = []; private ngUnsubscribe = new Subject(); @@ -73,15 +57,15 @@ export class NaturalColumnsPickerComponent implements AfterViewInit, OnDestroy { private initColumns(): void { this.availableColumns?.forEach(col => { - col.checked = this._selections?.length ? this._selections.includes(col.key) : col.checked; + col.checked = this.initialSelection ? this.initialSelection.includes(col.key) : col.checked; }); - // Show options only for columns that are not hidden this.displayedColumns = this.availableColumns?.filter(col => !col.hidden) ?? []; } public updateColumns(): void { const selectedColumns = this.availableColumns?.filter(col => col.checked).map(col => col.key); + this.selectionChange.emit(selectedColumns); } diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 495a575..73c9585 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -92,7 +92,7 @@ const routes: Routes = [ component: ListComponent, data: { title: 'Listing of something else', - selectedColumns: ['name', 'description', 'hidden'], + initialColumns: ['name', 'description', 'hidden'], }, }, ], diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html index 3fe7d91..4ac1c81 100644 --- a/src/app/home/home.component.html +++ b/src/app/home/home.component.html @@ -44,7 +44,7 @@ diff --git a/src/app/list/list.component.html b/src/app/list/list.component.html index 1e77241..074a3fe 100644 --- a/src/app/list/list.component.html +++ b/src/app/list/list.component.html @@ -16,7 +16,7 @@

NaturalAbstractList

[selections]="naturalSearchSelections" fxFlex > - + select id name @@ -28,8 +28,8 @@

NaturalAbstractList

- - + + - - - - -
@@ -67,13 +67,6 @@

NaturalAbstractList

hidden visible but hidden in dropdown Not in pickershould never be visible, even if solicited by url
@@ -95,7 +88,7 @@

NaturalAbstractList

-
columnsForTable : {{ columnsForTable | json }}
+
initialColumns : {{ initialColumns | json }}
selectedColumns : {{ selectedColumns | json }}
variables : {{ variablesManager.variables.value | json }}
row selection : {{ selection.selected | json }}
diff --git a/src/app/list/list.component.spec.ts b/src/app/list/list.component.spec.ts index 620b27a..2889c79 100644 --- a/src/app/list/list.component.spec.ts +++ b/src/app/list/list.component.spec.ts @@ -3,7 +3,7 @@ import {Injectable, NgZone} from '@angular/core'; import {ComponentFixture, fakeAsync, TestBed, tick, waitForAsync} from '@angular/core/testing'; import {HAMMER_LOADER} from '@angular/platform-browser'; import {NoopAnimationsModule} from '@angular/platform-browser/animations'; -import {ActivatedRoute, convertToParamMap, Router, Routes} from '@angular/router'; +import {ActivatedRoute, Router, Routes} from '@angular/router'; import {RouterTestingModule} from '@angular/router/testing'; import { memorySessionStorageProvider, @@ -67,7 +67,6 @@ describe('Demo ListComponent', () => { let ngZone: NgZone; let router: Router; - let activatedRoute: ActivatedRoute; let location: Location; let storage: NaturalStorage; @@ -107,7 +106,6 @@ describe('Demo ListComponent', () => { location = TestBed.inject(Location); router = TestBed.inject(Router); - activatedRoute = TestBed.inject(ActivatedRoute); storage = TestBed.inject(SESSION_STORAGE); ngZone.run(() => router.navigateByUrl('/my/home;cat=123/list-a;dog=456')); // both route levels have params tick(); @@ -128,48 +126,21 @@ describe('Demo ListComponent', () => { sorting: [{field: 'name', order: SortingOrder.DESC}], }); - expect(component.columnsForTable).toEqual([]); - expect(component.selectedColumns).toBeUndefined(); + expect(component.selectedColumns).toEqual([]); + expect(component.initialColumns).toBeUndefined(); }); it('should initialize with initial columns', fakeAsync(() => { // Before init - component.selectedColumns = ['name', 'description']; + component.initialColumns = ['name', 'description']; // Init fixture.detectChanges(); - expect(component.selectedColumns).withContext('initial columns').toEqual(['name', 'description']); - expect(component.columnsForTable).withContext('empty selected columns').toEqual([]); + expect(component.initialColumns).withContext('initial columns').toEqual(['name', 'description']); + expect(component.selectedColumns).withContext('empty selected columns').toEqual([]); tick(1000); // to consider columns picker observable (selectionChange) call - expect(component.columnsForTable).withContext('initialized selected columns').toEqual(['name', 'description']); - })); - - it('should retrieve columns from url', fakeAsync(() => { - spyOnProperty(activatedRoute.snapshot, 'paramMap').and.returnValue( - convertToParamMap({dog: '456', col: '"select,hidden,in-table-but-not-in-picker,does-not-exist"'}), - ); - - // Init - fixture.detectChanges(); - tick(1000); - expect(component.persistSearch).withContext('with persistance').toBeTrue(); - expect(activatedRoute.snapshot.paramMap.get('col')).toEqual( - '"select,hidden,in-table-but-not-in-picker,does-not-exist"', - ); - })); - - it('should initialize columns without inapplicable ones', fakeAsync(() => { - spyOnProperty(activatedRoute.snapshot, 'paramMap').and.returnValue( - convertToParamMap({dog: '456', col: '"select,hidden,in-table-but-not-in-picker,does-not-exist"'}), - ); - - // Init - fixture.detectChanges(); - tick(1000); - expect(component.columnsForTable) - .withContext('initialize applicable columns from url') - .toEqual(['select', 'hidden']); + expect(component.selectedColumns).withContext('initialized selected columns').toEqual(['name', 'description']); })); it('should initialize with forced variables (no session storage)', () => { @@ -186,7 +157,7 @@ describe('Demo ListComponent', () => { }; // Before init - component.selectedColumns = ['name', 'description']; + component.initialColumns = ['name', 'description']; component.forcedVariables = variables; expect(component.variablesManager.variables.value) .withContext('variables before initialization') diff --git a/src/app/navigable-list/navigable-list.component.html b/src/app/navigable-list/navigable-list.component.html index 1ebd210..517d722 100644 --- a/src/app/navigable-list/navigable-list.component.html +++ b/src/app/navigable-list/navigable-list.component.html @@ -17,7 +17,10 @@

NaturalAbstractNavigableList

[selections]="naturalSearchSelections" fxFlex > - + select navigation name @@ -28,8 +31,8 @@

NaturalAbstractNavigableList

- - + +
@@ -95,7 +98,7 @@

NaturalAbstractNavigableList

-
columnsForTable : {{ columnsForTable | json }}
+
initialColumns : {{ initialColumns | json }}
selectedColumns : {{ selectedColumns | json }}
variables : {{ variablesManager.variables.value | json }}
row selection : {{ selection.selected | json }}