Merge pull request #751 from Alfresco/dev-mvitale-732

Give the possibility to restrict list of tasks to a specific appId
This commit is contained in:
Denys Vuika 2016-09-15 15:26:44 +01:00 committed by GitHub
commit 3e734fbdbd
18 changed files with 575 additions and 90 deletions

View File

@ -1,4 +1,5 @@
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
<activiti-apps (appClick)="onAppClick($event)"></activiti-apps>
<header class="mdl-layout__header">
<!-- Tabs -->
<div class="mdl-layout__tab-bar mdl-js-ripple-effect">
@ -13,7 +14,7 @@
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--2-col task-column mdl-shadow--2dp">
<span>Task Filters</span>
<activiti-filters [appId]="appId" (filterClick)="onTaskFilterClick($event)"></activiti-filters>
<activiti-filters [appId]="appId" (filterClick)="onTaskFilterClick($event)" #activitifilter></activiti-filters>
</div>
<div class="mdl-cell mdl-cell--3-col task-column mdl-shadow--2dp">
<span>Task List</span>
@ -36,12 +37,14 @@
<div class="mdl-cell mdl-cell--2-col task-column">
<span>Process Filters</span>
<activiti-start-process-instance [appId]="appId"></activiti-start-process-instance>
<activiti-process-instance-filters (filterClick)="onProcessFilterClick($event)"></activiti-process-instance-filters>
<activiti-process-instance-filters [appId]="appId"
(filterClick)="onProcessFilterClick($event)"></activiti-process-instance-filters>
</div>
<div class="mdl-cell mdl-cell--3-col task-column">
<span>Process List</span>
<activiti-process-instance-list [filter]="processFilter" [schemaColumn]="processSchemaColumns"
(rowClick)="onProcessRowClick($event)" #activitiprocesslist></activiti-process-instance-list>
(rowClick)="onProcessRowClick($event)" (onSuccess)="onSuccessProcessList($event)"
#activitiprocesslist></activiti-process-instance-list>
</div>
<div class="mdl-cell mdl-cell--7-col task-column">
<span>Process Details</span>

View File

