[ACA-3529] Custom filter doesn't work properly when Direction is set to ASC (#5829)

* [ACA-3479] Sort Order arrow not displayed in task and process list

* Added unit tests

* Fixed lint

* Updated constant prefix

* Added retention of sorting when ItemsPerPage changes

* Removed unwanted changes check; Renamed sortInput

* Updated unit tests

* [ACA-3529] Custom filter doesn't work properly when Direction is set to "ASC"

* Added server side sorting, when sort on column is changed

* Added unit tests
This commit is contained in:
Mercy Chrysolite
2020-07-07 17:39:27 +05:30
committed by GitHub
parent 4ae484c617
commit ed12b13c87
7 changed files with 161 additions and 16 deletions

View File

@@ -253,6 +253,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
this.resetSelection(); this.resetSelection();
} else if (rowChanges) { } else if (rowChanges) {
this.setTableRows(changes['rows'].currentValue); this.setTableRows(changes['rows'].currentValue);
this.setTableSorting(this.sorting);
} else { } else {
this.setTableColumns(changes['columns'].currentValue); this.setTableColumns(changes['columns'].currentValue);
} }
@@ -544,6 +545,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
if (current && column.key === current.key) { if (current && column.key === current.key) {
newDirection = current.direction === 'asc' ? 'desc' : 'asc'; newDirection = current.direction === 'asc' ? 'desc' : 'asc';
} }
this.sorting = [column.key, newDirection];
this.data.setSorting(new DataSorting(column.key, newDirection)); this.data.setSorting(new DataSorting(column.key, newDirection));
this.emitSortingChangedEvent(column.key, newDirection); this.emitSortingChangedEvent(column.key, newDirection);
} }

View File

@@ -3,6 +3,7 @@
[columns]="columns" [columns]="columns"
[stickyHeader]="stickyHeader" [stickyHeader]="stickyHeader"
[loading]="isLoading" [loading]="isLoading"
[sorting]="formattedSorting"
[selectionMode]="selectionMode" [selectionMode]="selectionMode"
[multiselect]="multiselect" [multiselect]="multiselect"
[actions]="showActions" [actions]="showActions"
@@ -14,7 +15,8 @@
(rowClick)="onRowClick($event)" (rowClick)="onRowClick($event)"
(row-select)="onRowSelect($event)" (row-select)="onRowSelect($event)"
(row-unselect)="onRowUnselect($event)" (row-unselect)="onRowUnselect($event)"
(row-keyup)="onRowKeyUp($event)"> (row-keyup)="onRowKeyUp($event)"
(sorting-changed)="onSortingChanged($event)">
<adf-loading-content-template> <adf-loading-content-template>
<ng-template> <ng-template>
<mat-progress-spinner <mat-progress-spinner

View File

