mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
[ACA-30333]FE - [Process-services] Create ADF task form. (#5611)
* [ACA-3033] FE - [Process-services] Create ADF task form. * * Modifed task-from-template * * Refactored details component with the task-form * * Updated unit tests to the recent changes * * Modified task-details component * * Fixed failing tests * * Fixed failing tests* Added doc * * Fixed task-details-form e2e * Fixed failing test on tas-details e2e * * Fixed flaky process-services e2e * * Fixed flaky e2e tests
This commit is contained in:
parent
fde037498f
commit
ea1454dde0
@ -76,6 +76,7 @@
|
|||||||
<adf-task-details #activitiDetails
|
<adf-task-details #activitiDetails
|
||||||
[debugMode]="true"
|
[debugMode]="true"
|
||||||
[taskId]="currentTaskId"
|
[taskId]="currentTaskId"
|
||||||
|
[showFormTitle]="true"
|
||||||
[fieldValidators]="fieldValidators"
|
[fieldValidators]="fieldValidators"
|
||||||
[showHeaderContent]="showHeaderContent"
|
[showHeaderContent]="showHeaderContent"
|
||||||
(formCompleted)="onFormCompleted()"
|
(formCompleted)="onFormCompleted()"
|
||||||
|
54
docs/process-services/components/task-form.component.md
Normal file
54
docs/process-services/components/task-form.component.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
Title: Task Form component
|
||||||
|
Added: v2.0.0
|
||||||
|
Status: Active
|
||||||
|
Last reviewed: 2020-04-21
|
||||||
|
---
|
||||||
|
|
||||||
|
# [Task Form component](../../../lib/process-services/src/lib/task-list/components/task-form/task-form.component.ts "Defined in task-form.component.ts")
|
||||||
|
|
||||||
|
Shows a [`form`](../../../lib/process-services/src/lib/task-list/models/form.model.ts) for a task.
|
||||||
|
|
||||||
|
## Basic Usage
|
||||||
|
|
||||||
|
```html
|
||||||
|
<adf-task-form
|
||||||
|
[taskId]="taskId">
|
||||||
|
</adf-task-form>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Class members
|
||||||
|
|
||||||
|
### Properties
|
||||||
|
|
||||||
|
| Name | Type | Default value | Description |
|
||||||
|
| ---- | ---- | ------------- | ----------- |
|
||||||
|
| fieldValidators | [`FormFieldValidator`](../../../lib/core/form/components/widgets/core/form-field-validator.ts)`[]` | \[] | Field validators for use with the form. |
|
||||||
|
| readOnlyForm | `boolean` | false | Toggles read-only state of the form. All form widgets render as read-only if enabled. |
|
||||||
|
| showFormCompleteButton | `boolean` | true | Toggles rendering of the `Complete` outcome button. |
|
||||||
|
| showFormRefreshButton | `boolean` | true | Toggles rendering of the `Refresh` button. |
|
||||||
|
| showFormSaveButton | `boolean` | true | Toggles rendering of the `Save` outcome button. |
|
||||||
|
| showFormTitle | `boolean` | false | Toggles rendering of the form title. |
|
||||||
|
| showCancelButton | `boolean` | true | Toggles rendering of the `Cancel` empty form button. |
|
||||||
|
| showFormValidationIcon | `boolean` | true | Toggle rendering of the validation icon
|
||||||
|
| taskId | `string` | | (**required**) The id of the task whose details we are asking for. |
|
||||||
|
|
||||||
|
### Events
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | ---- | ----------- |
|
||||||
|
| cancel | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<void>` | Emitted when the "Cancel" button is clicked. |
|
||||||
|
| completed | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<void>` | Emitted when the form associated with the task is completed. |
|
||||||
|
| error | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when an error occurs. |
|
||||||
|
| executeOutcome | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormOutcomeEvent`](../../../lib/core/form/components/widgets/core/form-outcome-event.model.ts)`>` | Emitted when any outcome is executed. Default behaviour can be prevented via `event.preventDefault()`. |
|
||||||
|
| formCompleted | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormModel`](../../../lib/core/form/components/widgets/core/form.model.ts)`>` | Emitted when the form is submitted with the `Complete` outcome. |
|
||||||
|
| formContentClicked | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`ContentLinkModel`](../../../lib/core/form/components/widgets/core/content-link.model.ts)`>` | Emitted when the form field content is clicked. |
|
||||||
|
| formLoaded | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormModel`](../../../lib/core/form/components/widgets/core/form.model.ts)`>` | Emitted when the form is loaded or reloaded. |
|
||||||
|
| formError | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormFieldModel`](../../core/models/form-field.model.md)`[]>` | Emitted when the supplied form values have a validation error. |
|
||||||
|
| formSaved | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormModel`](../../../lib/core/form/components/widgets/core/form.model.ts)`>` | Emitted when the form is submitted with the `Save` or custom outcomes. |
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
- [Form component](./form.component.md)
|
||||||
|
- [Form field model](../../core/models/form-field.model.md)
|
||||||
|
- [Form service](../../core/services/form.service.md)
|
@ -20,11 +20,11 @@ import { BrowserVisibility, BrowserActions, DropdownPage } from '@alfresco/adf-t
|
|||||||
|
|
||||||
export class AttachFormPage {
|
export class AttachFormPage {
|
||||||
|
|
||||||
noFormMessage: ElementFinder = element(by.id('adf-no-form-message'));
|
noFormMessage: ElementFinder = element(by.css('.adf-empty-content__title'));
|
||||||
attachFormButton: ElementFinder = element(by.id('adf-no-form-attach-form-button'));
|
attachFormButton: ElementFinder = element(by.id('adf-attach-form-attach-button'));
|
||||||
completeButton: ElementFinder = element(by.id('adf-no-form-complete-button'));
|
completeButton: ElementFinder = element(by.id('adf-attach-form-complete-button'));
|
||||||
formDropdown: ElementFinder = element(by.id('form_id'));
|
formDropdown: ElementFinder = element(by.id('form_id'));
|
||||||
cancelButton: ElementFinder = element(by.id('adf-no-form-cancel-button'));
|
cancelButton: ElementFinder = element(by.id('adf-attach-form-cancel-button'));
|
||||||
defaultTitle: ElementFinder = element(by.css('mat-card-title[class="mat-card-title mat-card-title"]'));
|
defaultTitle: ElementFinder = element(by.css('mat-card-title[class="mat-card-title mat-card-title"]'));
|
||||||
attachFormDropdown = new DropdownPage(element(by.css("div[class='adf-attach-form-row']")));
|
attachFormDropdown = new DropdownPage(element(by.css("div[class='adf-attach-form-row']")));
|
||||||
|
|
||||||
@ -66,6 +66,6 @@ export class AttachFormPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async checkAttachFormButtonIsDisabled(): Promise<void> {
|
async checkAttachFormButtonIsDisabled(): Promise<void> {
|
||||||
await BrowserVisibility.waitUntilElementIsVisible(element(by.css('button[id="adf-no-form-attach-form-button"][disabled]')));
|
await BrowserVisibility.waitUntilElementIsVisible(element(by.css('button[id="adf-attach-form-attach-button"][disabled]')));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,10 +55,11 @@ export class TaskDetailsPage {
|
|||||||
involvePeopleHeader: ElementFinder = element(by.css('div[class="adf-search-text-header"]'));
|
involvePeopleHeader: ElementFinder = element(by.css('div[class="adf-search-text-header"]'));
|
||||||
removeInvolvedPeople: ElementFinder = element(by.css('button[data-automation-id="Remove"]'));
|
removeInvolvedPeople: ElementFinder = element(by.css('button[data-automation-id="Remove"]'));
|
||||||
peopleTitle: ElementFinder = element(by.id('people-title'));
|
peopleTitle: ElementFinder = element(by.id('people-title'));
|
||||||
|
noFormMessage: ElementFinder = element(by.css('span[id*="no-form-message"]'));
|
||||||
cancelAttachForm: ElementFinder = element(by.id('adf-no-form-cancel-button'));
|
cancelAttachForm: ElementFinder = element(by.id('adf-no-form-cancel-button'));
|
||||||
attachFormButton: ElementFinder = element(by.id('adf-no-form-attach-form-button'));
|
attachFormButton: ElementFinder = element(by.id('adf-no-form-attach-form-button'));
|
||||||
disabledAttachFormButton: ElementFinder = element(by.css('button[id="adf-no-form-attach-form-button"][disabled]'));
|
disabledAttachFormButton: ElementFinder = element(by.css('button[id="adf-no-form-attach-form-button"][disabled]'));
|
||||||
removeAttachForm: ElementFinder = element(by.id('adf-no-form-remove-button'));
|
removeAttachForm: ElementFinder = element(by.id('adf-attach-form-remove-button'));
|
||||||
attachFormName: ElementFinder = element(by.css('span[class="adf-form-title ng-star-inserted"]'));
|
attachFormName: ElementFinder = element(by.css('span[class="adf-form-title ng-star-inserted"]'));
|
||||||
emptyTaskDetails: ElementFinder = element(by.css('adf-task-details > div > div'));
|
emptyTaskDetails: ElementFinder = element(by.css('adf-task-details > div > div'));
|
||||||
priority: ElementFinder = element(by.css('span[data-automation-id*="priority"] span'));
|
priority: ElementFinder = element(by.css('span[data-automation-id*="priority"] span'));
|
||||||
@ -163,6 +164,14 @@ export class TaskDetailsPage {
|
|||||||
await BrowserActions.click(this.formNameField);
|
await BrowserActions.click(this.formNameField);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async checkStandaloneNoFormMessageIsDisplayed(): Promise<void> {
|
||||||
|
await BrowserVisibility.waitUntilElementIsVisible(this.noFormMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getNoFormMessage(): Promise<string> {
|
||||||
|
return BrowserActions.getText(this.noFormMessage);
|
||||||
|
}
|
||||||
|
|
||||||
getAssignee(): Promise<string> {
|
getAssignee(): Promise<string> {
|
||||||
return BrowserActions.getText(this.assigneeField);
|
return BrowserActions.getText(this.assigneeField);
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,7 @@ describe('Attach Folder', () => {
|
|||||||
await contentNodeSelector.clickMoveCopyButton();
|
await contentNodeSelector.clickMoveCopyButton();
|
||||||
await widget.attachFolderWidget().checkFolderIsAttached(app.UPLOAD_FOLDER_FORM_CS.FIELD.widget_id, user.email);
|
await widget.attachFolderWidget().checkFolderIsAttached(app.UPLOAD_FOLDER_FORM_CS.FIELD.widget_id, user.email);
|
||||||
await widget.attachFolderWidget().removeFolder(app.UPLOAD_FOLDER_FORM_CS.FIELD.widget_id, user.email);
|
await widget.attachFolderWidget().removeFolder(app.UPLOAD_FOLDER_FORM_CS.FIELD.widget_id, user.email);
|
||||||
|
await taskPage.formFields().checkWidgetIsVisible(app.UPLOAD_FOLDER_FORM_CS.FIELD.widget_id);
|
||||||
await widget.attachFolderWidget().checkFolderIsNotAttached(app.UPLOAD_FOLDER_FORM_CS.FIELD.widget_id, user.email);
|
await widget.attachFolderWidget().checkFolderIsNotAttached(app.UPLOAD_FOLDER_FORM_CS.FIELD.widget_id, user.email);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -22,12 +22,14 @@ import { UsersActions } from '../actions/users.actions';
|
|||||||
import { NavigationBarPage } from '../pages/adf/navigation-bar.page';
|
import { NavigationBarPage } from '../pages/adf/navigation-bar.page';
|
||||||
import { AttachFormPage } from '../pages/adf/process-services/attach-form.page';
|
import { AttachFormPage } from '../pages/adf/process-services/attach-form.page';
|
||||||
import { TasksPage } from '../pages/adf/process-services/tasks.page';
|
import { TasksPage } from '../pages/adf/process-services/tasks.page';
|
||||||
|
import { TaskDetailsPage } from '../pages/adf/process-services/task-details.page';
|
||||||
import CONSTANTS = require('../util/constants');
|
import CONSTANTS = require('../util/constants');
|
||||||
|
|
||||||
describe('Attach Form Component', () => {
|
describe('Attach Form Component', () => {
|
||||||
|
|
||||||
const loginPage = new LoginPage();
|
const loginPage = new LoginPage();
|
||||||
const taskPage = new TasksPage();
|
const taskPage = new TasksPage();
|
||||||
|
const taskDetailsPage = new TaskDetailsPage();
|
||||||
const attachFormPage = new AttachFormPage();
|
const attachFormPage = new AttachFormPage();
|
||||||
const formFields = new FormFields();
|
const formFields = new FormFields();
|
||||||
const navigationBarPage = new NavigationBarPage();
|
const navigationBarPage = new NavigationBarPage();
|
||||||
@ -83,9 +85,9 @@ describe('Attach Form Component', () => {
|
|||||||
await taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS);
|
await taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS);
|
||||||
await taskPage.tasksListPage().selectRow(testNames.taskName);
|
await taskPage.tasksListPage().selectRow(testNames.taskName);
|
||||||
|
|
||||||
await attachFormPage.checkNoFormMessageIsDisplayed();
|
await taskPage.taskDetails().checkStandaloneNoFormMessageIsDisplayed();
|
||||||
await attachFormPage.checkAttachFormButtonIsDisplayed();
|
await taskPage.taskDetails().checkAttachFormButtonIsDisplayed();
|
||||||
await attachFormPage.checkCompleteButtonIsDisplayed();
|
await taskPage.taskDetails().checkCompleteTaskButtonIsDisplayed();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('[C280048] Should be able to view the attach-form component after clicking cancel button', async () => {
|
it('[C280048] Should be able to view the attach-form component after clicking cancel button', async () => {
|
||||||
@ -94,7 +96,7 @@ describe('Attach Form Component', () => {
|
|||||||
await taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS);
|
await taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS);
|
||||||
await taskPage.tasksListPage().selectRow(testNames.taskName);
|
await taskPage.tasksListPage().selectRow(testNames.taskName);
|
||||||
|
|
||||||
await attachFormPage.clickAttachFormButton();
|
await taskPage.taskDetails().clickAttachFormButton();
|
||||||
await attachFormPage.checkDefaultFormTitleIsDisplayed(testNames.formTitle);
|
await attachFormPage.checkDefaultFormTitleIsDisplayed(testNames.formTitle);
|
||||||
await attachFormPage.checkFormDropdownIsDisplayed();
|
await attachFormPage.checkFormDropdownIsDisplayed();
|
||||||
await attachFormPage.checkCancelButtonIsDisplayed();
|
await attachFormPage.checkCancelButtonIsDisplayed();
|
||||||
@ -104,7 +106,7 @@ describe('Attach Form Component', () => {
|
|||||||
await formFields.checkWidgetIsReadOnlyMode(testNames.widgetTitle);
|
await formFields.checkWidgetIsReadOnlyMode(testNames.widgetTitle);
|
||||||
|
|
||||||
await attachFormPage.clickCancelButton();
|
await attachFormPage.clickCancelButton();
|
||||||
await attachFormPage.checkAttachFormButtonIsDisplayed();
|
await taskPage.taskDetails().checkAttachFormButtonIsDisplayed();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('[C280017] Should be able to attach a form on a standalone task and complete', async () => {
|
it('[C280017] Should be able to attach a form on a standalone task and complete', async () => {
|
||||||
@ -113,7 +115,7 @@ describe('Attach Form Component', () => {
|
|||||||
await taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS);
|
await taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS);
|
||||||
await taskPage.tasksListPage().selectRow(testNames.taskName);
|
await taskPage.tasksListPage().selectRow(testNames.taskName);
|
||||||
|
|
||||||
await attachFormPage.clickAttachFormButton();
|
await taskDetailsPage.clickAttachFormButton();
|
||||||
await attachFormPage.selectAttachFormOption(testNames.formName);
|
await attachFormPage.selectAttachFormOption(testNames.formName);
|
||||||
await attachFormPage.clickAttachFormButton();
|
await attachFormPage.clickAttachFormButton();
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ describe('Start Task - Task App', () => {
|
|||||||
await taskPage.taskDetails().checkAttachFormButtonIsDisplayed();
|
await taskPage.taskDetails().checkAttachFormButtonIsDisplayed();
|
||||||
await taskPage.taskDetails().checkAttachFormButtonIsEnabled();
|
await taskPage.taskDetails().checkAttachFormButtonIsEnabled();
|
||||||
await expect(await taskPage.taskDetails().getFormName()).toEqual(CONSTANTS.TASK_DETAILS.NO_FORM);
|
await expect(await taskPage.taskDetails().getFormName()).toEqual(CONSTANTS.TASK_DETAILS.NO_FORM);
|
||||||
await expect(await taskPage.formFields().getNoFormMessage()).toEqual(noFormMessage);
|
await expect(await taskDetails.getNoFormMessage()).toEqual(noFormMessage);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('[C268910] Should a standalone task be displayed in completed tasks when completing it', async () => {
|
it('[C268910] Should a standalone task be displayed in completed tasks when completing it', async () => {
|
||||||
@ -107,17 +107,20 @@ describe('Start Task - Task App', () => {
|
|||||||
|
|
||||||
await taskPage.tasksListPage().checkContentIsDisplayed(tasks[2]);
|
await taskPage.tasksListPage().checkContentIsDisplayed(tasks[2]);
|
||||||
await taskPage.formFields().noFormIsDisplayed();
|
await taskPage.formFields().noFormIsDisplayed();
|
||||||
|
await taskPage.taskDetails().clickAttachFormButton();
|
||||||
|
|
||||||
const formFields = await taskPage.formFields();
|
const formFields = await taskPage.formFields();
|
||||||
await formFields.clickOnAttachFormButton();
|
|
||||||
await formFields.selectForm(app.formName);
|
await formFields.selectForm(app.formName);
|
||||||
await formFields.clickOnAttachFormButton();
|
await formFields.clickOnAttachFormButton();
|
||||||
|
|
||||||
|
await taskPage.formFields().checkFormIsDisplayed();
|
||||||
|
await taskPage.taskDetails().checkCompleteFormButtonIsDisplayed();
|
||||||
await expect(await taskPage.taskDetails().getFormName()).toEqual(app.formName);
|
await expect(await taskPage.taskDetails().getFormName()).toEqual(app.formName);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('[C268912] Should a standalone task be displayed when removing the form from APS', async () => {
|
it('[C268912] Should a standalone task be displayed when removing the form from APS', async () => {
|
||||||
const task = await taskPage.createNewTask();
|
const task = await taskPage.createNewTask();
|
||||||
|
const taskDetails = await taskPage.taskDetails();
|
||||||
await task.addName(tasks[3]);
|
await task.addName(tasks[3]);
|
||||||
await task.selectForm(app.formName);
|
await task.selectForm(app.formName);
|
||||||
await task.clickStartButton();
|
await task.clickStartButton();
|
||||||
@ -134,6 +137,6 @@ describe('Start Task - Task App', () => {
|
|||||||
|
|
||||||
await taskPage.formFields().noFormIsDisplayed();
|
await taskPage.formFields().noFormIsDisplayed();
|
||||||
await expect(await taskPage.taskDetails().getFormName()).toEqual(CONSTANTS.TASK_DETAILS.NO_FORM);
|
await expect(await taskPage.taskDetails().getFormName()).toEqual(CONSTANTS.TASK_DETAILS.NO_FORM);
|
||||||
await expect(await taskPage.formFields().getNoFormMessage()).toEqual(noFormMessage);
|
await expect(await taskDetails.getNoFormMessage()).toEqual(noFormMessage);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -27,11 +27,13 @@ import { TaskDetailsPage } from '../pages/adf/process-services/task-details.page
|
|||||||
import { TasksListPage } from '../pages/adf/process-services/tasks-list.page';
|
import { TasksListPage } from '../pages/adf/process-services/tasks-list.page';
|
||||||
import CONSTANTS = require('../util/constants');
|
import CONSTANTS = require('../util/constants');
|
||||||
import { TasksPage } from '../pages/adf/process-services/tasks.page';
|
import { TasksPage } from '../pages/adf/process-services/tasks.page';
|
||||||
|
import { AttachFormPage } from '../pages/adf/process-services/attach-form.page';
|
||||||
|
|
||||||
describe('Task Details - Form', () => {
|
describe('Task Details - Form', () => {
|
||||||
const loginPage = new LoginPage();
|
const loginPage = new LoginPage();
|
||||||
const tasksListPage = new TasksListPage();
|
const tasksListPage = new TasksListPage();
|
||||||
const taskDetailsPage = new TaskDetailsPage();
|
const taskDetailsPage = new TaskDetailsPage();
|
||||||
|
const attachFormPage = new AttachFormPage();
|
||||||
const taskPage = new TasksPage();
|
const taskPage = new TasksPage();
|
||||||
const filtersPage = new FiltersPage();
|
const filtersPage = new FiltersPage();
|
||||||
const widget = new Widget();
|
const widget = new Widget();
|
||||||
@ -101,25 +103,27 @@ describe('Task Details - Form', () => {
|
|||||||
await tasksListPage.selectRow(task.name);
|
await tasksListPage.selectRow(task.name);
|
||||||
await taskDetailsPage.clickForm();
|
await taskDetailsPage.clickForm();
|
||||||
|
|
||||||
await taskDetailsPage.checkAttachFormDropdownIsDisplayed();
|
await attachFormPage.checkFormDropdownIsDisplayed();
|
||||||
await taskDetailsPage.checkAttachFormButtonIsDisabled();
|
await attachFormPage.checkAttachFormButtonIsDisabled();
|
||||||
|
|
||||||
await taskDetailsPage.selectAttachFormOption(newForm.name);
|
await attachFormPage.selectAttachFormOption(newForm.name);
|
||||||
await taskDetailsPage.checkSelectedForm(newForm.name);
|
await taskDetailsPage.checkSelectedForm(newForm.name);
|
||||||
await taskDetailsPage.checkAttachFormButtonIsEnabled();
|
await attachFormPage.checkAttachFormButtonIsDisplayed();
|
||||||
|
|
||||||
await taskDetailsPage.checkCancelAttachFormIsDisplayed();
|
await attachFormPage.checkCancelButtonIsDisplayed();
|
||||||
await taskDetailsPage.clickCancelAttachForm();
|
await attachFormPage.clickCancelButton();
|
||||||
|
|
||||||
await taskDetailsPage.checkFormIsAttached(attachedForm.name);
|
await taskDetailsPage.checkFormIsAttached(attachedForm.name);
|
||||||
|
|
||||||
await taskDetailsPage.clickForm();
|
await taskDetailsPage.clickForm();
|
||||||
|
|
||||||
await taskDetailsPage.checkAttachFormDropdownIsDisplayed();
|
await attachFormPage.checkFormDropdownIsDisplayed();
|
||||||
await taskDetailsPage.selectAttachFormOption(newForm.name);
|
await attachFormPage.checkAttachFormButtonIsDisabled();
|
||||||
|
await attachFormPage.selectAttachFormOption(newForm.name);
|
||||||
|
await taskDetailsPage.checkSelectedForm(newForm.name);
|
||||||
|
|
||||||
await taskDetailsPage.checkAttachFormButtonIsDisplayed();
|
await attachFormPage.checkAttachFormButtonIsDisplayed();
|
||||||
await taskDetailsPage.clickAttachFormButton();
|
await attachFormPage.clickAttachFormButton();
|
||||||
|
|
||||||
await taskDetailsPage.checkFormIsAttached(newForm.name);
|
await taskDetailsPage.checkFormIsAttached(newForm.name);
|
||||||
});
|
});
|
||||||
|
@ -336,5 +336,20 @@
|
|||||||
"CHOOSE_ITEM": "Choose {{ name }} to...",
|
"CHOOSE_ITEM": "Choose {{ name }} to...",
|
||||||
"CHOOSE_IN": "Choose file in {{ name }}..."
|
"CHOOSE_IN": "Choose file in {{ name }}..."
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"ADF_TASK_FORM": {
|
||||||
|
"EMPTY_FORM": {
|
||||||
|
"SUBTITLE": "Attach a form that can be viewed later",
|
||||||
|
"COMPLETE-TASK-MESSAGE": "Task {{taskName}} completed",
|
||||||
|
"COMPLETE-TASK-SUB-MESSAGE": "No forms to be added",
|
||||||
|
"BUTTONS": {
|
||||||
|
"COMPLETE": "COMPLETE",
|
||||||
|
"CANCEL": "CANCEL"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"COMPLETED_TASK": {
|
||||||
|
"TITLE": "Task {{taskName}} completed",
|
||||||
|
"SUBTITLE": "No forms to be added"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,46 @@ export let standaloneTaskWithoutForm = new TaskDetailsModel({
|
|||||||
memberOfCandidateGroup: false
|
memberOfCandidateGroup: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export let completedStandaloneTaskWithoutForm = new TaskDetailsModel({
|
||||||
|
id: '200',
|
||||||
|
name: 'Standalone Task Without Form',
|
||||||
|
description: null,
|
||||||
|
category: null,
|
||||||
|
assignee: {
|
||||||
|
id: 1001,
|
||||||
|
firstName: 'Wilbur',
|
||||||
|
lastName: 'Adams',
|
||||||
|
email: 'wilbur@app.activiti.com'
|
||||||
|
},
|
||||||
|
created: '2016-11-03T15:25:42.749+0000',
|
||||||
|
dueDate: null,
|
||||||
|
endDate: new Date(),
|
||||||
|
duration: null,
|
||||||
|
priority: 50,
|
||||||
|
parentTaskId: null,
|
||||||
|
parentTaskName: null,
|
||||||
|
processInstanceId: null,
|
||||||
|
processInstanceName: null,
|
||||||
|
processDefinitionId: null,
|
||||||
|
processDefinitionName: null,
|
||||||
|
processDefinitionDescription: null,
|
||||||
|
processDefinitionKey: null,
|
||||||
|
processDefinitionCategory: null,
|
||||||
|
processDefinitionVersion: null,
|
||||||
|
processDefinitionDeploymentId: null,
|
||||||
|
formKey: null,
|
||||||
|
processInstanceStartUserId: null,
|
||||||
|
initiatorCanCompleteTask: false,
|
||||||
|
adhocTaskCanBeReassigned: false,
|
||||||
|
taskDefinitionKey: 'sid-DDECD9E4-0299-433F-9193-C3D905C3EEBE',
|
||||||
|
executionId: '86',
|
||||||
|
involvedGroups: [],
|
||||||
|
involvedPeople: [],
|
||||||
|
memberOfCandidateUsers: false,
|
||||||
|
managerOfCandidateGroup: false,
|
||||||
|
memberOfCandidateGroup: false
|
||||||
|
});
|
||||||
|
|
||||||
export let taskDetailsMock = new TaskDetailsModel({
|
export let taskDetailsMock = new TaskDetailsModel({
|
||||||
id: '91',
|
id: '91',
|
||||||
name: 'Request translation',
|
name: 'Request translation',
|
||||||
@ -137,6 +177,54 @@ export let taskDetailsMock = new TaskDetailsModel({
|
|||||||
memberOfCandidateGroup: false
|
memberOfCandidateGroup: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export let initiatorCanCompleteTaskDetailsMock = new TaskDetailsModel({
|
||||||
|
id: '91',
|
||||||
|
name: 'Request translation',
|
||||||
|
description: null,
|
||||||
|
category: null,
|
||||||
|
assignee: { email: 'mock-user-email' },
|
||||||
|
created: '2016-11-03T15:25:42.749+0000',
|
||||||
|
dueDate: null,
|
||||||
|
endDate: null,
|
||||||
|
duration: null,
|
||||||
|
priority: 50,
|
||||||
|
parentTaskId: null,
|
||||||
|
parentTaskName: null,
|
||||||
|
processInstanceId: '86',
|
||||||
|
processInstanceName: null,
|
||||||
|
processDefinitionId: 'TranslationProcess:2:8',
|
||||||
|
processDefinitionName: 'Translation Process',
|
||||||
|
processDefinitionDescription: null,
|
||||||
|
processDefinitionKey: 'TranslationProcess',
|
||||||
|
processDefinitionCategory: 'http://www.activiti.org/processdef',
|
||||||
|
processDefinitionVersion: 2,
|
||||||
|
processDefinitionDeploymentId: '5',
|
||||||
|
formKey: '4',
|
||||||
|
processInstanceStartUserId: '1001',
|
||||||
|
initiatorCanCompleteTask: true,
|
||||||
|
adhocTaskCanBeReassigned: false,
|
||||||
|
taskDefinitionKey: 'sid-DDECD9E4-0299-433F-9193-C3D905C3EEBE',
|
||||||
|
executionId: '86',
|
||||||
|
involvedGroups: [],
|
||||||
|
involvedPeople: [
|
||||||
|
{
|
||||||
|
id: 1001,
|
||||||
|
firstName: 'Wilbur',
|
||||||
|
lastName: 'Adams',
|
||||||
|
email: 'wilbur@app.activiti.com'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 111,
|
||||||
|
firstName: 'fake-first-name',
|
||||||
|
lastName: 'fake-last-name',
|
||||||
|
email: 'fake@app.activiti.com'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
memberOfCandidateUsers: false,
|
||||||
|
managerOfCandidateGroup: false,
|
||||||
|
memberOfCandidateGroup: false
|
||||||
|
});
|
||||||
|
|
||||||
export let taskDetailsWithOutAssigneeMock = new TaskDetailsModel({
|
export let taskDetailsWithOutAssigneeMock = new TaskDetailsModel({
|
||||||
id: '91',
|
id: '91',
|
||||||
name: 'Request translation',
|
name: 'Request translation',
|
||||||
@ -183,6 +271,7 @@ export let claimableTaskDetailsMock = new TaskDetailsModel({
|
|||||||
endDate: null,
|
endDate: null,
|
||||||
duration: null,
|
duration: null,
|
||||||
priority: 50,
|
priority: 50,
|
||||||
|
formKey: '4',
|
||||||
parentTaskId: null,
|
parentTaskId: null,
|
||||||
parentTaskName: null,
|
parentTaskName: null,
|
||||||
processInstanceId: '86',
|
processInstanceId: '86',
|
||||||
@ -353,6 +442,36 @@ export let taskDetailsWithOutCandidateGroup = new TaskDetailsModel({
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export let completedTaskWithFormMock = new TaskDetailsModel({
|
||||||
|
id: '91',
|
||||||
|
name: 'Request translation',
|
||||||
|
description: null,
|
||||||
|
category: null,
|
||||||
|
assignee: {
|
||||||
|
id: 1001,
|
||||||
|
firstName: 'Wilbur',
|
||||||
|
lastName: 'Adams',
|
||||||
|
email: 'wilbur@app.activiti.com'
|
||||||
|
},
|
||||||
|
created: '2016-11-03T15:25:42.749+0000',
|
||||||
|
dueDate: null,
|
||||||
|
endDate: new Date(),
|
||||||
|
duration: null,
|
||||||
|
priority: 50,
|
||||||
|
formKey: '91',
|
||||||
|
parentTaskId: null,
|
||||||
|
parentTaskName: null,
|
||||||
|
processInstanceId: '86',
|
||||||
|
processInstanceName: null,
|
||||||
|
processDefinitionId: 'TranslationProcess:2:8',
|
||||||
|
processDefinitionName: 'Translation Process',
|
||||||
|
involvedGroups: [],
|
||||||
|
involvedPeople: [],
|
||||||
|
managerOfCandidateGroup: true,
|
||||||
|
memberOfCandidateGroup: true,
|
||||||
|
memberOfCandidateUsers: false
|
||||||
|
});
|
||||||
|
|
||||||
export let completedTaskDetailsMock = new TaskDetailsModel({
|
export let completedTaskDetailsMock = new TaskDetailsModel({
|
||||||
id: '91',
|
id: '91',
|
||||||
name: 'Request translation',
|
name: 'Request translation',
|
||||||
@ -366,9 +485,10 @@ export let completedTaskDetailsMock = new TaskDetailsModel({
|
|||||||
},
|
},
|
||||||
created: '2016-11-03T15:25:42.749+0000',
|
created: '2016-11-03T15:25:42.749+0000',
|
||||||
dueDate: null,
|
dueDate: null,
|
||||||
endDate: '2016-11-03T15:25:42.749+0000',
|
endDate: new Date(),
|
||||||
duration: null,
|
duration: null,
|
||||||
priority: 50,
|
priority: 50,
|
||||||
|
formKey: null,
|
||||||
parentTaskId: null,
|
parentTaskId: null,
|
||||||
parentTaskName: null,
|
parentTaskName: null,
|
||||||
processInstanceId: '86',
|
processInstanceId: '86',
|
||||||
@ -382,6 +502,40 @@ export let completedTaskDetailsMock = new TaskDetailsModel({
|
|||||||
memberOfCandidateUsers: false
|
memberOfCandidateUsers: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export let taskDetailsWithOutFormMock = new TaskDetailsModel({
|
||||||
|
'id': '91',
|
||||||
|
'name': 'Request translation',
|
||||||
|
'description': 'fake description',
|
||||||
|
'category': null,
|
||||||
|
'assignee': {'id': 1001, 'firstName': 'Admin', 'lastName': 'Paul', 'email': 'my@mymail.com' },
|
||||||
|
'created': '2016-11-03T15:25:42.749+0000',
|
||||||
|
'dueDate': '2016-11-03T15:25:42.749+0000',
|
||||||
|
'endDate': null,
|
||||||
|
'duration': null,
|
||||||
|
'priority': 50,
|
||||||
|
'parentTaskId': null,
|
||||||
|
'parentTaskName': null,
|
||||||
|
'processInstanceId': '86',
|
||||||
|
'processInstanceName': null,
|
||||||
|
'processDefinitionId': 'TranslationProcess:2:8',
|
||||||
|
'processDefinitionName': 'Translation Process',
|
||||||
|
'processDefinitionDescription': null,
|
||||||
|
'processDefinitionKey': 'TranslationProcess',
|
||||||
|
'processDefinitionCategory': 'http://www.activiti.org/processdef',
|
||||||
|
'processDefinitionVersion': 2,
|
||||||
|
'processDefinitionDeploymentId': '5',
|
||||||
|
'formKey': null,
|
||||||
|
'processInstanceStartUserId': '1001',
|
||||||
|
'initiatorCanCompleteTask': false,
|
||||||
|
'adhocTaskCanBeReassigned': false,
|
||||||
|
'taskDefinitionKey': 'sid-DDECD9E4-0299-433F-9193-C3D905C3EEBE',
|
||||||
|
'executionId': '86',
|
||||||
|
'involvedPeople': [],
|
||||||
|
'memberOfCandidateUsers': false,
|
||||||
|
'managerOfCandidateGroup': false,
|
||||||
|
'memberOfCandidateGroup': false
|
||||||
|
});
|
||||||
|
|
||||||
export const taskFormMock = {
|
export const taskFormMock = {
|
||||||
id: 4,
|
id: 4,
|
||||||
name: 'Translation request',
|
name: 'Translation request',
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
@import '../content-widget/attach-file-widget-dialog.component';
|
@import '../content-widget/attach-file-widget-dialog.component';
|
||||||
@import '../form/start-form.component';
|
@import '../form/start-form.component';
|
||||||
@import '../process-list/components/start-process.component';
|
@import '../process-list/components/start-process.component';
|
||||||
|
@import '../task-list/components/task-form/task-form.component';
|
||||||
|
|
||||||
@mixin adf-process-services-theme($theme) {
|
@mixin adf-process-services-theme($theme) {
|
||||||
@include adf-process-filters-theme($theme);
|
@include adf-process-filters-theme($theme);
|
||||||
@ -26,4 +27,5 @@
|
|||||||
@include adf-attach-file-widget-dialog-component-theme($theme);
|
@include adf-attach-file-widget-dialog-component-theme($theme);
|
||||||
@include adf-start-form-component-theme($theme);
|
@include adf-start-form-component-theme($theme);
|
||||||
@include adf-process-services-create-theme($theme);
|
@include adf-process-services-create-theme($theme);
|
||||||
|
@include adf-task-form-theme($theme);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<div class="adf-attach-form">
|
<div class="adf-attach-form">
|
||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<div class="adf-no-form-message-container">
|
<div class="adf-attache-form-message-container">
|
||||||
<mat-card-title class="mat-card-title">
|
<mat-card-title class="mat-card-title">
|
||||||
<h4 class="adf-form-title">{{ 'ADF_TASK_LIST.ATTACH_FORM.SELECT_FORM' | translate }}</h4>
|
<h4 class="adf-form-title">{{ 'ADF_TASK_LIST.ATTACH_FORM.SELECT_FORM' | translate }}</h4>
|
||||||
</mat-card-title>
|
</mat-card-title>
|
||||||
@ -23,13 +23,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
|
|
||||||
<mat-card-actions class="adf-no-form-mat-card-actions">
|
<mat-card-actions class="adf-attach-form-mat-card-actions">
|
||||||
<div>
|
<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>
|
<button mat-button id="adf-attach-form-remove-button" color="warn" *ngIf="formKey" (click)="onRemoveButtonClick()">{{ 'ADF_TASK_LIST.ATTACH_FORM.REMOVE_FORM' | translate }}</button>
|
||||||
</div>
|
</div>
|
||||||
<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-attach-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" [disabled]="disableSubmit" color="primary" (click)="onAttachFormButtonClick()">{{ 'ADF_TASK_LIST.START_TASK.FORM.LABEL.ATTACHFORM' | translate }}</button>
|
<button mat-button id="adf-attach-form-attach-button" [disabled]="disableSubmit" color="primary" (click)="onAttachFormButtonClick()">{{ 'ADF_TASK_LIST.START_TASK.FORM.LABEL.ATTACHFORM' | translate }}</button>
|
||||||
</div>
|
</div>
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.adf-no-form-mat-card-actions {
|
.adf-attach-form-mat-card-actions {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
@ -51,7 +51,7 @@ describe('AttachFormComponent', () => {
|
|||||||
it('should show the attach button disabled', async(() => {
|
it('should show the attach button disabled', async(() => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
fixture.whenStable().then(() => {
|
fixture.whenStable().then(() => {
|
||||||
const attachButton = fixture.debugElement.query(By.css('#adf-no-form-attach-form-button'));
|
const attachButton = fixture.debugElement.query(By.css('#adf-attach-form-attach-button'));
|
||||||
expect(attachButton.nativeElement.disabled).toBeTruthy();
|
expect(attachButton.nativeElement.disabled).toBeTruthy();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
@ -60,7 +60,7 @@ describe('AttachFormComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
fixture.whenStable().then(() => {
|
fixture.whenStable().then(() => {
|
||||||
const emitSpy = spyOn(component.cancelAttachForm, 'emit');
|
const emitSpy = spyOn(component.cancelAttachForm, 'emit');
|
||||||
const el = fixture.nativeElement.querySelector('#adf-no-form-cancel-button');
|
const el = fixture.nativeElement.querySelector('#adf-attach-form-cancel-button');
|
||||||
el.click();
|
el.click();
|
||||||
expect(emitSpy).toHaveBeenCalled();
|
expect(emitSpy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
@ -72,8 +72,8 @@ describe('AttachFormComponent', () => {
|
|||||||
spyOn(taskService, 'attachFormToATask').and.returnValue(of(true));
|
spyOn(taskService, 'attachFormToATask').and.returnValue(of(true));
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
fixture.whenStable().then(() => {
|
fixture.whenStable().then(() => {
|
||||||
expect(element.querySelector('#adf-no-form-attach-form-button')).toBeDefined();
|
expect(element.querySelector('#adf-attach-form-attach-button')).toBeDefined();
|
||||||
const el = fixture.nativeElement.querySelector('#adf-no-form-attach-form-button');
|
const el = fixture.nativeElement.querySelector('#adf-attach-form-attach-button');
|
||||||
el.click();
|
el.click();
|
||||||
expect(taskService.attachFormToATask).toHaveBeenCalledWith(1, 2);
|
expect(taskService.attachFormToATask).toHaveBeenCalledWith(1, 2);
|
||||||
});
|
});
|
||||||
@ -87,7 +87,7 @@ describe('AttachFormComponent', () => {
|
|||||||
spyOn(taskService, 'attachFormToATask').and.returnValue(of(true));
|
spyOn(taskService, 'attachFormToATask').and.returnValue(of(true));
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
fixture.whenStable().then(() => {
|
fixture.whenStable().then(() => {
|
||||||
const attachButton = fixture.debugElement.query(By.css('#adf-no-form-attach-form-button'));
|
const attachButton = fixture.debugElement.query(By.css('#adf-attach-form-attach-button'));
|
||||||
expect(attachButton.nativeElement.disabled).toBeFalsy();
|
expect(attachButton.nativeElement.disabled).toBeFalsy();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
@ -103,7 +103,7 @@ describe('AttachFormComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
component.attachFormControl.setValue(2);
|
component.attachFormControl.setValue(2);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const attachButton = fixture.debugElement.query(By.css('#adf-no-form-attach-form-button'));
|
const attachButton = fixture.debugElement.query(By.css('#adf-attach-form-attach-button'));
|
||||||
expect(attachButton.nativeElement.disabled).toBeTruthy();
|
expect(attachButton.nativeElement.disabled).toBeTruthy();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
@ -140,8 +140,8 @@ describe('AttachFormComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
fixture.whenStable().then(() => {
|
fixture.whenStable().then(() => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(element.querySelector('#adf-no-form-remove-button')).toBeDefined();
|
expect(element.querySelector('#adf-attach-form-remove-button')).toBeDefined();
|
||||||
const el = fixture.nativeElement.querySelector('#adf-no-form-remove-button');
|
const el = fixture.nativeElement.querySelector('#adf-attach-form-remove-button');
|
||||||
el.click();
|
el.click();
|
||||||
expect(component.formId).toBeNull();
|
expect(component.formId).toBeNull();
|
||||||
});
|
});
|
||||||
@ -163,7 +163,7 @@ describe('AttachFormComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
fixture.whenStable().then(() => {
|
fixture.whenStable().then(() => {
|
||||||
const emitSpy = spyOn(component.success, 'emit');
|
const emitSpy = spyOn(component.success, 'emit');
|
||||||
const el = fixture.nativeElement.querySelector('#adf-no-form-attach-form-button');
|
const el = fixture.nativeElement.querySelector('#adf-attach-form-attach-button');
|
||||||
el.click();
|
el.click();
|
||||||
expect(emitSpy).toHaveBeenCalled();
|
expect(emitSpy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
@ -17,19 +17,14 @@
|
|||||||
|
|
||||||
import { NoTaskDetailsTemplateDirective } from './no-task-detail-template.directive';
|
import { NoTaskDetailsTemplateDirective } from './no-task-detail-template.directive';
|
||||||
import { TaskDetailsComponent } from './task-details.component';
|
import { TaskDetailsComponent } from './task-details.component';
|
||||||
import { AuthenticationService } from '@alfresco/adf-core';
|
|
||||||
import { of } from 'rxjs';
|
|
||||||
|
|
||||||
describe('NoTaskDetailsTemplateDirective', () => {
|
describe('NoTaskDetailsTemplateDirective', () => {
|
||||||
|
|
||||||
let component: NoTaskDetailsTemplateDirective;
|
let component: NoTaskDetailsTemplateDirective;
|
||||||
let detailsComponent: TaskDetailsComponent;
|
let detailsComponent: TaskDetailsComponent;
|
||||||
let authService: AuthenticationService;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
authService = new AuthenticationService(null, null, null, null, null);
|
detailsComponent = new TaskDetailsComponent(null, null, null, null, null);
|
||||||
spyOn(authService, 'getBpmLoggedUser').and.returnValue(of({ email: 'fake-email' }));
|
|
||||||
detailsComponent = new TaskDetailsComponent(null, authService, null, null, null, null);
|
|
||||||
component = new NoTaskDetailsTemplateDirective(detailsComponent);
|
component = new NoTaskDetailsTemplateDirective(detailsComponent);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -22,51 +22,21 @@
|
|||||||
|
|
||||||
<div class="adf-task-details-core-form">
|
<div class="adf-task-details-core-form">
|
||||||
<div *ngIf="isAssigned()">
|
<div *ngIf="isAssigned()">
|
||||||
<adf-form *ngIf="isFormComponentVisible()" #activitiForm
|
<adf-task-form
|
||||||
[taskId]="taskDetails.id"
|
[taskId]="taskDetails.id"
|
||||||
[showTitle]="showFormTitle"
|
[showFormTitle]="showFormTitle"
|
||||||
[showRefreshButton]="showFormRefreshButton"
|
[showFormRefreshButton]="showFormRefreshButton"
|
||||||
[showCompleteButton]="showFormCompleteButton"
|
[showCancelButton]="true"
|
||||||
[disableCompleteButton]="!isCompleteButtonEnabled()"
|
|
||||||
[showSaveButton]="isSaveButtonVisible()"
|
|
||||||
[readOnly]="internalReadOnlyForm"
|
|
||||||
[fieldValidators]="fieldValidators"
|
[fieldValidators]="fieldValidators"
|
||||||
(formSaved)='onFormSaved($event)'
|
(formSaved)='onFormSaved($event)'
|
||||||
(formCompleted)='onFormCompleted($event)'
|
(formCompleted)='onFormCompleted($event)'
|
||||||
(formContentClicked)='onFormContentClick($event)'
|
(formContentClicked)='onFormContentClick($event)'
|
||||||
(formLoaded)='onFormLoaded($event)'
|
(formLoaded)='onFormLoaded($event)'
|
||||||
(error)='onFormError($event)'
|
(completed)="onComplete()"
|
||||||
(executeOutcome)='onFormExecuteOutcome($event)'>
|
(showAttachForm)="onShowAttachForm()"
|
||||||
</adf-form>
|
(executeOutcome)='onFormExecuteOutcome($event)'
|
||||||
<adf-task-standalone *ngIf="isTaskStandaloneComponentVisible()"
|
(error)="onFormError($event)" #activitiTaskForm>
|
||||||
[taskName]="taskDetails.name"
|
</adf-task-form>
|
||||||
[taskId]="taskDetails.id"
|
|
||||||
[isCompleted]="isCompletedTask()"
|
|
||||||
[hasCompletePermission]="isCompleteButtonEnabled()"
|
|
||||||
[hideCancelButton]="true"
|
|
||||||
(complete)="onComplete()"
|
|
||||||
(showAttachForm)="onShowAttachForm()">
|
|
||||||
</adf-task-standalone>
|
|
||||||
|
|
||||||
<mat-card class="adf-message-card" *ngIf="!isTaskStandaloneComponentVisible() && !isCompletedTask() && !isFormComponentVisible()" >
|
|
||||||
<mat-card-content>
|
|
||||||
<div class="adf-no-form-message-container">
|
|
||||||
<div class="adf-no-form-message-list">
|
|
||||||
<div *ngIf="!isCompletedTask()" class="adf-no-form-message">
|
|
||||||
<span id="adf-no-form-message">{{'ADF_TASK_LIST.STANDALONE_TASK.NO_FORM_MESSAGE' | translate}}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</mat-card-content>
|
|
||||||
|
|
||||||
<mat-card-actions class="adf-no-form-mat-card-actions">
|
|
||||||
<div>
|
|
||||||
<button mat-button id="adf-no-form-complete-button" color="primary" (click)="onComplete()">{{ 'ADF_TASK_LIST.DETAILS.BUTTON.COMPLETE' | translate }}</button>
|
|
||||||
</div>
|
|
||||||
</mat-card-actions>
|
|
||||||
|
|
||||||
</mat-card>
|
|
||||||
|
|
||||||
<adf-attach-form *ngIf="isShowAttachForm()"
|
<adf-attach-form *ngIf="isShowAttachForm()"
|
||||||
[taskId]="taskDetails.id"
|
[taskId]="taskDetails.id"
|
||||||
[formKey]="taskDetails.formKey"
|
[formKey]="taskDetails.formKey"
|
||||||
|
@ -36,8 +36,6 @@ import { TaskDetailsModel } from '../models/task-details.model';
|
|||||||
import {
|
import {
|
||||||
noDataMock,
|
noDataMock,
|
||||||
taskDetailsMock,
|
taskDetailsMock,
|
||||||
standaloneTaskWithForm,
|
|
||||||
standaloneTaskWithoutForm,
|
|
||||||
taskFormMock,
|
taskFormMock,
|
||||||
tasksMock,
|
tasksMock,
|
||||||
taskDetailsWithOutAssigneeMock
|
taskDetailsWithOutAssigneeMock
|
||||||
@ -64,7 +62,6 @@ describe('TaskDetailsComponent', () => {
|
|||||||
let getTaskDetailsSpy: jasmine.Spy;
|
let getTaskDetailsSpy: jasmine.Spy;
|
||||||
let getTasksSpy: jasmine.Spy;
|
let getTasksSpy: jasmine.Spy;
|
||||||
let assignTaskSpy: jasmine.Spy;
|
let assignTaskSpy: jasmine.Spy;
|
||||||
let completeTaskSpy: jasmine.Spy;
|
|
||||||
let logService: LogService;
|
let logService: LogService;
|
||||||
let commentProcessService: CommentProcessService;
|
let commentProcessService: CommentProcessService;
|
||||||
let peopleProcessService: PeopleProcessService;
|
let peopleProcessService: PeopleProcessService;
|
||||||
@ -99,7 +96,6 @@ describe('TaskDetailsComponent', () => {
|
|||||||
|
|
||||||
getTasksSpy = spyOn(service, 'getTasks').and.returnValue(of(tasksMock));
|
getTasksSpy = spyOn(service, 'getTasks').and.returnValue(of(tasksMock));
|
||||||
assignTaskSpy = spyOn(service, 'assignTask').and.returnValue(of(fakeUser));
|
assignTaskSpy = spyOn(service, 'assignTask').and.returnValue(of(fakeUser));
|
||||||
completeTaskSpy = spyOn(service, 'completeTask').and.returnValue(of({}));
|
|
||||||
commentProcessService = TestBed.get(CommentProcessService);
|
commentProcessService = TestBed.get(CommentProcessService);
|
||||||
|
|
||||||
authService = TestBed.get(AuthenticationService);
|
authService = TestBed.get(AuthenticationService);
|
||||||
@ -175,42 +171,6 @@ describe('TaskDetailsComponent', () => {
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should display task standalone component when the task does not have an associated form', async(() => {
|
|
||||||
component.taskId = '123';
|
|
||||||
getTaskDetailsSpy.and.returnValue(of(standaloneTaskWithoutForm));
|
|
||||||
|
|
||||||
fixture.detectChanges();
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(component.isStandaloneTaskWithoutForm()).toBeTruthy();
|
|
||||||
expect(fixture.debugElement.query(By.css('adf-task-standalone'))).not.toBeNull();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should not display task standalone component when the task has a form', async(() => {
|
|
||||||
component.taskId = '123';
|
|
||||||
getTaskDetailsSpy.and.returnValue(of(standaloneTaskWithForm));
|
|
||||||
fixture.detectChanges();
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(component.isStandaloneTaskWithForm()).toBeTruthy();
|
|
||||||
expect(fixture.debugElement.query(By.css('adf-task-standalone'))).toBeDefined();
|
|
||||||
expect(fixture.debugElement.query(By.css('adf-task-standalone'))).not.toBeNull();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should display the AttachFormComponent when standaloneTaskWithForm and click on attach button', async(() => {
|
|
||||||
component.taskId = '123';
|
|
||||||
getTaskDetailsSpy.and.returnValue(of(standaloneTaskWithForm));
|
|
||||||
fixture.detectChanges();
|
|
||||||
component.onShowAttachForm();
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(component.isStandaloneTaskWithForm()).toBeTruthy();
|
|
||||||
expect(fixture.debugElement.query(By.css('adf-attach-form'))).toBeDefined();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should display the claim message when the task is not assigned', async(() => {
|
it('should display the claim message when the task is not assigned', async(() => {
|
||||||
component.taskDetails = taskDetailsWithOutAssigneeMock;
|
component.taskDetails = taskDetailsWithOutAssigneeMock;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@ -229,86 +189,6 @@ describe('TaskDetailsComponent', () => {
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('and form with visiblity', () => {
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
component.taskId = '123';
|
|
||||||
spyOn(formService, 'completeTaskForm').and.returnValue(of({}));
|
|
||||||
taskDetailsMock.formKey = '4';
|
|
||||||
getTaskDetailsSpy.and.returnValue(of(taskDetailsMock));
|
|
||||||
fixture.detectChanges();
|
|
||||||
await fixture.whenStable();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('[C312410] - Should be possible to complete a task that has an invisible field on a form with a value', async (done) => {
|
|
||||||
component.formCompleted.subscribe((form: FormModel) => {
|
|
||||||
expect(form.id).toBe(taskFormMock.id);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
component.taskDetails.initiatorCanCompleteTask = true;
|
|
||||||
component.showNextTask = false;
|
|
||||||
|
|
||||||
fixture.detectChanges();
|
|
||||||
await fixture.whenStable();
|
|
||||||
const inputTextOne: HTMLInputElement = fixture.nativeElement.querySelector('#text1');
|
|
||||||
expect(inputTextOne).toBeDefined();
|
|
||||||
expect(inputTextOne).not.toBeNull();
|
|
||||||
const inputTextTwo: HTMLInputElement = fixture.nativeElement.querySelector('#text2');
|
|
||||||
expect(inputTextTwo).toBeDefined();
|
|
||||||
expect(inputTextTwo).not.toBeNull();
|
|
||||||
let inputTextThree: HTMLInputElement = fixture.nativeElement.querySelector('#text3');
|
|
||||||
expect(inputTextThree).toBeDefined();
|
|
||||||
expect(inputTextThree).not.toBeNull();
|
|
||||||
|
|
||||||
inputTextOne.value = 'a';
|
|
||||||
inputTextOne.dispatchEvent(new Event('input'));
|
|
||||||
inputTextTwo.value = 'a';
|
|
||||||
inputTextTwo.dispatchEvent(new Event('input'));
|
|
||||||
inputTextThree.value = 'a';
|
|
||||||
inputTextThree.dispatchEvent(new Event('input'));
|
|
||||||
fixture.detectChanges();
|
|
||||||
await fixture.whenStable();
|
|
||||||
inputTextThree = fixture.nativeElement.querySelector('#text3');
|
|
||||||
expect(inputTextThree).toBeDefined();
|
|
||||||
expect(inputTextThree).not.toBeNull();
|
|
||||||
|
|
||||||
inputTextOne.value = 'b';
|
|
||||||
inputTextOne.dispatchEvent(new Event('input'));
|
|
||||||
fixture.detectChanges();
|
|
||||||
await fixture.whenStable();
|
|
||||||
const inputThreeContainer = fixture.nativeElement.querySelector('#field-text3-container');
|
|
||||||
expect(inputThreeContainer.hidden).toBe(true);
|
|
||||||
const completeOutcomeButton: HTMLButtonElement = fixture.nativeElement.querySelector('#adf-form-complete');
|
|
||||||
expect(completeOutcomeButton.hidden).toBe(false);
|
|
||||||
completeOutcomeButton.click();
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('[C277278] - Should show if the form is valid via the validation icon', async () => {
|
|
||||||
const numberInput: HTMLInputElement = fixture.nativeElement.querySelector('#numberField');
|
|
||||||
let validationForm = fixture.nativeElement.querySelector('#adf-valid-form-icon');
|
|
||||||
|
|
||||||
expect(numberInput).toBeDefined();
|
|
||||||
expect(numberInput).not.toBeNull();
|
|
||||||
expect(validationForm.textContent).toBe('check_circle');
|
|
||||||
|
|
||||||
numberInput.value = 'a';
|
|
||||||
numberInput.dispatchEvent(new Event('input'));
|
|
||||||
fixture.detectChanges();
|
|
||||||
await fixture.whenStable();
|
|
||||||
const invalidForm = fixture.nativeElement.querySelector('#adf-invalid-form-icon');
|
|
||||||
expect(invalidForm).not.toBeNull();
|
|
||||||
expect(invalidForm.textContent).toBe('error');
|
|
||||||
|
|
||||||
numberInput.value = '4';
|
|
||||||
numberInput.dispatchEvent(new Event('input'));
|
|
||||||
fixture.detectChanges();
|
|
||||||
await fixture.whenStable();
|
|
||||||
validationForm = fixture.nativeElement.querySelector('#adf-valid-form-icon');
|
|
||||||
expect(validationForm.textContent).toBe('check_circle');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('change detection', () => {
|
describe('change detection', () => {
|
||||||
|
|
||||||
let change;
|
let change;
|
||||||
@ -414,11 +294,6 @@ describe('TaskDetailsComponent', () => {
|
|||||||
expect(getTasksSpy).not.toHaveBeenCalled();
|
expect(getTasksSpy).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call service to complete task when complete button clicked', () => {
|
|
||||||
component.onComplete();
|
|
||||||
expect(completeTaskSpy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should emit a complete event when complete button clicked and task completed', () => {
|
it('should emit a complete event when complete button clicked and task completed', () => {
|
||||||
const emitSpy: jasmine.Spy = spyOn(component.formCompleted, 'emit');
|
const emitSpy: jasmine.Spy = spyOn(component.formCompleted, 'emit');
|
||||||
component.onComplete();
|
component.onComplete();
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
PeopleProcessService, UserProcessModel,
|
PeopleProcessService, UserProcessModel,
|
||||||
AuthenticationService,
|
|
||||||
CardViewUpdateService,
|
CardViewUpdateService,
|
||||||
ClickNotification,
|
ClickNotification,
|
||||||
LogService,
|
LogService,
|
||||||
@ -42,8 +41,8 @@ import { Observable, Observer, of, Subject } from 'rxjs';
|
|||||||
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 { TaskListService } from './../services/tasklist.service';
|
import { TaskListService } from './../services/tasklist.service';
|
||||||
import { UserRepresentation } from '@alfresco/js-api';
|
|
||||||
import { catchError, share, takeUntil } from 'rxjs/operators';
|
import { catchError, share, takeUntil } from 'rxjs/operators';
|
||||||
|
import { TaskFormComponent } from './task-form/task-form.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-task-details',
|
selector: 'adf-task-details',
|
||||||
@ -61,6 +60,9 @@ export class TaskDetailsComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
@ViewChild('errorDialog')
|
@ViewChild('errorDialog')
|
||||||
errorDialog: TemplateRef<any>;
|
errorDialog: TemplateRef<any>;
|
||||||
|
|
||||||
|
@ViewChild('activitiTaskForm')
|
||||||
|
taskFormComponent: TaskFormComponent;
|
||||||
|
|
||||||
/** Toggles debug mode. */
|
/** Toggles debug mode. */
|
||||||
@Input()
|
@Input()
|
||||||
debugMode: boolean = false;
|
debugMode: boolean = false;
|
||||||
@ -179,11 +181,9 @@ export class TaskDetailsComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
|
|
||||||
peopleSearch: Observable<UserProcessModel[]>;
|
peopleSearch: Observable<UserProcessModel[]>;
|
||||||
|
|
||||||
currentLoggedUser: UserRepresentation;
|
|
||||||
data: any;
|
data: any;
|
||||||
|
|
||||||
constructor(private taskListService: TaskListService,
|
constructor(private taskListService: TaskListService,
|
||||||
private authService: AuthenticationService,
|
|
||||||
private peopleProcessService: PeopleProcessService,
|
private peopleProcessService: PeopleProcessService,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
private cardViewUpdateService: CardViewUpdateService,
|
private cardViewUpdateService: CardViewUpdateService,
|
||||||
@ -192,9 +192,6 @@ export class TaskDetailsComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.peopleSearch = new Observable<UserProcessModel[]>((observer) => this.peopleSearchObserver = observer).pipe(share());
|
this.peopleSearch = new Observable<UserProcessModel[]>((observer) => this.peopleSearchObserver = observer).pipe(share());
|
||||||
this.authService.getBpmLoggedUser().subscribe(user => {
|
|
||||||
this.currentLoggedUser = user;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.taskId) {
|
if (this.taskId) {
|
||||||
this.loadDetails(this.taskId);
|
this.loadDetails(this.taskId);
|
||||||
@ -225,26 +222,6 @@ export class TaskDetailsComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isStandaloneTask(): boolean {
|
|
||||||
return !(this.taskDetails && (!!this.taskDetails.processDefinitionId));
|
|
||||||
}
|
|
||||||
|
|
||||||
isStandaloneTaskWithForm(): boolean {
|
|
||||||
return this.isStandaloneTask() && this.hasFormKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
isStandaloneTaskWithoutForm(): boolean {
|
|
||||||
return this.isStandaloneTask() && !this.hasFormKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
isFormComponentVisible(): boolean {
|
|
||||||
return this.hasFormKey() && !this.isShowAttachForm();
|
|
||||||
}
|
|
||||||
|
|
||||||
isTaskStandaloneComponentVisible(): boolean {
|
|
||||||
return this.isStandaloneTaskWithoutForm() && !this.isShowAttachForm();
|
|
||||||
}
|
|
||||||
|
|
||||||
isShowAttachForm(): boolean {
|
isShowAttachForm(): boolean {
|
||||||
return this.showAttachForm;
|
return this.showAttachForm;
|
||||||
}
|
}
|
||||||
@ -256,13 +233,6 @@ export class TaskDetailsComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
this.taskDetails = null;
|
this.taskDetails = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the task has a form
|
|
||||||
*/
|
|
||||||
hasFormKey(): boolean {
|
|
||||||
return (this.taskDetails && (!!this.taskDetails.formKey));
|
|
||||||
}
|
|
||||||
|
|
||||||
isTaskActive() {
|
isTaskActive() {
|
||||||
return this.taskDetails && this.taskDetails.duration === null;
|
return this.taskDetails && this.taskDetails.duration === null;
|
||||||
}
|
}
|
||||||
@ -329,44 +299,6 @@ export class TaskDetailsComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
return !!this.taskDetails.assignee;
|
return !!this.taskDetails.assignee;
|
||||||
}
|
}
|
||||||
|
|
||||||
private hasEmailAddress(): boolean {
|
|
||||||
return this.taskDetails.assignee.email ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
isAssignedToMe(): boolean {
|
|
||||||
return this.isAssigned() && this.hasEmailAddress() ?
|
|
||||||
this.isEmailEqual(this.taskDetails.assignee.email, this.currentLoggedUser.email) :
|
|
||||||
this.isExternalIdEqual(this.taskDetails.assignee.externalId, this.currentLoggedUser.externalId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private isEmailEqual(assigneeMail: string, currentLoggedEmail: string): boolean {
|
|
||||||
return assigneeMail.toLocaleLowerCase() === currentLoggedEmail.toLocaleLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
private isExternalIdEqual(assigneeExternalId: string, currentUserExternalId: string): boolean {
|
|
||||||
return assigneeExternalId.toLocaleLowerCase() === currentUserExternalId.toLocaleLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
isCompleteButtonEnabled(): boolean {
|
|
||||||
return this.isAssignedToMe() || this.canInitiatorComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
isCompleteButtonVisible(): boolean {
|
|
||||||
return !this.hasFormKey() && this.isTaskActive() && this.isCompleteButtonEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
canInitiatorComplete(): boolean {
|
|
||||||
return this.taskDetails.initiatorCanCompleteTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
isSaveButtonVisible(): boolean {
|
|
||||||
return this.hasSaveButton() && (!this.canInitiatorComplete() || this.isAssignedToMe());
|
|
||||||
}
|
|
||||||
|
|
||||||
hasSaveButton(): boolean {
|
|
||||||
return this.showFormSaveButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the next open task
|
* Retrieve the next open task
|
||||||
* @param processInstanceId
|
* @param processInstanceId
|
||||||
@ -395,9 +327,7 @@ export class TaskDetailsComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
* Complete button clicked
|
* Complete button clicked
|
||||||
*/
|
*/
|
||||||
onComplete(): void {
|
onComplete(): void {
|
||||||
this.taskListService
|
this.onFormCompleted(null);
|
||||||
.completeTask(this.taskId)
|
|
||||||
.subscribe(() => this.onFormCompleted(null));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onShowAttachForm() {
|
onShowAttachForm() {
|
||||||
@ -410,6 +340,7 @@ export class TaskDetailsComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
|
|
||||||
onCompleteAttachForm() {
|
onCompleteAttachForm() {
|
||||||
this.showAttachForm = false;
|
this.showAttachForm = false;
|
||||||
|
this.taskFormComponent.loadTask(this.taskId);
|
||||||
this.loadDetails(this.taskId);
|
this.loadDetails(this.taskId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,10 +395,6 @@ export class TaskDetailsComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
this.loadDetails(taskId);
|
this.loadDetails(taskId);
|
||||||
}
|
}
|
||||||
|
|
||||||
isCompletedTask(): boolean {
|
|
||||||
return this.taskDetails && this.taskDetails.endDate ? true : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
searchUser(searchedWord: string) {
|
searchUser(searchedWord: string) {
|
||||||
this.peopleProcessService.getWorkflowUsers(null, searchedWord)
|
this.peopleProcessService.getWorkflowUsers(null, searchedWord)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
<ng-container *ngIf="!loading; else loadingTemplate">
|
||||||
|
<adf-form *ngIf="hasFormKey(); else withoutForm"
|
||||||
|
[taskId]="taskDetails?.id"
|
||||||
|
[showTitle]="showFormTitle"
|
||||||
|
[showValidationIcon]="showFormValidationIcon"
|
||||||
|
[showRefreshButton]="showFormRefreshButton"
|
||||||
|
[showCompleteButton]="showFormCompleteButton"
|
||||||
|
[disableCompleteButton]="!isCompleteButtonEnabled()"
|
||||||
|
[showSaveButton]="isSaveButtonVisible()"
|
||||||
|
[readOnly]="isReadOnlyForm()"
|
||||||
|
[fieldValidators]="fieldValidators"
|
||||||
|
(formSaved)='onFormSaved($event)'
|
||||||
|
(formCompleted)='onFormCompleted($event)'
|
||||||
|
(formContentClicked)='onFormContentClick($event)'
|
||||||
|
(formLoaded)='onFormLoaded($event)'
|
||||||
|
(formError)='onFormError($event)'
|
||||||
|
(error)='onError($event)'
|
||||||
|
(executeOutcome)='onFormExecuteOutcome($event)'>
|
||||||
|
</adf-form>
|
||||||
|
<ng-template #withoutForm>
|
||||||
|
<adf-task-standalone *ngIf="isStandaloneTask(); else emptyFormMessage"
|
||||||
|
[taskName]="taskDetails.name"
|
||||||
|
[taskId]="taskDetails.id"
|
||||||
|
[isCompleted]="isCompletedTask()"
|
||||||
|
[hasCompletePermission]="isCompleteButtonVisible()"
|
||||||
|
[hideCancelButton]="showCancelButton"
|
||||||
|
(complete)="onCompleteTask()"
|
||||||
|
(showAttachForm)="onShowAttachForm()">
|
||||||
|
</adf-task-standalone>
|
||||||
|
<ng-template #emptyFormMessage>
|
||||||
|
<mat-card class="adf-task-form-container">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>
|
||||||
|
<h4>
|
||||||
|
<span class="adf-form-title">
|
||||||
|
{{taskDetails.name}}
|
||||||
|
<ng-container *ngIf="!taskDetails.name">
|
||||||
|
{{'FORM.FORM_RENDERER.NAMELESS_TASK' | translate}}
|
||||||
|
</ng-container>
|
||||||
|
</span>
|
||||||
|
</h4>
|
||||||
|
</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content>
|
||||||
|
<adf-empty-content *ngIf="isCompletedTask(); else emptyFormTemplate"
|
||||||
|
[icon]="'description'"
|
||||||
|
[title]="getCompletedTaskTranslatedMessage() | async"
|
||||||
|
[subtitle]="'ADF_TASK_FORM.COMPLETED_TASK.SUBTITLE'">
|
||||||
|
</adf-empty-content>
|
||||||
|
<ng-template #emptyFormTemplate>
|
||||||
|
<adf-empty-content
|
||||||
|
[icon]="'description'"
|
||||||
|
[title]="'ADF_TASK_LIST.STANDALONE_TASK.NO_FORM_MESSAGE'"
|
||||||
|
[subtitle]="'ADF_TASK_FORM.EMPTY_FORM.SUBTITLE'">
|
||||||
|
</adf-empty-content>
|
||||||
|
</ng-template>
|
||||||
|
</mat-card-content>
|
||||||
|
<mat-card-actions class="adf-task-form-actions">
|
||||||
|
<button id="adf-no-form-cancel-button" mat-button *ngIf="showCancelButton" (click)="onCancel()">
|
||||||
|
{{'ADF_TASK_FORM.EMPTY_FORM.BUTTONS.CANCEL' | translate}}
|
||||||
|
</button>
|
||||||
|
<button mat-button *ngIf="!isCompletedTask()" color="primary" (click)="onCompleteTask()" id="adf-no-form-complete-button">
|
||||||
|
{{'ADF_TASK_FORM.EMPTY_FORM.BUTTONS.COMPLETE' | translate}}
|
||||||
|
</button>
|
||||||
|
</mat-card-actions>
|
||||||
|
</mat-card>
|
||||||
|
</ng-template>
|
||||||
|
</ng-template>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #loadingTemplate>
|
||||||
|
<div fxLayout="row" fxLayoutAlign="center stretch">
|
||||||
|
<mat-spinner></mat-spinner>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
@ -0,0 +1,32 @@
|
|||||||
|
@mixin adf-task-form-theme($theme) {
|
||||||
|
|
||||||
|
$config: mat-typography-config();
|
||||||
|
|
||||||
|
.adf-task-form {
|
||||||
|
&-container {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-actions {
|
||||||
|
float: right;
|
||||||
|
padding-bottom: 25px !important;
|
||||||
|
padding-right: 25px !important;
|
||||||
|
|
||||||
|
& .mat-button {
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 5px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
& .mat-button-wrapper {
|
||||||
|
width: 58px;
|
||||||
|
height: 20px;
|
||||||
|
opacity: 0.54;
|
||||||
|
font-size: mat-font-size($config, body-2);
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,504 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2019 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 { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TaskFormComponent } from './task-form.component';
|
||||||
|
import {
|
||||||
|
setupTestBed,
|
||||||
|
TranslationService,
|
||||||
|
TranslationMock,
|
||||||
|
FormService,
|
||||||
|
AuthenticationService,
|
||||||
|
FormModel,
|
||||||
|
FormOutcomeEvent,
|
||||||
|
FormOutcomeModel
|
||||||
|
} from '@alfresco/adf-core';
|
||||||
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
import { TaskListService } from '../../services/tasklist.service';
|
||||||
|
import { TranslateStore } from '@ngx-translate/core';
|
||||||
|
import { NO_ERRORS_SCHEMA, SimpleChange } from '@angular/core';
|
||||||
|
import { of, throwError } from 'rxjs';
|
||||||
|
import {
|
||||||
|
taskFormMock,
|
||||||
|
taskDetailsMock,
|
||||||
|
completedTaskDetailsMock,
|
||||||
|
taskDetailsWithOutFormMock,
|
||||||
|
standaloneTaskWithoutForm,
|
||||||
|
completedStandaloneTaskWithoutForm,
|
||||||
|
claimableTaskDetailsMock,
|
||||||
|
initiatorCanCompleteTaskDetailsMock
|
||||||
|
} from '../../../mock/task/task-details.mock';
|
||||||
|
import { TaskDetailsModel } from '../../models/task-details.model';
|
||||||
|
import { TaskListModule } from '../../task-list.module';
|
||||||
|
|
||||||
|
describe('TaskFormComponent', () => {
|
||||||
|
let component: TaskFormComponent;
|
||||||
|
let fixture: ComponentFixture<TaskFormComponent>;
|
||||||
|
let formService: FormService;
|
||||||
|
let taskListService: TaskListService;
|
||||||
|
let getTaskDetailsSpy: jasmine.Spy;
|
||||||
|
let completeTaskSpy: jasmine.Spy;
|
||||||
|
let element: HTMLElement;
|
||||||
|
let authService: AuthenticationService;
|
||||||
|
let getBpmLoggedUserSpy: jasmine.Spy;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
NoopAnimationsModule,
|
||||||
|
TaskListModule
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
{ provide: TranslationService, useClass: TranslationMock },
|
||||||
|
TranslateStore],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(TaskFormComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
element = fixture.nativeElement;
|
||||||
|
|
||||||
|
taskListService = TestBed.get(TaskListService);
|
||||||
|
formService = TestBed.get(FormService);
|
||||||
|
|
||||||
|
getTaskDetailsSpy = spyOn(taskListService, 'getTaskDetails').and.returnValue(of(taskDetailsMock));
|
||||||
|
completeTaskSpy = spyOn(taskListService, 'completeTask').and.returnValue(of({}));
|
||||||
|
spyOn(formService, 'getTaskForm').and.returnValue(of(taskFormMock));
|
||||||
|
taskDetailsMock.processDefinitionId = null;
|
||||||
|
spyOn(formService, 'getTask').and.returnValue(of(taskDetailsMock));
|
||||||
|
authService = TestBed.get(AuthenticationService);
|
||||||
|
getBpmLoggedUserSpy = spyOn(authService, 'getBpmLoggedUser').and.returnValue(of({ email: 'fake-email' }));
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async() => {
|
||||||
|
await fixture.whenStable();
|
||||||
|
getTaskDetailsSpy.calls.reset();
|
||||||
|
fixture.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Task with form', () => {
|
||||||
|
|
||||||
|
beforeEach(async() => {
|
||||||
|
await fixture.whenStable();
|
||||||
|
getTaskDetailsSpy.calls.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to display task form', async () => {
|
||||||
|
component.taskId = '123';
|
||||||
|
taskDetailsMock.formKey = '4';
|
||||||
|
component.currentLoggedUser = taskDetailsMock.assignee;
|
||||||
|
getTaskDetailsSpy.and.returnValue(of(taskDetailsMock));
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const activitFormSelector = element.querySelector('adf-form');
|
||||||
|
const inputFieldOne = fixture.debugElement.nativeElement.querySelector('#text1');
|
||||||
|
const inputFieldTwo = fixture.debugElement.nativeElement.querySelector('#text2');
|
||||||
|
const inputFieldThree = fixture.debugElement.nativeElement.querySelector('#text3');
|
||||||
|
expect(activitFormSelector).toBeDefined();
|
||||||
|
expect(inputFieldOne['disabled']).toEqual(false);
|
||||||
|
expect(inputFieldTwo['disabled']).toEqual(false);
|
||||||
|
expect(inputFieldThree['disabled']).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to complete assigned task', async () => {
|
||||||
|
getBpmLoggedUserSpy.and.returnValue(of({ id: 1001, firstName: 'Wilbur', lastName: 'Adams', email: 'wilbur@app.activiti.com' }));
|
||||||
|
getTaskDetailsSpy.and.returnValue(of(taskDetailsMock));
|
||||||
|
const formCompletedSpy: jasmine.Spy = spyOn(component.formCompleted, 'emit');
|
||||||
|
const completeTaskFormSpy = spyOn(formService, 'completeTaskForm').and.returnValue(of({}));
|
||||||
|
component.taskId = '123';
|
||||||
|
component.ngOnInit();
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const completeButton = fixture.debugElement.nativeElement.querySelector('#adf-form-complete');
|
||||||
|
expect(completeButton['disabled']).toEqual(false);
|
||||||
|
completeButton.click();
|
||||||
|
expect(completeTaskFormSpy).toHaveBeenCalled();
|
||||||
|
expect(formCompletedSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to complete the task as a process initiator', async () => {
|
||||||
|
const formCompletedSpy: jasmine.Spy = spyOn(component.formCompleted, 'emit');
|
||||||
|
const completeTaskFormSpy = spyOn(formService, 'completeTaskForm').and.returnValue(of({}));
|
||||||
|
getTaskDetailsSpy.and.returnValue(of(initiatorCanCompleteTaskDetailsMock));
|
||||||
|
component.taskId = '123';
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const activitFormSelector = element.querySelector('adf-form');
|
||||||
|
const completeButton = fixture.debugElement.nativeElement.querySelector('#adf-form-complete');
|
||||||
|
expect(activitFormSelector).toBeDefined();
|
||||||
|
expect(completeButton['disabled']).toEqual(false);
|
||||||
|
completeButton.click();
|
||||||
|
expect(completeTaskFormSpy).toHaveBeenCalled();
|
||||||
|
expect(formCompletedSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should emit error event in case form complete service fails', async () => {
|
||||||
|
const errorSpy: jasmine.Spy = spyOn(component.error, 'emit');
|
||||||
|
const completeTaskFormSpy = spyOn(formService, 'completeTaskForm').and.returnValue(throwError({message: 'servce failed'}));
|
||||||
|
getTaskDetailsSpy.and.returnValue(of(initiatorCanCompleteTaskDetailsMock));
|
||||||
|
component.taskId = '123';
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const activitFormSelector = element.querySelector('adf-form');
|
||||||
|
const completeButton = fixture.debugElement.nativeElement.querySelector('#adf-form-complete');
|
||||||
|
expect(activitFormSelector).toBeDefined();
|
||||||
|
expect(completeButton['disabled']).toEqual(false);
|
||||||
|
completeButton.click();
|
||||||
|
expect(completeTaskFormSpy).toHaveBeenCalled();
|
||||||
|
expect(errorSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('change detection', () => {
|
||||||
|
|
||||||
|
beforeEach(async() => {
|
||||||
|
component.taskId = '123';
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
getTaskDetailsSpy.calls.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fetch new task details when taskId changed', () => {
|
||||||
|
const change = new SimpleChange('123', '456', true);
|
||||||
|
component.ngOnChanges({ 'taskId': change });
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(getTaskDetailsSpy).toHaveBeenCalledWith('123');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT fetch new task details when taskId changed to null', async () => {
|
||||||
|
const nullChange = new SimpleChange('123', null, true);
|
||||||
|
component.ngOnChanges({ 'taskId': nullChange });
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
expect(getTaskDetailsSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Task assigned to candidates', () => {
|
||||||
|
|
||||||
|
beforeEach(async() => {
|
||||||
|
component.taskId = '123';
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
getTaskDetailsSpy.calls.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to display form in readonly mode if the task assigned to candidates', async() => {
|
||||||
|
getTaskDetailsSpy.and.returnValue(of(claimableTaskDetailsMock));
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const activitFormSelector = element.querySelector('adf-form');
|
||||||
|
const inputFieldOne = fixture.debugElement.nativeElement.querySelector('#text1');
|
||||||
|
const inputFieldTwo = fixture.debugElement.nativeElement.querySelector('#text2');
|
||||||
|
const inputFieldThree = fixture.debugElement.nativeElement.querySelector('#text3');
|
||||||
|
expect(activitFormSelector).toBeDefined();
|
||||||
|
expect(inputFieldOne['disabled']).toEqual(true);
|
||||||
|
expect(inputFieldTwo['disabled']).toEqual(true);
|
||||||
|
expect(inputFieldThree['disabled']).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Form events', () => {
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
component.taskId = '123';
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should emit a save event when form saved', () => {
|
||||||
|
const formSavedSpy: jasmine.Spy = spyOn(component.formSaved, 'emit');
|
||||||
|
component.onFormSaved(new FormModel());
|
||||||
|
expect(formSavedSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should emit a outcome execution event when form outcome executed', () => {
|
||||||
|
const executeOutcomeSpy: jasmine.Spy = spyOn(component.executeOutcome, 'emit');
|
||||||
|
component.onFormExecuteOutcome(new FormOutcomeEvent(new FormOutcomeModel(new FormModel())));
|
||||||
|
expect(executeOutcomeSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should emit a complete event when form completed', () => {
|
||||||
|
const formCompletedSpy: jasmine.Spy = spyOn(component.formCompleted, 'emit');
|
||||||
|
component.onFormCompleted(new FormModel());
|
||||||
|
expect(formCompletedSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should call service to complete task when complete button clicked', () => {
|
||||||
|
component.onCompleteTask();
|
||||||
|
expect(completeTaskSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should emit a complete event when complete button clicked and task completed', () => {
|
||||||
|
const completeSpy: jasmine.Spy = spyOn(component.completed, 'emit');
|
||||||
|
component.onCompleteTask();
|
||||||
|
expect(completeSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should emit a load event when form loaded', () => {
|
||||||
|
const formLoadedSpy: jasmine.Spy = spyOn(component.formLoaded, 'emit');
|
||||||
|
component.onFormLoaded(new FormModel());
|
||||||
|
expect(formLoadedSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should emit an error event when form error occurs', () => {
|
||||||
|
const formErrorSpy: jasmine.Spy = spyOn(component.formError, 'emit');
|
||||||
|
component.onFormError({});
|
||||||
|
expect(formErrorSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should emit an error event when form services fails', () => {
|
||||||
|
const errorSpy: jasmine.Spy = spyOn(component.error, 'emit');
|
||||||
|
component.onError({});
|
||||||
|
expect(errorSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Completed Process Task', () => {
|
||||||
|
|
||||||
|
beforeEach(async() => {
|
||||||
|
component.taskId = '123';
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
getTaskDetailsSpy.calls.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to display form in readonly mode if the task completed', async() => {
|
||||||
|
getTaskDetailsSpy.and.returnValue(of(completedTaskDetailsMock));
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const activitFormSelector = element.querySelector('adf-form');
|
||||||
|
const inputFieldOne = fixture.debugElement.nativeElement.querySelector('#text1');
|
||||||
|
const inputFieldTwo = fixture.debugElement.nativeElement.querySelector('#text2');
|
||||||
|
const inputFieldThree = fixture.debugElement.nativeElement.querySelector('#text3');
|
||||||
|
expect(activitFormSelector).toBeDefined();
|
||||||
|
expect(inputFieldOne['disabled']).toEqual(true);
|
||||||
|
expect(inputFieldTwo['disabled']).toEqual(true);
|
||||||
|
expect(inputFieldThree['disabled']).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to show completed message and cancel button for the completed task without form', async () => {
|
||||||
|
completedTaskDetailsMock.formKey = null;
|
||||||
|
component.taskDetails = new TaskDetailsModel(completedTaskDetailsMock);
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const completeButtonElement = fixture.debugElement.nativeElement.querySelector('#adf-no-form-complete-button');
|
||||||
|
const cancelButtonElement = fixture.debugElement.nativeElement.querySelector('#adf-no-form-cancel-button');
|
||||||
|
const completedFormMessage = fixture.debugElement.nativeElement.querySelector('.adf-empty-content__title');
|
||||||
|
const subMessage = fixture.debugElement.nativeElement.querySelector('.adf-empty-content__subtitle');
|
||||||
|
expect(completeButtonElement).toBeNull();
|
||||||
|
expect(cancelButtonElement).not.toBeNull();
|
||||||
|
expect(completedFormMessage.innerText).toContain('ADF_TASK_FORM.COMPLETED_TASK.TITLE');
|
||||||
|
expect(subMessage.innerText).toContain('ADF_TASK_FORM.COMPLETED_TASK.SUBTITLE');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should not display complete button to the completed task without form', async () => {
|
||||||
|
completedTaskDetailsMock.formKey = null;
|
||||||
|
component.taskDetails = new TaskDetailsModel(completedTaskDetailsMock);
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const completeButtonElement = fixture.debugElement.nativeElement.querySelector('#adf-no-form-complete-button');
|
||||||
|
expect(completeButtonElement).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Process Task with no form', () => {
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
component.taskId = '123';
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to show no form message if the task does not attached a form', async () => {
|
||||||
|
component.taskDetails = new TaskDetailsModel(taskDetailsWithOutFormMock);
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const completeButtonElement = fixture.debugElement.nativeElement.querySelector('#adf-no-form-complete-button');
|
||||||
|
const cancelButtonElement = fixture.debugElement.nativeElement.querySelector('#adf-no-form-cancel-button');
|
||||||
|
const completedFormMessage = fixture.debugElement.nativeElement.querySelector('.adf-empty-content__title');
|
||||||
|
const subMessage = fixture.debugElement.nativeElement.querySelector('.adf-empty-content__subtitle');
|
||||||
|
expect(completeButtonElement).not.toBeNull();
|
||||||
|
expect(cancelButtonElement).not.toBeNull();
|
||||||
|
expect(completedFormMessage.innerText).toContain('ADF_TASK_LIST.STANDALONE_TASK.NO_FORM_MESSAGE');
|
||||||
|
expect(subMessage.innerText).toContain('ADF_TASK_FORM.EMPTY_FORM.SUBTITLE');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able display complete button to a task without form', async () => {
|
||||||
|
component.taskDetails = new TaskDetailsModel(taskDetailsWithOutFormMock);
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const completeButtonElement = fixture.debugElement.nativeElement.querySelector('#adf-no-form-complete-button');
|
||||||
|
expect(completeButtonElement).not.toBeNull();
|
||||||
|
expect(completeButtonElement['disabled']).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to complete a task with no form when complete button is clicked', async () => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
component.taskDetails = new TaskDetailsModel(taskDetailsWithOutFormMock);
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const completeButtonElement = fixture.debugElement.nativeElement.querySelector('#adf-no-form-complete-button');
|
||||||
|
completeButtonElement.click();
|
||||||
|
expect(completeTaskSpy).toHaveBeenCalledWith('91');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should emit error event in case complete task service fails', async () => {
|
||||||
|
const errorSpy: jasmine.Spy = spyOn(component.error, 'emit');
|
||||||
|
completeTaskSpy.and.returnValue(throwError({message: 'servce failed'}));
|
||||||
|
component.taskDetails = new TaskDetailsModel(taskDetailsWithOutFormMock);
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const activitFormSelector = element.querySelector('adf-form');
|
||||||
|
const completeButtonElement = fixture.debugElement.nativeElement.querySelector('#adf-no-form-complete-button');
|
||||||
|
expect(activitFormSelector).toBeDefined();
|
||||||
|
expect(completeButtonElement['disabled']).toEqual(false);
|
||||||
|
completeButtonElement.click();
|
||||||
|
expect(errorSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to emit cancel event on task with no-form when cancel button is clicked', async () => {
|
||||||
|
const cancelSpy = spyOn(component.cancel, 'emit');
|
||||||
|
getTaskDetailsSpy.and.returnValue(of(taskDetailsWithOutFormMock));
|
||||||
|
component.taskDetails = new TaskDetailsModel(taskDetailsWithOutFormMock);
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const cancelButtonElement = fixture.debugElement.nativeElement.querySelector('#adf-no-form-cancel-button');
|
||||||
|
cancelButtonElement.click();
|
||||||
|
expect(cancelSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Standalone Task with no form', () => {
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
component.taskId = '123';
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to display empty template in case standalone task does not attached a form', async () => {
|
||||||
|
component.taskDetails = new TaskDetailsModel(standaloneTaskWithoutForm);
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const taskStandAlone = element.querySelector('adf-task-standalone');
|
||||||
|
const noFormMessage = fixture.debugElement.nativeElement.querySelector('#adf-no-form-message');
|
||||||
|
expect(taskStandAlone).not.toBeNull();
|
||||||
|
expect(noFormMessage.innerText).toContain('ADF_TASK_LIST.STANDALONE_TASK.NO_FORM_MESSAGE');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able display attach form button for a standalone task without form', async() => {
|
||||||
|
const showAttachFormSpy = spyOn(component.showAttachForm, 'emit');
|
||||||
|
component.taskDetails = new TaskDetailsModel(standaloneTaskWithoutForm);
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const attacheFormButton = fixture.debugElement.nativeElement.querySelector('#adf-no-form-attach-form-button');
|
||||||
|
expect(attacheFormButton).not.toBeNull();
|
||||||
|
attacheFormButton.click();
|
||||||
|
expect(showAttachFormSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to display completed template if standalone task completed', async() => {
|
||||||
|
component.taskDetails = completedStandaloneTaskWithoutForm;
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const taskStandAlone = element.querySelector('adf-task-standalone');
|
||||||
|
const completedFormMessage = fixture.debugElement.nativeElement.querySelector('#adf-completed-form-message');
|
||||||
|
const subMessage = fixture.debugElement.nativeElement.querySelector('.adf-no-form-submessage');
|
||||||
|
expect(taskStandAlone).not.toBeNull();
|
||||||
|
expect(completedFormMessage.innerText).toContain('ADF_TASK_LIST.STANDALONE_TASK.COMPLETE_TASK_MESSAGE');
|
||||||
|
expect(subMessage.innerText).toContain('ADF_TASK_LIST.STANDALONE_TASK.COMPLETE_TASK_SUB_MESSAGE');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Form with visiblity', () => {
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
component.taskId = '123';
|
||||||
|
spyOn(formService, 'completeTaskForm').and.returnValue(of({}));
|
||||||
|
taskDetailsMock.formKey = '4';
|
||||||
|
getTaskDetailsSpy.and.returnValue(of(taskDetailsMock));
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('[C312410] - Should be possible to complete a task that has an invisible field on a form with a value', async () => {
|
||||||
|
component.formCompleted.subscribe((form: FormModel) => {
|
||||||
|
expect(form.id).toBe(taskFormMock.id);
|
||||||
|
});
|
||||||
|
component.taskDetails.initiatorCanCompleteTask = true;
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const inputTextOne: HTMLInputElement = fixture.nativeElement.querySelector('#text1');
|
||||||
|
expect(inputTextOne).toBeDefined();
|
||||||
|
expect(inputTextOne).not.toBeNull();
|
||||||
|
const inputTextTwo: HTMLInputElement = fixture.nativeElement.querySelector('#text2');
|
||||||
|
expect(inputTextTwo).toBeDefined();
|
||||||
|
expect(inputTextTwo).not.toBeNull();
|
||||||
|
let inputTextThree: HTMLInputElement = fixture.nativeElement.querySelector('#text3');
|
||||||
|
expect(inputTextThree).toBeDefined();
|
||||||
|
expect(inputTextThree).not.toBeNull();
|
||||||
|
|
||||||
|
inputTextOne.value = 'a';
|
||||||
|
inputTextOne.dispatchEvent(new Event('input'));
|
||||||
|
inputTextTwo.value = 'a';
|
||||||
|
inputTextTwo.dispatchEvent(new Event('input'));
|
||||||
|
inputTextThree.value = 'a';
|
||||||
|
inputTextThree.dispatchEvent(new Event('input'));
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
inputTextThree = fixture.nativeElement.querySelector('#text3');
|
||||||
|
expect(inputTextThree).toBeDefined();
|
||||||
|
expect(inputTextThree).not.toBeNull();
|
||||||
|
|
||||||
|
inputTextOne.value = 'b';
|
||||||
|
inputTextOne.dispatchEvent(new Event('input'));
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const inputThreeContainer = fixture.nativeElement.querySelector('#field-text3-container');
|
||||||
|
expect(inputThreeContainer.hidden).toBe(true);
|
||||||
|
const completeOutcomeButton: HTMLButtonElement = fixture.nativeElement.querySelector('#adf-form-complete');
|
||||||
|
expect(completeOutcomeButton.hidden).toBe(false);
|
||||||
|
completeOutcomeButton.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('[C277278] - Should show if the form is valid via the validation icon', async () => {
|
||||||
|
const numberInput: HTMLInputElement = fixture.nativeElement.querySelector('#numberField');
|
||||||
|
let validationForm = fixture.nativeElement.querySelector('#adf-valid-form-icon');
|
||||||
|
|
||||||
|
expect(numberInput).toBeDefined();
|
||||||
|
expect(numberInput).not.toBeNull();
|
||||||
|
expect(validationForm.textContent).toBe('check_circle');
|
||||||
|
|
||||||
|
numberInput.value = 'a';
|
||||||
|
numberInput.dispatchEvent(new Event('input'));
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const invalidForm = fixture.nativeElement.querySelector('#adf-invalid-form-icon');
|
||||||
|
expect(invalidForm).not.toBeNull();
|
||||||
|
expect(invalidForm.textContent).toBe('error');
|
||||||
|
|
||||||
|
numberInput.value = '4';
|
||||||
|
numberInput.dispatchEvent(new Event('input'));
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
validationForm = fixture.nativeElement.querySelector('#adf-valid-form-icon');
|
||||||
|
expect(validationForm.textContent).toBe('check_circle');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,287 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2019 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, OnInit, Input, Output, EventEmitter, SimpleChanges } from '@angular/core';
|
||||||
|
import {
|
||||||
|
FormModel,
|
||||||
|
ContentLinkModel,
|
||||||
|
FormRenderingService,
|
||||||
|
FormFieldValidator,
|
||||||
|
FormOutcomeEvent,
|
||||||
|
AuthenticationService,
|
||||||
|
TranslationService,
|
||||||
|
FormFieldModel
|
||||||
|
} from '@alfresco/adf-core';
|
||||||
|
import { TaskDetailsModel } from '../../models/task-details.model';
|
||||||
|
import { TaskListService } from '../../services/tasklist.service';
|
||||||
|
import { UserRepresentation } from '@alfresco/js-api';
|
||||||
|
import { AttachFileWidgetComponent } from '../../../content-widget/attach-file-widget.component';
|
||||||
|
import { AttachFolderWidgetComponent } from '../../../content-widget/attach-folder-widget.component';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-task-form',
|
||||||
|
templateUrl: './task-form.component.html',
|
||||||
|
styleUrls: ['./task-form.component.scss']
|
||||||
|
})
|
||||||
|
export class TaskFormComponent implements OnInit {
|
||||||
|
|
||||||
|
/** (**required**) The id of the task whose details we are asking for. */
|
||||||
|
@Input()
|
||||||
|
taskId: string;
|
||||||
|
|
||||||
|
/** Toggles rendering of the form title. */
|
||||||
|
@Input()
|
||||||
|
showFormTitle: boolean = false;
|
||||||
|
|
||||||
|
/** Toggles rendering of the `Complete` outcome button. */
|
||||||
|
@Input()
|
||||||
|
showFormCompleteButton: boolean = true;
|
||||||
|
|
||||||
|
/** Toggles rendering of the `Save` outcome button. */
|
||||||
|
@Input()
|
||||||
|
showFormSaveButton: boolean = true;
|
||||||
|
|
||||||
|
/** Toggle rendering of the `Cancel` button. */
|
||||||
|
@Input()
|
||||||
|
showCancelButton: boolean = true;
|
||||||
|
|
||||||
|
/** Toggles read-only state of the form. All form widgets render as read-only
|
||||||
|
* if enabled.
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
readOnlyForm: boolean = false;
|
||||||
|
|
||||||
|
/** Toggles rendering of the `Refresh` button. */
|
||||||
|
@Input()
|
||||||
|
showFormRefreshButton: boolean = true;
|
||||||
|
|
||||||
|
/** Toggle rendering of the validation icon next to the form title. */
|
||||||
|
@Input()
|
||||||
|
showFormValidationIcon: boolean = true;
|
||||||
|
|
||||||
|
/** Field validators for use with the form. */
|
||||||
|
@Input()
|
||||||
|
fieldValidators: FormFieldValidator[] = [];
|
||||||
|
|
||||||
|
/** Emitted when the form is submitted with the `Save` or custom outcomes. */
|
||||||
|
@Output()
|
||||||
|
formSaved = new EventEmitter<FormModel>();
|
||||||
|
|
||||||
|
/** Emitted when the form is submitted with the `Complete` outcome. */
|
||||||
|
@Output()
|
||||||
|
formCompleted = new EventEmitter<FormModel>();
|
||||||
|
|
||||||
|
/** Emitted when the form field content is clicked. */
|
||||||
|
@Output()
|
||||||
|
formContentClicked = new EventEmitter<ContentLinkModel>();
|
||||||
|
|
||||||
|
/** Emitted when the form is loaded or reloaded. */
|
||||||
|
@Output()
|
||||||
|
formLoaded = new EventEmitter<FormModel>();
|
||||||
|
|
||||||
|
/** Emitted when the form associated with the form task is attached. */
|
||||||
|
@Output()
|
||||||
|
showAttachForm: EventEmitter<void> = new EventEmitter<void>();
|
||||||
|
|
||||||
|
/** Emitted when any outcome is executed. Default behaviour can be prevented
|
||||||
|
* via `event.preventDefault()`.
|
||||||
|
*/
|
||||||
|
@Output()
|
||||||
|
executeOutcome = new EventEmitter<FormOutcomeEvent>();
|
||||||
|
|
||||||
|
/** Emitted when the form associated with the task is completed. */
|
||||||
|
@Output()
|
||||||
|
completed = new EventEmitter<void>();
|
||||||
|
|
||||||
|
/** Emitted when the supplied form values have a validation error. */
|
||||||
|
@Output()
|
||||||
|
formError: EventEmitter<FormFieldModel[]> = new EventEmitter<FormFieldModel[]>();
|
||||||
|
|
||||||
|
/** Emitted when an error occurs. */
|
||||||
|
@Output()
|
||||||
|
error = new EventEmitter<any>();
|
||||||
|
|
||||||
|
/** Emitted when the "Cancel" button is clicked. */
|
||||||
|
@Output()
|
||||||
|
cancel = new EventEmitter<void>();
|
||||||
|
|
||||||
|
taskDetails: TaskDetailsModel;
|
||||||
|
currentLoggedUser: UserRepresentation;
|
||||||
|
loading: boolean = false;
|
||||||
|
completedTaskMessage: string;
|
||||||
|
internalReadOnlyForm: boolean = false;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private taskListService: TaskListService,
|
||||||
|
private authService: AuthenticationService,
|
||||||
|
private formRenderingService: FormRenderingService,
|
||||||
|
private translationService: TranslationService
|
||||||
|
) {
|
||||||
|
this.formRenderingService.setComponentTypeResolver('upload', () => AttachFileWidgetComponent, true);
|
||||||
|
this.formRenderingService.setComponentTypeResolver('select-folder', () => AttachFolderWidgetComponent, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.authService.getBpmLoggedUser().subscribe(user => {
|
||||||
|
this.currentLoggedUser = user;
|
||||||
|
});
|
||||||
|
this.loadTask(this.taskId);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
|
const taskId = changes['taskId'];
|
||||||
|
if (taskId && taskId.currentValue) {
|
||||||
|
this.loadTask(this.taskId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadTask(taskId: string) {
|
||||||
|
this.loading = true;
|
||||||
|
if (taskId) {
|
||||||
|
this.taskListService.getTaskDetails(taskId).subscribe(
|
||||||
|
(res: TaskDetailsModel) => {
|
||||||
|
this.taskDetails = res;
|
||||||
|
|
||||||
|
if (!this.taskDetails.name) {
|
||||||
|
this.taskDetails.name = 'No name';
|
||||||
|
}
|
||||||
|
|
||||||
|
const endDate: any = res.endDate;
|
||||||
|
if (endDate && !isNaN(endDate.getTime())) {
|
||||||
|
this.internalReadOnlyForm = true;
|
||||||
|
} else {
|
||||||
|
this.internalReadOnlyForm = this.readOnlyForm;
|
||||||
|
}
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onFormSaved(savedForm: FormModel) {
|
||||||
|
this.formSaved.emit(savedForm);
|
||||||
|
}
|
||||||
|
|
||||||
|
onFormCompleted(form: FormModel) {
|
||||||
|
this.formCompleted.emit(form);
|
||||||
|
}
|
||||||
|
|
||||||
|
onFormLoaded(form: FormModel): void {
|
||||||
|
this.formLoaded.emit(form);
|
||||||
|
}
|
||||||
|
|
||||||
|
onFormContentClick(content: ContentLinkModel): void {
|
||||||
|
this.formContentClicked.emit(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
onFormExecuteOutcome(outcome: FormOutcomeEvent) {
|
||||||
|
this.executeOutcome.emit(outcome);
|
||||||
|
}
|
||||||
|
|
||||||
|
onFormError(error: any) {
|
||||||
|
this.formError.emit(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
onError(error: any) {
|
||||||
|
this.error.emit(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
onCompleteTask() {
|
||||||
|
this.taskListService.completeTask(this.taskDetails.id).subscribe(
|
||||||
|
() => this.completed.emit(),
|
||||||
|
(error) => this.error.emit(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
onCancel() {
|
||||||
|
this.cancel.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
onShowAttachForm() {
|
||||||
|
this.showAttachForm.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
hasFormKey(): boolean {
|
||||||
|
return (this.taskDetails && (!!this.taskDetails.formKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
isStandaloneTask(): boolean {
|
||||||
|
return !(this.taskDetails && (!!this.taskDetails.processDefinitionId));
|
||||||
|
}
|
||||||
|
|
||||||
|
isTaskLoaded(): boolean {
|
||||||
|
return !!this.taskDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
isCompletedTask(): boolean {
|
||||||
|
return this.taskDetails && this.taskDetails.endDate !== undefined && this.taskDetails.endDate !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
isCompleteButtonVisible(): boolean {
|
||||||
|
return !this.hasFormKey() && this.isTaskActive() && this.isCompleteButtonEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
isTaskActive() {
|
||||||
|
return this.taskDetails && this.taskDetails.duration === null;
|
||||||
|
}
|
||||||
|
|
||||||
|
isAssigned(): boolean {
|
||||||
|
return !!this.taskDetails.assignee;
|
||||||
|
}
|
||||||
|
|
||||||
|
private hasEmailAddress(): boolean {
|
||||||
|
return this.taskDetails.assignee.email ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
isAssignedToMe(): boolean {
|
||||||
|
return this.isAssigned() && this.hasEmailAddress() ?
|
||||||
|
this.isEmailEqual() :
|
||||||
|
this.isExternalIdEqual();
|
||||||
|
}
|
||||||
|
|
||||||
|
private isEmailEqual(): boolean {
|
||||||
|
return (this.taskDetails.assignee && this.currentLoggedUser) && ( this.taskDetails.assignee.email.toLocaleLowerCase() === this.currentLoggedUser.email.toLocaleLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
private isExternalIdEqual(): boolean {
|
||||||
|
return (this.taskDetails.assignee && this.currentLoggedUser) && (this.taskDetails.assignee.externalId === this.currentLoggedUser.externalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
isCompleteButtonEnabled(): boolean {
|
||||||
|
return this.isAssignedToMe() || this.canInitiatorComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
canInitiatorComplete(): boolean {
|
||||||
|
return this.taskDetails.initiatorCanCompleteTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
isReadOnlyForm(): boolean {
|
||||||
|
return this.internalReadOnlyForm || !(this.isAssignedToMe() || this.canInitiatorComplete());
|
||||||
|
}
|
||||||
|
|
||||||
|
isSaveButtonVisible(): boolean {
|
||||||
|
return this.showFormSaveButton && (!this.canInitiatorComplete() || this.isAssignedToMe());
|
||||||
|
}
|
||||||
|
|
||||||
|
canCompleteTask(): boolean {
|
||||||
|
return !this.isCompletedTask() && this.isAssignedToMe();
|
||||||
|
}
|
||||||
|
|
||||||
|
getCompletedTaskTranslatedMessage(): Observable<string> {
|
||||||
|
return this.translationService.get('ADF_TASK_FORM.COMPLETED_TASK.TITLE', { taskName: this.taskDetails.name });
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,7 @@ export * from './components/checklist.component';
|
|||||||
export * from './components/task-header.component';
|
export * from './components/task-header.component';
|
||||||
export * from './components/no-task-detail-template.directive';
|
export * from './components/no-task-detail-template.directive';
|
||||||
export * from './components/task-filters.component';
|
export * from './components/task-filters.component';
|
||||||
|
export * from './components/task-form/task-form.component';
|
||||||
export * from './components/task-details.component';
|
export * from './components/task-details.component';
|
||||||
export * from './components/task-audit.directive';
|
export * from './components/task-audit.directive';
|
||||||
export * from './components/start-task.component';
|
export * from './components/start-task.component';
|
||||||
|
@ -31,6 +31,7 @@ import { NoTaskDetailsTemplateDirective } from './components/no-task-detail-temp
|
|||||||
import { StartTaskComponent } from './components/start-task.component';
|
import { StartTaskComponent } from './components/start-task.component';
|
||||||
import { TaskAuditDirective } from './components/task-audit.directive';
|
import { TaskAuditDirective } from './components/task-audit.directive';
|
||||||
import { TaskDetailsComponent } from './components/task-details.component';
|
import { TaskDetailsComponent } from './components/task-details.component';
|
||||||
|
import { TaskFormComponent } from './components/task-form/task-form.component';
|
||||||
import { TaskFiltersComponent } from './components/task-filters.component';
|
import { TaskFiltersComponent } from './components/task-filters.component';
|
||||||
import { TaskHeaderComponent } from './components/task-header.component';
|
import { TaskHeaderComponent } from './components/task-header.component';
|
||||||
import { TaskListComponent } from './components/task-list.component';
|
import { TaskListComponent } from './components/task-list.component';
|
||||||
@ -56,6 +57,7 @@ import { FormModule } from '../form/form.module';
|
|||||||
TaskFiltersComponent,
|
TaskFiltersComponent,
|
||||||
TaskListComponent,
|
TaskListComponent,
|
||||||
TaskDetailsComponent,
|
TaskDetailsComponent,
|
||||||
|
TaskFormComponent,
|
||||||
TaskAuditDirective,
|
TaskAuditDirective,
|
||||||
ChecklistComponent,
|
ChecklistComponent,
|
||||||
TaskHeaderComponent,
|
TaskHeaderComponent,
|
||||||
@ -68,6 +70,7 @@ import { FormModule } from '../form/form.module';
|
|||||||
TaskFiltersComponent,
|
TaskFiltersComponent,
|
||||||
TaskListComponent,
|
TaskListComponent,
|
||||||
TaskDetailsComponent,
|
TaskDetailsComponent,
|
||||||
|
TaskFormComponent,
|
||||||
TaskAuditDirective,
|
TaskAuditDirective,
|
||||||
ChecklistComponent,
|
ChecklistComponent,
|
||||||
TaskHeaderComponent,
|
TaskHeaderComponent,
|
||||||
|
@ -26,9 +26,9 @@ export class FormFields {
|
|||||||
saveButton: ElementFinder = element(by.cssContainingText('mat-card-actions[class*="adf-for"] span', 'SAVE'));
|
saveButton: ElementFinder = element(by.cssContainingText('mat-card-actions[class*="adf-for"] span', 'SAVE'));
|
||||||
valueLocator: Locator = by.css('input');
|
valueLocator: Locator = by.css('input');
|
||||||
labelLocator: Locator = by.css('label');
|
labelLocator: Locator = by.css('label');
|
||||||
noFormMessage: ElementFinder = element(by.css('span[id*="no-form-message"]'));
|
noFormMessage: ElementFinder = element(by.css('.adf-empty-content__title'));
|
||||||
completedTaskNoFormMessage: ElementFinder = element(by.css('div[id*="completed-form-message"] p'));
|
completedTaskNoFormMessage: ElementFinder = element(by.css('div[id*="completed-form-message"] p'));
|
||||||
attachFormButton: ElementFinder = element(by.id('adf-no-form-attach-form-button'));
|
attachFormButton: ElementFinder = element(by.id('adf-attach-form-attach-button'));
|
||||||
completeButton: ElementFinder = element(by.id('adf-form-complete'));
|
completeButton: ElementFinder = element(by.id('adf-form-complete'));
|
||||||
errorMessage: Locator = by.css('.adf-error-text-container .adf-error-text');
|
errorMessage: Locator = by.css('.adf-error-text-container .adf-error-text');
|
||||||
|
|
||||||
|
@ -28,9 +28,9 @@ export class FormFieldsPage {
|
|||||||
saveButton: ElementFinder = element(by.cssContainingText('mat-card-actions[class*="adf-for"] span', 'SAVE'));
|
saveButton: ElementFinder = element(by.cssContainingText('mat-card-actions[class*="adf-for"] span', 'SAVE'));
|
||||||
valueLocator: Locator = by.css('input');
|
valueLocator: Locator = by.css('input');
|
||||||
labelLocator: Locator = by.css('label');
|
labelLocator: Locator = by.css('label');
|
||||||
noFormMessage: ElementFinder = element(by.css('span[id*="no-form-message"]'));
|
noFormMessage: ElementFinder = element(by.css('.adf-empty-content__title'));
|
||||||
completedTaskNoFormMessage: ElementFinder = element(by.css('div[id*="completed-form-message"] p'));
|
completedTaskNoFormMessage: ElementFinder = element(by.css('div[id*="completed-form-message"] p'));
|
||||||
attachFormButton: ElementFinder = element(by.id('adf-no-form-attach-form-button'));
|
attachFormButton: ElementFinder = element(by.id('adf-attach-form-attach-button'));
|
||||||
completeButton: ElementFinder = element(by.id('adf-form-complete'));
|
completeButton: ElementFinder = element(by.id('adf-form-complete'));
|
||||||
errorMessage: Locator = by.css('.adf-error-text-container .adf-error-text');
|
errorMessage: Locator = by.css('.adf-error-text-container .adf-error-text');
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user