@ -16,7 +16,12 @@
*/
import { Component, AfterViewChecked, ViewChild, Input } from '@angular/core';
import { ALFRESCO_TASKLIST_DIRECTIVES, TaskQueryRequestRepresentationModel } from 'ng2-activiti-tasklist';
import { ALFRESCO_TASKLIST_DIRECTIVES,
TaskQueryRequestRepresentationModel,
AppDefinitionRepresentationModel,
FilterRepresentationModel,
UserTaskFilterRepresentationModel
} from 'ng2-activiti-tasklist';
import { ACTIVITI_PROCESSLIST_DIRECTIVES } from 'ng2-activiti-processlist';
import { ActivitiForm } from 'ng2-activiti-form';
import { ActivatedRoute } from '@angular/router';
@ -36,6 +41,9 @@ export class ActivitiDemoComponent implements AfterViewChecked {
currentChoice: string = 'task-list';
@ViewChild('activitifilter')
activitifilter: any;
@ViewChild('activitidetails')
activitidetails: any;
@ -60,7 +68,7 @@ export class ActivitiDemoComponent implements AfterViewChecked {
sub: Subscription;
@Input()
appId: string;
appId: number;
setChoice($event) {
this.currentChoice = $event.target.value;
@ -94,36 +102,37 @@ export class ActivitiDemoComponent implements AfterViewChecked {
this.sub.unsubscribe();
}
onTaskFilterClick(event: any) {
this.taskFilter = event;
let requestNode = {appDefinitionId: this.taskFilter.appId,
processDefinitionId: this.taskFilter.filter.processDefinitionId,
text: this.taskFilter.filter.name,
assignment: this.taskFilter.filter.assignment,
state: this.taskFilter.filter.state,
sort: this.taskFilter.filter.sort
};
this.activititasklist.load(new TaskQueryRequestRepresentationModel(requestNode));
onAppClick(app: AppDefinitionRepresentationModel) {
this.appId = app.id;
this.taskFilter = null;
this.currentTaskId = null;
this.processFilter = null;
this.currentProcessInstanceId = null;
}
onSuccessTaskList(event: any) {
onTaskFilterClick(event: FilterRepresentationModel) {
this.taskFilter = event;
}
onSuccessTaskList(event: UserTaskFilterRepresentationModel) {
this.currentTaskId = this.activititasklist.getCurrentTaskId();
this.activitidetails.loadDetails(this.currentTaskId);
}
onProcessFilterClick(event: any) {
this.processFilter = event.filter;
this.activitiprocesslist.load(this.processFilter);
this.processFilter = event;
}
onSuccessProcessList(event: any) {
this.currentProcessInstanceId = this.activitiprocesslist.getCurrentProcessId();
}
onTaskRowClick(taskId) {
this.currentTaskId = taskId;
this.activitidetails.loadDetails(this.currentTaskId);
}
onProcessRowClick(processInstanceId) {
this.currentProcessInstanceId = processInstanceId;
this.activitiprocessdetails.load(this.currentProcessInstanceId);
}
processCancelled(data: any) {
@ -136,7 +145,7 @@ export class ActivitiDemoComponent implements AfterViewChecked {
}
onFormCompleted(form) {
this.activititasklist.load(this.taskFilter);
this.activititasklist.load(this.taskFilter);npm
this.currentTaskId = null;
this.activitidetails.loadDetails(this.currentTaskId);
}

View File

@ -15,10 +15,10 @@
* limitations under the License.
*/
import { Component, Output, EventEmitter, OnInit, Input } from '@angular/core';
import { Component, Output, EventEmitter, OnInit, Input, OnChanges, SimpleChanges } from '@angular/core';
import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core';
import { ActivitiProcessService } from './../services/activiti-process.service';
import { FilterModel } from '../models/filter.model';
import { FilterRepresentationModel } from '../models/filter.model';
import { Observer } from 'rxjs/Observer';
import { Observable } from 'rxjs/Observable';
@ -34,10 +34,10 @@ declare let __moduleName: string;
pipes: [AlfrescoPipeTranslate]
})
export class ActivitiProcessFilters implements OnInit {
export class ActivitiProcessFilters implements OnInit, OnChanges {
@Output()
filterClick: EventEmitter<FilterModel> = new EventEmitter<FilterModel>();
filterClick: EventEmitter<FilterRepresentationModel> = new EventEmitter<FilterRepresentationModel>();
@Output()
onSuccess: EventEmitter<any> = new EventEmitter<any>();
@ -51,12 +51,12 @@ export class ActivitiProcessFilters implements OnInit {
@Input()
appName: string;
private filterObserver: Observer<FilterModel>;
filter$: Observable<FilterModel>;
private filterObserver: Observer<FilterRepresentationModel>;
filter$: Observable<FilterRepresentationModel>;
currentFilter: FilterModel;
currentFilter: FilterRepresentationModel;
filters: FilterModel [] = [];
filters: FilterRepresentationModel [] = [];
/**
* Constructor
@ -67,7 +67,7 @@ export class ActivitiProcessFilters implements OnInit {
constructor(private auth: AlfrescoAuthenticationService,
private translate: AlfrescoTranslationService,
public activiti: ActivitiProcessService) {
this.filter$ = new Observable<FilterModel>(observer => this.filterObserver = observer).share();
this.filter$ = new Observable<FilterRepresentationModel>(observer => this.filterObserver = observer).share();
if (translate) {
translate.addTranslationFolder('node_modules/ng2-activiti-processlist/src');
@ -75,18 +75,27 @@ export class ActivitiProcessFilters implements OnInit {
}
ngOnInit() {
this.filter$.subscribe((filter: FilterModel) => {
this.filter$.subscribe((filter: FilterRepresentationModel) => {
this.filters.push(filter);
});
this.load();
}
ngOnChanges(changes: SimpleChanges) {
let appId = changes['appId'];
if (appId && appId.currentValue) {
this.load();
return;
}
}
/**
* The method call the adapter data table component for render the task list
* @param tasks
*/
private load() {
this.resetFilter();
if (this.appName) {
this.filterByAppName();
} else {
@ -96,7 +105,7 @@ export class ActivitiProcessFilters implements OnInit {
private filterByAppId(appId) {
this.activiti.getProcessFilters(appId).subscribe(
(res: FilterModel[]) => {
(res: FilterRepresentationModel[]) => {
res.forEach((filter) => {
this.filterObserver.next(filter);
});
@ -124,8 +133,16 @@ export class ActivitiProcessFilters implements OnInit {
* Pass the selected filter as next
* @param filter
*/
public selectFilter(filter: FilterModel) {
public selectFilter(filter: FilterRepresentationModel) {
this.currentFilter = filter;
this.filterClick.emit(filter);
}
/**
* Reset the filters properties
*/
private resetFilter() {
this.filters = [];
this.currentFilter = null;
}
}

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Component, Input, ViewChild, Output, EventEmitter } from '@angular/core';
import { Component, Input, ViewChild, Output, EventEmitter, OnInit, OnChanges, SimpleChanges } from '@angular/core';
import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core';
import { ActivitiProcessService } from './../services/activiti-process.service';
import { ActivitiProcessInstanceHeader } from './activiti-process-instance-header.component';
@ -37,7 +37,7 @@ declare let __moduleName: string;
pipes: [AlfrescoPipeTranslate]
})
export class ActivitiProcessInstanceDetails {
export class ActivitiProcessInstanceDetails implements OnInit, OnChanges {
@Input()
processInstanceId: string;
@ -80,6 +80,31 @@ export class ActivitiProcessInstanceDetails {
}
}
ngOnInit() {
if (this.processInstanceId) {
this.load(this.processInstanceId);
}
}
ngOnChanges(changes: SimpleChanges) {
let processInstanceId = changes['processInstanceId'];
if (processInstanceId && !processInstanceId.currentValue) {
this.reset();
return;
}
if (processInstanceId && processInstanceId.currentValue) {
this.load(processInstanceId.currentValue);
return;
}
}
/**
* Reset the task detail to undefined
*/
reset() {
this.processInstanceDetails = null;
}
load(processId: string) {
if (processId) {
this.activitiProcess.getProcess(processId).subscribe(

View File

@ -15,11 +15,11 @@
* limitations under the License.
*/
import {Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import {Component, OnInit, Input, Output, EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
import { AlfrescoPipeTranslate, AlfrescoTranslationService, CONTEXT_MENU_DIRECTIVES, CONTEXT_MENU_PROVIDERS } from 'ng2-alfresco-core';
import { ALFRESCO_DATATABLE_DIRECTIVES, ObjectDataTableAdapter, DataRowEvent } from 'ng2-alfresco-datatable';
import { ActivitiProcessService } from '../services/activiti-process.service';
import { FilterModel } from '../models/filter.model';
import { UserProcessInstanceFilterRepresentationModel, TaskQueryRequestRepresentationModel } from '../models/filter.model';
declare let __moduleName: string;
@ -38,14 +38,14 @@ declare let __moduleName: string;
pipes: [ AlfrescoPipeTranslate ],
providers: [ CONTEXT_MENU_PROVIDERS, ActivitiProcessService ]
})
export class ActivitiProcessInstanceListComponent implements OnInit {
export class ActivitiProcessInstanceListComponent implements OnInit, OnChanges {
errorMessage: string;
data: ObjectDataTableAdapter;
currentProcessInstanceId: string;
@Input()
filter: FilterModel;
filter: UserProcessInstanceFilterRepresentationModel;
@Input()
schemaColumn: any[] = [
@ -76,15 +76,26 @@ export class ActivitiProcessInstanceListComponent implements OnInit {
this.schemaColumn
);
if (this.filter) {
this.load(this.filter);
let requestNode = this.convertProcessInstanceToTaskQuery(this.filter);
this.load(requestNode);
}
}
load(filter: FilterModel) {
this.processService.getProcessInstances(filter)
ngOnChanges(changes: SimpleChanges) {
let filter = changes['filter'];
if (filter && filter.currentValue) {
let requestNode = this.convertProcessInstanceToTaskQuery(filter.currentValue);
this.load(requestNode);
return;
}
}
load(requestNode: TaskQueryRequestRepresentationModel) {
this.processService.getProcessInstances(requestNode)
.subscribe(
(processInstances) => {
this.renderProcessInstances(processInstances);
this.selectFirstProcess();
this.onSuccess.emit(processInstances);
},
error => {
@ -93,10 +104,6 @@ export class ActivitiProcessInstanceListComponent implements OnInit {
});
}
reload() {
this.load(this.filter);
}
/**
* Render the process list
*
@ -110,6 +117,25 @@ export class ActivitiProcessInstanceListComponent implements OnInit {
);
}
/**
* Select the first process of a process list if present
*/
private selectFirstProcess() {
if (!this.isListEmpty()) {
this.currentProcessInstanceId = this.data.getRows()[0].getValue('id');
} else {
this.currentProcessInstanceId = null;
}
}
/**
* Return the current process
* @returns {string}
*/
getCurrentProcessId(): string {
return this.currentProcessInstanceId;
}
/**
* Check if the list is empty
* @returns {ObjectDataTableAdapter|boolean}
@ -144,4 +170,13 @@ export class ActivitiProcessInstanceListComponent implements OnInit {
});
return tasks;
}
private convertProcessInstanceToTaskQuery(processFilter: UserProcessInstanceFilterRepresentationModel) {
let requestNode = {appDefinitionId: processFilter.appId,
processDefinitionKey: processFilter.filter.processDefinitionKey,
text: processFilter.filter.name,
state: processFilter.filter.state,
sort: processFilter.filter.sort};
return new TaskQueryRequestRepresentationModel(requestNode);
}
}

View File

@ -15,26 +15,58 @@
* limitations under the License.
*/
/**
*
* This object represent the app definition.
*
*
* @returns {AppDefinitionRepresentationModel} .
*/
export class AppDefinitionRepresentationModel {
defaultAppId: string;
deploymentId: string;
name: string;
description: string;
theme: string;
id: number;
modelId: number;
tenantId: number;
constructor(obj?: any) {
this.defaultAppId = obj && obj.defaultAppId || null;
this.deploymentId = obj && obj.deploymentId || false;
this.name = obj && obj.name || null;
this.description = obj && obj.description || null;
this.theme = obj && obj.theme || null;
this.id = obj && obj.id;
this.modelId = obj && obj.modelId;
this.tenantId = obj && obj.tenantId;
}
}
/**
*
* This object represent the filter.
*
*
* @returns {FilterModel} .
* @returns {FilterRepresentationModel} .
*/
export class FilterModel {
export class FilterRepresentationModel {
id: number;
appId: string;
name: string;
recent: boolean = false;
recent: boolean;
icon: string;
filter: FilterParamsModel;
appId: number;
filter: FilterParamRepresentationModel;
index: number;
constructor(name: string, recent: boolean, icon: string, query: string, state: string, assignment: string, appDefinitionId?: string) {
this.name = name;
this.recent = recent;
this.icon = icon;
this.filter = new FilterParamsModel(query, state, assignment, appDefinitionId);
constructor(obj?: any) {
this.appId = obj && obj.appId || null;
this.name = obj && obj.name || null;
this.recent = obj && obj.recent || false;
this.icon = obj && obj.icon || null;
this.filter = new FilterParamRepresentationModel(obj.filter);
this.index = obj && obj.index;
}
}
@ -43,18 +75,81 @@ export class FilterModel {
* This object represent the parameters of a filter.
*
*
* @returns {FilterModel} .
* @returns {FilterParamRepresentationModel} .
*/
export class FilterParamsModel {
export class FilterParamRepresentationModel {
processDefinitionId: string;
processDefinitionKey: string;
name: string;
sort: string;
state: string;
appDefinitionId: string;
sort: string;
constructor(query: string, sort: string, state: string, appDefinitionId?: string) {
this.name = query;
this.sort = sort;
this.state = state;
this.appDefinitionId = appDefinitionId;
constructor(obj?: any) {
this.processDefinitionId = obj && obj.processDefinitionId || null;
this.processDefinitionKey = obj && obj.processDefinitionKey || null;
this.name = obj && obj.name || null;
this.state = obj && obj.state || null;
this.sort = obj && obj.sort || null;
}
}
export class UserProcessInstanceFilterRepresentationModel extends FilterRepresentationModel {
public filter: ProcessInstanceFilterRepresentation;
constructor(obj?: any) {
super(obj);
this.filter = new ProcessInstanceFilterRepresentation(obj.filter);
}
}
export class ProcessInstanceFilterRepresentation extends FilterParamRepresentationModel {
constructor(obj?: any) {
super(obj);
}
}
export class UserTaskFilterRepresentationModel extends FilterRepresentationModel {
public filter: TaskFilterRepresentationModel;
constructor(obj?: any) {
super(obj);
this.filter = new TaskFilterRepresentationModel(obj.filter);
}
}
export class TaskFilterRepresentationModel extends FilterParamRepresentationModel {
assignment: string;
dueAfter: Date;
dueBefore: Date;
constructor(obj?: any) {
super(obj);
this.assignment = obj && obj.assignment || null;
this.dueAfter = obj && obj.dueAfter || null;
this.dueBefore = obj && obj.dueBefore || null;
}
}
export class TaskQueryRequestRepresentationModel {
appDefinitionId: string;
processInstanceId: string;
processDefinitionId: string;
processDefinitionKey: string;
text: string;
assignment: string;
state: string;
sort: string;
page: number;
size: number;
constructor(obj?: any) {
this.appDefinitionId = obj && obj.appDefinitionId || null;
this.processInstanceId = obj && obj.processInstanceId || null;
this.processDefinitionId = obj && obj.processDefinitionId || null;
this.processDefinitionKey = obj && obj.processDefinitionKey || null;
this.text = obj && obj.text || null;
this.assignment = obj && obj.assignment || null;
this.state = obj && obj.state || null;
this.sort = obj && obj.sort || null;
this.page = obj && obj.page || 0;
this.size = obj && obj.size || 25;
}
}

View File

@ -17,7 +17,7 @@
import {AlfrescoAuthenticationService} from 'ng2-alfresco-core';
import {ProcessInstance} from '../models/process-instance';
import {FilterModel} from '../models/filter.model';
import {TaskQueryRequestRepresentationModel} from '../models/filter.model';
import {User} from '../models/user.model';
import {Comment} from '../models/comment.model';
import {Injectable} from '@angular/core';
@ -49,8 +49,8 @@ export class ActivitiProcessService {
.catch(this.handleError);
}
getProcessInstances(filter: FilterModel): Observable<ProcessInstance[]> {
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.processApi.getProcessInstances(filter))
getProcessInstances(requestNode: TaskQueryRequestRepresentationModel): Observable<ProcessInstance[]> {
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.processApi.getProcessInstances(requestNode))
.map(this.extractData)
.catch(this.handleError);
}

View File

@ -15,13 +15,21 @@
* limitations under the License.
*/
import { ActivitiApps } from './src/components/activiti-apps.component';
import { ActivitiTaskList } from './src/components/activiti-tasklist.component';
import { ActivitiTaskDetails } from './src/components/activiti-task-details.component';
import { ActivitiFilters } from './src/components/activiti-filters.component';
import { NoTaskDetailsTemplateComponent } from './src/components/no-task-detail-template.component';
export * from './src/components/activiti-apps.component';
export * from './src/components/activiti-tasklist.component';
export * from './src/services/activiti-tasklist.service';
export * from './src/models/filter.model';
export const ALFRESCO_TASKLIST_DIRECTIVES: [any] = [NoTaskDetailsTemplateComponent, ActivitiFilters, ActivitiTaskList, ActivitiTaskDetails];
export const ALFRESCO_TASKLIST_DIRECTIVES: [any] = [
NoTaskDetailsTemplateComponent,
ActivitiApps,
ActivitiFilters,
ActivitiTaskList,
ActivitiTaskDetails
];

View File

@ -0,0 +1,3 @@
:host {
width: 100%;
}

View File

@ -0,0 +1,10 @@
<div class="menu-container" *ngIf="!isEmpty()">
<ul class='mdl-list'>
<li class="mdl-list__item" (click)="selectApp(app)" *ngFor="let app of appList">
<span class="mdl-list__item-primary-content">
<i class="material-icons mdl-list__item-icon">touch_app</i>
{{app.name}}
</span>
</li>
</ul>
</div>

View File

@ -0,0 +1,99 @@
/*!
* @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.
*/
import { Component, OnInit, Output, EventEmitter } from '@angular/core';
import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core';
import { ActivitiTaskListService } from './../services/activiti-tasklist.service';
import { AppDefinitionRepresentationModel } from '../models/filter.model';
import { Observer } from 'rxjs/Observer';
import { Observable } from 'rxjs/Observable';
declare let componentHandler: any;
declare let __moduleName: string;
@Component({
selector: 'activiti-apps',
moduleId: __moduleName,
templateUrl: './activiti-apps.component.html',
styleUrls: ['./activiti-apps.component.css'],
providers: [ActivitiTaskListService],
pipes: [AlfrescoPipeTranslate]
})
export class ActivitiApps implements OnInit {
@Output()
appClick: EventEmitter<AppDefinitionRepresentationModel> = new EventEmitter<AppDefinitionRepresentationModel>();
private appsObserver: Observer<AppDefinitionRepresentationModel>;
apps$: Observable<AppDefinitionRepresentationModel>;
currentApp: AppDefinitionRepresentationModel;
appList: AppDefinitionRepresentationModel [] = [];
/**
* Constructor
* @param auth
* @param translate
*/
constructor(private auth: AlfrescoAuthenticationService,
private translate: AlfrescoTranslationService,
private activitiTaskList: ActivitiTaskListService) {
if (translate) {
translate.addTranslationFolder('node_modules/ng2-activiti-tasklist/src');
}
this.apps$ = new Observable<AppDefinitionRepresentationModel>(observer => this.appsObserver = observer).share();
}
ngOnInit() {
this.apps$.subscribe((app: any) => {
this.appList.push(app);
});
this.load();
}
public load(name?: string) {
this.activitiTaskList.getDeployedApplications(name).subscribe(
(res) => {
res.forEach((app) => {
if (app.deploymentId) {
this.appsObserver.next(app);
}
});
},
(err) => {
console.log(err);
}
);
}
/**
* Pass the selected app as next
* @param app
*/
public selectApp(app: AppDefinitionRepresentationModel) {
this.currentApp = app;
this.appClick.emit(app);
}
isEmpty(): boolean {
return this.appList.length === 0;
}
}

View File

@ -1,6 +1,6 @@
<div class="menu-container">
<ul class='mdl-list'>
<li class="mdl-list__item"(click)="selectFilter(filter)" *ngFor="let filter of filters">
<li class="mdl-list__item" (click)="selectFilter(filter)" *ngFor="let filter of filters">
<span class="mdl-list__item-primary-content">
<i class="material-icons mdl-list__item-icon">assignment</i>
{{filter.name}}

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Component, Output, EventEmitter, OnInit, Input } from '@angular/core';
import { Component, Output, EventEmitter, OnInit, Input, SimpleChanges, OnChanges } from '@angular/core';
import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core';
import { ActivitiTaskListService } from './../services/activiti-tasklist.service';
import { FilterRepresentationModel } from '../models/filter.model';
@ -34,7 +34,7 @@ declare let __moduleName: string;
pipes: [AlfrescoPipeTranslate]
})
export class ActivitiFilters implements OnInit {
export class ActivitiFilters implements OnInit, OnChanges {
@Output()
filterClick: EventEmitter<FilterRepresentationModel> = new EventEmitter<FilterRepresentationModel>();
@ -82,11 +82,20 @@ export class ActivitiFilters implements OnInit {
this.load();
}
ngOnChanges(changes: SimpleChanges) {
let appId = changes['appId'];
if (appId && appId.currentValue) {
this.load();
return;
}
}
/**
* The method call the adapter data table component for render the task list
* @param tasks
*/
private load() {
this.resetFilter();
if (this.appName) {
this.filterByAppName();
} else {
@ -128,4 +137,12 @@ export class ActivitiFilters implements OnInit {
this.currentFilter = filter;
this.filterClick.emit(filter);
}
/**
* Reset the filters properties
*/
private resetFilter() {
this.filters = [];
this.currentFilter = null;
}
}

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Component, Input, OnInit, ViewChild, Output, EventEmitter, TemplateRef } from '@angular/core';
import { Component, Input, OnInit, ViewChild, Output, EventEmitter, TemplateRef, OnChanges, SimpleChanges } from '@angular/core';
import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core';
import { ActivitiTaskListService } from './../services/activiti-tasklist.service';
import { ActivitiTaskHeader } from './activiti-task-header.component';
@ -40,7 +40,7 @@ declare let __moduleName: string;
pipes: [AlfrescoPipeTranslate]
})
export class ActivitiTaskDetails implements OnInit {
export class ActivitiTaskDetails implements OnInit, OnChanges {
@Input()
taskId: string;
@ -110,6 +110,18 @@ export class ActivitiTaskDetails implements OnInit {
}
}
ngOnChanges(changes: SimpleChanges) {
let taskId = changes['taskId'];
if (taskId && !taskId.currentValue) {
this.reset();
return;
}
if (taskId && taskId.currentValue) {
this.loadDetails(taskId.currentValue);
return;
}
}
/**
* Reset the task detail to undefined
*/

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';
import { Component, Input, Output, EventEmitter, OnInit, OnChanges, SimpleChanges } from '@angular/core';
import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core';
import { ALFRESCO_DATATABLE_DIRECTIVES, ObjectDataTableAdapter, DataTableAdapter, DataRowEvent } from 'ng2-alfresco-datatable';
import { ActivitiTaskListService } from './../services/activiti-tasklist.service';
@ -34,7 +34,7 @@ declare let __moduleName: string;
pipes: [AlfrescoPipeTranslate]
})
export class ActivitiTaskList implements OnInit {
export class ActivitiTaskList implements OnInit, OnChanges {
@Input()
taskFilter: UserTaskFilterRepresentationModel;
@ -84,16 +84,20 @@ export class ActivitiTaskList implements OnInit {
);
if (this.taskFilter) {
let requestNode = {appDefinitionId: this.taskFilter.appId,
processDefinitionId: this.taskFilter.filter.processDefinitionId,
text: this.taskFilter.filter.name,
assignment: this.taskFilter.filter.assignment,
state: this.taskFilter.filter.state,
sort: this.taskFilter.filter.sort};
let requestNode = this.convertTaskUserToTaskQuery(this.taskFilter);
this.load(new TaskQueryRequestRepresentationModel(requestNode));
}
}
ngOnChanges(changes: SimpleChanges) {
let taskFilter = changes['taskFilter'];
if (taskFilter && taskFilter.currentValue) {
let requestNode = this.convertTaskUserToTaskQuery(taskFilter.currentValue);
this.load(new TaskQueryRequestRepresentationModel(requestNode));
return;
}
}
public load(requestNode: TaskQueryRequestRepresentationModel) {
this.activiti.getTotalTasks(requestNode).subscribe(
(res) => {
@ -174,4 +178,14 @@ export class ActivitiTaskList implements OnInit {
});
return tasks;
}
private convertTaskUserToTaskQuery(userTask: UserTaskFilterRepresentationModel) {
let requestNode = {appDefinitionId: userTask.appId,
processDefinitionId: userTask.filter.processDefinitionId,
text: userTask.filter.name,
assignment: userTask.filter.assignment,
state: userTask.filter.state,
sort: userTask.filter.sort};
return new TaskQueryRequestRepresentationModel(requestNode);
}
}

View File

@ -15,6 +15,35 @@
* limitations under the License.
*/
/**
*
* This object represent the app definition.
*
*
* @returns {AppDefinitionRepresentationModel} .
*/
export class AppDefinitionRepresentationModel {
defaultAppId: string;
deploymentId: string;
name: string;
description: string;
theme: string;
id: number;
modelId: number;
tenantId: number;
constructor(obj?: any) {
this.defaultAppId = obj && obj.defaultAppId || null;
this.deploymentId = obj && obj.deploymentId || false;
this.name = obj && obj.name || null;
this.description = obj && obj.description || null;
this.theme = obj && obj.theme || null;
this.id = obj && obj.id;
this.modelId = obj && obj.modelId;
this.tenantId = obj && obj.tenantId;
}
}
/**
*
* This object represent the filter.
@ -103,6 +132,7 @@ export class TaskQueryRequestRepresentationModel {
appDefinitionId: string;
processInstanceId: string;
processDefinitionId: string;
processDefinitionKey: string;
text: string;
assignment: string;
state: string;
@ -114,6 +144,7 @@ export class TaskQueryRequestRepresentationModel {
this.appDefinitionId = obj && obj.appDefinitionId || null;
this.processInstanceId = obj && obj.processInstanceId || null;
this.processDefinitionId = obj && obj.processDefinitionId || null;
this.processDefinitionKey = obj && obj.processDefinitionKey || null;
this.text = obj && obj.text || null;
this.assignment = obj && obj.assignment || null;
this.state = obj && obj.state || null;

View File

@ -19,7 +19,7 @@ import { it, describe, inject, beforeEach, beforeEachProviders } from '@angular/
import { ActivitiTaskListService } from './activiti-tasklist.service';
import { AlfrescoSettingsService, AlfrescoAuthenticationService, AlfrescoApiService } from 'ng2-alfresco-core';
import { TaskDetailsModel } from '../models/task-details.model';
import { UserTaskFilterRepresentationModel } from '../models/filter.model';
import { UserTaskFilterRepresentationModel, AppDefinitionRepresentationModel } from '../models/filter.model';
import { Comment } from '../models/comment.model';
declare let AlfrescoApi: any;
@ -36,10 +36,12 @@ describe('ActivitiTaskListService', () => {
let fakeFilters = {
size: 2, total: 2, start: 0,
data: [
{
id: 1, name: 'FakeInvolvedTasks', recent: false, icon: 'glyphicon-align-left',
filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-involved'}
},
new AppDefinitionRepresentationModel(
{
id: 1, name: 'FakeInvolvedTasks', recent: false, icon: 'glyphicon-align-left',
filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-involved'}
}
),
{
id: 2, name: 'FakeMyTasks', recent: false, icon: 'glyphicon-align-left',
filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-assignee'}
@ -47,6 +49,30 @@ describe('ActivitiTaskListService', () => {
]
};
let fakeAppFilter = {
size: 1, total: 1, start: 0,
data: [
{
id: 1, name: 'FakeInvolvedTasks', recent: false, icon: 'glyphicon-align-left',
filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-involved'}
}
]
};
let fakeApps = {
size: 2, total: 2, start: 0,
data: [
{
id: 1, defaultAppId: null, name: 'Sales-Fakes-App', description: 'desc-fake1', modelId: 22,
theme: 'theme-1-fake', icon: 'glyphicon-asterisk', 'deploymentId': '111', 'tenantId': null
},
{
id: 2, defaultAppId: null, name: 'health-care-Fake', description: 'desc-fake2', modelId: 33,
theme: 'theme-2-fake', icon: 'glyphicon-asterisk', 'deploymentId': '444', 'tenantId': null
}
]
};
let fakeFilter = {
sort: 'created-desc', text: '', state: 'open', assignment: 'fake-assignee'
};
@ -98,6 +124,10 @@ describe('ActivitiTaskListService', () => {
]
};
let fakeAppPromise = new Promise(function (resolve, reject) {
resolve(fakeAppFilter);
});
beforeEachProviders(() => {
return [
ActivitiTaskListService,
@ -134,6 +164,36 @@ describe('ActivitiTaskListService', () => {
});
});
it('should call the api withthe appId', (done) => {
spyOn(service, 'callApiTaskFilters').and.returnValue((fakeAppPromise));
let appId = 1;
service.getTaskListFilters(appId).subscribe(
(res) => {
expect(service.callApiTaskFilters).toHaveBeenCalledWith(appId);
done();
}
);
});
it('should return the app filter by id', (done) => {
let appId = 1;
service.getTaskListFilters(appId).subscribe(
(res) => {
expect(res).toBeDefined();
expect(res.length).toEqual(1);
expect(res[0].name).toEqual('FakeInvolvedTasks');
done();
}
);
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeAppFilter)
});
});
it('should return the task list filtered', (done) => {
service.getTasks(fakeFilter).subscribe(
res => {
@ -375,5 +435,47 @@ describe('ActivitiTaskListService', () => {
});
});
it('should get the deployed apps ', (done) => {
service.getDeployedApplications().subscribe(
(res: any) => {
expect(res).toBeDefined();
expect(res.length).toEqual(2);
expect(res[0].name).toEqual('Sales-Fakes-App');
expect(res[0].description).toEqual('desc-fake1');
expect(res[0].deploymentId).toEqual('111');
expect(res[1].name).toEqual('health-care-Fake');
expect(res[1].description).toEqual('desc-fake2');
expect(res[1].deploymentId).toEqual('444');
done();
}
);
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeApps)
});
});
it('should get the filter deployed app ', (done) => {
let name = 'health-care-Fake';
service.getDeployedApplications(name).subscribe(
(res: any) => {
expect(res).toBeDefined();
expect(res.name).toEqual('health-care-Fake');
expect(res.description).toEqual('desc-fake2');
expect(res.deploymentId).toEqual('444');
done();
}
);
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeApps)
});
});
});

View File

@ -34,9 +34,14 @@ export class ActivitiTaskListService {
* Retrive all the Deployed app
* @returns {Observable<any>}
*/
getDeployedApplications(name: string): Observable<any> {
getDeployedApplications(name?: string): Observable<any> {
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.appsApi.getAppDefinitions())
.map((response: any) => response.data.find(p => p.name === name))
.map((response: any) => {
if (name) {
return response.data.find(p => p.name === name);
}
return response.data;
})
.do(data => console.log('Application: ' + JSON.stringify(data)));
}