From 3649e9239f5a4d9d9b7dec19704c21d40975c4b7 Mon Sep 17 00:00:00 2001 From: arditdomi <32884230+arditdomi@users.noreply.github.com> Date: Fri, 29 May 2020 14:34:42 +0100 Subject: [PATCH] [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 --- .../datatable/datatable.component.spec.ts | 15 +++++ .../datatable/datatable.component.ts | 40 +++++++++---- .../process/process-instances-list.mock.ts | 26 ++++++--- .../src/lib/mock/task/task-list.mock.ts | 26 ++++++--- .../components/process-list.component.spec.ts | 54 +++++++++++------- .../components/process-list.component.ts | 5 ++ .../components/task-list.component.spec.ts | 56 +++++++++++++------ .../components/task-list.component.ts | 5 ++ 8 files changed, 163 insertions(+), 64 deletions(-) diff --git a/lib/core/datatable/components/datatable/datatable.component.spec.ts b/lib/core/datatable/components/datatable/datatable.component.spec.ts index 8fe95f17d3..e086c301ef 100644 --- a/lib/core/datatable/components/datatable/datatable.component.spec.ts +++ b/lib/core/datatable/components/datatable/datatable.component.spec.ts @@ -1228,6 +1228,21 @@ describe('DataTable', () => { expect(dataTable.data.getRows().length).toEqual(2); 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', () => { diff --git a/lib/core/datatable/components/datatable/datatable.component.ts b/lib/core/datatable/components/datatable/datatable.component.ts index 2461e7cdc6..2c2353461c 100644 --- a/lib/core/datatable/components/datatable/datatable.component.ts +++ b/lib/core/datatable/components/datatable/datatable.component.ts @@ -32,6 +32,7 @@ import { DataTableAdapter } from '../../data/datatable-adapter'; import { DataTableRowComponent } from '../datatable-row/datatable-row.component'; import { ObjectDataRow } from '../../data/object-datarow.model'; +import { ObjectDataColumn } from '../../data/object-datacolumn.model'; import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter'; import { DataCellEvent } from '../data-cell.event'; import { DataRowActionEvent } from '../data-row-action.event'; @@ -225,21 +226,23 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, ngOnChanges(changes: SimpleChanges) { this.initAndSubscribeClickStream(); - if (this.isPropertyChanged(changes['data'])) { - if (this.isTableEmpty()) { - this.initTable(); - } else { - this.data = changes['data'].currentValue; - this.resetSelection(); - } - return; - } - if (this.isPropertyChanged(changes['rows'])) { + 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()) { this.initTable(); } else { - this.setTableRows(changes['rows'].currentValue); + if (dataChanges) { + this.data = changes['data'].currentValue; + this.resetSelection(); + } else if (rowChanges) { + this.setTableRows(changes['rows'].currentValue); + } else { + this.setTableColumns(changes['columns'].currentValue); + } } return; } @@ -280,6 +283,10 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, 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 { if (sorting && sorting.length > 0) { return new DataSorting(sorting[0], sorting[1]); @@ -366,7 +373,16 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, private setTableRows(rows: any[]) { if (this.data) { 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); } } diff --git a/lib/process-services/src/lib/mock/process/process-instances-list.mock.ts b/lib/process-services/src/lib/mock/process/process-instances-list.mock.ts index d409197cee..d3840171ee 100644 --- a/lib/process-services/src/lib/mock/process/process-instances-list.mock.ts +++ b/lib/process-services/src/lib/mock/process/process-instances-list.mock.ts @@ -15,8 +15,6 @@ * limitations under the License. */ -import { ObjectDataColumn } from '@alfresco/adf-core'; - export let fakeProcessInstance = { size: 2, total: 2, @@ -133,28 +131,42 @@ export let fakeProcessInstancesEmpty = { }; export let fakeProcessCustomSchema = [ - new ObjectDataColumn({ + { key: 'fakeName', type: 'text', title: 'ADF_PROCESS_LIST.PROPERTIES.FAKE', sortable: true - }), - new ObjectDataColumn({ + }, + { key: 'fakeProcessName', type: 'text', title: 'ADF_PROCESS_LIST.PROPERTIES.PROCESS_FAKE', sortable: true - }) + } ]; export let fakeProcessColumnSchema = { default: [ { - key: 'name', + key: 'default-name', type: 'text', title: 'ADF_PROCESS_LIST.PROPERTIES.NAME', 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 }; diff --git a/lib/process-services/src/lib/mock/task/task-list.mock.ts b/lib/process-services/src/lib/mock/task/task-list.mock.ts index be77b3094c..ab87b4ede1 100644 --- a/lib/process-services/src/lib/mock/task/task-list.mock.ts +++ b/lib/process-services/src/lib/mock/task/task-list.mock.ts @@ -15,8 +15,6 @@ * limitations under the License. */ -import { ObjectDataColumn } from '@alfresco/adf-core'; - export const fakeGlobalTask = { size: 2, start: 0, @@ -79,29 +77,43 @@ export const fakeGlobalTask = { }; export let fakeCustomSchema = [ - new ObjectDataColumn({ + { key: 'fakeName', type: 'text', title: 'ADF_TASK_LIST.PROPERTIES.FAKE', sortable: true - }), - new ObjectDataColumn({ + }, + { key: 'fakeTaskName', type: 'text', title: 'ADF_TASK_LIST.PROPERTIES.TASK_FAKE', sortable: true - }) + } ]; export let fakeColumnSchema = { default: [ { - key: 'name', + key: 'default-name', type: 'text', title: 'ADF_TASK_LIST.PROPERTIES.NAME', 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 }; diff --git a/lib/process-services/src/lib/process-list/components/process-list.component.spec.ts b/lib/process-services/src/lib/process-list/components/process-list.component.spec.ts index 9d66948768..5b09ced0aa 100644 --- a/lib/process-services/src/lib/process-list/components/process-list.component.spec.ts +++ b/lib/process-services/src/lib/process-list/components/process-list.component.spec.ts @@ -22,9 +22,14 @@ import { By } from '@angular/platform-browser'; import { ProcessInstanceListComponent } from './process-list.component'; import { AppConfigService, setupTestBed, DataRow, DataColumn, - DataRowEvent, ObjectDataRow, ObjectDataTableAdapter, DataCellEvent + DataRowEvent, ObjectDataRow, ObjectDataTableAdapter, DataCellEvent, ObjectDataColumn } 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 { ProcessTestingModule } from '../../testing/process.testing.module'; import { TranslateModule } from '@ngx-translate/core'; @@ -60,22 +65,7 @@ describe('ProcessInstanceListComponent', () => { getProcessInstancesSpy = spyOn(service, 'getProcessInstances').and.returnValue(of(fakeProcessInstance)); appConfig.config['adf-process-list'] = { - 'presets': { - '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 - } - ] - } + 'presets': fakeProcessColumnSchema }; })); @@ -89,7 +79,8 @@ describe('ProcessInstanceListComponent', () => { it('should use the default schemaColumn as default', () => { component.ngAfterContentInit(); 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', () => { @@ -109,7 +100,9 @@ describe('ProcessInstanceListComponent', () => { component.presetColumn = 'fakeProcessCustomSchema'; component.ngAfterContentInit(); 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', () => { @@ -437,6 +430,27 @@ describe('ProcessInstanceListComponent', () => { 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); + }); }); }); diff --git a/lib/process-services/src/lib/process-list/components/process-list.component.ts b/lib/process-services/src/lib/process-list/components/process-list.component.ts index d523cba3dd..1e54268d5c 100644 --- a/lib/process-services/src/lib/process-list/components/process-list.component.ts +++ b/lib/process-services/src/lib/process-list/components/process-list.component.ts @@ -181,6 +181,11 @@ export class ProcessInstanceListComponent extends DataTableSchema implements OnC } this.reload(); } + + const presetColumnChanges = changes['presetColumn']; + if (presetColumnChanges && !presetColumnChanges.firstChange) { + this.columns = this.mergeJsonAndHtmlSchema(); + } } private isSortChanged(changes: SimpleChanges): boolean { diff --git a/lib/process-services/src/lib/task-list/components/task-list.component.spec.ts b/lib/process-services/src/lib/task-list/components/task-list.component.spec.ts index 5f69acc2e6..62066bcbe3 100644 --- a/lib/process-services/src/lib/task-list/components/task-list.component.spec.ts +++ b/lib/process-services/src/lib/task-list/components/task-list.component.spec.ts @@ -18,11 +18,16 @@ import { Component, SimpleChange, ViewChild, OnInit, Output, EventEmitter } from '@angular/core'; import { ComponentFixture, TestBed, async } from '@angular/core/testing'; 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 { TaskListComponent } from './task-list.component'; 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 { of, Subject } from 'rxjs'; @@ -52,24 +57,10 @@ describe('TaskListComponent', () => { appConfig.config = Object.assign(appConfig.config, { 'adf-task-list': { 'presets': { - '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 - } - ] + fakeCustomSchema } } }); - }); beforeEach(() => { @@ -114,7 +105,9 @@ describe('TaskListComponent', () => { component.presetColumn = 'fakeCustomSchema'; component.ngAfterContentInit(); 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', () => { @@ -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(() => { spyOn(taskListService, 'findTasksByState').and.returnValues(of(fakeGlobalTask), of(paginatedTask)); const state = new SimpleChange(null, 'open', true); diff --git a/lib/process-services/src/lib/task-list/components/task-list.component.ts b/lib/process-services/src/lib/task-list/components/task-list.component.ts index f6b6467552..e96474a83d 100644 --- a/lib/process-services/src/lib/task-list/components/task-list.component.ts +++ b/lib/process-services/src/lib/task-list/components/task-list.component.ts @@ -235,6 +235,11 @@ export class TaskListComponent extends DataTableSchema implements OnChanges, Aft } this.reload(); } + + const presetColumnChanges = changes['presetColumn']; + if (presetColumnChanges && !presetColumnChanges.firstChange) { + this.columns = this.mergeJsonAndHtmlSchema(); + } } private isSortChanged(changes: SimpleChanges): boolean {