Merge pull request #773 from Alfresco/dev-mvitale-677

Filter the tasks/processes by Date instead of Name
This commit is contained in:
Denys Vuika
2016-09-21 09:39:21 +01:00
committed by GitHub
7 changed files with 137 additions and 68 deletions

View File

@@ -24,7 +24,7 @@
</div> </div>
<div class="mdl-cell mdl-cell--3-col task-column mdl-shadow--2dp"> <div class="mdl-cell mdl-cell--3-col task-column mdl-shadow--2dp">
<span>Task List</span> <span>Task List</span>
<activiti-tasklist *ngIf="isTaskListSelected()" [taskFilter]="taskFilter" [schemaColumn]="taskSchemaColumns" <activiti-tasklist *ngIf="isTaskListSelected()" [taskFilter]="taskFilter" [data]="dataTasks"
(rowClick)="onTaskRowClick($event)" (onSuccess)="onSuccessTaskList($event)" (rowClick)="onTaskRowClick($event)" (onSuccess)="onSuccessTaskList($event)"
#activititasklist></activiti-tasklist> #activititasklist></activiti-tasklist>
</div> </div>
@@ -49,7 +49,7 @@
</div> </div>
<div class="mdl-cell mdl-cell--3-col task-column"> <div class="mdl-cell mdl-cell--3-col task-column">
<span>Process List</span> <span>Process List</span>
<activiti-process-instance-list [filter]="processFilter" [schemaColumn]="processSchemaColumns" <activiti-process-instance-list [filter]="processFilter" [data]="dataProcesses"
(rowClick)="onProcessRowClick($event)" (onSuccess)="onSuccessProcessList($event)" (rowClick)="onProcessRowClick($event)" (onSuccess)="onSuccessProcessList($event)"
#activitiprocesslist></activiti-process-instance-list> #activitiprocesslist></activiti-process-instance-list>
</div> </div>

View File

