mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-06-02 17:35:08 +00:00
Merge pull request #801 from Alfresco/dev-wabson-530
Add start task button component and add to demo-shell
This commit is contained in:
commit
ef1769bae7
@ -19,6 +19,7 @@
|
|||||||
<div class="mdl-grid">
|
<div class="mdl-grid">
|
||||||
<div class="mdl-cell mdl-cell--2-col task-column mdl-shadow--2dp">
|
<div class="mdl-cell mdl-cell--2-col task-column mdl-shadow--2dp">
|
||||||
<span>Task Filters</span>
|
<span>Task Filters</span>
|
||||||
|
<activiti-start-task [appId]="appId" (onSuccess)="onStartTaskSuccess($event)"></activiti-start-task>
|
||||||
<activiti-filters [appId]="appId" (filterClick)="onTaskFilterClick($event)" (onSuccess)="onSuccessTaskFilterList($event)"
|
<activiti-filters [appId]="appId" (filterClick)="onTaskFilterClick($event)" (onSuccess)="onSuccessTaskFilterList($event)"
|
||||||
#activitifilter></activiti-filters>
|
#activitifilter></activiti-filters>
|
||||||
</div>
|
</div>
|
||||||
|
@ -20,7 +20,8 @@ import { ALFRESCO_TASKLIST_DIRECTIVES,
|
|||||||
AppDefinitionRepresentationModel,
|
AppDefinitionRepresentationModel,
|
||||||
FilterRepresentationModel,
|
FilterRepresentationModel,
|
||||||
UserTaskFilterRepresentationModel,
|
UserTaskFilterRepresentationModel,
|
||||||
ActivitiApps
|
ActivitiApps,
|
||||||
|
ActivitiTaskList
|
||||||
} from 'ng2-activiti-tasklist';
|
} from 'ng2-activiti-tasklist';
|
||||||
import { ACTIVITI_PROCESSLIST_DIRECTIVES } from 'ng2-activiti-processlist';
|
import { ACTIVITI_PROCESSLIST_DIRECTIVES } from 'ng2-activiti-processlist';
|
||||||
import { ActivitiForm } from 'ng2-activiti-form';
|
import { ActivitiForm } from 'ng2-activiti-form';
|
||||||
@ -53,7 +54,7 @@ export class ActivitiDemoComponent implements AfterViewChecked {
|
|||||||
activitidetails: any;
|
activitidetails: any;
|
||||||
|
|
||||||
@ViewChild('activititasklist')
|
@ViewChild('activititasklist')
|
||||||
activititasklist: any;
|
activititasklist: ActivitiTaskList;
|
||||||
|
|
||||||
@ViewChild('activitiprocessfilter')
|
@ViewChild('activitiprocessfilter')
|
||||||
activitiprocessfilter: any;
|
activitiprocessfilter: any;
|
||||||
@ -146,6 +147,10 @@ export class ActivitiDemoComponent implements AfterViewChecked {
|
|||||||
this.taskFilter = this.activitifilter.getCurrentFilter();
|
this.taskFilter = this.activitifilter.getCurrentFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onStartTaskSuccess(event: any) {
|
||||||
|
this.activititasklist.reload();
|
||||||
|
}
|
||||||
|
|
||||||
onSuccessTaskList(event: UserTaskFilterRepresentationModel) {
|
onSuccessTaskList(event: UserTaskFilterRepresentationModel) {
|
||||||
this.currentTaskId = this.activititasklist.getCurrentTaskId();
|
this.currentTaskId = this.activititasklist.getCurrentTaskId();
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<label class="mdl-textfield__label" for="processDefinition">{{'START_PROCESS.DIALOG.LABEL.TYPE'|translate}}</label>
|
<label class="mdl-textfield__label" for="processDefinition">{{'START_PROCESS.DIALOG.LABEL.TYPE'|translate}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||||
<input class="mdl-textfield__input" type="text" [(ngModel)]="name" rows="1" id="processName" />
|
<input class="mdl-textfield__input" type="text" [(ngModel)]="name" id="processName" />
|
||||||
<label class="mdl-textfield__label" for="processName">{{'START_PROCESS.DIALOG.LABEL.NAME'|translate}}</label>
|
<label class="mdl-textfield__label" for="processName">{{'START_PROCESS.DIALOG.LABEL.NAME'|translate}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { ActivitiApps } from './src/components/activiti-apps.component';
|
import { ActivitiApps } from './src/components/activiti-apps.component';
|
||||||
|
import { ActivitiStartProcessButton } from './src/components/activiti-start-task.component';
|
||||||
import { ActivitiTaskList } from './src/components/activiti-tasklist.component';
|
import { ActivitiTaskList } from './src/components/activiti-tasklist.component';
|
||||||
import { ActivitiTaskDetails } from './src/components/activiti-task-details.component';
|
import { ActivitiTaskDetails } from './src/components/activiti-task-details.component';
|
||||||
import { ActivitiFilters } from './src/components/activiti-filters.component';
|
import { ActivitiFilters } from './src/components/activiti-filters.component';
|
||||||
@ -23,6 +24,7 @@ import { NoTaskDetailsTemplateComponent } from './src/components/no-task-detail-
|
|||||||
|
|
||||||
export * from './src/components/activiti-apps.component';
|
export * from './src/components/activiti-apps.component';
|
||||||
export * from './src/components/activiti-tasklist.component';
|
export * from './src/components/activiti-tasklist.component';
|
||||||
|
export * from './src/components/activiti-start-task.component';
|
||||||
export * from './src/services/activiti-tasklist.service';
|
export * from './src/services/activiti-tasklist.service';
|
||||||
export * from './src/models/filter.model';
|
export * from './src/models/filter.model';
|
||||||
|
|
||||||
@ -30,6 +32,7 @@ export const ALFRESCO_TASKLIST_DIRECTIVES: [any] = [
|
|||||||
NoTaskDetailsTemplateComponent,
|
NoTaskDetailsTemplateComponent,
|
||||||
ActivitiApps,
|
ActivitiApps,
|
||||||
ActivitiFilters,
|
ActivitiFilters,
|
||||||
|
ActivitiStartProcessButton,
|
||||||
ActivitiTaskList,
|
ActivitiTaskList,
|
||||||
ActivitiTaskDetails
|
ActivitiTaskDetails
|
||||||
];
|
];
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
:host {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activiti-label {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
<button type="button" (click)="showDialog()" class="mdl-button">{{'START_TASK.BUTTON'|translate}}</button>
|
||||||
|
|
||||||
|
<dialog class="mdl-dialog" #dialog>
|
||||||
|
<h4 class="mdl-dialog__title">{{'START_TASK.DIALOG.TITLE'|translate}}</h4>
|
||||||
|
<div class="mdl-dialog__content">
|
||||||
|
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||||
|
<input class="mdl-textfield__input" type="text" [(ngModel)]="name" id="taskName" />
|
||||||
|
<label class="mdl-textfield__label" for="taskName">{{'START_TASK.DIALOG.LABEL.NAME'|translate}}</label>
|
||||||
|
</div>
|
||||||
|
<div class="mdl-textfield mdl-js-textfield">
|
||||||
|
<textarea class="mdl-textfield__input" type="text" [(ngModel)]="description" rows="3" id="taskDescription"></textarea>
|
||||||
|
<label class="mdl-textfield__label" for="taskDescription">{{'START_TASK.DIALOG.LABEL.DESCRIPTION'|translate}}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mdl-dialog__actions">
|
||||||
|
<button type="button" (click)="start()" class="mdl-button">{{'START_TASK.DIALOG.ACTION.START'|translate}}</button>
|
||||||
|
<button type="button" (click)="cancel()" class="mdl-button close">{{'START_TASK.DIALOG.ACTION.CANCEL'|translate}}</button>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
@ -0,0 +1,105 @@
|
|||||||
|
/*!
|
||||||
|
* @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, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
|
||||||
|
import { AlfrescoTranslationService, AlfrescoAuthenticationService } from 'ng2-alfresco-core';
|
||||||
|
import { TaskDetailsModel } from '../models/task-details.model';
|
||||||
|
import { ActivitiTaskListService } from './../services/activiti-tasklist.service';
|
||||||
|
|
||||||
|
declare let componentHandler: any;
|
||||||
|
declare let __moduleName: string;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'activiti-start-task',
|
||||||
|
moduleId: __moduleName,
|
||||||
|
templateUrl: './activiti-start-task.component.html',
|
||||||
|
styleUrls: ['./activiti-start-task.component.css'],
|
||||||
|
providers: [ActivitiTaskListService]
|
||||||
|
})
|
||||||
|
export class ActivitiStartProcessButton implements OnInit {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
appId: string;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
onSuccess: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
|
@ViewChild('dialog')
|
||||||
|
dialog: any;
|
||||||
|
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param auth
|
||||||
|
* @param translate
|
||||||
|
* @param taskService
|
||||||
|
*/
|
||||||
|
constructor(private auth: AlfrescoAuthenticationService,
|
||||||
|
private translate: AlfrescoTranslationService,
|
||||||
|
private taskService: ActivitiTaskListService) {
|
||||||
|
|
||||||
|
if (translate) {
|
||||||
|
translate.addTranslationFolder('node_modules/ng2-activiti-tasklist/src');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public start() {
|
||||||
|
if (this.name) {
|
||||||
|
this.taskService.createNewTask(new TaskDetailsModel({
|
||||||
|
name: this.name,
|
||||||
|
description: this.description,
|
||||||
|
category: this.appId ? '' + this.appId : null
|
||||||
|
})).subscribe(
|
||||||
|
(res: any) => {
|
||||||
|
this.onSuccess.emit(res);
|
||||||
|
this.closeDialog();
|
||||||
|
this.resetForm();
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
window.alert('An error occurred while trying to add the task');
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public cancel() {
|
||||||
|
this.closeDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
public showDialog() {
|
||||||
|
if (this.dialog) {
|
||||||
|
this.dialog.nativeElement.showModal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private closeDialog() {
|
||||||
|
if (this.dialog) {
|
||||||
|
this.dialog.nativeElement.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private resetForm() {
|
||||||
|
this.name = '';
|
||||||
|
this.description = '';
|
||||||
|
}
|
||||||
|
}
|
@ -33,6 +33,8 @@
|
|||||||
(onError)='onErrorEmitter($event)'
|
(onError)='onErrorEmitter($event)'
|
||||||
(executeOutcome)='executeOutcomeEmitter($event)'
|
(executeOutcome)='executeOutcomeEmitter($event)'
|
||||||
#activitiForm>
|
#activitiForm>
|
||||||
|
|
||||||
</activiti-form>
|
</activiti-form>
|
||||||
|
<button type="button" class="mdl-button" *ngIf="!hasFormKey() && isTaskActive()" (click)="onComplete()">
|
||||||
|
{{ 'TASK_DETAILS.BUTTON.COMPLETE' | translate }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -133,6 +133,10 @@ export class ActivitiTaskDetails implements OnInit, OnChanges {
|
|||||||
&& this.taskDetails.formKey !== 'null';
|
&& this.taskDetails.formKey !== 'null';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isTaskActive() {
|
||||||
|
return this.taskDetails && this.taskDetails.duration === null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the activiti task details
|
* Load the activiti task details
|
||||||
* @param taskId
|
* @param taskId
|
||||||
@ -160,7 +164,6 @@ export class ActivitiTaskDetails implements OnInit, OnChanges {
|
|||||||
if (this.activitichecklist) {
|
if (this.activitichecklist) {
|
||||||
this.activitichecklist.load(this.taskDetails.id);
|
this.activitichecklist.load(this.taskDetails.id);
|
||||||
}
|
}
|
||||||
console.log(this.taskDetails);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -176,6 +179,7 @@ export class ActivitiTaskDetails implements OnInit, OnChanges {
|
|||||||
this.activitiTaskList.completeTask(this.taskId).subscribe(
|
this.activitiTaskList.completeTask(this.taskId).subscribe(
|
||||||
(res) => {
|
(res) => {
|
||||||
console.log(res);
|
console.log(res);
|
||||||
|
this.formCompleted.emit(res);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -132,6 +132,23 @@ describe('ActivitiTaskList', () => {
|
|||||||
taskList.ngOnInit();
|
taskList.ngOnInit();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should reload tasks when reload() is called', (done) => {
|
||||||
|
spyOn(taskList.activiti, 'getTotalTasks').and.returnValue(Observable.fromPromise(fakeGlobalTotalTasksPromise));
|
||||||
|
spyOn(taskList.activiti, 'getTasks').and.returnValue(Observable.fromPromise(fakeGlobalTaskPromise));
|
||||||
|
taskList.taskFilter = new UserTaskFilterRepresentationModel({filter: { state: 'open', assignment: 'fake-assignee'}});
|
||||||
|
taskList.ngOnInit();
|
||||||
|
taskList.onSuccess.subscribe( (res) => {
|
||||||
|
expect(res).toBeDefined();
|
||||||
|
expect(taskList.data).toBeDefined();
|
||||||
|
expect(taskList.isTaskListEmpty()).not.toBeTruthy();
|
||||||
|
expect(taskList.data.getRows().length).toEqual(2);
|
||||||
|
expect(taskList.data.getRows()[0].getValue('name')).toEqual('fake-long-name-fake-long-name-fake-long-name-fak50...');
|
||||||
|
expect(taskList.data.getRows()[1].getValue('name')).toEqual('Nameless task');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
taskList.reload();
|
||||||
|
});
|
||||||
|
|
||||||
it('should emit row click event', (done) => {
|
it('should emit row click event', (done) => {
|
||||||
let row = new ObjectDataRow({
|
let row = new ObjectDataRow({
|
||||||
id: 999
|
id: 999
|
||||||
|
@ -96,6 +96,13 @@ export class ActivitiTaskList implements OnInit, OnChanges {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public reload() {
|
||||||
|
if (this.taskFilter) {
|
||||||
|
let requestNode = this.convertTaskUserToTaskQuery(this.taskFilter);
|
||||||
|
this.load(new TaskQueryRequestRepresentationModel(requestNode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public load(requestNode: TaskQueryRequestRepresentationModel) {
|
public load(requestNode: TaskQueryRequestRepresentationModel) {
|
||||||
this.activiti.getTotalTasks(requestNode).subscribe(
|
this.activiti.getTotalTasks(requestNode).subscribe(
|
||||||
(res) => {
|
(res) => {
|
||||||
|
@ -13,6 +13,9 @@
|
|||||||
"COMMENTS": "Comments",
|
"COMMENTS": "Comments",
|
||||||
"CHECKLIST": "Checklist"
|
"CHECKLIST": "Checklist"
|
||||||
},
|
},
|
||||||
|
"BUTTON": {
|
||||||
|
"COMPLETE": "Complete"
|
||||||
|
},
|
||||||
"MESSAGES": {
|
"MESSAGES": {
|
||||||
"NONE": "No task details found."
|
"NONE": "No task details found."
|
||||||
},
|
},
|
||||||
@ -36,5 +39,19 @@
|
|||||||
"MESSAGES": {
|
"MESSAGES": {
|
||||||
"NONE": "No task filter selected."
|
"NONE": "No task filter selected."
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"START_TASK": {
|
||||||
|
"BUTTON": "Start Task",
|
||||||
|
"DIALOG": {
|
||||||
|
"TITLE": "Start Task",
|
||||||
|
"LABEL": {
|
||||||
|
"NAME": "Name",
|
||||||
|
"DESCRIPTION": "Description"
|
||||||
|
},
|
||||||
|
"ACTION": {
|
||||||
|
"START": "Start",
|
||||||
|
"CANCEL": "Cancel"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -64,6 +64,7 @@ export class TaskDetailsModel {
|
|||||||
this.priority = obj && obj.priority;
|
this.priority = obj && obj.priority;
|
||||||
this.assignee = new User(obj.assignee);
|
this.assignee = new User(obj.assignee);
|
||||||
this.adhocTaskCanBeReassigned = obj && obj.adhocTaskCanBeReassigned;
|
this.adhocTaskCanBeReassigned = obj && obj.adhocTaskCanBeReassigned;
|
||||||
|
this.category = obj && obj.category || null;
|
||||||
this.created = obj && obj.created || null;
|
this.created = obj && obj.created || null;
|
||||||
this.description = obj && obj.description || null;
|
this.description = obj && obj.description || null;
|
||||||
this.dueDate = obj && obj.dueDate || null;
|
this.dueDate = obj && obj.dueDate || null;
|
||||||
|
@ -477,5 +477,38 @@ describe('ActivitiTaskListService', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should create a new standalone task ', (done) => {
|
||||||
|
let taskFake = new TaskDetailsModel({
|
||||||
|
name: 'FakeNameTask',
|
||||||
|
description: 'FakeDescription',
|
||||||
|
category: '3'
|
||||||
|
});
|
||||||
|
|
||||||
|
service.createNewTask(taskFake).subscribe(
|
||||||
|
(res: TaskDetailsModel) => {
|
||||||
|
expect(res).toBeDefined();
|
||||||
|
expect(res.id).not.toEqual('');
|
||||||
|
expect(res.name).toEqual('FakeNameTask');
|
||||||
|
expect(res.description).toEqual('FakeDescription');
|
||||||
|
expect(res.category).toEqual('3');
|
||||||
|
expect(res.created).not.toEqual('');
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||||
|
'status': 200,
|
||||||
|
contentType: 'application/json',
|
||||||
|
responseText: JSON.stringify({
|
||||||
|
id: '777',
|
||||||
|
name: 'FakeNameTask',
|
||||||
|
description: 'FakeDescription',
|
||||||
|
category: '3',
|
||||||
|
assignee: fakeUser,
|
||||||
|
created: '2016-07-15T11:19:17.440+0000'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -216,6 +216,19 @@ export class ActivitiTaskListService {
|
|||||||
}).catch(this.handleError);
|
}).catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new standalone task
|
||||||
|
* @param task - TaskDetailsModel
|
||||||
|
* @returns {TaskDetailsModel}
|
||||||
|
*/
|
||||||
|
createNewTask(task: TaskDetailsModel): Observable<TaskDetailsModel> {
|
||||||
|
return Observable.fromPromise(this.callApiCreateTask(task))
|
||||||
|
.map(res => res)
|
||||||
|
.map((response: TaskDetailsModel) => {
|
||||||
|
return new TaskDetailsModel(response);
|
||||||
|
}).catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
private callApiTasksFiltered(requestNode: TaskQueryRequestRepresentationModel) {
|
private callApiTasksFiltered(requestNode: TaskQueryRequestRepresentationModel) {
|
||||||
return this.authService.getAlfrescoApi().activiti.taskApi.listTasks(requestNode);
|
return this.authService.getAlfrescoApi().activiti.taskApi.listTasks(requestNode);
|
||||||
}
|
}
|
||||||
@ -256,6 +269,10 @@ export class ActivitiTaskListService {
|
|||||||
return this.authService.getAlfrescoApi().activiti.taskApi.completeTask(id);
|
return this.authService.getAlfrescoApi().activiti.taskApi.completeTask(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private callApiCreateTask(task: TaskDetailsModel) {
|
||||||
|
return this.authService.getAlfrescoApi().activiti.taskApi.createNewTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
private handleError(error: any) {
|
private handleError(error: any) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
return Observable.throw(error || 'Server error');
|
return Observable.throw(error || 'Server error');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user