Activtiti apps - Provide a way to filter the apps (#1804)

* Provide a way to filter the apps
#1389

* Add unit test
#1389

* Add documentation
#1389

* Improve docs
#1389

* Correct image

* Add parameter filtersAppId to docs
This commit is contained in:
Maurizio Vitale
2017-04-05 16:00:28 +01:00
committed by Mario Romano
parent 25a430c933
commit 7239b37dac
8 changed files with 162 additions and 22 deletions

View File

@@ -224,10 +224,10 @@ Example:
```json ```json
[ [
{type: 'text', key: 'id', title: 'Id'}, {"type": "text", "key": "id", "title": "Id"},
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true}, {"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": "formKey", "title": "Form Key", "sortable": true},
{type: 'text', key: 'created', title: 'Created', sortable: true} {"type": "text", "key": "created", "title": "Created", "sortable": true}
] ]
``` ```
@@ -310,6 +310,31 @@ The component shows all the available apps.
| Name | Type | Required | Description | | Name | Type | Required | Description |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| `layoutType` | {string} | required | Define the layout of the apps. There are two possible values: GRID or LIST. | | `layoutType` | {string} | required | Define the layout of the apps. There are two possible values: GRID or LIST. |
| `filtersAppId` | {Object} | | Provide a way to filter the apps to show. |
### How filter the activiti apps
If you want show some specific apps you can specify them through the filtersAppId parameters
```html
<activiti-apps [filtersAppId]="'[{defaultAppId: 'tasks'}, {deploymentId: '15037'}, {name : 'my app name'}]'"></activiti-apps>
```
In this specific case only the Tasks app, the app with deploymentId 15037 and the app with "my app name" will be showed
![how-filter-apps](docs/assets/how-filter-apps.png)
You can use inside the filter one of the following property
```json
{
"defaultAppId": "string",
"deploymentId": "string",
"name": "string",
"id": "number",
"modelId": "number",
"tenantId": "number"
}
```
## Basic usage example Activiti Filter ## Basic usage example Activiti Filter

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

View File

