Merge pull request #1312 from Alfresco/dev-mvitale-1305

Claim a task
This commit is contained in:
Mario Romano 2016-12-16 16:37:12 +00:00 committed by GitHub
commit 128d3af54a
11 changed files with 103 additions and 22 deletions

View File

@ -144,7 +144,7 @@ export class ActivitiProcessInstanceTasks implements OnInit, OnChanges {
? user.firstName + ' ' : '') + ? user.firstName + ' ' : '') +
user.lastName; user.lastName;
} }
return ''; return 'Nobody';
} }
getFormatDate(value, format: string) { getFormatDate(value, format: string) {

View File

@ -9,7 +9,10 @@
</div> </div>
<div *ngIf="taskDetails"> <div *ngIf="taskDetails">
<h2 class="mdl-card__title-text">{{taskDetails.name}}</h2> <h2 class="mdl-card__title-text">{{taskDetails.name}}</h2>
<activiti-task-header [taskDetails]="taskDetails" [formName]="taskFormName"></activiti-task-header> <activiti-task-header
[taskDetails]="taskDetails"
[formName]="taskFormName"
(claim)="onClaimTask($event)"></activiti-task-header>
<div class="mdl-grid"> <div class="mdl-grid">
<div class="mdl-cell mdl-cell--4-col"> <div class="mdl-cell mdl-cell--4-col">
<activiti-people [people]="taskPeople" [readOnly]="readOnlyForm" <activiti-people [people]="taskPeople" [readOnly]="readOnlyForm"
@ -24,6 +27,7 @@
#activitichecklist></activiti-checklist> #activitichecklist></activiti-checklist>
</div> </div>
</div> </div>
<div *ngIf="isAssignedToMe()">
<activiti-form *ngIf="hasFormKey()" [taskId]="taskDetails.id" <activiti-form *ngIf="hasFormKey()" [taskId]="taskDetails.id"
[showTitle]="showFormTitle" [showTitle]="showFormTitle"
[showRefreshButton]="showFormRefreshButton" [showRefreshButton]="showFormRefreshButton"
@ -37,6 +41,10 @@
(executeOutcome)='onFormExecuteOutcome($event)' (executeOutcome)='onFormExecuteOutcome($event)'
#activitiForm> #activitiForm>
</activiti-form> </activiti-form>
</div>
<div *ngIf="!isAssignedToMe()">
{{ 'TASK_DETAILS.MESSAGES.CLAIM' | translate }}
</div>
<button type="button" class="mdl-button" *ngIf="!hasFormKey() && isTaskActive()" (click)="onComplete()"> <button type="button" class="mdl-button" *ngIf="!hasFormKey() && isTaskActive()" (click)="onComplete()">
{{ 'TASK_DETAILS.BUTTON.COMPLETE' | translate }} {{ 'TASK_DETAILS.BUTTON.COMPLETE' | translate }}
</button> </button>

View File

@ -178,6 +178,10 @@ export class ActivitiTaskDetails implements OnInit, OnChanges {
} }
} }
isAssignedToMe(): boolean {
return this.taskDetails.assignee ? true : false;
}
/** /**
* Retrieve the next open task * Retrieve the next open task
* @param processInstanceId * @param processInstanceId
@ -243,4 +247,8 @@ export class ActivitiTaskDetails implements OnInit, OnChanges {
closeErrorDialog(): void { closeErrorDialog(): void {
this.errorDialog.nativeElement.close(); this.errorDialog.nativeElement.close();
} }
onClaimTask(taskId: string) {
this.loadDetails(taskId);
}
} }

View File

@ -15,5 +15,10 @@
<span class="activiti-task-header__value" *ngIf="formName">{{ formName }}</span> <span class="activiti-task-header__value" *ngIf="formName">{{ formName }}</span>
<span class="activiti-task-header__value" *ngIf="!formName">{{ 'TASK_DETAILS.FORM.NONE' | translate }}</span> <span class="activiti-task-header__value" *ngIf="!formName">{{ 'TASK_DETAILS.FORM.NONE' | translate }}</span>
</div> </div>
<button *ngIf="!isAssignedToMe()" data-automation-id="header-claim-button" type="button" id="claim-task"
(click)="claimTask(taskDetails.id)" class="mdl-button">{{ 'TASK_DETAILS.BUTTON.CLAIM' | translate }}
</button>
</div> </div>
</div> </div>

View File

@ -24,9 +24,11 @@ import { ActivitiTaskHeader } from './activiti-task-header.component';
import { TranslationMock } from './../assets/translation.service.mock'; import { TranslationMock } from './../assets/translation.service.mock';
import { taskDetailsMock } from './../assets/task-details.mock'; import { taskDetailsMock } from './../assets/task-details.mock';
import { TaskDetailsModel } from '../models/task-details.model'; import { TaskDetailsModel } from '../models/task-details.model';
import { ActivitiTaskListService } from './../services/activiti-tasklist.service';
describe('ActivitiTaskHeader', () => { describe('ActivitiTaskHeader', () => {
let service: ActivitiTaskListService;
let componentHandler: any; let componentHandler: any;
let component: ActivitiTaskHeader; let component: ActivitiTaskHeader;
let fixture: ComponentFixture<ActivitiTaskHeader>; let fixture: ComponentFixture<ActivitiTaskHeader>;
@ -40,7 +42,8 @@ describe('ActivitiTaskHeader', () => {
ActivitiTaskHeader ActivitiTaskHeader
], ],
providers: [ providers: [
{ provide: AlfrescoTranslationService, useClass: TranslationMock } { provide: AlfrescoTranslationService, useClass: TranslationMock },
ActivitiTaskListService
] ]
}).compileComponents(); }).compileComponents();
})); }));
@ -49,6 +52,7 @@ describe('ActivitiTaskHeader', () => {
fixture = TestBed.createComponent(ActivitiTaskHeader); fixture = TestBed.createComponent(ActivitiTaskHeader);
component = fixture.componentInstance; component = fixture.componentInstance;
service = fixture.debugElement.injector.get(ActivitiTaskListService);
component.taskDetails = new TaskDetailsModel(taskDetailsMock); component.taskDetails = new TaskDetailsModel(taskDetailsMock);
@ -78,6 +82,13 @@ describe('ActivitiTaskHeader', () => {
expect(valueEl.nativeElement.innerText).toBe('TASK_DETAILS.ASSIGNEE.NONE'); expect(valueEl.nativeElement.innerText).toBe('TASK_DETAILS.ASSIGNEE.NONE');
}); });
it('should display the claim button if no assignee', () => {
component.taskDetails.assignee = null;
fixture.detectChanges();
let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-claim-button"]'));
expect(valueEl.nativeElement.innerText).toBe('TASK_DETAILS.BUTTON.CLAIM');
});
it('should display due date', () => { it('should display due date', () => {
component.taskDetails.dueDate = '2016-11-03T15:25:42.749+0000'; component.taskDetails.dueDate = '2016-11-03T15:25:42.749+0000';
fixture.detectChanges(); fixture.detectChanges();

View File

@ -15,9 +15,10 @@
* limitations under the License. * limitations under the License.
*/ */
import { Component, Input } from '@angular/core'; import { Component, Input, Output, EventEmitter } from '@angular/core';
import { AlfrescoTranslationService } from 'ng2-alfresco-core'; import { AlfrescoTranslationService } from 'ng2-alfresco-core';
import { TaskDetailsModel } from '../models/task-details.model'; import { TaskDetailsModel } from '../models/task-details.model';
import { ActivitiTaskListService } from './../services/activiti-tasklist.service';
@Component({ @Component({
selector: 'activiti-task-header', selector: 'activiti-task-header',
@ -33,7 +34,11 @@ export class ActivitiTaskHeader {
@Input() @Input()
taskDetails: TaskDetailsModel; taskDetails: TaskDetailsModel;
constructor(private translate: AlfrescoTranslationService) { @Output()
claim: EventEmitter<any> = new EventEmitter<any>();
constructor(private translate: AlfrescoTranslationService,
private activitiTaskService: ActivitiTaskListService) {
if (translate) { if (translate) {
translate.addTranslationFolder('ng2-activiti-tasklist', 'node_modules/ng2-activiti-tasklist/src'); translate.addTranslationFolder('ng2-activiti-tasklist', 'node_modules/ng2-activiti-tasklist/src');
} }
@ -42,4 +47,16 @@ export class ActivitiTaskHeader {
public hasAssignee(): boolean { public hasAssignee(): boolean {
return (this.taskDetails && this.taskDetails.assignee) ? true : false; return (this.taskDetails && this.taskDetails.assignee) ? true : false;
} }
isAssignedToMe(): boolean {
return this.taskDetails.assignee ? true : false;
}
claimTask(taskId: string) {
this.activitiTaskService.claimTask(taskId).subscribe(
(res: any) => {
console.log('Task claimed');
this.claim.emit(taskId);
});
}
} }

View File

@ -14,10 +14,12 @@
"CHECKLIST": "Checklist" "CHECKLIST": "Checklist"
}, },
"BUTTON": { "BUTTON": {
"COMPLETE": "Complete" "COMPLETE": "Complete",
"CLAIM": "Claim"
}, },
"MESSAGES": { "MESSAGES": {
"NONE": "No task details found." "NONE": "No task details found.",
"CLAIM": "To work on this task, you need to claim it first. You can do that by pressing the Claim button above."
}, },
"FORM": { "FORM": {
"NONE": "No form." "NONE": "No form."

View File

@ -13,8 +13,13 @@
"COMMENTS": "Commenti", "COMMENTS": "Commenti",
"CHECKLIST": "Checklist" "CHECKLIST": "Checklist"
}, },
"BUTTON": {
"COMPLETE": "Completa",
"CLAIM": "Richiedi"
},
"MESSAGES": { "MESSAGES": {
"NONE": "Nessun dettaglio task trovato." "NONE": "Nessun dettaglio task trovato.",
"CLAIM": "Per lavorare con questo task, hai bisogno di richiederlo prima. Per richiedere il task basta premere il tasto Richiedi"
}, },
"FORM": { "FORM": {
"NONE": "Nessuna form." "NONE": "Nessuna form."

View File

@ -61,7 +61,7 @@ export class TaskDetailsModel {
this.id = obj && obj.id || null; this.id = obj && obj.id || null;
this.name = obj && obj.name || null; this.name = obj && obj.name || null;
this.priority = obj && obj.priority; this.priority = obj && obj.priority;
this.assignee = new User(obj.assignee); this.assignee = obj.assignee ? new User(obj.assignee) : null;
this.adhocTaskCanBeReassigned = obj && obj.adhocTaskCanBeReassigned; this.adhocTaskCanBeReassigned = obj && obj.adhocTaskCanBeReassigned;
this.category = obj && obj.category || null; this.category = obj && obj.category || null;
this.created = obj && obj.created || null; this.created = obj && obj.created || null;

View File

@ -513,4 +513,20 @@ describe('ActivitiTaskListService', () => {
}); });
}); });
it('should claim a task', (done) => {
let taskId = '111';
service.claimTask(taskId).subscribe(
(res: any) => {
done();
}
);
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
contentType: 'application/json',
responseText: JSON.stringify({})
});
});
}); });

View File

@ -232,6 +232,15 @@ export class ActivitiTaskListService {
}).catch(this.handleError); }).catch(this.handleError);
} }
/**
* Claim a task
* @param id - taskId
*/
claimTask(taskId: string): Observable<TaskDetailsModel> {
return Observable.fromPromise(this.apiService.getInstance().activiti.taskApi.claimTask(taskId))
.catch(this.handleError);
}
private callApiTasksFiltered(requestNode: TaskQueryRequestRepresentationModel) { private callApiTasksFiltered(requestNode: TaskQueryRequestRepresentationModel) {
return this.apiService.getInstance().activiti.taskApi.listTasks(requestNode); return this.apiService.getInstance().activiti.taskApi.listTasks(requestNode);
} }