[ADF-3237] Change and remove form from a task (#3597)

* button added for task standalone

* rebase fixed

* review fix

* test added & fixes

* refresh task details

* change and remove form added

* localize & documentation work

* tests added

* tests fixes

* tests fixes
This commit is contained in:
bbcodrin 2018-07-18 12:14:54 +03:00 committed by Eugenio Romano
parent c6c573bcfb
commit 54380fd693
13 changed files with 160 additions and 65 deletions

View File

@ -33,3 +33,4 @@ This component can be used when there is no form attached to a task.
| -- | -- | -- |
| cancel | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<void>` | Emitted when the "Cancel" button is clicked. |
| complete | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<void>` | Emitted when the form associated with the task is completed. |
| showAttachForm | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<void>` | Emitted when the "Show Form" button is clicked. |

View File

@ -154,7 +154,9 @@
"COMPLETE_TASK_SUB_MESSAGE": "No forms to be added"
},
"ATTACH_FORM":{
"SELECT_FORM": "Select Form To Attach"
"SELECT_FORM": "Select Form To Attach",
"REMOVE_FORM": "Remove Form",
"SELECT_OPTION": "Please select option"
}
},
"ADF_PROCESS_LIST": {

View File

@ -7,24 +7,30 @@
</mat-card-title>
<div class="adf-attach-form-row">
<mat-form-field class="adf-grid-full-width">
<mat-select id="form_id" [(ngModel)]="formKey">
<mat-select placeholder="{{ 'ADF_TASK_LIST.ATTACH_FORM.SELECT_OPTION' | translate }}" id="form_id" [(ngModel)]="formId">
<mat-option *ngFor="let form of forms" [value]="form.id">{{ form.name }}</mat-option>
</mat-select>
</mat-form-field>
</div>
<adf-form
[formId]="formKey"
[formId]="formId"
[readOnly]="true"
[disableCompleteButton]="true"
[showRefreshButton]="false">
[showCompleteButton]="false"
[showRefreshButton]="false"
[showValidationIcon]="false">
</adf-form>
</div>
</mat-card-content>
<mat-card-actions class="adf-no-form-mat-card-actions">
<button mat-button id="adf-no-form-cancel-button" (click)="onCancelButtonClick()">{{ 'ADF_TASK_LIST.START_TASK.FORM.ACTION.CANCEL' | translate }}</button>
<button mat-button id="adf-no-form-attach-form-button" color="primary" (click)="onAttachFormButtonClick()">{{ 'ADF_TASK_LIST.START_TASK.FORM.LABEL.ATTACHFORM' | translate }}</button>
<div>
<button mat-button id="adf-no-form-remove-button" color="warn" *ngIf="formKey" (click)="onRemoveButtonClick()">{{ 'ADF_TASK_LIST.ATTACH_FORM.REMOVE_FORM' | translate }}</button>
</div>
<div>
<button mat-button id="adf-no-form-cancel-button" (click)="onCancelButtonClick()">{{ 'ADF_TASK_LIST.START_TASK.FORM.ACTION.CANCEL' | translate }}</button>
<button mat-button id="adf-no-form-attach-form-button" color="primary" (click)="onAttachFormButtonClick()">{{ 'ADF_TASK_LIST.START_TASK.FORM.LABEL.ATTACHFORM' | translate }}</button>
</div>
</mat-card-actions>
</mat-card>
</div>

View File

@ -10,7 +10,7 @@
}
.adf-no-form-mat-card-actions {
justify-content: flex-end;
justify-content: space-between;
margin-top: 30px;
text-align: right;
}

View File

@ -54,7 +54,7 @@ describe('AttachFormComponent', () => {
it('should call attachFormToATask if clicked on Complete Button', async(() => {
component.taskId = 1;
component.formKey = 2;
component.formId = 2;
spyOn(taskService, 'attachFormToATask').and.returnValue(Observable.of(true));
fixture.detectChanges();
fixture.whenStable().then(() => {
@ -75,4 +75,52 @@ describe('AttachFormComponent', () => {
expect(formContainer).not.toBeNull();
});
}));
it('should show the formPreview of the selected form', async(() => {
component.formKey = 12;
fixture.detectChanges();
const formContainer = fixture.debugElement.nativeElement.querySelector('.adf-form-container');
fixture.whenStable().then(() => {
expect(formContainer).toBeDefined();
expect(formContainer).toBeNull();
});
}));
it('should remove form if it is present', (done) => {
component.taskId = 1;
component.formId = 10;
component.formKey = 12;
spyOn(taskService, 'deleteForm').and.returnValue(Observable.of({}));
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('#adf-no-form-remove-button')).toBeDefined();
const el = fixture.nativeElement.querySelector('#adf-no-form-remove-button');
el.click();
expect(component.formId).toBeNull();
done();
});
});
it('should emit success when form is changed', async(() => {
component.taskId = 1;
component.formId = 10;
spyOn(taskService, 'attachFormToATask').and.returnValue(Observable.of(
{
id: 91,
name: 'fakeName',
formKey: 1204,
assignee: null
}
));
fixture.detectChanges();
fixture.whenStable().then(() => {
const emitSpy = spyOn(component.success, 'emit');
const el = fixture.nativeElement.querySelector('#adf-no-form-attach-form-button');
el.click();
expect(emitSpy).toHaveBeenCalled();
});
}));
});

View File

@ -15,8 +15,8 @@
* limitations under the License.
*/
import { LogService } from '@alfresco/adf-core';
import { Component, EventEmitter, Input, OnInit, OnChanges, Output } from '@angular/core';
import { FormService, LogService } from '@alfresco/adf-core';
import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';
import { Form } from '../models/form.model';
import { TaskListService } from './../services/tasklist.service';
@ -26,44 +26,53 @@ import { TaskListService } from './../services/tasklist.service';
styleUrls: ['./attach-form.component.scss']
})
export class AttachFormComponent implements OnInit, OnChanges {
export class AttachFormComponent implements OnChanges {
constructor(private taskService: TaskListService,
private logService: LogService) { }
private logService: LogService,
private formService: FormService) { }
/** The id of the task whose details we are asking for. */
@Input()
taskId;
/** Emitted when the "Cancel" button is clicked. */
@Input()
formKey;
@Output()
cancelAttachForm: EventEmitter<void> = new EventEmitter<void>();
/** Emitted when the form associated with the form task is attached. */
@Output()
completeAttachForm: EventEmitter<void> = new EventEmitter<void>();
success: EventEmitter<void> = new EventEmitter<void>();
/** Emitted when an error occurs. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
forms: Form[];
formKey: number;
ngOnInit() {
this.loadFormsTask();
}
formId: number;
ngOnChanges() {
this.loadFormsTask();
this.onFormAttached();
}
onCancelButtonClick(): void {
this.cancelAttachForm.emit();
}
onRemoveButtonClick(): void {
this.taskService.deleteForm(this.taskId).subscribe(
() => {
this.formId = null;
this.success.emit();
},
(err) => {
this.error.emit(err);
this.logService.error('An error occurred while trying to delete the form');
});
}
onAttachFormButtonClick(): void {
this.attachForm(this.taskId, this.formKey);
this.attachForm(this.taskId, this.formId);
}
private loadFormsTask(): void {
@ -76,11 +85,26 @@ export class AttachFormComponent implements OnInit, OnChanges {
});
}
private attachForm(taskId: string, formKey: number) {
if (taskId && formKey) {
this.taskService.attachFormToATask(taskId, formKey)
.subscribe((res) => {
this.completeAttachForm.emit();
private onFormAttached() {
this.formService.getTaskForm(this.taskId)
.subscribe((res) => {
this.formService.getFormDefinitionByName(res.name).subscribe((formDef) => {
this.formId = formDef;
});
}, (err) => {
this.error.emit(err);
this.logService.error('Could not load forms');
});
}
private attachForm(taskId: string, formId: number) {
if (taskId && formId) {
this.taskService.attachFormToATask(taskId, formId)
.subscribe(() => {
this.success.emit();
}, (err) => {
this.error.emit(err);
this.logService.error('Could not attach form');
});
}
}

View File

@ -22,7 +22,7 @@
<div class="adf-task-details-core-form">
<div *ngIf="isAssigned()">
<adf-form *ngIf="hasFormKey()" #activitiForm
<adf-form *ngIf="hasFormKey() && !showAttachForm" #activitiForm
[showDebugButton]="debugMode"
[taskId]="taskDetails.id"
[showTitle]="showFormTitle"
@ -39,15 +39,21 @@
(error)='onFormError($event)'
(executeOutcome)='onFormExecuteOutcome($event)'>
</adf-form>
<adf-task-standalone *ngIf="!hasFormKey()"
[taskName]= "taskDetails.name"
[taskId]= "taskDetails.id"
<adf-task-standalone *ngIf="!hasFormKey() && !showAttachForm"
[taskName]="taskDetails.name"
[taskId]="taskDetails.id"
[isCompleted]="isCompletedTask()"
[hasCompletePermission]="isCompleteButtonEnabled()"
[hideCancelButton]="true"
(complete)="onComplete()"
(formAttached)="onFormAttached()">
(showAttachForm)="onShowAttachForm()">
</adf-task-standalone>
<adf-attach-form *ngIf="showAttachForm"
[taskId]="taskDetails.id"
[formKey]="taskDetails.formKey"
(cancelAttachForm)="onCancelAttachForm()"
(success)="onCompleteAttachForm()">
</adf-attach-form>
</div>
<div *ngIf="!isAssigned()" id="claim-message-id">
{{ 'ADF_TASK_LIST.DETAILS.MESSAGES.CLAIM' | translate }}

View File

@ -21,7 +21,6 @@ import {
CardViewUpdateService,
ClickNotification,
LogService,
FormService,
UpdateNotification,
FormRenderingService,
CommentsComponent
@ -97,7 +96,7 @@ export class TaskDetailsComponent implements OnInit, OnChanges {
/** Toggles rendering of the form title. */
@Input()
showFormTitle: boolean = true;
showFormTitle: boolean = false;
/** Toggles rendering of the `Complete` outcome button. */
@Input()
@ -175,6 +174,7 @@ export class TaskDetailsComponent implements OnInit, OnChanges {
noTaskDetailsTemplateComponent: TemplateRef<any>;
showAssignee: boolean = false;
showAttachForm: boolean = false;
private peopleSearchObserver: Observer<UserProcessModel[]>;
public errorDialogRef: MatDialogRef<TemplateRef<any>>;
@ -187,7 +187,6 @@ export class TaskDetailsComponent implements OnInit, OnChanges {
private authService: AuthenticationService,
private peopleProcessService: PeopleProcessService,
private formRenderingService: FormRenderingService,
private formService: FormService,
private logService: LogService,
private cardViewUpdateService: CardViewUpdateService,
private dialog: MatDialog) {
@ -259,6 +258,9 @@ export class TaskDetailsComponent implements OnInit, OnChanges {
if (clickNotification.target.key === 'assignee') {
this.showAssignee = true;
}
if (clickNotification.target.key === 'formName') {
this.showAttachForm = true;
}
}
/**
@ -290,7 +292,7 @@ export class TaskDetailsComponent implements OnInit, OnChanges {
}
isAssigned(): boolean {
return this.taskDetails.assignee ? true : false;
return !!this.taskDetails.assignee;
}
private hasEmailAddress(): boolean {
@ -364,11 +366,17 @@ export class TaskDetailsComponent implements OnInit, OnChanges {
);
}
onFormAttached() {
this.formService.getTaskForm(this.taskId)
.subscribe((res) => {
this.loadDetails(this.taskId);
}, error => this.logService.error('Could not load forms'));
onShowAttachForm() {
this.showAttachForm = true;
}
onCancelAttachForm() {
this.showAttachForm = false;
}
onCompleteAttachForm() {
this.showAttachForm = false;
this.loadDetails(this.taskId);
}
onFormContentClick(content: ContentLinkModel): void {

View File

@ -301,7 +301,7 @@ describe('TaskHeaderComponent', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-formName"] .adf-property-value'));
let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-formName"] .adf-textitem-clickable-value'));
expect(valueEl.nativeElement.innerText).toBe('test form');
});
}));

View File

@ -153,7 +153,9 @@ export class TaskHeaderComponent implements OnChanges, OnInit {
label: 'ADF_TASK_LIST.PROPERTIES.FORM_NAME',
value: this.formName,
key: 'formName',
default: this.translationService.instant('ADF_TASK_LIST.PROPERTIES.FORM_NAME_DEFAULT')
default: this.translationService.instant('ADF_TASK_LIST.PROPERTIES.FORM_NAME_DEFAULT'),
clickable: !!this.formName,
icon: 'create'
}
)
];

View File

@ -1,4 +1,4 @@
<mat-card class="adf-message-card" *ngIf="!showAttachForm">
<mat-card class="adf-message-card">
<mat-card-content>
<div class="adf-no-form-message-container">
<div class="adf-no-form-message-list">
@ -25,9 +25,3 @@
</div>
</mat-card-actions>
</mat-card>
<adf-attach-form *ngIf="showAttachForm"
[taskId]="taskId"
(cancelAttachForm)="onCancelAttachForm()"
(completeAttachForm)="onCompleteAttachForm()">
</adf-attach-form>

View File

@ -54,10 +54,9 @@ export class TaskStandaloneComponent {
@Output()
complete: EventEmitter<void> = new EventEmitter<void>();
/** Emitted when the form associated with the form task is attached. */
@Output()
formAttached: EventEmitter<void> = new EventEmitter<void>();
showAttachForm: boolean = false;
showAttachForm: EventEmitter<void> = new EventEmitter<void>();
constructor() { }
@ -82,15 +81,6 @@ export class TaskStandaloneComponent {
}
onShowAttachForm() {
this.showAttachForm = true;
}
onCancelAttachForm() {
this.showAttachForm = false;
}
onCompleteAttachForm() {
this.showAttachForm = false;
this.formAttached.emit();
this.showAttachForm.emit();
}
}

View File

@ -219,6 +219,16 @@ export class TaskListService {
.catch(err => this.handleError(err));
}
/**
* Deletes a form from a task.
* @param taskId Task id related to form
* @returns Null response notifying when the operation is complete
*/
deleteForm(taskId: string): Observable<TaskDetailsModel> {
return Observable.fromPromise(this.callApiDeleteForm(taskId))
.catch(err => this.handleError(err));
}
/**
* Gives completed status to a task.
* @param taskId ID of the target task
@ -353,6 +363,10 @@ export class TaskListService {
return this.apiService.taskApi.deleteTask(taskId);
}
private callApiDeleteForm(taskId: string) {
return this.apiService.taskApi.removeForm(taskId);
}
private callApiTaskChecklist(taskId: string) {
return this.apiService.taskApi.getChecklist(taskId);
}