@@ -29,6 +29,7 @@ import { fakeCustomSchema, fakeProcessCloudList, processListSchemaMock } from '.
import { of } from 'rxjs'; import { of } from 'rxjs';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module'; import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
@Component({ @Component({
template: ` template: `
@@ -249,6 +250,47 @@ describe('ProcessListCloudComponent', () => {
expect(component.isListEmpty()).toBeFalsy(); expect(component.isListEmpty()).toBeFalsy();
expect(getProcessByRequestSpy).toHaveBeenCalled(); expect(getProcessByRequestSpy).toHaveBeenCalled();
}); });
it('should set formattedSorting if sorting input changes', () => {
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(fakeProcessCloudList));
spyOn(component, 'formatSorting').and.callThrough();
component.appName = 'mock-app-name';
const mockSort = [
new ProcessListCloudSortingModel({
orderBy: 'startDate',
direction: 'DESC'
})
];
const sortChange = new SimpleChange(undefined, mockSort, true);
component.ngOnChanges({
'sorting': sortChange
});
fixture.detectChanges();
expect(component.formatSorting).toHaveBeenCalledWith(mockSort);
expect(component.formattedSorting).toEqual([ProcessListCloudComponent.ENTRY_PREFIX + 'startDate', 'desc']);
});
it('should reload process list when sorting on a column changes', () => {
const getProcessByRequestSpy = spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(fakeProcessCloudList));
component.onSortingChanged(new CustomEvent('sorting-changed', {
detail: {
key: 'fakeName',
direction: 'asc'
},
bubbles: true
}));
fixture.detectChanges();
expect(component.sorting).toEqual([
new ProcessListCloudSortingModel({
orderBy: 'fakeName',
direction: 'ASC'
})
]);
expect(component.formattedSorting).toEqual(['entry.fakeName', 'asc']);
expect(component.isListEmpty()).toBeFalsy();
expect(getProcessByRequestSpy).toHaveBeenCalled();
});
}); });
describe('Injecting custom colums for tasklist - CustomTaskListComponent', () => { describe('Injecting custom colums for tasklist - CustomTaskListComponent', () => {

View File

@@ -35,6 +35,7 @@ import { ProcessListCloudSortingModel } from '../models/process-list-sorting.mod
export class ProcessListCloudComponent extends DataTableSchema implements OnChanges, AfterContentInit, PaginatedComponent { export class ProcessListCloudComponent extends DataTableSchema implements OnChanges, AfterContentInit, PaginatedComponent {
static PRESET_KEY = 'adf-cloud-process-list.presets'; static PRESET_KEY = 'adf-cloud-process-list.presets';
static ENTRY_PREFIX = 'entry.';
@ContentChild(CustomEmptyContentTemplateDirective) @ContentChild(CustomEmptyContentTemplateDirective)
emptyCustomContent: CustomEmptyContentTemplateDirective; emptyCustomContent: CustomEmptyContentTemplateDirective;
@@ -156,7 +157,9 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
selectedInstances: any[]; selectedInstances: any[];
isLoading = true; isLoading = true;
rows: any[] = []; rows: any[] = [];
formattedSorting: any[];
requestNode: ProcessQueryCloudRequestModel; requestNode: ProcessQueryCloudRequestModel;
private defaultSorting = { key: 'startDate', direction: 'desc' };
constructor(private processListCloudService: ProcessListCloudService, constructor(private processListCloudService: ProcessListCloudService,
appConfigService: AppConfigService, appConfigService: AppConfigService,
@@ -178,7 +181,10 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
} }
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
if (this.isPropertyChanged(changes)) { if (this.isPropertyChanged(changes, 'sorting')) {
this.formatSorting(changes['sorting'].currentValue);
}
if (this.isAnyPropertyChanged(changes)) {
this.reload(); this.reload();
} }
} }
@@ -210,18 +216,19 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
}); });
} }
private isPropertyChanged(changes: SimpleChanges): boolean { private isAnyPropertyChanged(changes: SimpleChanges): boolean {
for (const property in changes) { for (const property in changes) {
if (changes.hasOwnProperty(property)) { if (this.isPropertyChanged(changes, property)) {
if (changes[property] && return true;
(changes[property].currentValue !== changes[property].previousValue)) {
return true;
}
} }
} }
return false; return false;
} }
private isPropertyChanged(changes: SimpleChanges, property: string): boolean {
return changes.hasOwnProperty(property);
}
isListEmpty(): boolean { isListEmpty(): boolean {
return !this.rows || this.rows.length === 0; return !this.rows || this.rows.length === 0;
} }
@@ -233,6 +240,12 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
this.reload(); this.reload();
} }
onSortingChanged(event: CustomEvent) {
this.setSorting(event.detail);
this.formatSorting(this.sorting);
this.reload();
}
onRowClick(item: DataRowEvent) { onRowClick(item: DataRowEvent) {
this.currentInstanceId = item.value.getValue('entry.id'); this.currentInstanceId = item.value.getValue('entry.id');
this.rowClick.emit(this.currentInstanceId); this.rowClick.emit(this.currentInstanceId);
@@ -288,4 +301,18 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
return new ProcessQueryCloudRequestModel(requestNode); return new ProcessQueryCloudRequestModel(requestNode);
} }
setSorting(sortDetail) {
const sorting = sortDetail ? {
orderBy: sortDetail.key.replace(ProcessListCloudComponent.ENTRY_PREFIX, ''),
direction: sortDetail.direction.toUpperCase()
} : { ... this.defaultSorting };
this.sorting = [new ProcessListCloudSortingModel(sorting)];
}
formatSorting(sorting: ProcessListCloudSortingModel[]) {
this.formattedSorting = sorting.length ? [
ProcessListCloudComponent.ENTRY_PREFIX + sorting[0].orderBy,
sorting[0].direction.toLocaleLowerCase()
] : null;
}
} }

