[ADF-923] Added check for only involved user cannot complete a task (#2068)

* [ADF-923] Added check for only involved user cannot complete a task

* [ADF-923] fix compilation error

* [ADF-923] added review changes

* [ADF-923] corrected mispelling
This commit is contained in:
Vito 2017-07-12 04:26:51 -07:00 committed by Eugenio Romano
parent acfe257327
commit 6f8e984d75
6 changed files with 81 additions and 58 deletions

View File

@ -157,6 +157,7 @@ The recommended set of properties can be found in the following table:
| data | FormValues | | Custom form values map to be used with the rendered form. | | data | FormValues | | Custom form values map to be used with the rendered form. |
| showTitle | boolean | true | Toggle rendering of the form title. | | showTitle | boolean | true | Toggle rendering of the form title. |
| showCompleteButton | boolean | true | Toggle rendering of the `Complete` outcome button. | | showCompleteButton | boolean | true | Toggle rendering of the `Complete` outcome button. |
| disableCompleteButton | boolean | false | The `Complete` outcome button is showed but it will be disabled. |
| showSaveButton | boolean | true | Toggle rendering of the `Save` outcome button. | | showSaveButton | boolean | true | Toggle rendering of the `Save` outcome button. |
| readOnly | boolean | false | Toggle readonly state of the form. Enforces all form widgets render readonly if enabled. | | readOnly | boolean | false | Toggle readonly state of the form. Enforces all form widgets render readonly if enabled. |
| showRefreshButton | boolean | true | Toggle rendering of the `Refresh` button. | | showRefreshButton | boolean | true | Toggle rendering of the `Refresh` button. |

View File

@ -795,6 +795,17 @@ describe('ActivitiForm', () => {
expect(formComponent.isOutcomeButtonEnabled(outcome)).toBeFalsy(); expect(formComponent.isOutcomeButtonEnabled(outcome)).toBeFalsy();
}); });
it('should disable complete outcome button when disableCompleteButton is true', () => {
let formModel = new FormModel();
formComponent.form = formModel;
formComponent.disableCompleteButton = true;
expect(formModel.isValid).toBeTruthy();
let completeOutcome = formComponent.form.outcomes.find(outcome => outcome.name === FormOutcomeModel.COMPLETE_ACTION);
expect(formComponent.isOutcomeButtonEnabled(completeOutcome)).toBeFalsy();
});
it('should raise [executeOutcome] event for formService', (done) => { it('should raise [executeOutcome] event for formService', (done) => {
formService.executeOutcome.subscribe(() => { formService.executeOutcome.subscribe(() => {
done(); done();
@ -834,5 +845,4 @@ describe('ActivitiForm', () => {
expect(labelField.value).toBe('option_1'); expect(labelField.value).toBe('option_1');
expect(radioField.value).toBe('option_1'); expect(radioField.value).toBe('option_1');
}); });
}); });

View File

@ -24,7 +24,7 @@ import { NodeService } from './../services/node.service';
import { ContentLinkModel } from './widgets/core/content-link.model'; import { ContentLinkModel } from './widgets/core/content-link.model';
import { FormFieldModel, FormModel, FormOutcomeEvent, FormOutcomeModel, FormValues } from './widgets/core/index'; import { FormFieldModel, FormModel, FormOutcomeEvent, FormOutcomeModel, FormValues } from './widgets/core/index';
import { WidgetVisibilityService } from './../services/widget-visibility.service'; import { WidgetVisibilityService } from './../services/widget-visibility.service';
declare var componentHandler: any; declare var componentHandler: any;
@ -73,6 +73,9 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
@Input() @Input()
showCompleteButton: boolean = true; showCompleteButton: boolean = true;
@Input()
disableCompleteButton: boolean = false;
@Input() @Input()
showSaveButton: boolean = true; showSaveButton: boolean = true;
@ -141,6 +144,9 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
if (outcome.name === FormOutcomeModel.SAVE_ACTION) { if (outcome.name === FormOutcomeModel.SAVE_ACTION) {
return true; return true;
} }
if (outcome.name === FormOutcomeModel.COMPLETE_ACTION) {
return this.disableCompleteButton ? false : this.form.isValid;
}
return this.form.isValid; return this.form.isValid;
} }
return false; return false;
@ -152,7 +158,7 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
return this.showCompleteButton; return this.showCompleteButton;
} }
if (isFormReadOnly) { if (isFormReadOnly) {
return outcome.isSelected ; return outcome.isSelected;
} }
if (outcome.name === FormOutcomeModel.SAVE_ACTION) { if (outcome.name === FormOutcomeModel.SAVE_ACTION) {
return this.showSaveButton; return this.showSaveButton;
@ -312,22 +318,22 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
getFormByTaskId(taskId: string): Promise<FormModel> { getFormByTaskId(taskId: string): Promise<FormModel> {
return new Promise<FormModel>((resolve, reject) => { return new Promise<FormModel>((resolve, reject) => {
this.loadFormProcessVariables(this.taskId).then(_ => { this.loadFormProcessVariables(this.taskId).then(_ => {
this.formService this.formService
.getTaskForm(taskId) .getTaskForm(taskId)
.subscribe( .subscribe(
form => { form => {
this.form = new FormModel(form, this.data, this.readOnly, this.formService); this.form = new FormModel(form, this.data, this.readOnly, this.formService);
this.onFormLoaded(this.form); this.onFormLoaded(this.form);
resolve(this.form); resolve(this.form);
}, },
error => { error => {
this.handleError(error); this.handleError(error);
// reject(error); // reject(error);
resolve(null); resolve(null);
} }
); );
}); });
}); });
} }
@ -335,14 +341,14 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
this.formService this.formService
.getFormDefinitionById(formId) .getFormDefinitionById(formId)
.subscribe( .subscribe(
form => { form => {
this.formName = form.name; this.formName = form.name;
this.form = this.parseForm(form); this.form = this.parseForm(form);
this.onFormLoaded(this.form); this.onFormLoaded(this.form);
}, },
(error) => { (error) => {
this.handleError(error); this.handleError(error);
} }
); );
} }
@ -350,20 +356,20 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
this.formService this.formService
.getFormDefinitionByName(formName) .getFormDefinitionByName(formName)
.subscribe( .subscribe(
id => { id => {
this.formService.getFormDefinitionById(id).subscribe( this.formService.getFormDefinitionById(id).subscribe(
form => { form => {
this.form = this.parseForm(form); this.form = this.parseForm(form);
this.onFormLoaded(this.form); this.onFormLoaded(this.form);
}, },
(error) => { (error) => {
this.handleError(error); this.handleError(error);
} }
); );
}, },
(error) => { (error) => {
this.handleError(error); this.handleError(error);
} }
); );
} }
@ -372,11 +378,11 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
this.formService this.formService
.saveTaskForm(this.form.taskId, this.form.values) .saveTaskForm(this.form.taskId, this.form.values)
.subscribe( .subscribe(
() => { () => {
this.onTaskSaved(this.form); this.onTaskSaved(this.form);
this.storeFormAsMetadata(); this.storeFormAsMetadata();
}, },
error => this.onTaskSavedError(this.form, error) error => this.onTaskSavedError(this.form, error)
); );
} }
} }
@ -386,11 +392,11 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
this.formService this.formService
.completeTaskForm(this.form.taskId, this.form.values, outcome) .completeTaskForm(this.form.taskId, this.form.values, outcome)
.subscribe( .subscribe(
() => { () => {
this.onTaskCompleted(this.form); this.onTaskCompleted(this.form);
this.storeFormAsMetadata(); this.storeFormAsMetadata();
}, },
error => this.onTaskCompletedError(this.form, error) error => this.onTaskCompletedError(this.form, error)
); );
} }
} }
@ -435,9 +441,9 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
private loadFormForEcmNode(nodeId: string): void { private loadFormForEcmNode(nodeId: string): void {
this.nodeService.getNodeMetadata(nodeId).subscribe(data => { this.nodeService.getNodeMetadata(nodeId).subscribe(data => {
this.data = data.metadata; this.data = data.metadata;
this.loadFormFromActiviti(data.nodeType); this.loadFormFromActiviti(data.nodeType);
}, },
this.handleError); this.handleError);
} }
@ -466,8 +472,8 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
private storeFormAsMetadata() { private storeFormAsMetadata() {
if (this.saveMetadata) { if (this.saveMetadata) {
this.ecmModelService.createEcmTypeForActivitiForm(this.formName, this.form).subscribe(type => { this.ecmModelService.createEcmTypeForActivitiForm(this.formName, this.form).subscribe(type => {
this.nodeService.createNodeMetadata(type.nodeType || type.entry.prefixedName, EcmModelService.MODEL_NAMESPACE, this.form.values, this.path, this.nameNode); this.nodeService.createNodeMetadata(type.nodeType || type.entry.prefixedName, EcmModelService.MODEL_NAMESPACE, this.form.values, this.path, this.nameNode);
}, },
(error) => { (error) => {
this.handleError(error); this.handleError(error);
} }

View File

@ -36,13 +36,14 @@
</div> </div>
</div> </div>
</div> </div>
<div *ngIf="isAssignedToMe()"> <div *ngIf="isAssigned()">
<adf-form *ngIf="hasFormKey()" #activitiForm <adf-form *ngIf="hasFormKey()" #activitiForm
[showDebugButton]="debugMode" [showDebugButton]="debugMode"
[taskId]="taskDetails.id" [taskId]="taskDetails.id"
[showTitle]="showFormTitle" [showTitle]="showFormTitle"
[showRefreshButton]="showFormRefreshButton" [showRefreshButton]="showFormRefreshButton"
[showCompleteButton]="showFormCompleteButton" [showCompleteButton]="showFormCompleteButton"
[disableCompleteButton]="!isAssignedToMe()"
[showSaveButton]="showFormSaveButton" [showSaveButton]="showFormSaveButton"
[readOnly]="readOnlyForm" [readOnly]="readOnlyForm"
(formSaved)='onFormSaved($event)' (formSaved)='onFormSaved($event)'
@ -53,7 +54,7 @@
(executeOutcome)='onFormExecuteOutcome($event)'> (executeOutcome)='onFormExecuteOutcome($event)'>
</adf-form> </adf-form>
</div> </div>
<div *ngIf="!isAssignedToMe()"> <div *ngIf="!isAssigned()">
{{ 'TASK_DETAILS.MESSAGES.CLAIM' | translate }} {{ 'TASK_DETAILS.MESSAGES.CLAIM' | translate }}
</div> </div>
<button md-raised-button class="activiti-task-details__action-button" *ngIf="!hasFormKey() && isTaskActive()" (click)="onComplete()"> <button md-raised-button class="activiti-task-details__action-button" *ngIf="!hasFormKey() && isTaskActive()" (click)="onComplete()">

View File

@ -27,7 +27,7 @@ import { Component,
ViewChild ViewChild
} from '@angular/core'; } from '@angular/core';
import { ContentLinkModel, FormModel, FormOutcomeEvent, FormService } from 'ng2-activiti-form'; import { ContentLinkModel, FormModel, FormOutcomeEvent, FormService } from 'ng2-activiti-form';
import { AlfrescoTranslationService, LogService } from 'ng2-alfresco-core'; import { AlfrescoAuthenticationService, AlfrescoTranslationService, LogService } from 'ng2-alfresco-core';
import { TaskQueryRequestRepresentationModel } from '../models/filter.model'; import { TaskQueryRequestRepresentationModel } from '../models/filter.model';
import { TaskDetailsModel } from '../models/task-details.model'; import { TaskDetailsModel } from '../models/task-details.model';
import { User } from '../models/user.model'; import { User } from '../models/user.model';
@ -141,7 +141,8 @@ export class ActivitiTaskDetails implements OnInit, OnChanges {
constructor(private translateService: AlfrescoTranslationService, constructor(private translateService: AlfrescoTranslationService,
private activitiForm: FormService, private activitiForm: FormService,
private activitiTaskList: ActivitiTaskListService, private activitiTaskList: ActivitiTaskListService,
private logService: LogService) { private logService: LogService,
private authService: AlfrescoAuthenticationService) {
if (translateService) { if (translateService) {
translateService.addTranslationFolder('ng2-activiti-tasklist', 'assets/ng2-activiti-tasklist'); translateService.addTranslationFolder('ng2-activiti-tasklist', 'assets/ng2-activiti-tasklist');
@ -212,10 +213,14 @@ export class ActivitiTaskDetails implements OnInit, OnChanges {
} }
} }
isAssignedToMe(): boolean { isAssigned(): boolean {
return this.taskDetails.assignee ? true : false; return this.taskDetails.assignee ? true : false;
} }
isAssignedToMe(): boolean {
return this.taskDetails.assignee.email === this.authService.getBpmUsername() ? true : false;
}
/** /**
* Retrieve the next open task * Retrieve the next open task
* @param processInstanceId * @param processInstanceId

View File

@ -24,7 +24,7 @@ describe('NoTaskDetailsTemplateComponent', () => {
let detailsComponent: ActivitiTaskDetails; let detailsComponent: ActivitiTaskDetails;
beforeEach(() => { beforeEach(() => {
detailsComponent = new ActivitiTaskDetails(null, null, null, null); detailsComponent = new ActivitiTaskDetails(null, null, null, null, null);
component = new NoTaskDetailsTemplateComponent(detailsComponent); component = new NoTaskDetailsTemplateComponent(detailsComponent);
}); });