mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-04-23 22:30:37 +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:
@@ -45,17 +45,19 @@ export abstract class DataTableSchema<T = unknown> {
|
||||
protected columnsSchemaSubject$ = new BehaviorSubject<boolean>(false);
|
||||
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 {
|
||||
this.loadLayoutPresets();
|
||||
|
||||
if (!this.columns || this.columns.length === 0) {
|
||||
this.createColumns();
|
||||
this.columnsSchemaSubject$.next(true);
|
||||
} else {
|
||||
this.columnsSchemaSubject$.next(true);
|
||||
}
|
||||
this.columnsSchemaSubject$.next(true);
|
||||
}
|
||||
|
||||
public createColumns(): void {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[columns]="columns"
|
||||
[data]="dataAdapter"
|
||||
[stickyHeader]="stickyHeader"
|
||||
[loading]="isLoading"
|
||||
[loading]="isLoading$ | async"
|
||||
[sorting]="formattedSorting"
|
||||
[selectionMode]="selectionMode"
|
||||
[multiselect]="multiselect"
|
||||
|
||||
@@ -34,7 +34,7 @@ import {
|
||||
} from '@alfresco/adf-core';
|
||||
import { ProcessListCloudService } from '../services/process-list-cloud.service';
|
||||
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 { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
|
||||
import { PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN } from '../../../services/cloud-token.service';
|
||||
@@ -338,15 +338,16 @@ describe('ProcessListCloudComponent', () => {
|
||||
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(fakeProcessCloudList));
|
||||
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(component.isLoading).toBe(true);
|
||||
expect(await firstValueFrom(component.isLoading$)).toBe(true);
|
||||
|
||||
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(true);
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
component.ngOnChanges({ appName });
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(component.isLoading).toBe(false);
|
||||
expect(await firstValueFrom(component.isLoading$)).toBe(false);
|
||||
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
|
||||
|
||||
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
|
||||
@@ -424,9 +425,10 @@ describe('ProcessListCloudComponent', () => {
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
component.ngAfterContentInit();
|
||||
component.appName = appName.currentValue;
|
||||
component.ngOnChanges({ appName });
|
||||
fixture.detectChanges();
|
||||
component.reload();
|
||||
});
|
||||
|
||||
it('should shown columns selector', () => {
|
||||
@@ -633,15 +635,13 @@ describe('ProcessListCloudComponent', () => {
|
||||
spyOn(processListCloudService, 'fetchProcessList').and.returnValue(of(fakeProcessCloudList));
|
||||
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(component.isLoading).toBe(true);
|
||||
|
||||
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(true);
|
||||
expect(await firstValueFrom(component.isLoading$)).toBe(true);
|
||||
|
||||
component.ngOnChanges({ appName });
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(component.isLoading).toBe(false);
|
||||
expect(await firstValueFrom(component.isLoading$)).toBe(false);
|
||||
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
|
||||
|
||||
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
|
||||
@@ -758,9 +758,9 @@ describe('ProcessListCloudComponent', () => {
|
||||
|
||||
done();
|
||||
});
|
||||
component.ngAfterContentInit();
|
||||
component.appName = appName.currentValue;
|
||||
component.ngOnChanges({ appName });
|
||||
fixture.detectChanges();
|
||||
component.reload();
|
||||
});
|
||||
|
||||
it('should shown columns selector', () => {
|
||||
@@ -954,6 +954,34 @@ describe('ProcessListCloudComponent', () => {
|
||||
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: [] } };
|
||||
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(emptyList));
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(component.isLoading).toBe(true);
|
||||
expect(await firstValueFrom(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);
|
||||
component.ngOnChanges({ appName });
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(await firstValueFrom(component.isLoading$)).toBe(false);
|
||||
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
|
||||
|
||||
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', () => {
|
||||
fixtureEmpty.componentInstance.processListCloud.isLoading = false;
|
||||
fixtureEmpty.componentInstance.processListCloud['isLoadingPreferences$'].next(false);
|
||||
|
||||
fixtureEmpty.detectChanges();
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { ProcessVariableFilterModel } from '../../../models/process-variable-filter.model';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
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';
|
||||
|
||||
@@ -81,7 +81,8 @@ const PRESET_KEY = 'adf-cloud-process-list.presets';
|
||||
EmptyContentComponent,
|
||||
NoContentTemplateDirective,
|
||||
LoadingContentTemplateDirective,
|
||||
NgIf
|
||||
NgIf,
|
||||
AsyncPipe
|
||||
],
|
||||
templateUrl: './process-list-cloud.component.html',
|
||||
styleUrls: ['./process-list-cloud.component.scss'],
|
||||
@@ -290,6 +291,12 @@ export class ProcessListCloudComponent
|
||||
@Input()
|
||||
processVariables: ProcessVariableFilterModel[];
|
||||
|
||||
/**
|
||||
* Enables reloading of preferences and process list when appName changes.
|
||||
*/
|
||||
@Input()
|
||||
enableAppChange: boolean = false;
|
||||
|
||||
/** Include subprocesses in the process list. */
|
||||
@Input()
|
||||
includeSubprocesses: boolean | null = null;
|
||||
@@ -331,7 +338,6 @@ export class ProcessListCloudComponent
|
||||
skipCount: number = 0;
|
||||
currentInstanceId: string;
|
||||
selectedInstances: any[];
|
||||
isLoading = true;
|
||||
|
||||
rows: any[] = [];
|
||||
formattedSorting: any[];
|
||||
@@ -341,6 +347,13 @@ export class ProcessListCloudComponent
|
||||
|
||||
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>();
|
||||
|
||||
constructor(
|
||||
@@ -361,10 +374,10 @@ export class ProcessListCloudComponent
|
||||
totalItems: 0
|
||||
});
|
||||
|
||||
combineLatest([this.isColumnSchemaCreated$, this.fetchProcessesTrigger$])
|
||||
combineLatest([this.isLoadingPreferences$, this.isColumnSchemaCreated$, this.fetchProcessesTrigger$])
|
||||
.pipe(
|
||||
tap(() => (this.isLoading = true)),
|
||||
filter(([isColumnSchemaCreated]) => isColumnSchemaCreated),
|
||||
tap(() => this.isReloadingSubject$.next(true)),
|
||||
filter(([isLoadingPreferences, isColumnSchemaCreated]) => !isLoadingPreferences && !!isColumnSchemaCreated),
|
||||
switchMap(() => {
|
||||
if (this.searchApiMethod === 'POST') {
|
||||
const requestNode = this.createProcessListRequestNode();
|
||||
@@ -373,7 +386,7 @@ export class ProcessListCloudComponent
|
||||
} else {
|
||||
const requestNode = this.createRequestNode();
|
||||
this.requestNode = requestNode;
|
||||
return this.processListCloudService.getProcessByRequest(requestNode).pipe(take(1));
|
||||
return this.processListCloudService.getProcessByRequest(requestNode).pipe();
|
||||
}
|
||||
}),
|
||||
takeUntilDestroyed()
|
||||
@@ -385,18 +398,46 @@ export class ProcessListCloudComponent
|
||||
this.dataAdapter = new ProcessListDatatableAdapter(this.rows, this.columns);
|
||||
|
||||
this.success.emit(processes);
|
||||
this.isLoading = false;
|
||||
this.isReloadingSubject$.next(false);
|
||||
this.pagination.next(processes.list.pagination);
|
||||
},
|
||||
error: (error) => {
|
||||
console.error(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() {
|
||||
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
|
||||
.getPreferences(this.appName)
|
||||
.pipe(
|
||||
@@ -411,7 +452,7 @@ export class ProcessListCloudComponent
|
||||
|
||||
return {
|
||||
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
|
||||
};
|
||||
}),
|
||||
@@ -419,7 +460,7 @@ export class ProcessListCloudComponent
|
||||
if (error.status === 404) {
|
||||
return of({
|
||||
columnsOrder: undefined,
|
||||
columnsVisibility: this.columnsVisibility,
|
||||
columnsVisibility: undefined,
|
||||
columnsWidths: undefined
|
||||
});
|
||||
} else {
|
||||
@@ -427,44 +468,37 @@ export class ProcessListCloudComponent
|
||||
}
|
||||
})
|
||||
)
|
||||
.subscribe(({ columnsOrder, columnsVisibility, columnsWidths }) => {
|
||||
if (columnsVisibility) {
|
||||
this.columnsVisibility = columnsVisibility;
|
||||
.subscribe(
|
||||
({ columnsOrder, columnsVisibility, columnsWidths }) => {
|
||||
if (columnsVisibility) {
|
||||
this.columnsVisibility = columnsVisibility;
|
||||
}
|
||||
|
||||
if (columnsOrder) {
|
||||
this.columnsOrder = columnsOrder;
|
||||
}
|
||||
|
||||
if (columnsWidths) {
|
||||
this.columnsWidths = columnsWidths;
|
||||
}
|
||||
|
||||
this.createDatatableSchema();
|
||||
if (this.enableAppChange) {
|
||||
this.createColumns();
|
||||
}
|
||||
this.isLoadingPreferences$.next(false);
|
||||
},
|
||||
(error) => {
|
||||
this.error.emit(error);
|
||||
this.isLoadingPreferences$.next(false);
|
||||
}
|
||||
|
||||
if (columnsOrder) {
|
||||
this.columnsOrder = columnsOrder;
|
||||
}
|
||||
|
||||
if (columnsWidths) {
|
||||
this.columnsWidths = columnsWidths;
|
||||
}
|
||||
|
||||
this.createDatatableSchema();
|
||||
});
|
||||
}
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (this.isPropertyChanged(changes, 'sorting')) {
|
||||
this.formatSorting(changes['sorting'].currentValue);
|
||||
}
|
||||
|
||||
if (this.isAnyPropertyChanged(changes)) {
|
||||
this.reload();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
getCurrentId(): string {
|
||||
return this.currentInstanceId;
|
||||
}
|
||||
|
||||
reload() {
|
||||
if (this.appName || this.appName === '') {
|
||||
this.fetchProcessesTrigger$.next();
|
||||
} else {
|
||||
this.rows = [];
|
||||
}
|
||||
}
|
||||
|
||||
private isAnyPropertyChanged(changes: SimpleChanges): boolean {
|
||||
for (const property in changes) {
|
||||
if (this.isPropertyChanged(changes, property)) {
|
||||
|
||||
Reference in New Issue
Block a user