[AAE-7819] Change column order - enable drag and drop for datatable - [1/3] (#7567)

* [AAE-7819] Enable drag and drop for datatable [1/3]

* [AAE-7819] Change column order - load and save columns order preferences for PROCESSES - [2/3] (#7568)

* [AAE-7819] Load and save column order preferences for processes

* [AAE-7819] Load and save column order preferences for tasks [3/3] (#7569)

* fix css

* fix icon module import

* Fix unit tests

* Fix test

* Fix e2e

* Fix C279927
This commit is contained in:
Bartosz Sekuła
2022-04-11 08:01:02 +02:00
committed by GitHub
parent e89cea79be
commit 48c3fac018
33 changed files with 614 additions and 136 deletions

View File

@@ -27,7 +27,9 @@ import {
LocalPreferenceCloudService,
PreferenceCloudServiceInterface,
PROCESS_FILTERS_SERVICE_TOKEN,
TASK_FILTERS_SERVICE_TOKEN
TASK_FILTERS_SERVICE_TOKEN,
PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN,
TASK_LIST_PREFERENCES_SERVICE_TOKEN
} from './services/public-api';
import { PeopleCloudModule } from './people/people-cloud.module';
import { CloudFormRenderingService } from './form/components/cloud-form-rendering.service';
@@ -67,7 +69,10 @@ import { ProcessServicesCloudPipeModule } from './pipes/process-services-cloud-p
]
})
export class ProcessServicesCloudModule {
static forRoot(preferenceServiceInstance?: PreferenceCloudServiceInterface): ModuleWithProviders<ProcessServicesCloudModule> {
static forRoot(
filterPreferenceServiceInstance?: PreferenceCloudServiceInterface,
listPreferenceServiceInstance?: PreferenceCloudServiceInterface
): ModuleWithProviders<ProcessServicesCloudModule> {
return {
ngModule: ProcessServicesCloudModule,
providers: [
@@ -79,8 +84,10 @@ export class ProcessServicesCloudModule {
source: 'assets/adf-process-services-cloud'
}
},
{ provide: PROCESS_FILTERS_SERVICE_TOKEN, useExisting: preferenceServiceInstance ?? LocalPreferenceCloudService },
{ provide: TASK_FILTERS_SERVICE_TOKEN, useExisting: preferenceServiceInstance ?? LocalPreferenceCloudService },
{ provide: PROCESS_FILTERS_SERVICE_TOKEN, useExisting: filterPreferenceServiceInstance ?? LocalPreferenceCloudService },
{ provide: TASK_FILTERS_SERVICE_TOKEN, useExisting: filterPreferenceServiceInstance ?? LocalPreferenceCloudService },
{ provide: PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN, useExisting: listPreferenceServiceInstance ?? LocalPreferenceCloudService },
{ provide: TASK_LIST_PREFERENCES_SERVICE_TOKEN, useExisting: listPreferenceServiceInstance ?? LocalPreferenceCloudService },
FormRenderingService,
{ provide: FormRenderingService, useClass: CloudFormRenderingService }
]

View File

@@ -16,7 +16,8 @@
(row-select)="onRowSelect($any($event))"
(row-unselect)="onRowUnselect($any($event))"
(row-keyup)="onRowKeyUp($any($event))"
(sorting-changed)="onSortingChanged($any($event))">
(sorting-changed)="onSortingChanged($any($event))"
(columnOrderChanged)="onColumnOrderChanged($event)">
<adf-loading-content-template>
<ng-template>
<mat-progress-spinner

View File

@@ -27,7 +27,7 @@ import { ProcessListCloudService } from '../services/process-list-cloud.service'
import { ProcessListCloudComponent } from './process-list-cloud.component';
import { fakeCustomSchema, fakeProcessCloudList, processListSchemaMock } from '../mock/process-list-service.mock';
import { of } from 'rxjs';
import { skip } from 'rxjs/operators';
import { shareReplay, skip } from 'rxjs/operators';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
@@ -102,6 +102,8 @@ describe('ProcessListCloudComponent', () => {
}
}
});
component.isColumnSchemaCreated$ = of(true).pipe(shareReplay(1));
});
afterEach(() => fixture.destroy());

View File

