mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
AAE-38626 Reload columns on appname change (#11560)
* [AAE-38626] Updating columns when appName changes [AAE-38626] Updating columns when appName changes * [AAE-38626] Added tests * Added indicator to handle app change * [ci:force] fixes * Checking enableAppChange in ngOnchange * Fixed tests --------- Co-authored-by: Fabian Kindgen <39992669+fkindgen@users.noreply.github.com>
This commit is contained in:
co-authored by
Fabian Kindgen
parent
15806d7c9f
commit
6131bf3890
@@ -45,17 +45,19 @@ export abstract class DataTableSchema<T = unknown> {
|
|||||||
protected columnsSchemaSubject$ = new BehaviorSubject<boolean>(false);
|
protected columnsSchemaSubject$ = new BehaviorSubject<boolean>(false);
|
||||||
isColumnSchemaCreated$ = this.columnsSchemaSubject$.asObservable();
|
isColumnSchemaCreated$ = this.columnsSchemaSubject$.asObservable();
|
||||||
|
|
||||||
constructor(private appConfigService: AppConfigService, protected presetKey: string, protected presetsModel: any) {}
|
constructor(
|
||||||
|
private appConfigService: AppConfigService,
|
||||||
|
protected presetKey: string,
|
||||||
|
protected presetsModel: any
|
||||||
|
) {}
|
||||||
|
|
||||||
public createDatatableSchema(): void {
|
public createDatatableSchema(): void {
|
||||||
this.loadLayoutPresets();
|
this.loadLayoutPresets();
|
||||||
|
|
||||||
if (!this.columns || this.columns.length === 0) {
|
if (!this.columns || this.columns.length === 0) {
|
||||||
this.createColumns();
|
this.createColumns();
|
||||||
this.columnsSchemaSubject$.next(true);
|
|
||||||
} else {
|
|
||||||
this.columnsSchemaSubject$.next(true);
|
|
||||||
}
|
}
|
||||||
|
this.columnsSchemaSubject$.next(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public createColumns(): void {
|
public createColumns(): void {
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
[columns]="columns"
|
[columns]="columns"
|
||||||
[data]="dataAdapter"
|
[data]="dataAdapter"
|
||||||
[stickyHeader]="stickyHeader"
|
[stickyHeader]="stickyHeader"
|
||||||
[loading]="isLoading"
|
[loading]="isLoading$ | async"
|
||||||
[sorting]="formattedSorting"
|
[sorting]="formattedSorting"
|
||||||
[selectionMode]="selectionMode"
|
[selectionMode]="selectionMode"
|
||||||
[multiselect]="multiselect"
|
[multiselect]="multiselect"
|
||||||
|
|||||||
+48
-18
@@ -34,7 +34,7 @@ import {
|
|||||||
} from '@alfresco/adf-core';
|
} from '@alfresco/adf-core';
|
||||||
import { ProcessListCloudService } from '../services/process-list-cloud.service';
|
import { ProcessListCloudService } from '../services/process-list-cloud.service';
|
||||||
import { ProcessListCloudComponent } from './process-list-cloud.component';
|
import { ProcessListCloudComponent } from './process-list-cloud.component';
|
||||||
import { of, throwError } from 'rxjs';
|
import { of, throwError, firstValueFrom } from 'rxjs';
|
||||||
import { shareReplay, skip } from 'rxjs/operators';
|
import { shareReplay, skip } from 'rxjs/operators';
|
||||||
import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
|
import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
|
||||||
import { PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN } from '../../../services/cloud-token.service';
|
import { PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN } from '../../../services/cloud-token.service';
|
||||||
@@ -338,15 +338,16 @@ describe('ProcessListCloudComponent', () => {
|
|||||||
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(fakeProcessCloudList));
|
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(fakeProcessCloudList));
|
||||||
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
|
|
||||||
fixture.detectChanges();
|
expect(await firstValueFrom(component.isLoading$)).toBe(true);
|
||||||
expect(component.isLoading).toBe(true);
|
|
||||||
|
|
||||||
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(true);
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
|
||||||
component.ngOnChanges({ appName });
|
component.ngOnChanges({ appName });
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
|
||||||
expect(component.isLoading).toBe(false);
|
expect(await firstValueFrom(component.isLoading$)).toBe(false);
|
||||||
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
|
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
|
||||||
|
|
||||||
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
|
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
|
||||||
@@ -424,9 +425,10 @@ describe('ProcessListCloudComponent', () => {
|
|||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
component.ngAfterContentInit();
|
||||||
component.appName = appName.currentValue;
|
component.appName = appName.currentValue;
|
||||||
component.ngOnChanges({ appName });
|
component.reload();
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should shown columns selector', () => {
|
it('should shown columns selector', () => {
|
||||||
@@ -633,15 +635,13 @@ describe('ProcessListCloudComponent', () => {
|
|||||||
spyOn(processListCloudService, 'fetchProcessList').and.returnValue(of(fakeProcessCloudList));
|
spyOn(processListCloudService, 'fetchProcessList').and.returnValue(of(fakeProcessCloudList));
|
||||||
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
|
|
||||||
fixture.detectChanges();
|
expect(await firstValueFrom(component.isLoading$)).toBe(true);
|
||||||
expect(component.isLoading).toBe(true);
|
|
||||||
|
|
||||||
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(true);
|
|
||||||
|
|
||||||
component.ngOnChanges({ appName });
|
component.ngOnChanges({ appName });
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
|
||||||
expect(component.isLoading).toBe(false);
|
expect(await firstValueFrom(component.isLoading$)).toBe(false);
|
||||||
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
|
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
|
||||||
|
|
||||||
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
|
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
|
||||||
@@ -758,9 +758,9 @@ describe('ProcessListCloudComponent', () => {
|
|||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
component.ngAfterContentInit();
|
||||||
component.appName = appName.currentValue;
|
component.appName = appName.currentValue;
|
||||||
component.ngOnChanges({ appName });
|
component.reload();
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should shown columns selector', () => {
|
it('should shown columns selector', () => {
|
||||||
@@ -954,6 +954,34 @@ describe('ProcessListCloudComponent', () => {
|
|||||||
component.resetPagination();
|
component.resetPagination();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should call loadPreferencesAndInitialize when appName changes', () => {
|
||||||
|
spyOn(preferencesService, 'getPreferences').and.returnValue(of({}));
|
||||||
|
|
||||||
|
spyOn(processListCloudService, 'fetchProcessList').and.returnValue(of(fakeProcessCloudList));
|
||||||
|
spyOn(component as any, 'createDatatableSchema');
|
||||||
|
spyOn(component as any, 'createColumns');
|
||||||
|
|
||||||
|
component.enableAppChange = true;
|
||||||
|
component.appName = 'old-app-name';
|
||||||
|
|
||||||
|
const appName = new SimpleChange('old-app-name', 'new-app-name', false);
|
||||||
|
component.appName = 'new-app-name';
|
||||||
|
component.ngOnChanges({ appName });
|
||||||
|
|
||||||
|
expect(preferencesService.getPreferences).toHaveBeenCalledWith('new-app-name');
|
||||||
|
expect((component as any).createDatatableSchema).toHaveBeenCalled();
|
||||||
|
expect((component as any).createColumns).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not call loadPreferencesAndInitialize when appName does not change', () => {
|
||||||
|
spyOn(preferencesService, 'getPreferences');
|
||||||
|
|
||||||
|
const status = new SimpleChange('old-status', 'new-status', false);
|
||||||
|
component.ngOnChanges({ status });
|
||||||
|
|
||||||
|
expect(preferencesService.getPreferences).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -974,15 +1002,17 @@ describe('ProcessListCloudComponent', () => {
|
|||||||
const emptyList = { list: { entries: [] } };
|
const emptyList = { list: { entries: [] } };
|
||||||
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(emptyList));
|
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(emptyList));
|
||||||
|
|
||||||
fixture.detectChanges();
|
expect(await firstValueFrom(component.isLoading$)).toBe(true);
|
||||||
expect(component.isLoading).toBe(true);
|
|
||||||
|
|
||||||
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(true);
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
|
||||||
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
component.ngOnChanges({ appName });
|
component.ngOnChanges({ appName });
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
|
||||||
|
expect(await firstValueFrom(component.isLoading$)).toBe(false);
|
||||||
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
|
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
|
||||||
|
|
||||||
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
|
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
|
||||||
@@ -1223,7 +1253,7 @@ describe('ProcessListCloudComponent: Creating an empty custom template - EmptyTe
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should render the custom template', () => {
|
it('should render the custom template', () => {
|
||||||
fixtureEmpty.componentInstance.processListCloud.isLoading = false;
|
fixtureEmpty.componentInstance.processListCloud['isLoadingPreferences$'].next(false);
|
||||||
|
|
||||||
fixtureEmpty.detectChanges();
|
fixtureEmpty.detectChanges();
|
||||||
|
|
||||||
|
|||||||
+62
-28
@@ -64,7 +64,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|||||||
import { ProcessVariableFilterModel } from '../../../models/process-variable-filter.model';
|
import { ProcessVariableFilterModel } from '../../../models/process-variable-filter.model';
|
||||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||||
import { TranslatePipe } from '@ngx-translate/core';
|
import { TranslatePipe } from '@ngx-translate/core';
|
||||||
import { NgIf } from '@angular/common';
|
import { AsyncPipe, NgIf } from '@angular/common';
|
||||||
|
|
||||||
const PRESET_KEY = 'adf-cloud-process-list.presets';
|
const PRESET_KEY = 'adf-cloud-process-list.presets';
|
||||||
|
|
||||||
@@ -81,7 +81,8 @@ const PRESET_KEY = 'adf-cloud-process-list.presets';
|
|||||||
EmptyContentComponent,
|
EmptyContentComponent,
|
||||||
NoContentTemplateDirective,
|
NoContentTemplateDirective,
|
||||||
LoadingContentTemplateDirective,
|
LoadingContentTemplateDirective,
|
||||||
NgIf
|
NgIf,
|
||||||
|
AsyncPipe
|
||||||
],
|
],
|
||||||
templateUrl: './process-list-cloud.component.html',
|
templateUrl: './process-list-cloud.component.html',
|
||||||
styleUrls: ['./process-list-cloud.component.scss'],
|
styleUrls: ['./process-list-cloud.component.scss'],
|
||||||
@@ -290,6 +291,12 @@ export class ProcessListCloudComponent
|
|||||||
@Input()
|
@Input()
|
||||||
processVariables: ProcessVariableFilterModel[];
|
processVariables: ProcessVariableFilterModel[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables reloading of preferences and process list when appName changes.
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
enableAppChange: boolean = false;
|
||||||
|
|
||||||
/** Include subprocesses in the process list. */
|
/** Include subprocesses in the process list. */
|
||||||
@Input()
|
@Input()
|
||||||
includeSubprocesses: boolean | null = null;
|
includeSubprocesses: boolean | null = null;
|
||||||
@@ -331,7 +338,6 @@ export class ProcessListCloudComponent
|
|||||||
skipCount: number = 0;
|
skipCount: number = 0;
|
||||||
currentInstanceId: string;
|
currentInstanceId: string;
|
||||||
selectedInstances: any[];
|
selectedInstances: any[];
|
||||||
isLoading = true;
|
|
||||||
|
|
||||||
rows: any[] = [];
|
rows: any[] = [];
|
||||||
formattedSorting: any[];
|
formattedSorting: any[];
|
||||||
@@ -341,6 +347,13 @@ export class ProcessListCloudComponent
|
|||||||
|
|
||||||
private defaultSorting = { key: 'startDate', direction: 'desc' };
|
private defaultSorting = { key: 'startDate', direction: 'desc' };
|
||||||
|
|
||||||
|
protected isLoadingPreferences$ = new BehaviorSubject<boolean>(true);
|
||||||
|
private readonly isReloadingSubject$ = new BehaviorSubject<boolean>(false);
|
||||||
|
|
||||||
|
isLoading$ = combineLatest([this.isLoadingPreferences$, this.isReloadingSubject$]).pipe(
|
||||||
|
map(([isLoadingPreferences, isReloading]) => isLoadingPreferences || isReloading)
|
||||||
|
);
|
||||||
|
|
||||||
private fetchProcessesTrigger$ = new Subject<void>();
|
private fetchProcessesTrigger$ = new Subject<void>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -361,10 +374,10 @@ export class ProcessListCloudComponent
|
|||||||
totalItems: 0
|
totalItems: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
combineLatest([this.isColumnSchemaCreated$, this.fetchProcessesTrigger$])
|
combineLatest([this.isLoadingPreferences$, this.isColumnSchemaCreated$, this.fetchProcessesTrigger$])
|
||||||
.pipe(
|
.pipe(
|
||||||
tap(() => (this.isLoading = true)),
|
tap(() => this.isReloadingSubject$.next(true)),
|
||||||
filter(([isColumnSchemaCreated]) => isColumnSchemaCreated),
|
filter(([isLoadingPreferences, isColumnSchemaCreated]) => !isLoadingPreferences && !!isColumnSchemaCreated),
|
||||||
switchMap(() => {
|
switchMap(() => {
|
||||||
if (this.searchApiMethod === 'POST') {
|
if (this.searchApiMethod === 'POST') {
|
||||||
const requestNode = this.createProcessListRequestNode();
|
const requestNode = this.createProcessListRequestNode();
|
||||||
@@ -373,7 +386,7 @@ export class ProcessListCloudComponent
|
|||||||
} else {
|
} else {
|
||||||
const requestNode = this.createRequestNode();
|
const requestNode = this.createRequestNode();
|
||||||
this.requestNode = requestNode;
|
this.requestNode = requestNode;
|
||||||
return this.processListCloudService.getProcessByRequest(requestNode).pipe(take(1));
|
return this.processListCloudService.getProcessByRequest(requestNode).pipe();
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
takeUntilDestroyed()
|
takeUntilDestroyed()
|
||||||
@@ -385,18 +398,46 @@ export class ProcessListCloudComponent
|
|||||||
this.dataAdapter = new ProcessListDatatableAdapter(this.rows, this.columns);
|
this.dataAdapter = new ProcessListDatatableAdapter(this.rows, this.columns);
|
||||||
|
|
||||||
this.success.emit(processes);
|
this.success.emit(processes);
|
||||||
this.isLoading = false;
|
this.isReloadingSubject$.next(false);
|
||||||
this.pagination.next(processes.list.pagination);
|
this.pagination.next(processes.list.pagination);
|
||||||
},
|
},
|
||||||
error: (error) => {
|
error: (error) => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
this.error.emit(error);
|
this.error.emit(error);
|
||||||
this.isLoading = false;
|
this.isReloadingSubject$.next(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reload() {
|
||||||
|
if (this.appName || this.appName === '') {
|
||||||
|
this.isReloadingSubject$.next(true);
|
||||||
|
this.fetchProcessesTrigger$.next();
|
||||||
|
} else {
|
||||||
|
this.rows = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ngAfterContentInit() {
|
ngAfterContentInit() {
|
||||||
|
this.retrieveProcessPreferences();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
|
if (this.isPropertyChanged(changes, 'sorting')) {
|
||||||
|
this.formatSorting(changes['sorting'].currentValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changes['appName'] && this.enableAppChange) {
|
||||||
|
this.retrieveProcessPreferences();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isAnyPropertyChanged(changes)) {
|
||||||
|
this.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private retrieveProcessPreferences(): void {
|
||||||
|
this.isLoadingPreferences$.next(true);
|
||||||
this.cloudPreferenceService
|
this.cloudPreferenceService
|
||||||
.getPreferences(this.appName)
|
.getPreferences(this.appName)
|
||||||
.pipe(
|
.pipe(
|
||||||
@@ -411,7 +452,7 @@ export class ProcessListCloudComponent
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
columnsOrder: columnsOrder ? JSON.parse(columnsOrder.entry.value) : undefined,
|
columnsOrder: columnsOrder ? JSON.parse(columnsOrder.entry.value) : undefined,
|
||||||
columnsVisibility: columnsVisibility ? JSON.parse(columnsVisibility.entry.value) : this.columnsVisibility,
|
columnsVisibility: columnsVisibility ? JSON.parse(columnsVisibility.entry.value) : undefined,
|
||||||
columnsWidths: columnsWidths ? JSON.parse(columnsWidths.entry.value) : undefined
|
columnsWidths: columnsWidths ? JSON.parse(columnsWidths.entry.value) : undefined
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
@@ -419,7 +460,7 @@ export class ProcessListCloudComponent
|
|||||||
if (error.status === 404) {
|
if (error.status === 404) {
|
||||||
return of({
|
return of({
|
||||||
columnsOrder: undefined,
|
columnsOrder: undefined,
|
||||||
columnsVisibility: this.columnsVisibility,
|
columnsVisibility: undefined,
|
||||||
columnsWidths: undefined
|
columnsWidths: undefined
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -427,7 +468,8 @@ export class ProcessListCloudComponent
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.subscribe(({ columnsOrder, columnsVisibility, columnsWidths }) => {
|
.subscribe(
|
||||||
|
({ columnsOrder, columnsVisibility, columnsWidths }) => {
|
||||||
if (columnsVisibility) {
|
if (columnsVisibility) {
|
||||||
this.columnsVisibility = columnsVisibility;
|
this.columnsVisibility = columnsVisibility;
|
||||||
}
|
}
|
||||||
@@ -441,30 +483,22 @@ export class ProcessListCloudComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.createDatatableSchema();
|
this.createDatatableSchema();
|
||||||
});
|
if (this.enableAppChange) {
|
||||||
|
this.createColumns();
|
||||||
}
|
}
|
||||||
ngOnChanges(changes: SimpleChanges) {
|
this.isLoadingPreferences$.next(false);
|
||||||
if (this.isPropertyChanged(changes, 'sorting')) {
|
},
|
||||||
this.formatSorting(changes['sorting'].currentValue);
|
(error) => {
|
||||||
}
|
this.error.emit(error);
|
||||||
|
this.isLoadingPreferences$.next(false);
|
||||||
if (this.isAnyPropertyChanged(changes)) {
|
|
||||||
this.reload();
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentId(): string {
|
getCurrentId(): string {
|
||||||
return this.currentInstanceId;
|
return this.currentInstanceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
reload() {
|
|
||||||
if (this.appName || this.appName === '') {
|
|
||||||
this.fetchProcessesTrigger$.next();
|
|
||||||
} else {
|
|
||||||
this.rows = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private isAnyPropertyChanged(changes: SimpleChanges): boolean {
|
private isAnyPropertyChanged(changes: SimpleChanges): boolean {
|
||||||
for (const property in changes) {
|
for (const property in changes) {
|
||||||
if (this.isPropertyChanged(changes, property)) {
|
if (this.isPropertyChanged(changes, property)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user