[ADF-1749] Task/Process List - Should be able to customize the rendered columns from JSON (#2613)

* [ADF-1749] Task List - Should be able to customize the rendered columns from JSON

* Refactored task/process list components to support customization key's
* Added Key properties to the app.config.json.
* Created preset model for task/process list .

* [ADF-1749] Task/Process List - Should be able to customize the rendered columns from JSON

* Fixed failing testcases.

* [ADF-1749] Task/Process List - Should be able to customize the rendered columns from JSON.

* Added test cases.
* Updated task/process list readme.md file

* * Updated task/process list readme.md file.
This commit is contained in:
siva kumar
2017-11-08 05:07:07 +05:30
committed by Eugenio Romano
parent 348f4971ce
commit 3204bdebcb
11 changed files with 454 additions and 35 deletions

View File

@@ -21,7 +21,7 @@ import { MatProgressSpinnerModule } from '@angular/material';
import { Observable } from 'rxjs/Rx';
import { ProcessInstanceListComponent } from './process-list.component';
import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core';
import { AlfrescoTranslationService, AppConfigService, CoreModule } from 'ng2-alfresco-core';
import { DataRowEvent, DataSorting, DataTableModule, ObjectDataRow, ObjectDataTableAdapter } from 'ng2-alfresco-datatable';
import { fakeProcessInstances, fakeProcessInstancesWithNoName } from '../assets/process-instances-list.mock';
@@ -34,6 +34,40 @@ describe('ProcessInstanceListComponent', () => {
let component: ProcessInstanceListComponent;
let service: ProcessService;
let getProcessInstancesSpy: jasmine.Spy;
let appConfig: AppConfigService;
let fakeCutomSchema = [
{
'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
}
];
let fakeColumnSchema = {
'default': [
{
'key': 'name',
'type': 'text',
'title': 'ADF_PROCESS_LIST.PROPERTIES.NAME',
'sortable': true
},
{
'key': 'created',
'type': 'text',
'title': 'ADF_PROCESS_LIST.PROPERTIES.CREATED',
'cssClass': 'hidden',
'sortable': true
}
]
, fakeCutomSchema };
beforeEach(async(() => {
TestBed.configureTestingModule({
@@ -50,9 +84,31 @@ describe('ProcessInstanceListComponent', () => {
}).compileComponents().then(() => {
fixture = TestBed.createComponent(ProcessInstanceListComponent);
component = fixture.componentInstance;
appConfig = TestBed.get(AppConfigService);
service = fixture.debugElement.injector.get(ProcessService);
getProcessInstancesSpy = spyOn(service, 'getProcessInstances').and.returnValue(Observable.of(fakeProcessInstances));
appConfig.config = Object.assign(appConfig.config, {
'adf-process-list': {
'presets': {
'fakeCutomSchema': [
{
'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
}
]
}
}
}
);
});
}));
@@ -76,6 +132,20 @@ describe('ProcessInstanceListComponent', () => {
expect(component.data.getColumns().length).toEqual(1);
});
it('should fetch the custom schemaColumn from app.config.json', () => {
component.ngAfterContentInit();
fixture.detectChanges();
expect(component.layoutPresets).toEqual(fakeColumnSchema);
});
it('should fetch custom schemaColumn when the input presetColumn is defined', () => {
component.presetColumn = 'fakeCutomColumns';
component.ngAfterContentInit();
fixture.detectChanges();
expect(component.data.getColumns()).toBeDefined();
expect(component.data.getColumns().length).toEqual(2);
});
it('should return an empty process list when no input parameters are passed', () => {
component.ngAfterContentInit();
expect(component.data).toBeDefined();

View File

@@ -17,10 +17,11 @@
import { DatePipe } from '@angular/common';
import { AfterContentInit, Component, ContentChild, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
import { DataColumnListComponent } from 'ng2-alfresco-core';
import { DataColumn, DataRowEvent, DataSorting, DataTableAdapter, ObjectDataRow, ObjectDataTableAdapter } from 'ng2-alfresco-datatable';
import { AppConfigService, DataColumnListComponent } from 'ng2-alfresco-core';
import { DataColumn, DataRowEvent, DataSorting, DataTableAdapter, ObjectDataColumn, ObjectDataRow, ObjectDataTableAdapter } from 'ng2-alfresco-datatable';
import { ProcessFilterParamRepresentationModel } from '../models/filter-process.model';
import { ProcessInstance } from '../models/process-instance.model';
import { processPresetsDefaultModel } from '../models/process-preset.model';
import { ProcessService } from '../services/process.service';
@Component({
@@ -47,6 +48,9 @@ export class ProcessInstanceListComponent implements OnChanges, AfterContentInit
@Input()
name: string;
@Input()
presetColumn: string;
requestNode: ProcessFilterParamRepresentationModel;
@Input()
@@ -63,16 +67,14 @@ export class ProcessInstanceListComponent implements OnChanges, AfterContentInit
currentInstanceId: string;
isLoading: boolean = true;
layoutPresets = {};
private defaultSchema: DataColumn[] = [
{ type: 'text', key: 'name', title: 'ADF_PROCESS_LIST.PROPERTIES.NAME', cssClass: 'full-width name-column', sortable: true },
{ type: 'text', key: 'created', title: 'ADF_PROCESS_LIST.PROPERTIES.CREATED', cssClass: 'hidden', sortable: true }
];
constructor(private processService: ProcessService) {
constructor(private processService: ProcessService,
private appConfig: AppConfigService) {
}
ngAfterContentInit() {
this.loadLayoutPresets();
this.setupSchema();
if (this.appId) {
@@ -92,12 +94,12 @@ export class ProcessInstanceListComponent implements OnChanges, AfterContentInit
}
if (!this.data) {
this.data = new ObjectDataTableAdapter([], schema.length > 0 ? schema : this.defaultSchema);
this.data = new ObjectDataTableAdapter([], schema.length > 0 ? schema : this.getLayoutPreset(this.presetColumn));
} else {
if (schema && schema.length > 0) {
this.data.setColumns(schema);
} else if (this.data.getColumns().length === 0) {
this.data.setColumns(this.defaultSchema);
this.presetColumn ? this.setupDefaultColumns(this.presetColumn) : this.setupDefaultColumns();
}
}
}
@@ -287,4 +289,26 @@ export class ProcessInstanceListComponent implements OnChanges, AfterContentInit
};
return new ProcessFilterParamRepresentationModel(requestNode);
}
setupDefaultColumns(preset: string = 'default'): void {
if (this.data) {
const columns = this.getLayoutPreset(preset);
this.data.setColumns(columns);
}
}
private loadLayoutPresets(): void {
const externalSettings = this.appConfig.get('adf-process-list.presets', null);
if (externalSettings) {
this.layoutPresets = Object.assign({}, processPresetsDefaultModel, externalSettings);
} else {
this.layoutPresets = processPresetsDefaultModel;
}
}
private getLayoutPreset(name: string = 'default'): DataColumn[] {
return (this.layoutPresets[name] || this.layoutPresets['default']).map(col => new ObjectDataColumn(col));
}
}

View File

@@ -0,0 +1,34 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export let processPresetsDefaultModel = {
'default': [
{
'key': 'name',
'type': 'text',
'title': 'ADF_PROCESS_LIST.PROPERTIES.NAME',
'sortable': true
},
{
'key': 'created',
'type': 'text',
'title': 'ADF_PROCESS_LIST.PROPERTIES.CREATED',
'cssClass': 'hidden',
'sortable': true
}
]
};

View File

@@ -84,9 +84,50 @@ describe('TaskListComponent', () => {
error: 'wrong request'
};
let fakeCutomSchema = [
{
'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
}
];
let fakeColumnSchema = {
'default': [
{
'key': 'name',
'type': 'text',
'title': 'ADF_TASK_LIST.PROPERTIES.NAME',
'sortable': true
},
{
'key': 'created',
'type': 'text',
'title': 'ADF_TASK_LIST.PROPERTIES.CREATED',
'cssClass': 'hidden',
'sortable': true
},
{
'key': 'assignee',
'type': 'text',
'title': 'ADF_TASK_LIST.PROPERTIES.ASSIGNEE',
'cssClass': 'hidden',
'sortable': true
}
]
, fakeCutomSchema };
let component: TaskListComponent;
let fixture: ComponentFixture<TaskListComponent>;
let taskListService: TaskListService;
let appConfig: AppConfigService;
beforeEach(async(() => {
TestBed.configureTestingModule({
@@ -107,13 +148,34 @@ describe('TaskListComponent', () => {
}));
beforeEach(() => {
let appConfig: AppConfigService = TestBed.get(AppConfigService);
appConfig = TestBed.get(AppConfigService);
appConfig.config.bpmHost = 'http://localhost:9876/bpm';
fixture = TestBed.createComponent(TaskListComponent);
component = fixture.componentInstance;
taskListService = TestBed.get(TaskListService);
appConfig.config = Object.assign(appConfig.config, {
'adf-task-list': {
'presets': {
'fakeCutomSchema': [
{
'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
}
]
}
}
}
);
});
@@ -128,7 +190,7 @@ describe('TaskListComponent', () => {
it('should use the default schemaColumn as default', () => {
component.ngAfterContentInit();
expect(component.data.getColumns()).toBeDefined();
expect(component.data.getColumns().length).toEqual(2);
expect(component.data.getColumns().length).toEqual(3);
});
it('should use the schemaColumn passed in input', () => {
@@ -144,6 +206,19 @@ describe('TaskListComponent', () => {
expect(component.data.getColumns().length).toEqual(1);
});
it('should use the custom schemaColumn from app.config.json', () => {
component.ngAfterContentInit();
fixture.detectChanges();
expect(component.layoutPresets).toEqual(fakeColumnSchema);
});
it('should fetch custom schemaColumn when the input presetColumn is defined', () => {
component.presetColumn = 'fakeCutomColumns';
fixture.detectChanges();
expect(component.data.getColumns()).toBeDefined();
expect(component.data.getColumns().length).toEqual(3);
});
it('should return an empty task list when no input parameters are passed', () => {
component.ngAfterContentInit();
expect(component.data).toBeDefined();

View File

@@ -16,11 +16,12 @@
*/
import { AfterContentInit, Component, ContentChild, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { DataColumnListComponent } from 'ng2-alfresco-core';
import { DataColumn, DataRowEvent, DataTableAdapter, ObjectDataRow, ObjectDataTableAdapter } from 'ng2-alfresco-datatable';
import { AppConfigService, DataColumnListComponent } from 'ng2-alfresco-core';
import { DataColumn, DataRowEvent, DataTableAdapter, ObjectDataColumn, ObjectDataRow, ObjectDataTableAdapter } from 'ng2-alfresco-datatable';
import { Observable } from 'rxjs/Rx';
import { TaskQueryRequestRepresentationModel } from '../models/filter.model';
import { TaskListModel } from '../models/task-list.model';
import { taskPresetsDefaultModel } from '../models/task-preset.model';
import { TaskListService } from './../services/tasklist.service';
const DEFAULT_SIZE = 5;
@@ -65,6 +66,9 @@ export class TaskListComponent implements OnChanges, OnInit, AfterContentInit {
@Input()
selectionMode: string = 'none'; // none|single|multiple
@Input()
presetColumn: string;
@Input()
multiselect: boolean = false;
@@ -82,6 +86,7 @@ export class TaskListComponent implements OnChanges, OnInit, AfterContentInit {
currentInstanceId: string;
selectedInstances: any[];
layoutPresets = {};
@Input()
page: number = 0;
@@ -102,12 +107,8 @@ export class TaskListComponent implements OnChanges, OnInit, AfterContentInit {
hasCustomDataSource: boolean = false;
isStreamLoaded = false;
private defaultSchemaColumn: DataColumn[] = [
{ type: 'text', key: 'name', title: 'ADF_TASK_LIST.PROPERTIES.NAME', cssClass: 'full-width name-column', sortable: true },
{ type: 'text', key: 'created', title: 'ADF_TASK_LIST.PROPERTIES.CREATED', cssClass: 'hidden', sortable: true }
];
constructor(private taskListService: TaskListService) {
constructor(private taskListService: TaskListService,
private appConfig: AppConfigService) {
}
initStream() {
@@ -135,6 +136,7 @@ export class TaskListComponent implements OnChanges, OnInit, AfterContentInit {
}
ngAfterContentInit() {
this.loadLayoutPresets();
this.setupSchema();
}
@@ -150,12 +152,13 @@ export class TaskListComponent implements OnChanges, OnInit, AfterContentInit {
}
if (!this.data) {
this.data = new ObjectDataTableAdapter([], schema.length > 0 ? schema : this.defaultSchemaColumn);
this.data = new ObjectDataTableAdapter([], schema.length > 0 ? schema : this.presetColumn ? this.getLayoutPreset(this.presetColumn) : this.getLayoutPreset());
} else {
if (schema && schema.length > 0) {
this.data.setColumns(schema);
} else if (this.data.getColumns().length === 0) {
this.data.setColumns(this.defaultSchemaColumn);
this.presetColumn ? this.setupDefaultColumns(this.presetColumn) : this.setupDefaultColumns();
}
}
}
@@ -324,4 +327,26 @@ export class TaskListComponent implements OnChanges, OnInit, AfterContentInit {
};
return new TaskQueryRequestRepresentationModel(requestNode);
}
setupDefaultColumns(preset: string = 'default'): void {
if (this.data) {
const columns = this.getLayoutPreset(preset);
this.data.setColumns(columns);
}
}
private loadLayoutPresets(): void {
const externalSettings = this.appConfig.get('adf-task-list.presets', null);
if (externalSettings) {
this.layoutPresets = Object.assign({}, taskPresetsDefaultModel, externalSettings);
} else {
this.layoutPresets = taskPresetsDefaultModel;
}
}
private getLayoutPreset(name: string = 'default'): DataColumn[] {
return (this.layoutPresets[name] || this.layoutPresets['default']).map(col => new ObjectDataColumn(col));
}
}

View File

@@ -0,0 +1,41 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export let taskPresetsDefaultModel = {
'default': [
{
'key': 'name',
'type': 'text',
'title': 'ADF_TASK_LIST.PROPERTIES.NAME',
'sortable': true
},
{
'key': 'created',
'type': 'text',
'title': 'ADF_TASK_LIST.PROPERTIES.CREATED',
'cssClass': 'hidden',
'sortable': true
},
{
'key': 'assignee',
'type': 'text',
'title': 'ADF_TASK_LIST.PROPERTIES.ASSIGNEE',
'cssClass': 'hidden',
'sortable': true
}
]
};