[ADF-702] Task/Process Filter - Provide a way to change the default filter (#1932)

* [ADF-702] Task/Process Filter - Provide a way to change the default filter

* Provide a way to select a custom menu filter

* Improve activiti process filter

* Add internal link

* Change link name

* add link
This commit is contained in:
Maurizio Vitale
2017-06-06 15:29:45 +01:00
committed by Eugenio Romano
parent 8b7b57efe6
commit c278fd9910
8 changed files with 274 additions and 30 deletions

View File

@@ -28,6 +28,7 @@
<adf-accordion>
<adf-accordion-group [heading]="'Tasks'" [isSelected]="true" [isOpen]="true" [headingIcon]="'assignment'">
<activiti-filters
[filterParam]="{name:'MY tasks'}"
[appId]="appId"
[hasIcon]="false"
(filterClick)="onTaskFilterClick($event)"
@@ -101,6 +102,7 @@
<adf-accordion>
<adf-accordion-group [heading]="'Processes'" [isSelected]="true" [isOpen]="true" [headingIcon]="'assessment'">
<activiti-process-instance-filters
[filterParam]="{index: 0}"
[appId]="appId"
(filterClick)="onProcessFilterClick($event)"
(onSuccess)="onSuccessProcessFilterList($event)">

View File

@@ -233,10 +233,12 @@ process instances are displayed in the list.
#### Options
| Name | Description |
| --- | --- |
| `appId` | Display filters available to the current user for the application with the specified ID |
| `appName` | Display filters available to the current user for the application with the specified name |
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `filterParam` | {[Filter Params models](#filter-params--models)} | optional | The params to filter the task filter. If there is no match the default one (first filter of the list) is selected |
| `appId` | {string} | optional | Display filters available to the current user for the application with the specified ID. |
| `appName` | {string} | optional | Display filters available to the current user for the application with the specified name. |
| `hasIcon` | {boolean} | optional | Toggle to show or not the filter's icon. |
If both `appId` and `appName` are specified then `appName` will take precedence and `appId` will be ignored.
@@ -246,7 +248,30 @@ If both `appId` and `appName` are specified then `appName` will take precedence
| --- | --- |
| `onSuccess` | Emitted when the list of filters hase been successfully loaded from the server |
| `onError` | Emitted when an error occurs |
| `ilterClick` | Emitted when the user selects a filter from the list |
| `filterClick` | Emitted when the user selects a filter from the list |
### How filter the activiti process filters
```html
<activiti-process-instance-filters [filterParam]="{index: 0}"></activiti-filters>
```
You can use inside the filterParam one of the following property.
## Filter Params models
```json
{
"id": "number",
"name": "string",
"index": "number"
}
```
| Name | Description |
| --- | --- |
| `id` | The id of the task filter |
| `name` | The name of the task filter, lowercase is checked |
| `index` | The position of the filter in the array. The first position is 0 |
### How to create an accordion menu with the processes filter

View File

@@ -18,7 +18,7 @@
import { Component, Output, EventEmitter, OnInit, Input, OnChanges, SimpleChanges } from '@angular/core';
import { Observable, Observer } from 'rxjs/Rx';
import { AlfrescoTranslationService, LogService } from 'ng2-alfresco-core';
import { FilterProcessRepresentationModel } from './../models/filter-process.model';
import { FilterProcessRepresentationModel, FilterParamsModel } from './../models/filter-process.model';
import { ActivitiProcessService } from './../services/activiti-process.service';
declare let componentHandler: any;
@@ -30,6 +30,9 @@ declare let componentHandler: any;
})
export class ActivitiProcessFilters implements OnInit, OnChanges {
@Input()
filterParam: FilterParamsModel;
@Output()
filterClick: EventEmitter<FilterProcessRepresentationModel> = new EventEmitter<FilterProcessRepresentationModel>();
@@ -99,7 +102,7 @@ export class ActivitiProcessFilters implements OnInit, OnChanges {
this.filterObserver.next(filter);
});
this.selectFirstFilter();
this.selectTaskFilter(this.filterParam);
this.onSuccess.emit(resDefault);
},
(errDefault: any) => {
@@ -112,7 +115,7 @@ export class ActivitiProcessFilters implements OnInit, OnChanges {
this.filterObserver.next(filter);
});
this.selectFirstFilter();
this.selectTaskFilter(this.filterParam);
this.onSuccess.emit(res);
}
},
@@ -130,7 +133,7 @@ export class ActivitiProcessFilters implements OnInit, OnChanges {
this.activiti.getDeployedApplications(appName).subscribe(
application => {
this.getFiltersByAppId(application.id);
this.selectFirstFilter();
this.selectTaskFilter(this.filterParam);
},
(err) => {
this.onError.emit(err);
@@ -149,11 +152,26 @@ export class ActivitiProcessFilters implements OnInit, OnChanges {
/**
* Select the first filter of a list if present
*/
public selectFirstFilter() {
public selectTaskFilter(filterParam: FilterParamsModel) {
if (filterParam) {
this.filters.filter((taskFilter: FilterProcessRepresentationModel, index) => {
if (filterParam.name && filterParam.name.toLowerCase() === taskFilter.name.toLowerCase() ||
filterParam.id === taskFilter.id || filterParam.index === index) {
this.currentFilter = taskFilter;
}
});
}
if (this.isCurrentFilterEmpty()) {
this.selectDefaultTaskFilter();
}
}
/**
* Select as default task filter the first in the list
*/
public selectDefaultTaskFilter() {
if (!this.isFilterListEmpty()) {
this.currentFilter = this.filters[0];
} else {
this.currentFilter = null;
}
}
@@ -178,6 +196,10 @@ export class ActivitiProcessFilters implements OnInit, OnChanges {
*/
private resetFilter() {
this.filters = [];
this.currentFilter = null;
this.currentFilter = undefined;
}
private isCurrentFilterEmpty(): boolean {
return this.currentFilter === undefined || null ? true : false;
}
}

View File

@@ -46,6 +46,25 @@ export class FilterProcessRepresentationModel {
}
}
/**
*
* This object represent the parameters to filter a filter.
*
*
* @returns {FilterParamsModel} .
*/
export class FilterParamsModel {
id: string;
name: string;
index: number;
constructor(obj?: any) {
this.id = obj && obj.id || null;
this.name = obj && obj.name || null;
this.index = obj && obj.index;
}
}
/**
*
* This object represent the parameters of a process filter.

View File

@@ -351,10 +351,43 @@ The component shows all the available filters.
| Name | Description |
| --- | --- |
| `filterClick` | The event is emitted when the filter in the list is clicked |
| `onSuccess` | The event is emitted when the list is loaded |
| `onError` | The event is emitted if there is an error during the loading |
#### Options
No options
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `filterParam` | {[Filter Params models](#filter-params--models)} | optional | The params to filter the task filter. If there is no match the default one (first filter of the list) is selected |
| `appId` | {string} | optional | Display filters available to the current user for the application with the specified ID. |
| `appName` | {string} | optional | Display filters available to the current user for the application with the specified name. |
| `hasIcon` | {boolean} | optional | Toggle to show or not the filter's icon. |
If both `appId` and `appName` are specified then `appName` will take precedence and `appId` will be ignored.
### How filter the activiti task filters
```html
<activiti-filters [filterParam]="{name:'My tasks'}"></activiti-filters>
```
You can use inside the filterParam one of the following property.
## Filter Params models
```json
{
"id": "number",
"name": "string",
"index": "number"
}
```
| Name | Description |
| --- | --- |
| `id` | The id of the task filter |
| `name` | The name of the task filter, lowercase is checked |
| `index` | The position of the filter in the array. The first position is 0 |
### How to create an accordion menu with the task filter

View File

@@ -21,7 +21,7 @@ import { Observable } from 'rxjs/Rx';
import { LogServiceMock } from 'ng2-alfresco-core';
import { ActivitiFilters } from './activiti-filters.component';
import { ActivitiTaskListService } from '../services/activiti-tasklist.service';
import { FilterRepresentationModel } from '../models/filter.model';
import { FilterRepresentationModel, FilterParamsModel } from '../models/filter.model';
describe('ActivitiFilters', () => {
@@ -32,14 +32,22 @@ describe('ActivitiFilters', () => {
let fakeGlobalFilter = [];
fakeGlobalFilter.push(new FilterRepresentationModel({
name: 'FakeInvolvedTasks',
id: 10,
filter: { state: 'open', assignment: 'fake-involved' }
}));
fakeGlobalFilter.push(new FilterRepresentationModel({
name: 'FakeMyTasks',
name: 'FakeMyTasks1',
id: 11,
filter: { state: 'open', assignment: 'fake-assignee' }
}));
fakeGlobalFilter.push(new FilterRepresentationModel({
name: 'FakeMyTasks2',
id: 12,
filter: { state: 'open', assignment: 'fake-assignee' }
}));
let fakeFilter = new FilterRepresentationModel({
name: 'FakeMyTasks',
name: 'FakeMyTasks1',
filter: { state: 'open', assignment: 'fake-assignee' }
});
@@ -70,9 +78,10 @@ describe('ActivitiFilters', () => {
filterList.onSuccess.subscribe((res) => {
expect(res).toBeDefined();
expect(filterList.filters).toBeDefined();
expect(filterList.filters.length).toEqual(2);
expect(filterList.filters.length).toEqual(3);
expect(filterList.filters[0].name).toEqual('FakeInvolvedTasks');
expect(filterList.filters[1].name).toEqual('FakeMyTasks');
expect(filterList.filters[1].name).toEqual('FakeMyTasks1');
expect(filterList.filters[2].name).toEqual('FakeMyTasks2');
done();
});
@@ -131,6 +140,99 @@ describe('ActivitiFilters', () => {
filterList.ngOnInit();
});
it('should select the first filter as default', (done) => {
spyOn(activitiService, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise));
const appId = '1';
let change = new SimpleChange(null, appId, true);
filterList.ngOnChanges({ 'appId': change });
filterList.onSuccess.subscribe((res) => {
expect(res).toBeDefined();
expect(filterList.currentFilter).toBeDefined();
expect(filterList.currentFilter.name).toEqual('FakeInvolvedTasks');
done();
});
filterList.ngOnInit();
});
it('should select the task filter based on the input by name param', (done) => {
spyOn(activitiService, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise));
filterList.filterParam = new FilterParamsModel({name: 'FakeMyTasks1'});
const appId = '1';
let change = new SimpleChange(null, appId, true);
filterList.ngOnChanges({ 'appId': change });
filterList.onSuccess.subscribe((res) => {
expect(res).toBeDefined();
expect(filterList.currentFilter).toBeDefined();
expect(filterList.currentFilter.name).toEqual('FakeMyTasks1');
done();
});
filterList.ngOnInit();
});
it('should select the default task filter if filter input does not exist', (done) => {
spyOn(activitiService, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise));
filterList.filterParam = new FilterParamsModel({name: 'UnexistableFilter'});
const appId = '1';
let change = new SimpleChange(null, appId, true);
filterList.ngOnChanges({ 'appId': change });
filterList.onSuccess.subscribe((res) => {
expect(res).toBeDefined();
expect(filterList.currentFilter).toBeDefined();
expect(filterList.currentFilter.name).toEqual('FakeInvolvedTasks');
done();
});
filterList.ngOnInit();
});
it('should select the task filter based on the input by index param', (done) => {
spyOn(activitiService, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise));
filterList.filterParam = new FilterParamsModel({index: 2});
const appId = '1';
let change = new SimpleChange(null, appId, true);
filterList.ngOnChanges({ 'appId': change });
filterList.onSuccess.subscribe((res) => {
expect(res).toBeDefined();
expect(filterList.currentFilter).toBeDefined();
expect(filterList.currentFilter.name).toEqual('FakeMyTasks2');
done();
});
filterList.ngOnInit();
});
it('should select the task filter based on the input by id param', (done) => {
spyOn(activitiService, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise));
filterList.filterParam = new FilterParamsModel({id: 10});
const appId = '1';
let change = new SimpleChange(null, appId, true);
filterList.ngOnChanges({ 'appId': change });
filterList.onSuccess.subscribe((res) => {
expect(res).toBeDefined();
expect(filterList.currentFilter).toBeDefined();
expect(filterList.currentFilter.name).toEqual('FakeInvolvedTasks');
done();
});
filterList.ngOnInit();
});
it('should emit an event when a filter is selected', (done) => {
let currentFilter = new FilterRepresentationModel({ filter: { state: 'open', assignment: 'fake-involved' } });
@@ -198,7 +300,8 @@ describe('ActivitiFilters', () => {
filterList.filters = fakeGlobalFilter;
filterList.selectFilterWithTask('111');
expect(filterList.currentFilter).toBe(fakeFilter);
expect(filterList.currentFilter.landingTaskId).toBeDefined();
expect(filterList.currentFilter.landingTaskId).toBe('111');
}));
it('should not change the current filter if no filter with taskid is found', async(() => {

View File

@@ -19,7 +19,7 @@ import { Component, Output, EventEmitter, OnInit, Input, SimpleChanges, OnChange
import { Observer, Observable } from 'rxjs/Rx';
import { AlfrescoTranslationService, LogService } from 'ng2-alfresco-core';
import { ActivitiTaskListService } from './../services/activiti-tasklist.service';
import { FilterRepresentationModel } from '../models/filter.model';
import { FilterRepresentationModel, FilterParamsModel } from '../models/filter.model';
declare let componentHandler: any;
@@ -31,6 +31,9 @@ declare let componentHandler: any;
})
export class ActivitiFilters implements OnInit, OnChanges {
@Input()
filterParam: FilterParamsModel;
@Output()
filterClick: EventEmitter<FilterRepresentationModel> = new EventEmitter<FilterRepresentationModel>();
@@ -115,7 +118,7 @@ export class ActivitiFilters implements OnInit, OnChanges {
this.filterObserver.next(filter);
});
this.selectFirstFilter();
this.selectTaskFilter(this.filterParam);
this.onSuccess.emit(resDefault);
},
(errDefault: any) => {
@@ -128,7 +131,7 @@ export class ActivitiFilters implements OnInit, OnChanges {
this.filterObserver.next(filter);
});
this.selectFirstFilter();
this.selectTaskFilter(this.filterParam);
this.onSuccess.emit(res);
}
},
@@ -146,7 +149,7 @@ export class ActivitiFilters implements OnInit, OnChanges {
this.activiti.getDeployedApplications(appName).subscribe(
application => {
this.getFiltersByAppId(application.id);
this.selectFirstFilter();
this.selectTaskFilter(this.filterParam);
},
(err) => {
this.onError.emit(err);
@@ -173,8 +176,7 @@ export class ActivitiFilters implements OnInit, OnChanges {
},
() => {
if (filteredFilterList.length > 0) {
let myTaskFilter = filteredFilterList.find(filter => filter.name === 'My Tasks');
this.currentFilter = myTaskFilter ? myTaskFilter : filteredFilterList[0];
this.selectTaskFilter(new FilterParamsModel({name: 'My Tasks'}));
this.currentFilter.landingTaskId = taskId;
this.filterClick.emit(this.currentFilter);
}
@@ -184,11 +186,26 @@ export class ActivitiFilters implements OnInit, OnChanges {
/**
* Select the first filter of a list if present
*/
public selectFirstFilter() {
public selectTaskFilter(filterParam: FilterParamsModel) {
if (filterParam) {
this.filters.filter((taskFilter: FilterRepresentationModel, index) => {
if (filterParam.name && filterParam.name.toLowerCase() === taskFilter.name.toLowerCase() ||
filterParam.id === taskFilter.id || filterParam.index === index) {
this.currentFilter = taskFilter;
}
});
}
if (this.isCurrentFilterEmpty()) {
this.selectDefaultTaskFilter();
}
}
/**
* Select as default task filter the first in the list
*/
public selectDefaultTaskFilter() {
if (!this.isFilterListEmpty()) {
this.currentFilter = this.filters[0];
} else {
this.currentFilter = null;
}
}
@@ -213,6 +230,10 @@ export class ActivitiFilters implements OnInit, OnChanges {
*/
private resetFilter() {
this.filters = [];
this.currentFilter = null;
this.currentFilter = undefined;
}
private isCurrentFilterEmpty(): boolean {
return this.currentFilter === undefined || null ? true : false;
}
}

View File

@@ -46,6 +46,25 @@ export class AppDefinitionRepresentationModel {
}
}
/**
*
* This object represent the parameters to filter a filter.
*
*
* @returns {FilterParamsModel} .
*/
export class FilterParamsModel {
id: string;
name: string;
index: number;
constructor(obj?: any) {
this.id = obj && obj.id || null;
this.name = obj && obj.name || null;
this.index = obj && obj.index;
}
}
/**
*
* This object represent the filter.