View File

@@ -4,6 +4,7 @@
[rows]="rows" [rows]="rows"
[columns]="columns" [columns]="columns"
[loading]="isLoading" [loading]="isLoading"
[sorting]="formattedSorting"
[multiselect]="multiselect" [multiselect]="multiselect"
[selectionMode]="selectionMode" [selectionMode]="selectionMode"
[stickyHeader]="stickyHeader" [stickyHeader]="stickyHeader"
@@ -16,7 +17,8 @@
(row-select)="onRowSelect($event)" (row-select)="onRowSelect($event)"
(row-unselect)="onRowUnselect($event)" (row-unselect)="onRowUnselect($event)"
(rowClick)="onRowClick($event)" (rowClick)="onRowClick($event)"
(row-keyup)="onRowKeyUp($event)"> (row-keyup)="onRowKeyUp($event)"
(sorting-changed)="onSortingChanged($event)">
<adf-loading-content-template> <adf-loading-content-template>
<ng-template> <ng-template>
<!-- Add your custom loading template here --> <!-- Add your custom loading template here -->

View File

@@ -27,6 +27,7 @@ import { ProcessServiceCloudTestingModule } from '../../../testing/process-servi
import { Person } from '@alfresco/js-api'; import { Person } from '@alfresco/js-api';
import { TaskListModule } from '@alfresco/adf-process-services'; import { TaskListModule } from '@alfresco/adf-process-services';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { TaskListCloudSortingModel } from '../models/task-list-sorting.model';
@Component({ @Component({
template: ` template: `
@@ -289,6 +290,47 @@ describe('TaskListCloudComponent', () => {
expect(component.isListEmpty()).toBeFalsy(); expect(component.isListEmpty()).toBeFalsy();
expect(getTaskByRequestSpy).toHaveBeenCalled(); expect(getTaskByRequestSpy).toHaveBeenCalled();
}); });
it('should set formattedSorting if sorting input changes', () => {
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTask));
spyOn(component, 'formatSorting').and.callThrough();
component.appName = 'mock-app-name';
const mockSort = [
new TaskListCloudSortingModel({
orderBy: 'startDate',
direction: 'DESC'
})
];
const sortChange = new SimpleChange(undefined, mockSort, true);
component.ngOnChanges({
'sorting': sortChange
});
fixture.detectChanges();
expect(component.formatSorting).toHaveBeenCalledWith(mockSort);
expect(component.formattedSorting).toEqual([TaskListCloudComponent.ENTRY_PREFIX + 'startDate', 'desc']);
});
it('should reload task list when sorting on a column changes', () => {
const getTaskByRequestSpy = spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTask));
component.onSortingChanged(new CustomEvent('sorting-changed', {
detail: {
key: 'fakeName',
direction: 'asc'
},
bubbles: true
}));
fixture.detectChanges();
expect(component.sorting).toEqual([
new TaskListCloudSortingModel({
orderBy: 'fakeName',
direction: 'ASC'
})
]);
expect(component.formattedSorting).toEqual(['entry.fakeName', 'asc']);
expect(component.isListEmpty()).toBeFalsy();
expect(getTaskByRequestSpy).toHaveBeenCalled();
});
}); });
describe('Injecting custom colums for tasklist - CustomTaskListComponent', () => { describe('Injecting custom colums for tasklist - CustomTaskListComponent', () => {

View File

@@ -37,6 +37,7 @@ import { takeUntil } from 'rxjs/operators';
export class TaskListCloudComponent extends DataTableSchema implements OnChanges, AfterContentInit, PaginatedComponent, OnDestroy, OnInit { export class TaskListCloudComponent extends DataTableSchema implements OnChanges, AfterContentInit, PaginatedComponent, OnDestroy, OnInit {
static PRESET_KEY = 'adf-cloud-task-list.presets'; static PRESET_KEY = 'adf-cloud-task-list.presets';
static ENTRY_PREFIX = 'entry.';
@ContentChild(CustomEmptyContentTemplateDirective) @ContentChild(CustomEmptyContentTemplateDirective)
emptyCustomContent: CustomEmptyContentTemplateDirective; emptyCustomContent: CustomEmptyContentTemplateDirective;
@@ -176,6 +177,8 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges
currentInstanceId: any; currentInstanceId: any;
isLoading = true; isLoading = true;
selectedInstances: any[]; selectedInstances: any[];
formattedSorting: any[];
private defaultSorting = { key: 'startDate', direction: 'desc' };
private onDestroy$ = new Subject<boolean>(); private onDestroy$ = new Subject<boolean>();
@@ -201,7 +204,10 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges
} }
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
if (this.isPropertyChanged(changes)) { if (this.isPropertyChanged(changes, 'sorting')) {
this.formatSorting(changes['sorting'].currentValue);
}
if (this.isAnyPropertyChanged(changes)) {
this.reload(); this.reload();
} }
} }
@@ -219,18 +225,19 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges
return this.currentInstanceId; return this.currentInstanceId;
} }
private isPropertyChanged(changes: SimpleChanges): boolean { private isAnyPropertyChanged(changes: SimpleChanges): boolean {
for (const property in changes) { for (const property in changes) {
if (changes.hasOwnProperty(property)) { if (this.isPropertyChanged(changes, property)) {
if (changes[property] && return true;
(changes[property].currentValue !== changes[property].previousValue)) {
return true;
}
} }
} }
return false; return false;
} }
private isPropertyChanged(changes: SimpleChanges, property: string): boolean {
return changes.hasOwnProperty(property);
}
reload() { reload() {
this.requestNode = this.createRequestNode(); this.requestNode = this.createRequestNode();
if (this.requestNode.appName || this.requestNode.appName === '') { if (this.requestNode.appName || this.requestNode.appName === '') {
@@ -265,6 +272,12 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges
this.reload(); this.reload();
} }
onSortingChanged(event: CustomEvent) {
this.setSorting(event.detail);
this.formatSorting(this.sorting);
this.reload();
}
onRowClick(item: DataRowEvent) { onRowClick(item: DataRowEvent) {
this.currentInstanceId = item.value.getValue('entry.id'); this.currentInstanceId = item.value.getValue('entry.id');
this.rowClick.emit(this.currentInstanceId); this.rowClick.emit(this.currentInstanceId);
@@ -324,4 +337,19 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges
}; };
return new TaskQueryCloudRequestModel(requestNode); return new TaskQueryCloudRequestModel(requestNode);
} }
setSorting(sortDetail) {
const sorting = sortDetail ? {
orderBy: sortDetail.key.replace(TaskListCloudComponent.ENTRY_PREFIX, ''),
direction: sortDetail.direction.toUpperCase()
} : { ... this.defaultSorting };
this.sorting = [new TaskListCloudSortingModel(sorting)];
}
formatSorting(sorting: TaskListCloudSortingModel[]) {
this.formattedSorting = sorting.length ? [
TaskListCloudComponent.ENTRY_PREFIX + sorting[0].orderBy,
sorting[0].direction.toLocaleLowerCase()
] : null;
}
} }