mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ADF-3282] Refactor Start Task Component (#4012)
* [ADF-3282] Refactor Start Task Component * [ADF-3282] Fix e2e test * [ADF-3282] Remove maxTaskNameLength from start task doc
This commit is contained in:
committed by
Eugenio Romano
parent
ca5543c48d
commit
49738ad555
@@ -497,6 +497,9 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"adf-start-task": {
|
||||
"name": "My Task Name"
|
||||
},
|
||||
"adf-task-list": {
|
||||
"presets": {
|
||||
"default": [
|
||||
|
@@ -104,6 +104,7 @@
|
||||
<div class="adf-grid-item adf-tasks-start" *ngIf="isStartTaskMode()" fxFlex.gt-md="1 1 auto">
|
||||
<adf-start-task
|
||||
[appId]="appId"
|
||||
[name]="defaultTaskName"
|
||||
(success)="onStartTaskSuccess($event)"
|
||||
(cancel)="onCancelStartTask()">
|
||||
</adf-start-task>
|
||||
|
@@ -137,6 +137,7 @@ export class ProcessServiceComponent implements AfterViewInit, OnDestroy, OnInit
|
||||
|
||||
defaultProcessDefinitionName: string;
|
||||
defaultProcessName: string;
|
||||
defaultTaskName: string;
|
||||
|
||||
activeTab: number = this.tabs.tasks; // tasks|processes|reports
|
||||
|
||||
@@ -175,6 +176,7 @@ export class ProcessServiceComponent implements AfterViewInit, OnDestroy, OnInit
|
||||
|
||||
this.defaultProcessName = this.appConfig.get<string>('adf-start-process.name');
|
||||
this.defaultProcessDefinitionName = this.appConfig.get<string>('adf-start-process.processDefinitionName');
|
||||
this.defaultTaskName = this.appConfig.get<string>('adf-start-task.name');
|
||||
|
||||
// Uncomment this line to replace all 'text' field editors with custom component
|
||||
// formRenderingService.setComponentTypeResolver('text', () => CustomEditorComponent, true);
|
||||
|
@@ -15,7 +15,8 @@ Creates/Starts a new task for the specified app
|
||||
|
||||
```html
|
||||
<adf-start-task
|
||||
[appId]="YOUR_APP_ID">
|
||||
[appId]="YOUR_APP_ID"
|
||||
[name]="My Task Name">
|
||||
</adf-start-task>
|
||||
```
|
||||
|
||||
@@ -26,6 +27,7 @@ Creates/Starts a new task for the specified app
|
||||
| Name | Type | Default value | Description |
|
||||
| ---- | ---- | ------------- | ----------- |
|
||||
| appId | `number` | | (required) The id of the app. |
|
||||
| name | `string` | | Default Task Name |
|
||||
|
||||
### Events
|
||||
|
||||
|
@@ -31,6 +31,7 @@ var StartTaskDialog = function () {
|
||||
|
||||
this.addName = function (userName) {
|
||||
Util.waitUntilElementIsVisible(name);
|
||||
name.clear();
|
||||
name.sendKeys(userName);
|
||||
return this;
|
||||
};
|
||||
|
@@ -114,6 +114,7 @@
|
||||
}
|
||||
},
|
||||
"START_TASK": {
|
||||
"DEFAULT_NAME": "My Default Task",
|
||||
"BUTTON": "CREATE TASK",
|
||||
"FORM": {
|
||||
"TITLE": "Start Task",
|
||||
@@ -130,8 +131,10 @@
|
||||
"START": "Start",
|
||||
"CANCEL": "Cancel"
|
||||
},
|
||||
"DATE": {
|
||||
"ERROR": "Date format DD/MM/YYYY"
|
||||
"ERROR": {
|
||||
"REQUIRED": "Field required",
|
||||
"DATE": "Date format DD/MM/YYYY",
|
||||
"MAXIMUM_LENGTH": "Length exceeded, {{characters}} characters max."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@@ -1,93 +1,95 @@
|
||||
<mat-card class="adf-new-task-layout-card">
|
||||
<mat-grid-list cols="1" rowHeight="60px">
|
||||
<mat-grid-tile>
|
||||
<div class="adf-new-task-heading">{{'ADF_TASK_LIST.START_TASK.FORM.TITLE'|translate}}</div>
|
||||
</mat-grid-tile>
|
||||
</mat-grid-list>
|
||||
<mat-card fxFlex="70%" class="adf-new-task-layout-card">
|
||||
<mat-card-header fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="10px" class="adf-new-task-heading">
|
||||
<mat-card-title>{{'ADF_TASK_LIST.START_TASK.FORM.TITLE' | translate}}</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<div class="adf-new-task-layout-card-content">
|
||||
<div class="adf-grid-full-width adf-grid-row">
|
||||
<mat-form-field class="adf-grid-full-width adf-grid-column">
|
||||
<input matInput
|
||||
class="adf-grid-full-width"
|
||||
placeholder="{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.NAME'|translate}}"
|
||||
[(ngModel)]="startTaskModel.name"
|
||||
required
|
||||
id="name_id">
|
||||
<form [formGroup]="taskForm" fxLayout="column" fxLayoutGap="10px">
|
||||
<div class="adf-task-name">
|
||||
<mat-form-field fxFlex>
|
||||
<mat-label>{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.NAME' | translate}}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
id="name_id"
|
||||
formControlName="name">
|
||||
<mat-error *ngIf="nameController.hasError('required')">
|
||||
{{ 'ADF_TASK_LIST.START_TASK.FORM.ERROR.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="nameController.hasError('maxlength')">
|
||||
{{ 'ADF_TASK_LIST.START_TASK.FORM.ERROR.MAXIMUM_LENGTH' | translate : { characters : maxTaskNameLength } }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="adf-grid-full-width adf-grid-row">
|
||||
<mat-form-field class="adf-grid-full-width adf-grid-column">
|
||||
<div class="adf-task-description">
|
||||
<mat-form-field fxFlex>
|
||||
<mat-label>{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.DESCRIPTION' | translate}}</mat-label>
|
||||
<textarea
|
||||
matInput
|
||||
class="adf-grid-full-width"
|
||||
placeholder="{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.DESCRIPTION'|translate}}"
|
||||
[(ngModel)]="startTaskModel.description"
|
||||
rows="1"
|
||||
id="description_id">
|
||||
id="description_id"
|
||||
formControlName="description">
|
||||
</textarea>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="adf-grid-full-width adf-grid-row">
|
||||
<div class="adf-grid-column adf-grid-half-width">
|
||||
<div class="adf-grid-full-width adf-grid-row">
|
||||
<mat-form-field class="adf-grid-full-width">
|
||||
<input matInput
|
||||
[matDatepicker]="taskDatePicker"
|
||||
(keydown)="true"
|
||||
(keyup)="onDateChanged($event.srcElement.value)"
|
||||
(dateInput)="onDateChanged($event.value)"
|
||||
placeholder="{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.DATE'|translate}}"
|
||||
[(ngModel)]="startTaskModel.dueDate"
|
||||
id="date_id">
|
||||
<mat-datepicker-toggle matSuffix [for]="taskDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #taskDatePicker
|
||||
[touchUi]="true"
|
||||
(dateChanged)="onDateChanged($event)"
|
||||
(opened)="clearDateInput()">
|
||||
</mat-datepicker>
|
||||
<div class="adf-error-text-container">
|
||||
<div *ngIf="dateError">
|
||||
<div class="adf-error-text">{{'ADF_TASK_LIST.START_TASK.FORM.DATE.ERROR'|translate}}</div>
|
||||
<mat-icon class="adf-error-icon">warning</mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
</mat-form-field>
|
||||
<div class="input-row" fxLayout="row" fxLayout.lt-md="column" fxLayoutGap="20px" fxLayoutGap.lt-md="0px">
|
||||
<mat-form-field fxFlex>
|
||||
<input
|
||||
matInput
|
||||
(keyup)="onDateChanged($event.srcElement.value)"
|
||||
(dateInput)="onDateChanged($event.value)"
|
||||
[matDatepicker]="taskDatePicker"
|
||||
placeholder="{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.DATE'|translate}}"
|
||||
id="date_id">
|
||||
<mat-datepicker-toggle
|
||||
matSuffix
|
||||
[for]="taskDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker
|
||||
#taskDatePicker
|
||||
[touchUi]="true">
|
||||
</mat-datepicker>
|
||||
<div class="adf-error-text-container">
|
||||
<div *ngIf="dateError">
|
||||
<div class="adf-error-text">{{'ADF_TASK_LIST.START_TASK.FORM.ERROR.DATE'|translate}}</div>
|
||||
<mat-icon class="adf-error-icon">warning</mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="adf-grid-full-width adf-grid-row">
|
||||
<mat-form-field class="adf-grid-full-width">
|
||||
<mat-select placeholder="{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.FORM'|translate}}" id="form_id" [(ngModel)]="formKey">
|
||||
<mat-option>{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.NONE'|translate}}</mat-option>
|
||||
<mat-option *ngFor="let form of forms" [value]="form.id">{{ form.name }}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="adf-grid-column adf-grid-half-width">
|
||||
</mat-form-field>
|
||||
<div fxFlex>
|
||||
<people-widget
|
||||
(peopleSelected)="getAssigneeId($event)"
|
||||
[field]="field"
|
||||
class="adf-people-widget-content"></people-widget>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="adf-task-form">
|
||||
<mat-form-field fxFlex="48%" fxFlex.xs="100%">
|
||||
<mat-label id="form_label">{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.FORM'|translate}}</mat-label>
|
||||
<mat-select
|
||||
id="form_id"
|
||||
class="form-control"
|
||||
formControlName="formKey">
|
||||
<mat-option>{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.NONE'|translate}}</mat-option>
|
||||
<mat-option *ngFor="let form of forms$ | async" [value]="form.id">{{ form.name }}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</form>
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
<mat-grid-list cols="1" rowHeight="60px">
|
||||
<mat-grid-tile>
|
||||
<div class="adf-new-task-footer">
|
||||
<button mat-button (click)="onCancel()" id="button-cancel">
|
||||
{{'ADF_TASK_LIST.START_TASK.FORM.ACTION.CANCEL'|translate}}
|
||||
</button>
|
||||
<button color="primary" mat-button [disabled]="!startTaskModel.name || dateError" (click)="start()" id="button-start">
|
||||
{{'ADF_TASK_LIST.START_TASK.FORM.ACTION.START'|translate}}
|
||||
</button>
|
||||
</div>
|
||||
</mat-grid-tile>
|
||||
</mat-grid-list>
|
||||
<div class="adf-new-task-footer" fxLayout="row" fxLayoutAlign="end end">
|
||||
<button
|
||||
mat-button
|
||||
(click)="onCancel()"
|
||||
id="button-cancel">
|
||||
{{'ADF_TASK_LIST.START_TASK.FORM.ACTION.CANCEL'|translate}}
|
||||
</button>
|
||||
<button
|
||||
color="primary"
|
||||
mat-button
|
||||
[disabled]="!isFormValid()"
|
||||
(click)="saveTask()"
|
||||
id="button-start">
|
||||
{{'ADF_TASK_LIST.START_TASK.FORM.ACTION.START'|translate}}
|
||||
</button>
|
||||
</div>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
|
||||
|
@@ -6,56 +6,26 @@
|
||||
$header-border: 1px solid mat-color($foreground, divider);
|
||||
|
||||
.adf-new-task-heading {
|
||||
padding: 12px 20px;
|
||||
font-weight: bold;
|
||||
padding-top: 12px;
|
||||
border-bottom: $header-border;
|
||||
font-size: 18px;
|
||||
float: left;
|
||||
text-align: left;
|
||||
width: calc(100% - 40px);
|
||||
.mat-card-title {
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.adf-new-task-form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.adf-new-task-layout-card {
|
||||
|
||||
width: 66%;
|
||||
margin: 10px auto;
|
||||
|
||||
&-content {
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
|
||||
.adf-grid-row {
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.adf-grid-column {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
}
|
||||
|
||||
.adf-grid-full-width {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.adf-grid-half-width {
|
||||
width: 49%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.adf-new-task-footer {
|
||||
padding: 4px;
|
||||
font-size: 18px;
|
||||
border-top: 1px solid #eee;
|
||||
float: left;
|
||||
width: calc(100% - 40px);
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.adf-mat-select {
|
||||
@@ -154,11 +124,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.adf-new-task-layout-card {
|
||||
width: 90%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
|
@@ -16,33 +16,36 @@
|
||||
*/
|
||||
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { setupTestBed } from '@alfresco/adf-core';
|
||||
import { Observable, of, throwError } from 'rxjs';
|
||||
import { startTaskMock } from '../../mock';
|
||||
import { StartTaskModel } from '../models/start-task.model';
|
||||
import { setupTestBed, LogService } from '@alfresco/adf-core';
|
||||
import { of, throwError, Observable } from 'rxjs';
|
||||
import { TaskListService } from '../services/tasklist.service';
|
||||
import { StartTaskComponent } from './start-task.component';
|
||||
import { ProcessTestingModule } from '../../testing/process.testing.module';
|
||||
import { taskDetailsMock } from '../../mock/task/task-details.mock';
|
||||
import { TaskDetailsModel } from '../models/task-details.model';
|
||||
|
||||
describe('StartTaskComponent', () => {
|
||||
|
||||
let component: StartTaskComponent;
|
||||
let fixture: ComponentFixture<StartTaskComponent>;
|
||||
let service: TaskListService;
|
||||
let logService: LogService;
|
||||
let element: HTMLElement;
|
||||
let getFormListSpy: jasmine.Spy;
|
||||
let createNewTaskSpy: jasmine.Spy;
|
||||
let fakeForms = [
|
||||
let logSpy: jasmine.Spy;
|
||||
let fakeForms$ = [
|
||||
{
|
||||
id: 123,
|
||||
name: 'Display Data'
|
||||
name: 'Display Data'
|
||||
},
|
||||
{
|
||||
{
|
||||
id: 1111,
|
||||
name: 'Employee Info'
|
||||
name: 'Employee Info'
|
||||
}
|
||||
];
|
||||
let testUser = {id: 1001, firstName: 'fakeName', email: 'fake@app.activiti.com'};
|
||||
|
||||
let testUser = { id: 1001, firstName: 'fakeName', email: 'fake@app.activiti.com' };
|
||||
|
||||
setupTestBed({
|
||||
imports: [ProcessTestingModule]
|
||||
@@ -54,21 +57,28 @@ describe('StartTaskComponent', () => {
|
||||
element = fixture.nativeElement;
|
||||
|
||||
service = TestBed.get(TaskListService);
|
||||
getFormListSpy = spyOn(service, 'getFormList').and.returnValue(of(fakeForms));
|
||||
logService = TestBed.get(LogService);
|
||||
getFormListSpy = spyOn(service, 'getFormList').and.returnValue(new Observable((observer) => {
|
||||
observer.next(fakeForms$);
|
||||
observer.complete();
|
||||
}));
|
||||
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
TestBed.resetTestingModule();
|
||||
});
|
||||
|
||||
it('should create instance of StartTaskComponent', () => {
|
||||
expect(fixture.componentInstance instanceof StartTaskComponent).toBe(true, 'should create StartTaskComponent');
|
||||
expect(component instanceof StartTaskComponent).toBe(true, 'should create StartTaskComponent');
|
||||
});
|
||||
|
||||
it('should fetch fake form on init', () => {
|
||||
component.ngOnInit();
|
||||
expect(component.forms).toEqual(fakeForms);
|
||||
expect(component.forms[0].name).toEqual('Display Data');
|
||||
expect(component.forms[1].name).toEqual('Employee Info');
|
||||
expect(component.forms[1].id).toEqual(1111);
|
||||
fixture.detectChanges();
|
||||
expect(component.forms$).toBeDefined();
|
||||
expect(getFormListSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -87,8 +97,7 @@ describe('StartTaskComponent', () => {
|
||||
|
||||
it('should create new task when start is clicked', () => {
|
||||
let successSpy = spyOn(component.success, 'emit');
|
||||
component.appId = 42;
|
||||
component.startTaskModel = new StartTaskModel(startTaskMock);
|
||||
component.taskForm.controls['name'].setValue('task');
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
createTaskButton.click();
|
||||
@@ -97,8 +106,8 @@ describe('StartTaskComponent', () => {
|
||||
|
||||
it('should send on success event when the task is started', () => {
|
||||
let successSpy = spyOn(component.success, 'emit');
|
||||
component.appId = 42;
|
||||
component.startTaskModel = new StartTaskModel(startTaskMock);
|
||||
component.taskDetailsModel = new TaskDetailsModel(taskDetailsMock);
|
||||
component.taskForm.controls['name'].setValue('fakeName');
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
createTaskButton.click();
|
||||
@@ -113,7 +122,7 @@ describe('StartTaskComponent', () => {
|
||||
it('should send on success event when only name is given', () => {
|
||||
let successSpy = spyOn(component.success, 'emit');
|
||||
component.appId = 42;
|
||||
component.startTaskModel.name = 'fakeName';
|
||||
component.taskForm.controls['name'].setValue('fakeName');
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
createTaskButton.click();
|
||||
@@ -122,7 +131,7 @@ describe('StartTaskComponent', () => {
|
||||
|
||||
it('should not emit success event when data not present', () => {
|
||||
let successSpy = spyOn(component.success, 'emit');
|
||||
component.startTaskModel = new StartTaskModel(null);
|
||||
component.taskDetailsModel = new TaskDetailsModel(null);
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
createTaskButton.click();
|
||||
@@ -141,6 +150,9 @@ describe('StartTaskComponent', () => {
|
||||
assignee: null
|
||||
}
|
||||
));
|
||||
});
|
||||
|
||||
it('should attach form to the task when a form is selected', () => {
|
||||
spyOn(service, 'attachFormToATask').and.returnValue(of(
|
||||
{
|
||||
id: 91,
|
||||
@@ -149,13 +161,11 @@ describe('StartTaskComponent', () => {
|
||||
assignee: null
|
||||
}
|
||||
));
|
||||
});
|
||||
|
||||
it('should attach form to the task when a form is selected', () => {
|
||||
let successSpy = spyOn(component.success, 'emit');
|
||||
component.taskForm.controls['name'].setValue('fakeName');
|
||||
component.taskForm.controls['formKey'].setValue(1204);
|
||||
component.appId = 42;
|
||||
component.startTaskModel = new StartTaskModel(startTaskMock);
|
||||
component.formKey = '1204';
|
||||
component.taskDetailsModel = new TaskDetailsModel(taskDetailsMock);
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
createTaskButton.click();
|
||||
@@ -168,10 +178,19 @@ describe('StartTaskComponent', () => {
|
||||
});
|
||||
|
||||
it('should not attach form to the task when a no form is selected', () => {
|
||||
spyOn(service, 'attachFormToATask').and.returnValue(of(
|
||||
{
|
||||
id: 91,
|
||||
name: 'fakeName',
|
||||
formKey: null,
|
||||
assignee: null
|
||||
}
|
||||
));
|
||||
let successSpy = spyOn(component.success, 'emit');
|
||||
component.taskForm.controls['name'].setValue('fakeName');
|
||||
component.taskForm.controls['formKey'].setValue(null);
|
||||
component.appId = 42;
|
||||
component.startTaskModel = new StartTaskModel(startTaskMock);
|
||||
component.formKey = null;
|
||||
component.taskDetailsModel = new TaskDetailsModel(taskDetailsMock);
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
createTaskButton.click();
|
||||
@@ -214,9 +233,9 @@ describe('StartTaskComponent', () => {
|
||||
|
||||
it('should assign task when an assignee is selected', () => {
|
||||
let successSpy = spyOn(component.success, 'emit');
|
||||
component.taskForm.controls['name'].setValue('fakeName');
|
||||
component.taskForm.controls['formKey'].setValue(1204);
|
||||
component.appId = 42;
|
||||
component.startTaskModel = new StartTaskModel(startTaskMock);
|
||||
component.formKey = '1204';
|
||||
component.assigneeId = testUser.id;
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
@@ -229,12 +248,31 @@ describe('StartTaskComponent', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should assign task with id of selected user assigned', () => {
|
||||
let successSpy = spyOn(component.success, 'emit');
|
||||
component.taskDetailsModel = new TaskDetailsModel(taskDetailsMock);
|
||||
component.taskForm.controls['name'].setValue('fakeName');
|
||||
component.taskForm.controls['formKey'].setValue(1204);
|
||||
component.appId = 42;
|
||||
component.getAssigneeId(testUser.id);
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
createTaskButton.click();
|
||||
expect(successSpy).toHaveBeenCalledWith({
|
||||
id: 91,
|
||||
name: 'fakeName',
|
||||
formKey: 1204,
|
||||
assignee: testUser
|
||||
});
|
||||
});
|
||||
|
||||
it('should not assign task when no assignee is selected', () => {
|
||||
let successSpy = spyOn(component.success, 'emit');
|
||||
component.taskForm.controls['name'].setValue('fakeName');
|
||||
component.taskForm.controls['formKey'].setValue(1204);
|
||||
component.appId = 42;
|
||||
component.formKey = '1204';
|
||||
component.assigneeId = null;
|
||||
component.startTaskModel = new StartTaskModel(startTaskMock);
|
||||
component.taskDetailsModel = new TaskDetailsModel(taskDetailsMock);
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
createTaskButton.click();
|
||||
@@ -245,27 +283,10 @@ describe('StartTaskComponent', () => {
|
||||
assignee: null
|
||||
});
|
||||
});
|
||||
|
||||
it('should assign task with id of selected user assigned', () => {
|
||||
let successSpy = spyOn(component.success, 'emit');
|
||||
component.appId = 42;
|
||||
component.startTaskModel = new StartTaskModel(startTaskMock);
|
||||
component.formKey = '1204';
|
||||
component.getAssigneeId(testUser.id);
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
createTaskButton.click();
|
||||
expect(successSpy).toHaveBeenCalledWith({
|
||||
id: 91,
|
||||
name: 'fakeName',
|
||||
formKey: 1204,
|
||||
assignee: testUser
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not attach a form when a form id is not selected', () => {
|
||||
let attachFormToATask = spyOn(service, 'attachFormToATask').and.returnValue(of());
|
||||
let attachFormToATask = spyOn(service, 'attachFormToATask').and.returnValue([]);
|
||||
spyOn(service, 'createNewTask').and.callFake(
|
||||
function() {
|
||||
return new Observable((observer) => {
|
||||
@@ -273,14 +294,16 @@ describe('StartTaskComponent', () => {
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
component.taskForm.controls['name'].setValue('fakeName');
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
component.startTaskModel.name = 'fake-name';
|
||||
fixture.detectChanges();
|
||||
createTaskButton.click();
|
||||
expect(attachFormToATask).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should show start task button', () => {
|
||||
fixture.detectChanges();
|
||||
expect(element.querySelector('#button-start')).toBeDefined();
|
||||
expect(element.querySelector('#button-start')).not.toBeNull();
|
||||
expect(element.querySelector('#button-start').textContent).toContain('ADF_TASK_LIST.START_TASK.FORM.ACTION.START');
|
||||
@@ -294,16 +317,15 @@ describe('StartTaskComponent', () => {
|
||||
});
|
||||
|
||||
it('should disable start button if name is empty', () => {
|
||||
component.startTaskModel.name = '';
|
||||
component.taskForm.controls['name'].setValue('');
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = fixture.nativeElement.querySelector('#button-start');
|
||||
let createTaskButton = fixture.nativeElement.querySelector('#button-start');
|
||||
expect(createTaskButton.disabled).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should cancel start task on cancel button click', () => {
|
||||
let emitSpy = spyOn(component.cancel, 'emit');
|
||||
let cancelTaskButton = fixture.nativeElement.querySelector('#button-cancel');
|
||||
component.startTaskModel.name = '';
|
||||
let cancelTaskButton = <HTMLElement> element.querySelector('#button-cancel');
|
||||
fixture.detectChanges();
|
||||
cancelTaskButton.click();
|
||||
expect(emitSpy).not.toBeNull();
|
||||
@@ -311,24 +333,24 @@ describe('StartTaskComponent', () => {
|
||||
});
|
||||
|
||||
it('should enable start button if name is filled out', () => {
|
||||
component.startTaskModel.name = 'fakeName';
|
||||
component.taskForm.controls['name'].setValue('fakeName');
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = fixture.nativeElement.querySelector('#button-start');
|
||||
expect(createTaskButton.disabled).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should define the select option for Forms', () => {
|
||||
component.forms = fakeForms;
|
||||
it('should define the select options for Forms', () => {
|
||||
component.forms$ = service.getFormList();
|
||||
fixture.detectChanges();
|
||||
let selectElement = fixture.nativeElement.querySelector('#form_id');
|
||||
expect(selectElement.attributes['aria-label'].value).toContain('ADF_TASK_LIST.START_TASK.FORM.LABEL.FORM');
|
||||
let selectElement = fixture.nativeElement.querySelector('#form_label');
|
||||
expect(selectElement.innerHTML).toContain('ADF_TASK_LIST.START_TASK.FORM.LABEL.FORM');
|
||||
});
|
||||
|
||||
it('should get formatted full name', () => {
|
||||
let testUser1 = {'id': 1001, 'firstName': 'Wilbur', 'lastName': 'Adams', 'email': 'wilbur@app.activiti.com'};
|
||||
let testUser2 = {'id': 1002, 'firstName': '', 'lastName': 'Adams', 'email': 'adams@app.activiti.com'};
|
||||
let testUser3 = {'id': 1003, 'firstName': 'Wilbur', 'lastName': '', 'email': 'wilbur@app.activiti.com'};
|
||||
let testUser4 = {'id': 1004, 'firstName': '', 'lastName': '', 'email': 'test@app.activiti.com'};
|
||||
it('should get formatted fullname', () => {
|
||||
let testUser1 = { 'id': 1001, 'firstName': 'Wilbur', 'lastName': 'Adams', 'email': 'wilbur@app.activiti.com' };
|
||||
let testUser2 = { 'id': 1002, 'firstName': '', 'lastName': 'Adams', 'email': 'adams@app.activiti.com' };
|
||||
let testUser3 = { 'id': 1003, 'firstName': 'Wilbur', 'lastName': '', 'email': 'wilbur@app.activiti.com' };
|
||||
let testUser4 = { 'id': 1004, 'firstName': '', 'lastName': '', 'email': 'test@app.activiti.com' };
|
||||
|
||||
let testFullName1 = component.getDisplayUser(testUser1.firstName, testUser1.lastName, ' ');
|
||||
let testFullName2 = component.getDisplayUser(testUser2.firstName, testUser2.lastName, ' ');
|
||||
@@ -342,12 +364,44 @@ describe('StartTaskComponent', () => {
|
||||
});
|
||||
|
||||
it('should emit error when there is an error while creating task', () => {
|
||||
component.taskForm.controls['name'].setValue('fakeName');
|
||||
let errorSpy = spyOn(component.error, 'emit');
|
||||
spyOn(service, 'createNewTask').and.returnValue(throwError({}));
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
component.startTaskModel.name = 'fake-name';
|
||||
fixture.detectChanges();
|
||||
createTaskButton.click();
|
||||
expect(errorSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should emit error when task name exceeds maximum length', () => {
|
||||
component.maxTaskNameLength = 2;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
let name = component.taskForm.controls['name'];
|
||||
name.setValue('task');
|
||||
fixture.detectChanges();
|
||||
expect(name.valid).toBeFalsy();
|
||||
name.setValue('ta');
|
||||
fixture.detectChanges();
|
||||
expect(name.valid).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should emit error when task name field is empty', () => {
|
||||
fixture.detectChanges();
|
||||
let name = component.taskForm.controls['name'];
|
||||
name.setValue('');
|
||||
fixture.detectChanges();
|
||||
expect(name.valid).toBeFalsy();
|
||||
name.setValue('task');
|
||||
fixture.detectChanges();
|
||||
expect(name.valid).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should call logService when task name exceeds maximum length', () => {
|
||||
logSpy = spyOn(logService, 'log').and.callThrough();
|
||||
component.maxTaskNameLength = 300;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
expect(logSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
@@ -23,10 +23,10 @@ import moment from 'moment-es6';
|
||||
import { Moment } from 'moment';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { Form } from '../models/form.model';
|
||||
import { StartTaskModel } from '../models/start-task.model';
|
||||
import { TaskDetailsModel } from '../models/task-details.model';
|
||||
import { TaskListService } from './../services/tasklist.service';
|
||||
import { switchMap, defaultIfEmpty } from 'rxjs/operators';
|
||||
import { FormBuilder, AbstractControl, Validators, FormGroup, FormControl } from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-start-task',
|
||||
@@ -40,36 +40,31 @@ import { switchMap, defaultIfEmpty } from 'rxjs/operators';
|
||||
export class StartTaskComponent implements OnInit {
|
||||
|
||||
public FORMAT_DATE: string = 'DD/MM/YYYY';
|
||||
MAX_LENGTH: number = 255;
|
||||
|
||||
/** (required) The id of the app. */
|
||||
@Input()
|
||||
appId: number;
|
||||
|
||||
/** Emitted when the task is successfully created. */
|
||||
@Input()
|
||||
name: string = '';
|
||||
|
||||
@Output()
|
||||
success: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
/** Emitted when the cancel button is clicked by the user. */
|
||||
@Output()
|
||||
cancel: EventEmitter<void> = new EventEmitter<void>();
|
||||
|
||||
/** Emitted when an error occurs. */
|
||||
@Output()
|
||||
error: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
startTaskModel: StartTaskModel = new StartTaskModel();
|
||||
|
||||
forms: Form[];
|
||||
|
||||
taskDetailsModel: TaskDetailsModel = new TaskDetailsModel();
|
||||
forms$: Observable<Form[]>;
|
||||
assigneeId: number;
|
||||
|
||||
formKey: string;
|
||||
|
||||
taskId: string;
|
||||
|
||||
dateError: boolean;
|
||||
|
||||
field: FormFieldModel;
|
||||
taskForm: FormGroup;
|
||||
dateError: boolean = false;
|
||||
maxTaskNameLength: number = this.MAX_LENGTH;
|
||||
loading = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@@ -80,44 +75,74 @@ export class StartTaskComponent implements OnInit {
|
||||
constructor(private taskService: TaskListService,
|
||||
private dateAdapter: DateAdapter<Moment>,
|
||||
private preferences: UserPreferencesService,
|
||||
private formBuilder: FormBuilder,
|
||||
private logService: LogService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.field = new FormFieldModel(new FormModel(), {id: this.assigneeId, value: this.assigneeId, placeholder: 'Assignee'});
|
||||
if (this.name) {
|
||||
this.taskDetailsModel.name = this.name;
|
||||
}
|
||||
|
||||
this.validateMaxTaskNameLength();
|
||||
|
||||
this.field = new FormFieldModel(new FormModel(), { id: this.assigneeId, value: this.assigneeId, placeholder: 'Assignee' });
|
||||
this.preferences.locale$.subscribe((locale) => {
|
||||
this.dateAdapter.setLocale(locale);
|
||||
});
|
||||
|
||||
this.loadFormsTask();
|
||||
this.buildForm();
|
||||
}
|
||||
|
||||
public start(): void {
|
||||
if (this.startTaskModel.name) {
|
||||
if (this.appId) {
|
||||
this.startTaskModel.category = this.appId.toString();
|
||||
}
|
||||
this.taskService.createNewTask(new TaskDetailsModel(this.startTaskModel))
|
||||
.pipe(
|
||||
switchMap((createRes: any) =>
|
||||
this.attachForm(createRes.id, this.formKey).pipe(
|
||||
defaultIfEmpty(createRes),
|
||||
switchMap((attachRes: any) =>
|
||||
this.assignTaskByUserId(createRes.id, this.assigneeId).pipe(
|
||||
defaultIfEmpty(attachRes ? attachRes : createRes)
|
||||
)
|
||||
buildForm() {
|
||||
this.taskForm = this.formBuilder.group({
|
||||
name: new FormControl(this.taskDetailsModel.name, [Validators.required, Validators.maxLength(this.maxTaskNameLength)]),
|
||||
description: new FormControl(''),
|
||||
formKey: new FormControl('')
|
||||
});
|
||||
|
||||
this.taskForm.valueChanges.subscribe((taskFormValues) => this.setTaskDetails(taskFormValues));
|
||||
}
|
||||
|
||||
setTaskDetails(form) {
|
||||
this.taskDetailsModel.name = form.name;
|
||||
this.taskDetailsModel.description = form.description;
|
||||
this.taskDetailsModel.formKey = form.formKey ? form.formKey.toString() : null;
|
||||
}
|
||||
|
||||
isFormValid() {
|
||||
return this.taskForm.valid && !this.dateError && !this.loading;
|
||||
}
|
||||
|
||||
public saveTask(): void {
|
||||
this.loading = true;
|
||||
if (this.appId) {
|
||||
this.taskDetailsModel.category = this.appId.toString();
|
||||
}
|
||||
this.taskService.createNewTask(this.taskDetailsModel)
|
||||
.pipe(
|
||||
switchMap((createRes: any) =>
|
||||
this.attachForm(createRes.id, this.taskDetailsModel.formKey).pipe(
|
||||
defaultIfEmpty(createRes),
|
||||
switchMap((attachRes: any) =>
|
||||
this.assignTaskByUserId(createRes.id, this.assigneeId).pipe(
|
||||
defaultIfEmpty(attachRes ? attachRes : createRes)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
.subscribe(
|
||||
(res: any) => {
|
||||
this.success.emit(res);
|
||||
},
|
||||
(err) => {
|
||||
this.error.emit(err);
|
||||
this.logService.error('An error occurred while creating new task');
|
||||
});
|
||||
}
|
||||
)
|
||||
.subscribe(
|
||||
(res: any) => {
|
||||
this.loading = false;
|
||||
this.success.emit(res);
|
||||
},
|
||||
(err) => {
|
||||
this.loading = false;
|
||||
this.error.emit(err);
|
||||
this.logService.error('An error occurred while creating new task');
|
||||
});
|
||||
}
|
||||
|
||||
getAssigneeId(userId) {
|
||||
@@ -145,13 +170,7 @@ export class StartTaskComponent implements OnInit {
|
||||
}
|
||||
|
||||
private loadFormsTask(): void {
|
||||
this.taskService.getFormList().subscribe((res: Form[]) => {
|
||||
this.forms = res;
|
||||
},
|
||||
(err) => {
|
||||
this.error.emit(err);
|
||||
this.logService.error('An error occurred while trying to get the forms');
|
||||
});
|
||||
this.forms$ = this.taskService.getFormList();
|
||||
}
|
||||
|
||||
public isUserNameEmpty(user: UserProcessModel): boolean {
|
||||
@@ -168,20 +187,45 @@ export class StartTaskComponent implements OnInit {
|
||||
return firstName + delimiter + lastName;
|
||||
}
|
||||
|
||||
onDateChanged(newDateValue): void {
|
||||
onDateChanged(newDateValue: any) {
|
||||
this.dateError = false;
|
||||
|
||||
if (newDateValue) {
|
||||
let momentDate = moment(newDateValue, this.FORMAT_DATE, true);
|
||||
if (!momentDate.isValid()) {
|
||||
this.dateError = true;
|
||||
let momentDate;
|
||||
|
||||
if (typeof newDateValue === 'string') {
|
||||
momentDate = moment(newDateValue, this.FORMAT_DATE, true);
|
||||
} else {
|
||||
momentDate = newDateValue;
|
||||
}
|
||||
|
||||
if (momentDate.isValid()) {
|
||||
this.taskDetailsModel.dueDate = momentDate.toDate();
|
||||
} else {
|
||||
this.dateError = true;
|
||||
this.taskDetailsModel.dueDate = null;
|
||||
}
|
||||
} else {
|
||||
this.taskDetailsModel.dueDate = null;
|
||||
}
|
||||
}
|
||||
|
||||
clearDateInput() {
|
||||
const emptyValue = '';
|
||||
this.startTaskModel.dueDate = emptyValue;
|
||||
this.onDateChanged(emptyValue);
|
||||
private validateMaxTaskNameLength() {
|
||||
if (this.maxTaskNameLength > this.MAX_LENGTH) {
|
||||
this.maxTaskNameLength = this.MAX_LENGTH;
|
||||
this.logService.log(`the task name length cannot be greater than ${this.MAX_LENGTH}`);
|
||||
}
|
||||
}
|
||||
|
||||
get nameController(): AbstractControl {
|
||||
return this.taskForm.get('name');
|
||||
}
|
||||
|
||||
get descriptionController(): AbstractControl {
|
||||
return this.taskForm.get('description');
|
||||
}
|
||||
|
||||
get formKeyController(): AbstractControl {
|
||||
return this.taskForm.get('formKey');
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user