@@ -26,6 +26,10 @@ import { ACTIVITI_PROCESSLIST_DIRECTIVES } from 'ng2-activiti-processlist';
import { ActivitiForm } from 'ng2-activiti-form'; import { ActivitiForm } from 'ng2-activiti-form';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs/Rx'; import { Subscription } from 'rxjs/Rx';
import {
ObjectDataTableAdapter,
DataSorting
} from 'ng2-alfresco-datatable';
declare let __moduleName: string; declare let __moduleName: string;
declare var componentHandler; declare var componentHandler;
@@ -74,6 +78,9 @@ export class ActivitiDemoComponent implements AfterViewChecked {
sub: Subscription; sub: Subscription;
dataTasks: ObjectDataTableAdapter;
dataProcesses: ObjectDataTableAdapter;
@Input() @Input()
appId: number; appId: number;
@@ -90,13 +97,23 @@ export class ActivitiDemoComponent implements AfterViewChecked {
} }
constructor(private route: ActivatedRoute) { constructor(private route: ActivatedRoute) {
this.taskSchemaColumns = [ this.dataTasks = new ObjectDataTableAdapter(
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true} [],
// {type: 'text', key: 'created', title: 'Created', sortable: true} [
]; {type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true},
this.processSchemaColumns = [ {type: 'text', key: 'created', title: 'Created', cssClass: 'hidden', sortable: true}
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true} ]
]; );
this.dataTasks.setSorting(new DataSorting('created', 'desc'));
this.dataProcesses = new ObjectDataTableAdapter(
[],
[
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true},
{type: 'text', key: 'started', title: 'Started', cssClass: 'hidden', sortable: true}
]
);
this.dataProcesses.setSorting(new DataSorting('started', 'desc'));
} }
ngOnInit() { ngOnInit() {

View File

@@ -17,7 +17,7 @@
import {Component, OnInit, Input, Output, EventEmitter, OnChanges, SimpleChanges } from '@angular/core'; import {Component, OnInit, Input, Output, EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
import { AlfrescoTranslationService, CONTEXT_MENU_DIRECTIVES, CONTEXT_MENU_PROVIDERS } from 'ng2-alfresco-core'; import { AlfrescoTranslationService, CONTEXT_MENU_DIRECTIVES, CONTEXT_MENU_PROVIDERS } from 'ng2-alfresco-core';
import { ALFRESCO_DATATABLE_DIRECTIVES, ObjectDataTableAdapter, DataRowEvent } from 'ng2-alfresco-datatable'; import { ALFRESCO_DATATABLE_DIRECTIVES, ObjectDataTableAdapter, DataRowEvent, DataTableAdapter, ObjectDataRow } from 'ng2-alfresco-datatable';
import { ActivitiProcessService } from '../services/activiti-process.service'; import { ActivitiProcessService } from '../services/activiti-process.service';
import { UserProcessInstanceFilterRepresentationModel, TaskQueryRequestRepresentationModel } from '../models/filter.model'; import { UserProcessInstanceFilterRepresentationModel, TaskQueryRequestRepresentationModel } from '../models/filter.model';
@@ -39,20 +39,11 @@ declare let __moduleName: string;
}) })
export class ActivitiProcessInstanceListComponent implements OnInit, OnChanges { export class ActivitiProcessInstanceListComponent implements OnInit, OnChanges {
errorMessage: string;
data: ObjectDataTableAdapter;
currentProcessInstanceId: string;
@Input() @Input()
filter: UserProcessInstanceFilterRepresentationModel; filter: UserProcessInstanceFilterRepresentationModel;
@Input() @Input()
schemaColumn: any[] = [ data: DataTableAdapter;
{type: 'text', key: 'id', title: 'Id', sortable: true},
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true},
{type: 'text', key: 'started', title: 'Started', sortable: true},
{type: 'text', key: 'startedBy.email', title: 'Started By', sortable: true}
];
@Output() @Output()
rowClick: EventEmitter<string> = new EventEmitter<string>(); rowClick: EventEmitter<string> = new EventEmitter<string>();
@@ -63,6 +54,16 @@ export class ActivitiProcessInstanceListComponent implements OnInit, OnChanges {
@Output() @Output()
onError: EventEmitter<any> = new EventEmitter<any>(); onError: EventEmitter<any> = new EventEmitter<any>();
errorMessage: string;
currentProcessInstanceId: string;
private defaultSchemaColumn: any[] = [
{type: 'text', key: 'id', title: 'Id', sortable: true},
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true},
{type: 'text', key: 'started', title: 'Started', sortable: true},
{type: 'text', key: 'startedBy.email', title: 'Started By', sortable: true}
];
constructor (private processService: ActivitiProcessService, private translate: AlfrescoTranslationService) { constructor (private processService: ActivitiProcessService, private translate: AlfrescoTranslationService) {
if (translate !== null) { if (translate !== null) {
translate.addTranslationFolder('node_modules/ng2-activiti-processlist/src'); translate.addTranslationFolder('node_modules/ng2-activiti-processlist/src');
@@ -70,10 +71,9 @@ export class ActivitiProcessInstanceListComponent implements OnInit, OnChanges {
} }
ngOnInit() { ngOnInit() {
this.data = new ObjectDataTableAdapter( if (!this.data) {
[], this.data = this.initDefaultSchemaColumns();
this.schemaColumn }
);
if (this.filter) { if (this.filter) {
let requestNode = this.convertProcessInstanceToTaskQuery(this.filter); let requestNode = this.convertProcessInstanceToTaskQuery(this.filter);
this.load(requestNode); this.load(requestNode);
@@ -89,11 +89,23 @@ export class ActivitiProcessInstanceListComponent implements OnInit, OnChanges {
} }
} }
/**
* Return an initDefaultSchemaColumns instance with the default Schema Column
* @returns {ObjectDataTableAdapter}
*/
initDefaultSchemaColumns(): ObjectDataTableAdapter {
return new ObjectDataTableAdapter(
[],
this.defaultSchemaColumn
);
}
load(requestNode: TaskQueryRequestRepresentationModel) { load(requestNode: TaskQueryRequestRepresentationModel) {
this.processService.getProcessInstances(requestNode) this.processService.getProcessInstances(requestNode)
.subscribe( .subscribe(
(processInstances) => { (processInstances) => {
this.renderProcessInstances(processInstances); let processRow = this.createDataRow(processInstances);
this.renderProcessInstances(processRow);
this.selectFirstProcess(); this.selectFirstProcess();
this.onSuccess.emit(processInstances); this.onSuccess.emit(processInstances);
}, },
@@ -103,6 +115,23 @@ export class ActivitiProcessInstanceListComponent implements OnInit, OnChanges {
}); });
} }
/**
* Create an array of ObjectDataRow
* @param processes
* @returns {ObjectDataRow[]}
*/
private createDataRow(processes: any[]): ObjectDataRow[] {
let processRows: ObjectDataRow[] = [];
processes.forEach((row) => {
processRows.push(new ObjectDataRow({
id: row.id,
name: row.name,
started: row.started
}));
});
return processRows;
}
/** /**
* Render the process list * Render the process list
* *
@@ -110,10 +139,7 @@ export class ActivitiProcessInstanceListComponent implements OnInit, OnChanges {
*/ */
private renderProcessInstances(processInstances: any[]) { private renderProcessInstances(processInstances: any[]) {
processInstances = this.optimizeProcessNames(processInstances); processInstances = this.optimizeProcessNames(processInstances);
this.data = new ObjectDataTableAdapter( this.data.setRows(processInstances);
processInstances,
this.schemaColumn
);
} }
/** /**
@@ -161,9 +187,9 @@ export class ActivitiProcessInstanceListComponent implements OnInit, OnChanges {
*/ */
private optimizeProcessNames(tasks: any[]) { private optimizeProcessNames(tasks: any[]) {
tasks = tasks.map(t => { tasks = tasks.map(t => {
t.name = t.name || 'No name'; t.obj.name = t.obj.name || 'No name';
if (t.name.length > 50) { if (t.obj.name.length > 50) {
t.name = t.name.substring(0, 50) + '...'; t.obj.name = t.obj.name.substring(0, 50) + '...';
} }
return t; return t;
}); });

View File

@@ -2,7 +2,7 @@
<div *ngIf="taskFilter"> <div *ngIf="taskFilter">
<div *ngIf="!isTaskListEmpty()"> <div *ngIf="!isTaskListEmpty()">
<alfresco-datatable <alfresco-datatable
[data]="tasks" [data]="data"
(rowClick)="onRowClick($event)"> (rowClick)="onRowClick($event)">
</alfresco-datatable> </alfresco-datatable>
</div> </div>

View File

@@ -26,7 +26,7 @@ import { ActivitiTaskList } from './activiti-tasklist.component';
import { ActivitiTaskListService } from '../services/activiti-tasklist.service'; import { ActivitiTaskListService } from '../services/activiti-tasklist.service';
import { UserTaskFilterRepresentationModel } from '../models/filter.model'; import { UserTaskFilterRepresentationModel } from '../models/filter.model';
import { Observable } from 'rxjs/Rx'; import { Observable } from 'rxjs/Rx';
import { ObjectDataRow, DataRowEvent } from 'ng2-alfresco-datatable'; import { ObjectDataRow, DataRowEvent, ObjectDataTableAdapter } from 'ng2-alfresco-datatable';
describe('ActivitiTaskList', () => { describe('ActivitiTaskList', () => {
@@ -79,23 +79,26 @@ describe('ActivitiTaskList', () => {
it('should use the default schemaColumn as default', () => { it('should use the default schemaColumn as default', () => {
taskList.ngOnInit(); taskList.ngOnInit();
expect(taskList.schemaColumn).toBeDefined(); expect(taskList.data.getColumns()).toBeDefined();
expect(taskList.schemaColumn.length).toEqual(4); expect(taskList.data.getColumns().length).toEqual(4);
}); });
it('should use the schemaColumn passed in input', () => { it('should use the schemaColumn passed in input', () => {
taskList.schemaColumn = [ taskList.data = new ObjectDataTableAdapter(
[],
[
{type: 'text', key: 'fake-id', title: 'Name'} {type: 'text', key: 'fake-id', title: 'Name'}
]; ]
);
taskList.ngOnInit(); taskList.ngOnInit();
expect(taskList.schemaColumn).toBeDefined(); expect(taskList.data.getColumns()).toBeDefined();
expect(taskList.schemaColumn.length).toEqual(1); expect(taskList.data.getColumns().length).toEqual(1);
}); });
it('should return an empty task list when the taskFilter is not passed', () => { it('should return an empty task list when the taskFilter is not passed', () => {
taskList.ngOnInit(); taskList.ngOnInit();
expect(taskList.tasks).toBeUndefined(); expect(taskList.data).toBeDefined();
expect(taskList.isTaskListEmpty()).toBeTruthy(); expect(taskList.isTaskListEmpty()).toBeTruthy();
}); });
@@ -106,11 +109,11 @@ describe('ActivitiTaskList', () => {
taskList.onSuccess.subscribe( (res) => { taskList.onSuccess.subscribe( (res) => {
expect(res).toBeDefined(); expect(res).toBeDefined();
expect(taskList.tasks).toBeDefined(); expect(taskList.data).toBeDefined();
expect(taskList.isTaskListEmpty()).not.toBeTruthy(); expect(taskList.isTaskListEmpty()).not.toBeTruthy();
expect(taskList.tasks.getRows().length).toEqual(2); expect(taskList.data.getRows().length).toEqual(2);
expect(taskList.tasks.getRows()[0].getValue('name')).toEqual('fake-long-name-fake-long-name-fake-long-name-fak50...'); expect(taskList.data.getRows()[0].getValue('name')).toEqual('fake-long-name-fake-long-name-fake-long-name-fak50...');
expect(taskList.tasks.getRows()[1].getValue('name')).toEqual('Nameless task'); expect(taskList.data.getRows()[1].getValue('name')).toEqual('Nameless task');
done(); done();
}); });

View File

@@ -17,7 +17,7 @@
import { Component, Input, Output, EventEmitter, OnInit, OnChanges, SimpleChanges } from '@angular/core'; import { Component, Input, Output, EventEmitter, OnInit, OnChanges, SimpleChanges } from '@angular/core';
import { AlfrescoTranslationService, AlfrescoAuthenticationService } from 'ng2-alfresco-core'; import { AlfrescoTranslationService, AlfrescoAuthenticationService } from 'ng2-alfresco-core';
import { ALFRESCO_DATATABLE_DIRECTIVES, ObjectDataTableAdapter, DataTableAdapter, DataRowEvent } from 'ng2-alfresco-datatable'; import { ALFRESCO_DATATABLE_DIRECTIVES, ObjectDataTableAdapter, DataTableAdapter, DataRowEvent, ObjectDataRow } from 'ng2-alfresco-datatable';
import { ActivitiTaskListService } from './../services/activiti-tasklist.service'; import { ActivitiTaskListService } from './../services/activiti-tasklist.service';
import { UserTaskFilterRepresentationModel, TaskQueryRequestRepresentationModel } from '../models/filter.model'; import { UserTaskFilterRepresentationModel, TaskQueryRequestRepresentationModel } from '../models/filter.model';
@@ -38,12 +38,7 @@ export class ActivitiTaskList implements OnInit, OnChanges {
taskFilter: UserTaskFilterRepresentationModel; taskFilter: UserTaskFilterRepresentationModel;
@Input() @Input()
schemaColumn: any[] = [ data: DataTableAdapter;
{type: 'text', key: 'id', title: 'Id'},
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true},
{type: 'text', key: 'formKey', title: 'Form Key', sortable: true},
{type: 'text', key: 'created', title: 'Created', sortable: true}
];
@Output() @Output()
rowClick: EventEmitter<string> = new EventEmitter<string>(); rowClick: EventEmitter<string> = new EventEmitter<string>();
@@ -54,12 +49,15 @@ export class ActivitiTaskList implements OnInit, OnChanges {
@Output() @Output()
onError: EventEmitter<any> = new EventEmitter<any>(); onError: EventEmitter<any> = new EventEmitter<any>();
data: DataTableAdapter;
tasks: ObjectDataTableAdapter;
currentTaskId: string; currentTaskId: string;
private defaultSchemaColumn: any[] = [
{type: 'text', key: 'id', title: 'Id'},
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true},
{type: 'text', key: 'formKey', title: 'Form Key', sortable: true},
{type: 'text', key: 'created', title: 'Created', sortable: true}
];
/** /**
* Constructor * Constructor
* @param auth * @param auth
@@ -76,10 +74,12 @@ export class ActivitiTaskList implements OnInit, OnChanges {
} }
ngOnInit() { ngOnInit() {
if (!this.data) {
this.data = new ObjectDataTableAdapter( this.data = new ObjectDataTableAdapter(
[], [],
this.schemaColumn this.defaultSchemaColumn
); );
}
if (this.taskFilter) { if (this.taskFilter) {
let requestNode = this.convertTaskUserToTaskQuery(this.taskFilter); let requestNode = this.convertTaskUserToTaskQuery(this.taskFilter);
@@ -102,7 +102,8 @@ export class ActivitiTaskList implements OnInit, OnChanges {
requestNode.size = res.total; requestNode.size = res.total;
this.activiti.getTasks(requestNode).subscribe( this.activiti.getTasks(requestNode).subscribe(
(response) => { (response) => {
this.renderTasks(response.data); let taskRow = this.createDataRow(response.data);
this.renderTasks(taskRow);
this.selectFirstTask(); this.selectFirstTask();
this.onSuccess.emit(response); this.onSuccess.emit(response);
}, (error) => { }, (error) => {
@@ -115,13 +116,31 @@ export class ActivitiTaskList implements OnInit, OnChanges {
}); });
} }
/**
* Create an array of ObjectDataRow
* @param tasks
* @returns {ObjectDataRow[]}
*/
private createDataRow(tasks: any[]): ObjectDataRow[] {
let taskRows: ObjectDataRow[] = [];
tasks.forEach((row) => {
taskRows.push(new ObjectDataRow({
id: row.id,
name: row.name,
created: row.created
}));
});
return taskRows;
}
/** /**
* The method call the adapter data table component for render the task list * The method call the adapter data table component for render the task list
* @param tasks * @param tasks
*/ */
private renderTasks(tasks: any[]) { private renderTasks(tasks: any[]) {
tasks = this.optimizeTaskName(tasks); tasks = this.optimizeTaskName(tasks);
this.tasks = new ObjectDataTableAdapter(tasks, this.data.getColumns()); this.data.setRows(tasks);
} }
/** /**
@@ -129,7 +148,7 @@ export class ActivitiTaskList implements OnInit, OnChanges {
*/ */
private selectFirstTask() { private selectFirstTask() {
if (!this.isTaskListEmpty()) { if (!this.isTaskListEmpty()) {
this.currentTaskId = this.tasks.getRows()[0].getValue('id'); this.currentTaskId = this.data.getRows()[0].getValue('id');
} else { } else {
this.currentTaskId = null; this.currentTaskId = null;
} }
@@ -148,7 +167,7 @@ export class ActivitiTaskList implements OnInit, OnChanges {
* @returns {ObjectDataTableAdapter|boolean} * @returns {ObjectDataTableAdapter|boolean}
*/ */
isTaskListEmpty(): boolean { isTaskListEmpty(): boolean {
return this.tasks === undefined || (this.tasks && this.tasks.getRows() && this.tasks.getRows().length === 0); return this.data === undefined || (this.data && this.data.getRows() && this.data.getRows().length === 0);
} }
/** /**
@@ -168,9 +187,9 @@ export class ActivitiTaskList implements OnInit, OnChanges {
*/ */
private optimizeTaskName(tasks: any[]) { private optimizeTaskName(tasks: any[]) {
tasks = tasks.map(t => { tasks = tasks.map(t => {
t.name = t.name || 'Nameless task'; t.obj.name = t.obj.name || 'Nameless task';
if (t.name.length > 50) { if (t.obj.name.length > 50) {
t.name = t.name.substring(0, 50) + '...'; t.obj.name = t.obj.name.substring(0, 50) + '...';
} }
return t; return t;
}); });

View File

@@ -87,6 +87,10 @@
border: 0; border: 0;
} }
.hidden {
display: none;
}
/* small desktop */ /* small desktop */
@media all and (max-width: 1200px) {} @media all and (max-width: 1200px) {}