[ACA-3368] Update datatable columns when presetColumn schema changes (#5732)

* [ACA-3368] Update datatable columns when presetColumn schema changes

* [ACA-3368] Add presetColumn change detection for task list

* [ACA-3368] Improve unit tests, fix comments

* [ACA-3368] More unit test improvements
This commit is contained in:
arditdomi
2020-05-29 14:34:42 +01:00
committed by GitHub
parent d782b5c4d2
commit 3649e9239f
8 changed files with 163 additions and 64 deletions

View File

@@ -1228,6 +1228,21 @@ describe('DataTable', () => {
expect(dataTable.data.getRows().length).toEqual(2); expect(dataTable.data.getRows().length).toEqual(2);
expect(dataTable.resolverFn).toHaveBeenCalledTimes(4); expect(dataTable.resolverFn).toHaveBeenCalledTimes(4);
}); });
it('should update data columns when columns input changes', () => {
const existingDataColumnsSchema = [new ObjectDataColumn({ key: 'id' })];
const existingData = [{ id: 'fake-data' }];
dataTable.data = new ObjectDataTableAdapter(
existingData,
existingDataColumnsSchema
);
const newDataColumnsSchema = { key: 'new-column'};
const columnsChange = new SimpleChange(null, [newDataColumnsSchema], false);
dataTable.ngOnChanges({ 'columns': columnsChange });
const expectedNewDataColumns = [new ObjectDataColumn(newDataColumnsSchema)];
expect(dataTable.data.getColumns()).toEqual(expectedNewDataColumns);
});
}); });
describe('Accesibility', () => { describe('Accesibility', () => {

View File

@@ -32,6 +32,7 @@ import { DataTableAdapter } from '../../data/datatable-adapter';
import { DataTableRowComponent } from '../datatable-row/datatable-row.component'; import { DataTableRowComponent } from '../datatable-row/datatable-row.component';
import { ObjectDataRow } from '../../data/object-datarow.model'; import { ObjectDataRow } from '../../data/object-datarow.model';
import { ObjectDataColumn } from '../../data/object-datacolumn.model';
import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter'; import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter';
import { DataCellEvent } from '../data-cell.event'; import { DataCellEvent } from '../data-cell.event';
import { DataRowActionEvent } from '../data-row-action.event'; import { DataRowActionEvent } from '../data-row-action.event';
@@ -225,21 +226,23 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
this.initAndSubscribeClickStream(); this.initAndSubscribeClickStream();
if (this.isPropertyChanged(changes['data'])) {
const dataChanges = changes['data'];
const rowChanges = changes['rows'];
const columnChanges = changes['columns'];
if (this.isPropertyChanged(dataChanges) || this.isPropertyChanged(rowChanges) || this.isPropertyChanged(columnChanges)) {
if (this.isTableEmpty()) { if (this.isTableEmpty()) {
this.initTable(); this.initTable();
} else { } else {
if (dataChanges) {
this.data = changes['data'].currentValue; this.data = changes['data'].currentValue;
this.resetSelection(); this.resetSelection();
} } else if (rowChanges) {
return;
}
if (this.isPropertyChanged(changes['rows'])) {
if (this.isTableEmpty()) {
this.initTable();
} else {
this.setTableRows(changes['rows'].currentValue); this.setTableRows(changes['rows'].currentValue);
} else {
this.setTableColumns(changes['columns'].currentValue);
}
} }
return; return;
} }
@@ -280,6 +283,10 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
return rows.map((row) => new ObjectDataRow(row, row.isSelected)); return rows.map((row) => new ObjectDataRow(row, row.isSelected));
} }
convertToColumnsData(columns: any []): ObjectDataColumn[] {
return columns.map((column) => new ObjectDataColumn(column));
}
convertToDataSorting(sorting: any[]): DataSorting | null { convertToDataSorting(sorting: any[]): DataSorting | null {
if (sorting && sorting.length > 0) { if (sorting && sorting.length > 0) {
return new DataSorting(sorting[0], sorting[1]); return new DataSorting(sorting[0], sorting[1]);
@@ -366,7 +373,16 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
private setTableRows(rows: any[]) { private setTableRows(rows: any[]) {
if (this.data) { if (this.data) {
this.resetSelection(); this.resetSelection();
this.data.setRows(this.convertToRowsData(rows)); const rowsData = this.convertToRowsData(rows);
this.data.setRows(rowsData);
}
}
private setTableColumns(columns: any[]) {
if (this.data) {
this.resetSelection();
const columnsData = this.convertToColumnsData(columns);
this.data.setColumns(columnsData);
} }
} }

View File

@@ -15,8 +15,6 @@
* limitations under the License. * limitations under the License.
*/ */
import { ObjectDataColumn } from '@alfresco/adf-core';
export let fakeProcessInstance = { export let fakeProcessInstance = {
size: 2, size: 2,
total: 2, total: 2,
@@ -133,28 +131,42 @@ export let fakeProcessInstancesEmpty = {
}; };
export let fakeProcessCustomSchema = [ export let fakeProcessCustomSchema = [
new ObjectDataColumn({ {
key: 'fakeName', key: 'fakeName',
type: 'text', type: 'text',
title: 'ADF_PROCESS_LIST.PROPERTIES.FAKE', title: 'ADF_PROCESS_LIST.PROPERTIES.FAKE',
sortable: true sortable: true
}), },
new ObjectDataColumn({ {
key: 'fakeProcessName', key: 'fakeProcessName',
type: 'text', type: 'text',
title: 'ADF_PROCESS_LIST.PROPERTIES.PROCESS_FAKE', title: 'ADF_PROCESS_LIST.PROPERTIES.PROCESS_FAKE',
sortable: true sortable: true
}) }
]; ];
export let fakeProcessColumnSchema = { export let fakeProcessColumnSchema = {
default: [ default: [
{ {
key: 'name', key: 'default-name',
type: 'text', type: 'text',
title: 'ADF_PROCESS_LIST.PROPERTIES.NAME', title: 'ADF_PROCESS_LIST.PROPERTIES.NAME',
sortable: true sortable: true
} }
], ],
fakeRunningProcessSchema: [
{
key: 'process-id',
type: 'text',
title: 'ADF_PROCESS_LIST.PROPERTIES.FAKE',
sortable: true
},
{
key: 'process-name',
type: 'text',
title: 'ADF_PROCESS_LIST.PROPERTIES.PROCESS_FAKE',
sortable: true
}
],
fakeProcessCustomSchema fakeProcessCustomSchema
}; };

View File

@@ -15,8 +15,6 @@
* limitations under the License. * limitations under the License.
*/ */
import { ObjectDataColumn } from '@alfresco/adf-core';
export const fakeGlobalTask = { export const fakeGlobalTask = {
size: 2, size: 2,
start: 0, start: 0,
@@ -79,29 +77,43 @@ export const fakeGlobalTask = {
}; };
export let fakeCustomSchema = [ export let fakeCustomSchema = [
new ObjectDataColumn({ {
key: 'fakeName', key: 'fakeName',
type: 'text', type: 'text',
title: 'ADF_TASK_LIST.PROPERTIES.FAKE', title: 'ADF_TASK_LIST.PROPERTIES.FAKE',
sortable: true sortable: true
}), },
new ObjectDataColumn({ {
key: 'fakeTaskName', key: 'fakeTaskName',
type: 'text', type: 'text',
title: 'ADF_TASK_LIST.PROPERTIES.TASK_FAKE', title: 'ADF_TASK_LIST.PROPERTIES.TASK_FAKE',
sortable: true sortable: true
}) }
]; ];
export let fakeColumnSchema = { export let fakeColumnSchema = {
default: [ default: [
{ {
key: 'name', key: 'default-name',
type: 'text', type: 'text',
title: 'ADF_TASK_LIST.PROPERTIES.NAME', title: 'ADF_TASK_LIST.PROPERTIES.NAME',
sortable: true sortable: true
} }
], ],
fakeMyTasksSchema: [
{
key: 'task-id',
type: 'text',
title: 'ADF_TASK_LIST.PROPERTIES.FAKE',
sortable: true
},
{
key: 'task-name',
type: 'text',
title: 'ADF_TASK_LIST.PROPERTIES.PROCESS_FAKE',
sortable: true
}
],
fakeCustomSchema fakeCustomSchema
}; };

View File

@@ -22,9 +22,14 @@ import { By } from '@angular/platform-browser';
import { ProcessInstanceListComponent } from './process-list.component'; import { ProcessInstanceListComponent } from './process-list.component';
import { import {
AppConfigService, setupTestBed, DataRow, DataColumn, AppConfigService, setupTestBed, DataRow, DataColumn,
DataRowEvent, ObjectDataRow, ObjectDataTableAdapter, DataCellEvent DataRowEvent, ObjectDataRow, ObjectDataTableAdapter, DataCellEvent, ObjectDataColumn
} from '@alfresco/adf-core'; } from '@alfresco/adf-core';
import { fakeProcessInstance, fakeProcessInstancesWithNoName, fakeProcessInstancesEmpty, fakeProcessCustomSchema } from '../../mock'; import {
fakeProcessInstance,
fakeProcessInstancesWithNoName,
fakeProcessInstancesEmpty,
fakeProcessColumnSchema
} from '../../mock';
import { ProcessService } from '../services/process.service'; import { ProcessService } from '../services/process.service';
import { ProcessTestingModule } from '../../testing/process.testing.module'; import { ProcessTestingModule } from '../../testing/process.testing.module';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
@@ -60,22 +65,7 @@ describe('ProcessInstanceListComponent', () => {
getProcessInstancesSpy = spyOn(service, 'getProcessInstances').and.returnValue(of(fakeProcessInstance)); getProcessInstancesSpy = spyOn(service, 'getProcessInstances').and.returnValue(of(fakeProcessInstance));
appConfig.config['adf-process-list'] = { appConfig.config['adf-process-list'] = {
'presets': { 'presets': fakeProcessColumnSchema
'fakeProcessCustomSchema': [
{
'key': 'fakeName',
'type': 'text',
'title': 'ADF_PROCESS_LIST.PROPERTIES.FAKE',
'sortable': true
},
{
'key': 'fakeProcessName',
'type': 'text',
'title': 'ADF_PROCESS_LIST.PROPERTIES.PROCESS_FAKE',
'sortable': true
}
]
}
}; };
})); }));
@@ -89,7 +79,8 @@ describe('ProcessInstanceListComponent', () => {
it('should use the default schemaColumn as default', () => { it('should use the default schemaColumn as default', () => {
component.ngAfterContentInit(); component.ngAfterContentInit();
expect(component.columns).toBeDefined(); expect(component.columns).toBeDefined();
expect(component.columns.length).toEqual(2); expect(component.columns.length).toEqual(1);
expect(component.columns[0]).toEqual(new ObjectDataColumn(fakeProcessColumnSchema.default[0]));
}); });
it('should use the schemaColumn passed in input', () => { it('should use the schemaColumn passed in input', () => {
@@ -109,7 +100,9 @@ describe('ProcessInstanceListComponent', () => {
component.presetColumn = 'fakeProcessCustomSchema'; component.presetColumn = 'fakeProcessCustomSchema';
component.ngAfterContentInit(); component.ngAfterContentInit();
fixture.detectChanges(); fixture.detectChanges();
expect(component.columns).toEqual(fakeProcessCustomSchema); expect(component.columns.length).toEqual(2);
expect(component.columns[0]).toEqual(new ObjectDataColumn(fakeProcessColumnSchema.fakeProcessCustomSchema[0]));
expect(component.columns[1]).toEqual(new ObjectDataColumn(fakeProcessColumnSchema.fakeProcessCustomSchema[1]));
}); });
it('should fetch custom schemaColumn when the input presetColumn is defined', () => { it('should fetch custom schemaColumn when the input presetColumn is defined', () => {
@@ -437,6 +430,27 @@ describe('ProcessInstanceListComponent', () => {
component.ngOnChanges({'processInstanceId': change}); component.ngOnChanges({'processInstanceId': change});
}); });
it('should update the columns when presetColumn schema changes', () => {
component.presetColumn = 'fakeProcessCustomSchema';
component.ngAfterContentInit();
const initialColumnSchema = component.mergeJsonAndHtmlSchema();
expect(component.columns).toEqual(initialColumnSchema);
component.presetColumn = 'fakeRunningProcessSchema';
const presetColumnChange = new SimpleChange(null, 'fakeRunningProcessSchema', false);
component.ngOnChanges({ 'presetColumn': presetColumnChange });
const newColumnSchema = component.mergeJsonAndHtmlSchema();
const expectedColumn1 = new ObjectDataColumn(fakeProcessColumnSchema.fakeRunningProcessSchema[0]);
const expectedColumn2 = new ObjectDataColumn(fakeProcessColumnSchema.fakeRunningProcessSchema[1]);
expect(component.columns).toEqual(newColumnSchema);
expect(initialColumnSchema).not.toEqual(newColumnSchema);
expect(component.columns.length).toEqual(2);
expect(component.columns[0]).toEqual(expectedColumn1);
expect(component.columns[1]).toEqual(expectedColumn2);
});
}); });
}); });

View File

@@ -181,6 +181,11 @@ export class ProcessInstanceListComponent extends DataTableSchema implements OnC
} }
this.reload(); this.reload();
} }
const presetColumnChanges = changes['presetColumn'];
if (presetColumnChanges && !presetColumnChanges.firstChange) {
this.columns = this.mergeJsonAndHtmlSchema();
}
} }
private isSortChanged(changes: SimpleChanges): boolean { private isSortChanged(changes: SimpleChanges): boolean {

View File

@@ -18,11 +18,16 @@
import { Component, SimpleChange, ViewChild, OnInit, Output, EventEmitter } from '@angular/core'; import { Component, SimpleChange, ViewChild, OnInit, Output, EventEmitter } from '@angular/core';
import { ComponentFixture, TestBed, async } from '@angular/core/testing'; import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { AppConfigService, setupTestBed, DataRowEvent, ObjectDataRow, DataCellEvent } from '@alfresco/adf-core'; import { AppConfigService, setupTestBed, DataRowEvent, ObjectDataRow, DataCellEvent, ObjectDataColumn } from '@alfresco/adf-core';
import { TaskListService } from '../services/tasklist.service'; import { TaskListService } from '../services/tasklist.service';
import { TaskListComponent } from './task-list.component'; import { TaskListComponent } from './task-list.component';
import { ProcessTestingModule } from '../../testing/process.testing.module'; import { ProcessTestingModule } from '../../testing/process.testing.module';
import { fakeGlobalTask, fakeCustomSchema, fakeEmptyTask, paginatedTask } from '../../mock'; import {
fakeGlobalTask,
fakeEmptyTask,
paginatedTask,
fakeColumnSchema, fakeCustomSchema
} from '../../mock';
import { TranslateService, TranslateModule } from '@ngx-translate/core'; import { TranslateService, TranslateModule } from '@ngx-translate/core';
import { of, Subject } from 'rxjs'; import { of, Subject } from 'rxjs';
@@ -52,24 +57,10 @@ describe('TaskListComponent', () => {
appConfig.config = Object.assign(appConfig.config, { appConfig.config = Object.assign(appConfig.config, {
'adf-task-list': { 'adf-task-list': {
'presets': { 'presets': {
'fakeCustomSchema': [ fakeCustomSchema
{
'key': 'fakeName',
'type': 'text',
'title': 'ADF_TASK_LIST.PROPERTIES.FAKE',
'sortable': true
},
{
'key': 'fakeTaskName',
'type': 'text',
'title': 'ADF_TASK_LIST.PROPERTIES.TASK_FAKE',
'sortable': true
}
]
} }
} }
}); });
}); });
beforeEach(() => { beforeEach(() => {
@@ -114,7 +105,9 @@ describe('TaskListComponent', () => {
component.presetColumn = 'fakeCustomSchema'; component.presetColumn = 'fakeCustomSchema';
component.ngAfterContentInit(); component.ngAfterContentInit();
fixture.detectChanges(); fixture.detectChanges();
expect(component.columns).toEqual(fakeCustomSchema); expect(component.columns.length).toEqual(2);
expect(component.columns[0]).toEqual(new ObjectDataColumn(fakeCustomSchema[0]));
expect(component.columns[1]).toEqual(new ObjectDataColumn(fakeCustomSchema[1]));
}); });
it('should fetch custom schemaColumn when the input presetColumn is defined', () => { it('should fetch custom schemaColumn when the input presetColumn is defined', () => {
@@ -535,6 +528,33 @@ describe('TaskListComponent', () => {
}); });
}); });
it('should update the columns when presetColumn schema changes', () => {
appConfig.config = Object.assign(appConfig.config, {
'adf-task-list': {
'presets': fakeColumnSchema
}
});
component.presetColumn = 'fakeCustomSchema';
component.ngAfterContentInit();
const initialColumnSchema = component.mergeJsonAndHtmlSchema();
expect(component.columns).toEqual(initialColumnSchema);
component.presetColumn = 'fakeMyTasksSchema';
const presetColumnChange = new SimpleChange(null, 'fakeMyTasksSchema', false);
component.ngOnChanges({ 'presetColumn': presetColumnChange });
const newColumnSchema = component.mergeJsonAndHtmlSchema();
const expectedColumn1 = new ObjectDataColumn(fakeColumnSchema.fakeMyTasksSchema[0]);
const expectedColumn2 = new ObjectDataColumn(fakeColumnSchema.fakeMyTasksSchema[1]);
expect(component.columns).toEqual(newColumnSchema);
expect(initialColumnSchema).not.toEqual(newColumnSchema);
expect(component.columns.length).toEqual(2);
expect(component.columns[0]).toEqual(expectedColumn1);
expect(component.columns[1]).toEqual(expectedColumn2);
});
it('should show the updated list when pagination changes', async(() => { it('should show the updated list when pagination changes', async(() => {
spyOn(taskListService, 'findTasksByState').and.returnValues(of(fakeGlobalTask), of(paginatedTask)); spyOn(taskListService, 'findTasksByState').and.returnValues(of(fakeGlobalTask), of(paginatedTask));
const state = new SimpleChange(null, 'open', true); const state = new SimpleChange(null, 'open', true);

View File

@@ -235,6 +235,11 @@ export class TaskListComponent extends DataTableSchema implements OnChanges, Aft
} }
this.reload(); this.reload();
} }
const presetColumnChanges = changes['presetColumn'];
if (presetColumnChanges && !presetColumnChanges.firstChange) {
this.columns = this.mergeJsonAndHtmlSchema();
}
} }
private isSortChanged(changes: SimpleChanges): boolean { private isSortChanged(changes: SimpleChanges): boolean {