@@ -17,22 +17,6 @@
import { AppDefinitionRepresentationModel } from '../models/filter.model'; import { AppDefinitionRepresentationModel } from '../models/filter.model';
export var deployedApps = [new AppDefinitionRepresentationModel({
id: '1',
name: 'App1',
icon: 'icon1',
deploymentId: '1'
}), new AppDefinitionRepresentationModel({
id: '2',
name: 'App2',
icon: 'icon2',
deploymentId: '2'
}), new AppDefinitionRepresentationModel({
id: '3',
name: 'App3',
icon: 'icon3',
deploymentId: '3'
})];
export var nonDeployedApps = [new AppDefinitionRepresentationModel({ export var nonDeployedApps = [new AppDefinitionRepresentationModel({
id: '1', id: '1',
name: '1', name: '1',
@@ -46,6 +30,50 @@ export var nonDeployedApps = [new AppDefinitionRepresentationModel({
name: '3', name: '3',
icon: 'icon3' icon: 'icon3'
})]; })];
export var deployedApps = [new AppDefinitionRepresentationModel({
id: 1,
name: 'App1',
icon: 'icon1',
deploymentId: '1',
defaultAppId: 'fake-app-1',
modelId: null,
tenantId: null
}), new AppDefinitionRepresentationModel({
id: 2,
name: 'App2',
icon: 'icon2',
deploymentId: '2',
modelId: null,
tenantId: null
}), new AppDefinitionRepresentationModel({
id: 3,
name: 'App3',
icon: 'icon3',
deploymentId: '3',
modelId: null,
tenantId: null
}), new AppDefinitionRepresentationModel({
id: 4,
name: 'App4',
icon: 'icon4',
deploymentId: '4',
modelId: 65,
tenantId: null
}), new AppDefinitionRepresentationModel({
id: 5,
name: 'App5',
icon: 'icon5',
deploymentId: '5',
modelId: 66,
tenantId: 9
}), new AppDefinitionRepresentationModel({
id: 6,
name: 'App6',
icon: 'icon6',
deploymentId: '6',
tenantId: 9,
modelId: 66
})];
export var defaultApp = [new AppDefinitionRepresentationModel({ export var defaultApp = [new AppDefinitionRepresentationModel({
defaultAppId: 'tasks' defaultAppId: 'tasks'
})]; })];

View File

@@ -22,3 +22,6 @@
</div> </div>
</div> </div>
</div> </div>
<div class="menu-container" *ngIf="isEmpty()">
{{ 'APPS.NONE' | translate }}
</div>

View File

@@ -59,7 +59,7 @@ describe('ActivitiApps', () => {
debugElement = fixture.debugElement; debugElement = fixture.debugElement;
service = fixture.debugElement.injector.get(ActivitiTaskListService); service = fixture.debugElement.injector.get(ActivitiTaskListService);
getAppsSpy = spyOn(service, 'getDeployedApplications').and.returnValue(Observable.of()); getAppsSpy = spyOn(service, 'getDeployedApplications').and.returnValue(Observable.of(deployedApps));
componentHandler = jasmine.createSpyObj('componentHandler', [ componentHandler = jasmine.createSpyObj('componentHandler', [
'upgradeAllRegistered', 'upgradeAllRegistered',
@@ -79,6 +79,59 @@ describe('ActivitiApps', () => {
expect(getAppsSpy).toHaveBeenCalled(); expect(getAppsSpy).toHaveBeenCalled();
}); });
it('should show the apps filterd by defaultAppId', () => {
component.filtersAppId = [{defaultAppId: 'fake-app-1'}];
fixture.detectChanges();
expect(component.isEmpty()).toBe(false);
expect(component.appList).toBeDefined();
expect(component.appList.length).toEqual(1);
});
it('should show the apps filterd by deploymentId', () => {
component.filtersAppId = [{deploymentId: '4'}];
fixture.detectChanges();
expect(component.isEmpty()).toBe(false);
expect(component.appList).toBeDefined();
expect(component.appList.length).toEqual(1);
expect(component.appList[0].deploymentId).toEqual('4');
});
it('should show the apps filterd by name', () => {
component.filtersAppId = [{name: 'App5'}];
fixture.detectChanges();
expect(component.isEmpty()).toBe(false);
expect(component.appList).toBeDefined();
expect(component.appList.length).toEqual(1);
expect(component.appList[0].name).toEqual('App5');
});
it('should show the apps filterd by id', () => {
component.filtersAppId = [{id: 6}];
fixture.detectChanges();
expect(component.isEmpty()).toBe(false);
expect(component.appList).toBeDefined();
expect(component.appList.length).toEqual(1);
expect(component.appList[0].id).toEqual(6);
});
it('should show the apps filterd by modelId', () => {
component.filtersAppId = [{modelId: 66}];
fixture.detectChanges();
expect(component.isEmpty()).toBe(false);
expect(component.appList).toBeDefined();
expect(component.appList.length).toEqual(2);
expect(component.appList[0].modelId).toEqual(66);
});
it('should show the apps filterd by tenandId', () => {
component.filtersAppId = [{tenantId: 9}];
fixture.detectChanges();
expect(component.isEmpty()).toBe(false);
expect(component.appList).toBeDefined();
expect(component.appList.length).toEqual(2);
expect(component.appList[0].tenantId).toEqual(9);
});
it('should emit an error when an error occurs loading apps', () => { it('should emit an error when an error occurs loading apps', () => {
let emitSpy = spyOn(component.error, 'emit'); let emitSpy = spyOn(component.error, 'emit');
getAppsSpy.and.returnValue(Observable.throw({})); getAppsSpy.and.returnValue(Observable.throw({}));
@@ -119,7 +172,7 @@ describe('ActivitiApps', () => {
it('should display all deployed apps', () => { it('should display all deployed apps', () => {
getAppsSpy.and.returnValue(Observable.of(deployedApps)); getAppsSpy.and.returnValue(Observable.of(deployedApps));
fixture.detectChanges(); fixture.detectChanges();
expect(debugElement.queryAll(By.css('h1')).length).toBe(3); expect(debugElement.queryAll(By.css('h1')).length).toBe(6);
}); });
it('should not display undeployed apps', () => { it('should not display undeployed apps', () => {

View File

@@ -45,6 +45,9 @@ export class ActivitiApps implements OnInit {
@Input() @Input()
layoutType: string = ActivitiApps.LAYOUT_GRID; layoutType: string = ActivitiApps.LAYOUT_GRID;
@Input()
filtersAppId: any[];
@Output() @Output()
appClick: EventEmitter<AppDefinitionRepresentationModel> = new EventEmitter<AppDefinitionRepresentationModel>(); appClick: EventEmitter<AppDefinitionRepresentationModel> = new EventEmitter<AppDefinitionRepresentationModel>();
@@ -90,6 +93,7 @@ export class ActivitiApps implements OnInit {
private load() { private load() {
this.activitiTaskList.getDeployedApplications().subscribe( this.activitiTaskList.getDeployedApplications().subscribe(
(res) => { (res) => {
res = this.filterApps(res);
res.forEach((app: AppDefinitionRepresentationModel) => { res.forEach((app: AppDefinitionRepresentationModel) => {
if (app.defaultAppId === ActivitiApps.DEFAULT_TASKS_APP) { if (app.defaultAppId === ActivitiApps.DEFAULT_TASKS_APP) {
app.name = ActivitiApps.DEFAULT_TASKS_APP_NAME; app.name = ActivitiApps.DEFAULT_TASKS_APP_NAME;
@@ -125,6 +129,27 @@ export class ActivitiApps implements OnInit {
return (this.currentApp !== undefined && appId === this.currentApp.id); return (this.currentApp !== undefined && appId === this.currentApp.id);
} }
private filterApps(apps: AppDefinitionRepresentationModel []): AppDefinitionRepresentationModel[] {
let filteredApps = [];
if (this.filtersAppId) {
apps.filter((app: AppDefinitionRepresentationModel) => {
this.filtersAppId.forEach((filter) => {
if (app.defaultAppId === filter.defaultAppId ||
app.deploymentId === filter.deploymentId ||
app.name === filter.name ||
app.id === filter.id ||
app.modelId === filter.modelId ||
app.tenantId === filter.tenantId) {
filteredApps.push(app);
}
});
});
} else {
return apps;
}
return filteredApps;
}
/** /**
* Check if the value of the layoutType property is an allowed value * Check if the value of the layoutType property is an allowed value
* @returns {boolean} * @returns {boolean}

View File

@@ -1,4 +1,7 @@
{ {
"APPS": {
"NONE": "No apps found."
},
"TASK_LIST": { "TASK_LIST": {
"MESSAGES": { "MESSAGES": {
"NONE": "No tasks list found." "NONE": "No tasks list found."

View File

@@ -1,4 +1,7 @@
{ {
"APPS": {
"NONE": "Nessuna applicazione trovata."
},
"TASK_LIST": { "TASK_LIST": {
"MESSAGES": { "MESSAGES": {
"NONE": "Nessuna lista tasks trovata." "NONE": "Nessuna lista tasks trovata."