@@ -15,16 +15,20 @@
* limitations under the License.
*/
import { Component, ViewEncapsulation, OnChanges, AfterContentInit, ContentChild, Output, EventEmitter, SimpleChanges, Input, ViewChild } from '@angular/core';
import { Component, ViewEncapsulation, OnChanges, AfterContentInit, ContentChild, Output, EventEmitter, SimpleChanges, Input, ViewChild, Inject } from '@angular/core';
import { DataTableSchema, PaginatedComponent,
CustomEmptyContentTemplateDirective, AppConfigService,
UserPreferencesService, PaginationModel,
UserPreferenceValues, DataRowEvent, CustomLoadingContentTemplateDirective, DataCellEvent, DataRowActionEvent, DataTableComponent } from '@alfresco/adf-core';
UserPreferenceValues, DataRowEvent, CustomLoadingContentTemplateDirective, DataCellEvent, DataRowActionEvent, DataTableComponent, DataColumn } from '@alfresco/adf-core';
import { ProcessListCloudService } from '../services/process-list-cloud.service';
import { BehaviorSubject } from 'rxjs';
import { BehaviorSubject, combineLatest } from 'rxjs';
import { processCloudPresetsDefaultModel } from '../models/process-cloud-preset.model';
import { ProcessQueryCloudRequestModel } from '../models/process-cloud-query-request.model';
import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
import { map, take } from 'rxjs/operators';
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
import { PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN } from '../../../services/cloud-token.service';
import { ProcessListCloudPreferences } from '../models/process-cloud-preferences';
const PRESET_KEY = 'adf-cloud-process-list.presets';
@@ -189,14 +193,17 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
currentInstanceId: string;
selectedInstances: any[];
isLoading = true;
rows: any[] = [];
formattedSorting: any[];
requestNode: ProcessQueryCloudRequestModel;
private defaultSorting = { key: 'startDate', direction: 'desc' };
constructor(private processListCloudService: ProcessListCloudService,
appConfigService: AppConfigService,
private userPreferences: UserPreferencesService) {
private userPreferences: UserPreferencesService,
@Inject(PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN) private cloudPreferenceService: PreferenceCloudServiceInterface) {
super(appConfigService, PRESET_KEY, processCloudPresetsDefaultModel);
this.size = userPreferences.paginationSize;
this.userPreferences.select(UserPreferenceValues.PaginationSize).subscribe((pageSize) => {
@@ -210,7 +217,23 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
}
ngAfterContentInit() {
this.createDatatableSchema();
this.cloudPreferenceService.getPreferences(this.appName)
.pipe(
take(1),
map((preferences => {
const preferencesList = preferences?.list?.entries ?? [];
const columnsOrder = preferencesList.find(preference => preference.entry.key === ProcessListCloudPreferences.columnOrder);
return {
columnsOrder: columnsOrder ? JSON.parse(columnsOrder.entry.value) : undefined
};
}))
)
.subscribe(({ columnsOrder }) => {
this.columnsOrder = columnsOrder;
this.createDatatableSchema();
});
}
ngOnChanges(changes: SimpleChanges) {
@@ -237,16 +260,21 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
private load(requestNode: ProcessQueryCloudRequestModel) {
this.isLoading = true;
this.processListCloudService.getProcessByRequest(requestNode).subscribe(
(processes) => {
this.rows = processes.list.entries;
this.success.emit(processes);
this.isLoading = false;
this.pagination.next(processes.list.pagination);
}, (error) => {
this.error.emit(error);
this.isLoading = false;
});
combineLatest([
this.processListCloudService.getProcessByRequest(requestNode),
this.isColumnSchemaCreated$
]).pipe(
take(1)
).subscribe(([processes]) => {
this.rows = processes.list.entries;
this.success.emit(processes);
this.isLoading = false;
this.pagination.next(processes.list.pagination);
}, (error) => {
this.error.emit(error);
this.isLoading = false;
});
}
private isAnyPropertyChanged(changes: SimpleChanges): boolean {
@@ -297,6 +325,17 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
this.reload();
}
onColumnOrderChanged(columnsWithNewOrder: DataColumn[]): void {
if (this.appName) {
const newColumnsOrder = columnsWithNewOrder.map(column => column.id);
this.cloudPreferenceService.updatePreference(
this.appName,
ProcessListCloudPreferences.columnOrder,
newColumnsOrder
);
}
}
onRowClick(item: DataRowEvent) {
this.currentInstanceId = item.value.getValue('id');
this.rowClick.emit(this.currentInstanceId);

View File

@@ -0,0 +1,4 @@
// eslint-disable-next-line no-shadow
export enum ProcessListCloudPreferences {
columnOrder = 'processes-cloud-list-columns-order'
}

View File

@@ -20,6 +20,7 @@ export * from './components/process-list-cloud.component';
export * from './models/process-cloud-query-request.model';
export * from './models/process-cloud-preset.model';
export * from './models/process-list-sorting.model';
export * from './models/process-cloud-preferences';
export * from './services/process-list-cloud.service';
export * from './services/process-task-list-cloud.service';

View File

@@ -19,6 +19,10 @@ import { InjectionToken } from '@angular/core';
import { PreferenceCloudServiceInterface } from './preference-cloud.interface';
import { TaskListCloudServiceInterface } from './task-list-cloud.service.interface';
export const PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN = new InjectionToken<PreferenceCloudServiceInterface>('proccesses-list-preferences-cloud');
export const TASK_LIST_PREFERENCES_SERVICE_TOKEN = new InjectionToken<PreferenceCloudServiceInterface>('tasks-list-preferences-cloud');
export const PROCESS_FILTERS_SERVICE_TOKEN = new InjectionToken<PreferenceCloudServiceInterface>('proccess-filters-cloud');
export const TASK_FILTERS_SERVICE_TOKEN = new InjectionToken<PreferenceCloudServiceInterface>('task-filters-cloud');

View File

@@ -18,11 +18,9 @@
import { Observable } from 'rxjs';
export interface PreferenceCloudServiceInterface {
getPreferences(appName: string, key?: string): Observable<any>;
getPreferenceByKey(appName: string, key: string): Observable<any>;
createPreference(appName: string, key: string, newPreference: any): Observable<any>;
updatePreference(appName: string, key: string, updatedPreference: any): Observable<any>;
deletePreference(appName: string, key: any): Observable<any>;
deletePreference(appName: string, key: string): Observable<any>;
}

View File

@@ -19,7 +19,8 @@
(row-unselect)="onRowUnselect($any($event))"
(rowClick)="onRowClick($any($event))"
(row-keyup)="onRowKeyUp($any($event))"
(sorting-changed)="onSortingChanged($any($event))">
(sorting-changed)="onSortingChanged($any($event))"
(columnOrderChanged)="onColumnOrderChanged($event)">
<adf-loading-content-template>
<ng-template>
<!-- Add your custom loading template here -->

View File

@@ -26,8 +26,10 @@ import { taskPresetsCloudDefaultModel } from '../models/task-preset-cloud.model'
import { TaskQueryCloudRequestModel } from '../../../models/filter-cloud-model';
import { BehaviorSubject, Subject } from 'rxjs';
import { TaskListCloudSortingModel } from '../../../models/task-list-sorting.model';
import { takeUntil } from 'rxjs/operators';
import { map, take, takeUntil } from 'rxjs/operators';
import { TaskCloudService } from '../../services/task-cloud.service';
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
import { TasksListCloudPreferences } from '../models/tasks-cloud-preferences';
@Directive()
// eslint-disable-next-line @angular-eslint/directive-class-suffix
@@ -120,7 +122,8 @@ export abstract class BaseTaskListCloudComponent extends DataTableSchema impleme
constructor(appConfigService: AppConfigService,
private taskCloudService: TaskCloudService,
private userPreferences: UserPreferencesService,
presetKey: string) {
presetKey: string,
private cloudPreferenceService: PreferenceCloudServiceInterface) {
super(appConfigService, presetKey, taskPresetsCloudDefaultModel);
this.size = userPreferences.paginationSize;
@@ -153,7 +156,18 @@ export abstract class BaseTaskListCloudComponent extends DataTableSchema impleme
}
ngAfterContentInit() {
this.createDatatableSchema();
this.cloudPreferenceService.getPreferences(this.appName).pipe(
take(1),
map((preferences => {
const preferencesList = preferences?.list?.entries ?? [];
const searchedPreferences = preferencesList.find(preference => preference.entry.key === TasksListCloudPreferences.columnOrder);
return searchedPreferences ? JSON.parse(searchedPreferences.entry.value) : null;
}))
).subscribe(columnsOrder => {
this.columnsOrder = columnsOrder;
this.createDatatableSchema();
}
);
}
reload() {
@@ -235,6 +249,18 @@ export abstract class BaseTaskListCloudComponent extends DataTableSchema impleme
this.executeRowAction.emit(row);
}
onColumnOrderChanged(columnsWithNewOrder: DataColumn[]): void {
this.columnsOrder = columnsWithNewOrder.map(column => column.id);
if (this.appName) {
this.cloudPreferenceService.updatePreference(
this.appName,
TasksListCloudPreferences.columnOrder,
this.columnsOrder
);
}
}
setSorting(sortDetail) {
const sorting = sortDetail ? {
orderBy: sortDetail.key,

View File

@@ -25,7 +25,7 @@ import { of } from 'rxjs';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { TaskListCloudSortingModel } from '../../../models/task-list-sorting.model';
import { skip } from 'rxjs/operators';
import { shareReplay, skip } from 'rxjs/operators';
import { ServiceTaskListCloudService } from '../services/service-task-list-cloud.service';
@Component({
@@ -111,6 +111,8 @@ describe('ServiceTaskListCloudComponent', () => {
}
}
});
component.isColumnSchemaCreated$ = of(true).pipe(shareReplay(1));
});
afterEach(() => {
@@ -384,6 +386,8 @@ describe('ServiceTaskListCloudComponent', () => {
componentCustom = fixtureCustom.componentInstance;
customCopyComponent = copyFixture.componentInstance;
element = copyFixture.debugElement.nativeElement;
customCopyComponent.taskList.isColumnSchemaCreated$ = of(true);
});
afterEach(() => {

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Component, ViewEncapsulation, Input } from '@angular/core';
import { Component, ViewEncapsulation, Input, Inject } from '@angular/core';
import {
AppConfigService, UserPreferencesService
} from '@alfresco/adf-core';
@@ -23,6 +23,9 @@ import { ServiceTaskQueryCloudRequestModel } from '../models/service-task-cloud.
import { BaseTaskListCloudComponent } from './base-task-list-cloud.component';
import { ServiceTaskListCloudService } from '../services/service-task-list-cloud.service';
import { TaskCloudService } from '../../services/task-cloud.service';
import { combineLatest } from 'rxjs';
import { PreferenceCloudServiceInterface, TASK_LIST_PREFERENCES_SERVICE_TOKEN } from '../../../services/public-api';
import { take } from 'rxjs/operators';
const PRESET_KEY = 'adf-cloud-service-task-list.presets';
@@ -39,14 +42,21 @@ export class ServiceTaskListCloudComponent extends BaseTaskListCloudComponent {
constructor(private serviceTaskListCloudService: ServiceTaskListCloudService,
appConfigService: AppConfigService,
taskCloudService: TaskCloudService,
userPreferences: UserPreferencesService) {
super(appConfigService, taskCloudService, userPreferences, PRESET_KEY);
userPreferences: UserPreferencesService,
@Inject(TASK_LIST_PREFERENCES_SERVICE_TOKEN) cloudPreferenceService: PreferenceCloudServiceInterface) {
super(appConfigService, taskCloudService, userPreferences, PRESET_KEY, cloudPreferenceService);
}
load(requestNode: ServiceTaskQueryCloudRequestModel) {
this.isLoading = true;
this.serviceTaskListCloudService.getServiceTaskByRequest(requestNode).subscribe(
(tasks) => {
combineLatest([
this.serviceTaskListCloudService.getServiceTaskByRequest(requestNode),
this.isColumnSchemaCreated$
]).pipe(
take(1)
).subscribe(
([tasks]) => {
this.rows = tasks.list.entries;
this.success.emit(tasks);
this.isLoading = false;

View File

@@ -26,7 +26,7 @@ import { of } from 'rxjs';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { TaskListCloudSortingModel } from '../../../models/task-list-sorting.model';
import { skip } from 'rxjs/operators';
import { shareReplay, skip } from 'rxjs/operators';
import { TaskListCloudServiceInterface } from '../../../services/task-list-cloud.service.interface';
import { TASK_LIST_CLOUD_TOKEN } from '../../../services/cloud-token.service';
@@ -124,6 +124,8 @@ describe('TaskListCloudComponent', () => {
}
}
});
component.isColumnSchemaCreated$ = of(true).pipe(shareReplay(1));
});
afterEach(() => {
@@ -419,6 +421,8 @@ describe('TaskListCloudComponent', () => {
componentCustom = fixtureCustom.componentInstance;
customCopyComponent = copyFixture.componentInstance;
element = copyFixture.debugElement.nativeElement;
customCopyComponent.taskList.isColumnSchemaCreated$ = of(true);
});
afterEach(() => {
@@ -542,7 +546,9 @@ describe('TaskListCloudComponent', () => {
element = fixture.debugElement.nativeElement;
taskSpy = spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTask));
component.isColumnSchemaCreated$ = of(true);
});
afterEach(() => {
fixture.destroy();
});

View File

@@ -20,8 +20,11 @@ import { AppConfigService, UserPreferencesService } from '@alfresco/adf-core';
import { TaskQueryCloudRequestModel } from '../../../models/filter-cloud-model';
import { BaseTaskListCloudComponent } from './base-task-list-cloud.component';
import { TaskCloudService } from '../../services/task-cloud.service';
import { TASK_LIST_CLOUD_TOKEN } from '../../../services/cloud-token.service';
import { TASK_LIST_CLOUD_TOKEN, TASK_LIST_PREFERENCES_SERVICE_TOKEN } from '../../../services/cloud-token.service';
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
import { TaskListCloudServiceInterface } from '../../../services/task-list-cloud.service.interface';
import { combineLatest } from 'rxjs';
import { take } from 'rxjs/operators';
const PRESET_KEY = 'adf-cloud-task-list.presets';
@@ -135,14 +138,21 @@ export class TaskListCloudComponent extends BaseTaskListCloudComponent {
constructor(@Inject(TASK_LIST_CLOUD_TOKEN) public taskListCloudService: TaskListCloudServiceInterface,
appConfigService: AppConfigService,
taskCloudService: TaskCloudService,
userPreferences: UserPreferencesService) {
super(appConfigService, taskCloudService, userPreferences, PRESET_KEY);
userPreferences: UserPreferencesService,
@Inject(TASK_LIST_PREFERENCES_SERVICE_TOKEN) cloudPreferenceService: PreferenceCloudServiceInterface) {
super(appConfigService, taskCloudService, userPreferences, PRESET_KEY, cloudPreferenceService);
}
load(requestNode: TaskQueryCloudRequestModel) {
this.isLoading = true;
this.taskListCloudService.getTaskByRequest(requestNode).subscribe(
(tasks) => {
combineLatest([
this.taskListCloudService.getTaskByRequest(requestNode),
this.isColumnSchemaCreated$
]).pipe(
take(1)
).subscribe(
([tasks]) => {
this.rows = tasks.list.entries;
this.success.emit(tasks);
this.isLoading = false;

View File

@@ -0,0 +1,4 @@
// eslint-disable-next-line no-shadow
export enum TasksListCloudPreferences {
columnOrder = 'tasks-list-cloud-columns-order'
}

View File

@@ -20,6 +20,7 @@ export * from './components/service-task-list-cloud.component';
export * from './models/service-task-cloud.model';
export * from './models/task-preset-cloud.model';
export * from './models/tasks-cloud-preferences';
export * from './services/task-list-cloud.service';
export * from './services/service-task-list-cloud.service';

View File

@@ -22,7 +22,7 @@ import { TaskListCloudComponent } from './components/task-list-cloud.component';
import { ServiceTaskListCloudComponent } from './components/service-task-list-cloud.component';
import { CoreModule } from '@alfresco/adf-core';
import { TASK_LIST_CLOUD_TOKEN } from '../../services/cloud-token.service';
import { TaskListCloudService } from './public-api';
import { TaskListCloudService } from './services/task-list-cloud.service';
@NgModule({
imports: [