From ea62b1e3bddd324f7de098a37e50dd861255721d Mon Sep 17 00:00:00 2001 From: siva kumar Date: Wed, 10 Jun 2020 15:13:23 +0530 Subject: [PATCH] [ACA-3416] Add Claim/Release actions on adf task form (#5753) * [ACA-3255] FE - Claim a task * * Added unit tests * * Added unit tests * Changed cloud directive names * * Added/Updated documents * * Added showReleaseClaim button flag * Add unit test too * * Used claim/release directive in task-header component. * * Fixed unit test * * Fixed one comment * * After rebase * * Fixed comments --- .../images/form-custom-outcomes.component.png | Bin 0 -> 13629 bytes ...ctive.md => claim-task-cloud.directive.md} | 12 +- .../unclaim-task-cloud.directive.md | 32 +++++ .../form-custom-outcome.component.md | 34 +++++ .../components/task-form.component.md | 2 + .../components/task-header.component.md | 1 + .../directives/claim-task.directive.md | 31 +++++ .../directives/unclaim-task.directive.md | 11 +- ....ts => claim-task-cloud.directive.spec.ts} | 24 ++-- ...ctive.ts => claim-task-cloud.directive.ts} | 2 +- .../src/lib/task/directives/public-api.ts | 4 +- .../task/directives/task-directive.module.ts | 12 +- ...s => unclaim-task-cloud.directive.spec.ts} | 24 ++-- ...ive.ts => unclaim-task-cloud.directive.ts} | 2 +- .../form/form-custom-outcomes.component.ts | 24 ++++ .../src/lib/form/form.component.html | 1 + .../src/lib/form/form.component.spec.ts | 79 ++++++++++- .../src/lib/form/form.module.ts | 7 +- .../src/lib/form/public-api.ts | 1 + .../components/task-details.component.html | 2 + .../task-form/claim-task.directive.spec.ts | 122 +++++++++++++++++ .../task-form/claim-task.directive.ts | 89 ++++++++++++ .../task-form/task-form.component.html | 22 +++ .../task-form/task-form.component.spec.ts | 127 +++++++++++++++++- .../task-form/task-form.component.ts | 32 +++++ .../task-form/unclaim-task.directive.spec.ts | 126 +++++++++++++++++ .../task-form/unclaim-task.directive.ts | 88 ++++++++++++ .../components/task-header.component.html | 22 ++- .../components/task-header.component.spec.ts | 73 ++++++---- .../components/task-header.component.ts | 34 ++--- .../src/lib/task-list/public-api.ts | 2 + .../src/lib/task-list/task-list.module.ts | 10 +- 32 files changed, 947 insertions(+), 105 deletions(-) create mode 100644 docs/docassets/images/form-custom-outcomes.component.png rename docs/process-services-cloud/directives/{claim-task.directive.md => claim-task-cloud.directive.md} (58%) create mode 100644 docs/process-services-cloud/directives/unclaim-task-cloud.directive.md create mode 100644 docs/process-services/components/form-custom-outcome.component.md create mode 100644 docs/process-services/directives/claim-task.directive.md rename docs/{process-services-cloud => process-services}/directives/unclaim-task.directive.md (62%) rename lib/process-services-cloud/src/lib/task/directives/{claim-task.directive.spec.ts => claim-task-cloud.directive.spec.ts} (88%) rename lib/process-services-cloud/src/lib/task/directives/{claim-task.directive.ts => claim-task-cloud.directive.ts} (97%) rename lib/process-services-cloud/src/lib/task/directives/{unclaim-tast.directive.spec.ts => unclaim-task-cloud.directive.spec.ts} (87%) rename lib/process-services-cloud/src/lib/task/directives/{unclaim-task.directive.ts => unclaim-task-cloud.directive.ts} (97%) create mode 100644 lib/process-services/src/lib/form/form-custom-outcomes.component.ts create mode 100644 lib/process-services/src/lib/task-list/components/task-form/claim-task.directive.spec.ts create mode 100644 lib/process-services/src/lib/task-list/components/task-form/claim-task.directive.ts create mode 100644 lib/process-services/src/lib/task-list/components/task-form/unclaim-task.directive.spec.ts create mode 100644 lib/process-services/src/lib/task-list/components/task-form/unclaim-task.directive.ts diff --git a/docs/docassets/images/form-custom-outcomes.component.png b/docs/docassets/images/form-custom-outcomes.component.png new file mode 100644 index 0000000000000000000000000000000000000000..196445c22c73986740912a04e98f84f498d1df40 GIT binary patch literal 13629 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

3H|m)o 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 KWpibWe*F&=G6ItT literal 0 HcmV?d00001 diff --git a/docs/process-services-cloud/directives/claim-task.directive.md b/docs/process-services-cloud/directives/claim-task-cloud.directive.md similarity index 58% rename from docs/process-services-cloud/directives/claim-task.directive.md rename to docs/process-services-cloud/directives/claim-task-cloud.directive.md index c1a8dba857..b0e2ac335e 100644 --- a/docs/process-services-cloud/directives/claim-task.directive.md +++ b/docs/process-services-cloud/directives/claim-task-cloud.directive.md @@ -1,18 +1,18 @@ --- -Title: Claim Task Directive -Added: v3.1.0 +Title: Claim Task Cloud Directive +Added: v3.9.0 Status: Experimental -Last reviewed: 2019-03-25 +Last reviewed: 2020-06-09 --- -# [Claim task directive](../../../lib/process-services-cloud/src/lib/task/directives/claim-task.directive.ts "Defined in claim-task.directive.ts") +# [Claim task Cloud directive](../../../lib/process-services-cloud/src/lib/task/directives/claim-task-cloud.directive.ts "Defined in claim-task-cloud.directive.ts") Claims a task ## Basic Usage ```html - + ``` ## Class members @@ -22,7 +22,7 @@ Claims a task | Name | Type | Default value | Description | | ---- | ---- | ------------- | ----------- | | appName | `string` | "" | (Required) The name of the application. | -| taskId | `string` | | (Required) The id of the task. | +| taskId | `string` | "" | (Required) The id of the task. | ### Events diff --git a/docs/process-services-cloud/directives/unclaim-task-cloud.directive.md b/docs/process-services-cloud/directives/unclaim-task-cloud.directive.md new file mode 100644 index 0000000000..7c32de34c2 --- /dev/null +++ b/docs/process-services-cloud/directives/unclaim-task-cloud.directive.md @@ -0,0 +1,32 @@ +--- +Title: Unclaim Task Cloud Directive +Added: v3.9.0 +Status: Experimental +Last reviewed: 2020-06-09 +--- + +# [Unclaim Task Cloud directive](../../../lib/process-services-cloud/src/lib/task/directives/unclaim-task-cloud.directive.ts "Defined in unclaim-task-cloud.directive.ts") + +Unclaims a task + +## Basic Usage + +```html + +``` + +## Class members + +### Properties + +| Name | Type | Default value | Description | +| ---- | ---- | ------------- | ----------- | +| appName | `string` | "" | (Required) The name of the application. | +| taskId | `string` | "" | (Required) The id of the task. | + +### Events + +| Name | Type | Description | +| ---- | ---- | ----------- | +| error | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`` | Emitted when the task cannot be completed. | +| success | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`` | Emitted when the task is completed. | diff --git a/docs/process-services/components/form-custom-outcome.component.md b/docs/process-services/components/form-custom-outcome.component.md new file mode 100644 index 0000000000..b7a7e867bf --- /dev/null +++ b/docs/process-services/components/form-custom-outcome.component.md @@ -0,0 +1,34 @@ +--- +Title: Form custom outcomes component +Added: v3.9.0 +Status: Active +Last reviewed: 2020-06-09 +--- + +# [Form custom outcomes component](../../../lib/process-services/src/lib/form/form-custom-outcomes.component.ts "Defined in form-custom-outcomes.component.ts") + +Supplies custom outcome buttons to be included in [Form component](form.component.md). + +![](../../docassets/images/form-custom-outcomes.component.png) + +## Basic Usage + +```html + + + + + + + +``` + +## See Also + +- [Form component](form.component.md) diff --git a/docs/process-services/components/task-form.component.md b/docs/process-services/components/task-form.component.md index 099bc1f2d0..8f1fe3c599 100644 --- a/docs/process-services/components/task-form.component.md +++ b/docs/process-services/components/task-form.component.md @@ -47,6 +47,8 @@ Shows a [`form`](../../../lib/process-services/src/lib/task-list/models/form.mod | 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. | | 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. | | showAttachForm | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`` | Emitted when the form associated with the form task is attached. | +| taskClaimed | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`` | Emitted when the task is claimed. | +| taskUnclaimed | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`` | Emitted when the task is unclaimed (ie, requeued). | ## See also diff --git a/docs/process-services/components/task-header.component.md b/docs/process-services/components/task-header.component.md index 59fcdb44f6..f8927caadb 100644 --- a/docs/process-services/components/task-header.component.md +++ b/docs/process-services/components/task-header.component.md @@ -27,6 +27,7 @@ Shows all the information related to a task. | ---- | ---- | ------------- | ----------- | | formName | `string` | null | The name of the form. | | taskDetails | [`TaskDetailsModel`](../../../lib/process-services/src/lib/task-list/models/task-details.model.ts) | | (required) Details related to the task. | +| showClaimRelease | `boolean` | true | Toggles display of the claim/release button. | ### Events diff --git a/docs/process-services/directives/claim-task.directive.md b/docs/process-services/directives/claim-task.directive.md new file mode 100644 index 0000000000..c6ca70f042 --- /dev/null +++ b/docs/process-services/directives/claim-task.directive.md @@ -0,0 +1,31 @@ +--- +Title: Claim Task Directive +Added: v3.9.0 +Status: Experimental +Last reviewed: 2020-06-09 +--- + +# [Claim task directive](../../../lib/process-services/src/lib/task-list/components/task-form/claim-task.directive.ts "Defined in claim-task.directive.ts") + +Claims a task + +## Basic Usage + +```html + +``` + +## Class members + +### Properties + +| Name | Type | Default value | Description | +| ---- | ---- | ------------- | ----------- | +| taskId | `string` | "" | (Required) The id of the task. | + +### Events + +| Name | Type | Description | +| ---- | ---- | ----------- | +| error | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`` | Emitted when the task cannot be completed. | +| success | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`` | Emitted when the task is completed. | diff --git a/docs/process-services-cloud/directives/unclaim-task.directive.md b/docs/process-services/directives/unclaim-task.directive.md similarity index 62% rename from docs/process-services-cloud/directives/unclaim-task.directive.md rename to docs/process-services/directives/unclaim-task.directive.md index 75d0c576f6..d6ba50ebb1 100644 --- a/docs/process-services-cloud/directives/unclaim-task.directive.md +++ b/docs/process-services/directives/unclaim-task.directive.md @@ -1,18 +1,18 @@ --- Title: Unclaim Task Directive -Added: v3.1.0 +Added: v3.9.0 Status: Experimental -Last reviewed: 2019-03-25 +Last reviewed: 2020-06-09 --- -# [Unclaim task directive](../../../lib/process-services-cloud/src/lib/task/directives/unclaim-task.directive.ts "Defined in unclaim-task.directive.ts") +# [Unclaim Task directive](../../../lib/process-services/src/lib/task-list/components/task-form/unclaim-task.directive.ts "Defined in unclaim-task.directive.ts") Unclaims a task ## Basic Usage ```html - + ``` ## Class members @@ -21,8 +21,7 @@ Unclaims a task | Name | Type | Default value | Description | | ---- | ---- | ------------- | ----------- | -| appName | `string` | "" | (Required) The name of the application. | -| taskId | `string` | | (Required) The id of the task. | +| taskId | `string` | "" | (Required) The id of the task. | ### Events diff --git a/lib/process-services-cloud/src/lib/task/directives/claim-task.directive.spec.ts b/lib/process-services-cloud/src/lib/task/directives/claim-task-cloud.directive.spec.ts similarity index 88% rename from lib/process-services-cloud/src/lib/task/directives/claim-task.directive.spec.ts rename to lib/process-services-cloud/src/lib/task/directives/claim-task-cloud.directive.spec.ts index a02d7b522a..70414451e1 100644 --- a/lib/process-services-cloud/src/lib/task/directives/claim-task.directive.spec.ts +++ b/lib/process-services-cloud/src/lib/task/directives/claim-task-cloud.directive.spec.ts @@ -19,12 +19,12 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { setupTestBed } from '@alfresco/adf-core'; import { TaskCloudService } from '../services/task-cloud.service'; import { of } from 'rxjs'; -import { ClaimTaskDirective } from './claim-task.directive'; +import { ClaimTaskCloudDirective } from './claim-task-cloud.directive'; import { taskClaimCloudMock } from '../task-header/mocks/fake-claim-task.mock'; import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module'; import { TranslateModule } from '@ngx-translate/core'; -describe('ClaimTaskDirective', () => { +describe('ClaimTaskCloudDirective', () => { @Component({ selector: 'adf-cloud-claim-test-component', @@ -35,8 +35,8 @@ describe('ClaimTaskDirective', () => { taskMock = 'test1234'; appNameMock = 'simple-app'; - @ViewChild(ClaimTaskDirective) - claimTaskDirective: ClaimTaskDirective; + @ViewChild(ClaimTaskCloudDirective) + claimTaskDirective: ClaimTaskCloudDirective; } let fixture: ComponentFixture; @@ -78,8 +78,8 @@ describe('Claim Task Directive validation errors', () => { appNameUndefined = undefined; appNameNull = null; - @ContentChildren(ClaimTaskDirective) - claimTaskValidationDirective: ClaimTaskDirective; + @ContentChildren(ClaimTaskCloudDirective) + claimTaskValidationDirective: ClaimTaskCloudDirective; } @Component({ @@ -90,8 +90,8 @@ describe('Claim Task Directive validation errors', () => { appName = 'simple-app'; - @ContentChildren(ClaimTaskDirective) - claimTaskValidationDirective: ClaimTaskDirective; + @ContentChildren(ClaimTaskCloudDirective) + claimTaskValidationDirective: ClaimTaskCloudDirective; } @Component({ @@ -103,8 +103,8 @@ describe('Claim Task Directive validation errors', () => { appNameUndefined = undefined; taskMock = 'test1234'; - @ContentChildren(ClaimTaskDirective) - claimTaskValidationDirective: ClaimTaskDirective; + @ContentChildren(ClaimTaskCloudDirective) + claimTaskValidationDirective: ClaimTaskCloudDirective; } @Component({ @@ -116,8 +116,8 @@ describe('Claim Task Directive validation errors', () => { appNameNull = null; taskMock = 'test1234'; - @ViewChild(ClaimTaskDirective) - claimTaskValidationDirective: ClaimTaskDirective; + @ViewChild(ClaimTaskCloudDirective) + claimTaskValidationDirective: ClaimTaskCloudDirective; } let fixture: ComponentFixture; diff --git a/lib/process-services-cloud/src/lib/task/directives/claim-task.directive.ts b/lib/process-services-cloud/src/lib/task/directives/claim-task-cloud.directive.ts similarity index 97% rename from lib/process-services-cloud/src/lib/task/directives/claim-task.directive.ts rename to lib/process-services-cloud/src/lib/task/directives/claim-task-cloud.directive.ts index c106285f7c..1fc45e062c 100644 --- a/lib/process-services-cloud/src/lib/task/directives/claim-task.directive.ts +++ b/lib/process-services-cloud/src/lib/task/directives/claim-task-cloud.directive.ts @@ -22,7 +22,7 @@ import { TaskCloudService } from '../services/task-cloud.service'; // tslint:disable-next-line: directive-selector selector: '[adf-cloud-claim-task]' }) -export class ClaimTaskDirective implements OnInit { +export class ClaimTaskCloudDirective implements OnInit { /** (Required) The id of the task. */ @Input() diff --git a/lib/process-services-cloud/src/lib/task/directives/public-api.ts b/lib/process-services-cloud/src/lib/task/directives/public-api.ts index 86f452a53e..bbf339e8d6 100644 --- a/lib/process-services-cloud/src/lib/task/directives/public-api.ts +++ b/lib/process-services-cloud/src/lib/task/directives/public-api.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -export * from './claim-task.directive'; -export * from './unclaim-task.directive'; +export * from './claim-task-cloud.directive'; +export * from './unclaim-task-cloud.directive'; export * from './complete-task.directive'; export * from './task-directive.module'; diff --git a/lib/process-services-cloud/src/lib/task/directives/task-directive.module.ts b/lib/process-services-cloud/src/lib/task/directives/task-directive.module.ts index 50aad9c624..632774f6a5 100644 --- a/lib/process-services-cloud/src/lib/task/directives/task-directive.module.ts +++ b/lib/process-services-cloud/src/lib/task/directives/task-directive.module.ts @@ -17,19 +17,19 @@ import { NgModule } from '@angular/core'; import { CompleteTaskDirective } from './complete-task.directive'; -import { ClaimTaskDirective } from './claim-task.directive'; -import { UnClaimTaskDirective } from './unclaim-task.directive'; +import { ClaimTaskCloudDirective } from './claim-task-cloud.directive'; +import { UnClaimTaskCloudDirective } from './unclaim-task-cloud.directive'; @NgModule({ declarations: [ CompleteTaskDirective, - ClaimTaskDirective, - UnClaimTaskDirective + ClaimTaskCloudDirective, + UnClaimTaskCloudDirective ], exports: [ CompleteTaskDirective, - ClaimTaskDirective, - UnClaimTaskDirective + ClaimTaskCloudDirective, + UnClaimTaskCloudDirective ] }) export class TaskDirectiveModule { } diff --git a/lib/process-services-cloud/src/lib/task/directives/unclaim-tast.directive.spec.ts b/lib/process-services-cloud/src/lib/task/directives/unclaim-task-cloud.directive.spec.ts similarity index 87% rename from lib/process-services-cloud/src/lib/task/directives/unclaim-tast.directive.spec.ts rename to lib/process-services-cloud/src/lib/task/directives/unclaim-task-cloud.directive.spec.ts index c47eff2d9c..1ce43ac148 100644 --- a/lib/process-services-cloud/src/lib/task/directives/unclaim-tast.directive.spec.ts +++ b/lib/process-services-cloud/src/lib/task/directives/unclaim-task-cloud.directive.spec.ts @@ -19,12 +19,12 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { setupTestBed } from '@alfresco/adf-core'; import { TaskCloudService } from '../services/task-cloud.service'; import { of } from 'rxjs'; -import { UnClaimTaskDirective } from './unclaim-task.directive'; +import { UnClaimTaskCloudDirective } from './unclaim-task-cloud.directive'; import { taskClaimCloudMock } from '../task-header/mocks/fake-claim-task.mock'; import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module'; import { TranslateModule } from '@ngx-translate/core'; -describe('UnClaimTaskDirective', () => { +describe('UnClaimTaskCloudDirective', () => { @Component({ selector: 'adf-cloud-test-component', @@ -35,8 +35,8 @@ describe('UnClaimTaskDirective', () => { appName = 'simple-app'; taskIdMock = '1234'; - @ContentChildren(UnClaimTaskDirective) - unclaimTaskDirective: UnClaimTaskDirective; + @ContentChildren(UnClaimTaskCloudDirective) + unclaimTaskDirective: UnClaimTaskCloudDirective; } let fixture: ComponentFixture; @@ -78,8 +78,8 @@ describe('UnClaim Task Directive validation errors', () => { appNameUndefined = undefined; appNameNull = null; - @ContentChildren(UnClaimTaskDirective) - claimTaskValidationDirective: UnClaimTaskDirective; + @ContentChildren(UnClaimTaskCloudDirective) + claimTaskValidationDirective: UnClaimTaskCloudDirective; } @Component({ @@ -90,8 +90,8 @@ describe('UnClaim Task Directive validation errors', () => { appName = 'simple-app'; - @ContentChildren(UnClaimTaskDirective) - claimTaskValidationDirective: UnClaimTaskDirective; + @ContentChildren(UnClaimTaskCloudDirective) + claimTaskValidationDirective: UnClaimTaskCloudDirective; } @Component({ @@ -103,8 +103,8 @@ describe('UnClaim Task Directive validation errors', () => { appNameUndefined = undefined; taskMock = 'test1234'; - @ContentChildren(UnClaimTaskDirective) - claimTaskValidationDirective: UnClaimTaskDirective; + @ContentChildren(UnClaimTaskCloudDirective) + claimTaskValidationDirective: UnClaimTaskCloudDirective; } @Component({ @@ -116,8 +116,8 @@ describe('UnClaim Task Directive validation errors', () => { appNameNull = null; taskMock = 'test1234'; - @ViewChild(UnClaimTaskDirective) - claimTaskValidationDirective: UnClaimTaskDirective; + @ViewChild(UnClaimTaskCloudDirective) + claimTaskValidationDirective: UnClaimTaskCloudDirective; } let fixture: ComponentFixture; diff --git a/lib/process-services-cloud/src/lib/task/directives/unclaim-task.directive.ts b/lib/process-services-cloud/src/lib/task/directives/unclaim-task-cloud.directive.ts similarity index 97% rename from lib/process-services-cloud/src/lib/task/directives/unclaim-task.directive.ts rename to lib/process-services-cloud/src/lib/task/directives/unclaim-task-cloud.directive.ts index 0e5ffc68f4..8897122541 100644 --- a/lib/process-services-cloud/src/lib/task/directives/unclaim-task.directive.ts +++ b/lib/process-services-cloud/src/lib/task/directives/unclaim-task-cloud.directive.ts @@ -21,7 +21,7 @@ import { TaskCloudService } from '../services/task-cloud.service'; // tslint:disable-next-line: directive-selector selector: '[adf-cloud-unclaim-task]' }) -export class UnClaimTaskDirective implements OnInit { +export class UnClaimTaskCloudDirective implements OnInit { /** (Required) The id of the task. */ @Input() diff --git a/lib/process-services/src/lib/form/form-custom-outcomes.component.ts b/lib/process-services/src/lib/form/form-custom-outcomes.component.ts new file mode 100644 index 0000000000..0af452b08d --- /dev/null +++ b/lib/process-services/src/lib/form/form-custom-outcomes.component.ts @@ -0,0 +1,24 @@ +/*! + * @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 } from '@angular/core'; + +@Component({ + selector: 'adf-form-custom-outcomes', + template: '' +}) +export class FormCustomOutcomesComponent {} diff --git a/lib/process-services/src/lib/form/form.component.html b/lib/process-services/src/lib/form/form.component.html index 5088c2c255..a0a27660c2 100644 --- a/lib/process-services/src/lib/form/form.component.html +++ b/lib/process-services/src/lib/form/form.component.html @@ -34,6 +34,7 @@ + + + + ` +}) + +class FormWithCustomOutComesComponent { + + @ViewChild('adfForm') + adfForm: FormComponent; + + onCustomButtonOneClick() { } + onCustomButtonTwoClick() { } +} + +describe('FormWithCustomOutComesComponent', () => { + + let fixture: ComponentFixture; + let customComponent: FormWithCustomOutComesComponent; + let debugElement: DebugElement; + + setupTestBed({ + imports: [ + TranslateModule.forRoot(), + ProcessTestingModule + ], + declarations: [FormWithCustomOutComesComponent] + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FormWithCustomOutComesComponent); + customComponent = fixture.componentInstance; + debugElement = fixture.debugElement; + const formRepresentation = { + fields: [ + { id: 'container1' } + ], + outcomes: [ + { id: 'outcome-1', name: 'outcome 1' } + ] + }; + + const form = new FormModel(formRepresentation); + customComponent.adfForm.form = form; + fixture.detectChanges(); + }); + + afterEach(() => { + fixture.destroy(); + }); + + it('should be able to inject custom outcomes and click on custom outcomes', () => { + const onCustomButtonOneSpy = spyOn(customComponent, 'onCustomButtonOneClick').and.callThrough(); + const buttonOneBtn = debugElement.query(By.css('#adf-custom-outcome-1')); + const buttonTwoBtn = debugElement.query(By.css('#adf-custom-outcome-2')); + + expect(buttonOneBtn).not.toBeNull(); + expect(buttonTwoBtn).not.toBeNull(); + + buttonOneBtn.nativeElement.click(); + + expect(onCustomButtonOneSpy).toHaveBeenCalled(); + expect(buttonOneBtn.nativeElement.innerText).toBe('CUSTOM-BUTTON-1'); + expect(buttonTwoBtn.nativeElement.innerText).toBe('CUSTOM-BUTTON-2'); + }); +}); diff --git a/lib/process-services/src/lib/form/form.module.ts b/lib/process-services/src/lib/form/form.module.ts index ac1d490143..17e7bf49cb 100644 --- a/lib/process-services/src/lib/form/form.module.ts +++ b/lib/process-services/src/lib/form/form.module.ts @@ -20,6 +20,7 @@ import { MaterialModule } from '../material.module'; import { CoreModule } from '@alfresco/adf-core'; import { FormComponent } from './form.component'; import { StartFormComponent } from './start-form.component'; +import { FormCustomOutcomesComponent } from './form-custom-outcomes.component'; @NgModule({ imports: [ @@ -28,11 +29,13 @@ import { StartFormComponent } from './start-form.component'; ], declarations: [ FormComponent, - StartFormComponent + StartFormComponent, + FormCustomOutcomesComponent ], exports: [ FormComponent, - StartFormComponent + StartFormComponent, + FormCustomOutcomesComponent ] }) export class FormModule {} diff --git a/lib/process-services/src/lib/form/public-api.ts b/lib/process-services/src/lib/form/public-api.ts index 58d4813277..d16c7c3488 100644 --- a/lib/process-services/src/lib/form/public-api.ts +++ b/lib/process-services/src/lib/form/public-api.ts @@ -18,4 +18,5 @@ export * from './form.component'; export * from './start-form.component'; export * from './process-form-rendering.service'; +export * from './form-custom-outcomes.component'; export * from './form.module'; diff --git a/lib/process-services/src/lib/task-list/components/task-details.component.html b/lib/process-services/src/lib/task-list/components/task-details.component.html index a8c352a037..42a187fd61 100644 --- a/lib/process-services/src/lib/task-list/components/task-details.component.html +++ b/lib/process-services/src/lib/task-list/components/task-details.component.html @@ -35,6 +35,8 @@ (completed)="onComplete()" (showAttachForm)="onShowAttachForm()" (executeOutcome)='onFormExecuteOutcome($event)' + (taskClaimed)="onClaimAction($event)" + (taskUnclaimed)="onUnclaimAction($event)" (error)="onFormError($event)" #activitiTaskForm> { + + @Component({ + selector: 'adf-claim-test-component', + template: '' + }) + class TestComponent { + taskId = 'test1234'; + @Output() + claim: EventEmitter = new EventEmitter(); + + onClaim(event) { + this.claim.emit(event); + } + } + + let fixture: ComponentFixture; + let taskListService: TaskListService; + + setupTestBed({ + imports: [ + ProcessTestingModule + ], + declarations: [ + TestComponent + ] + }); + + beforeEach(() => { + taskListService = TestBed.get(TaskListService); + fixture = TestBed.createComponent(TestComponent); + fixture.detectChanges(); + }); + + it('Should be able to call claim task service', () => { + const claimTaskSpy = spyOn(taskListService, 'claimTask').and.returnValue(of({})); + + const button = fixture.nativeElement.querySelector('button'); + button.click(); + + expect(claimTaskSpy).toHaveBeenCalledWith(fixture.componentInstance.taskId); + }); + + it('Should be able to catch success event on click of claim button', async() => { + spyOn(taskListService, 'claimTask').and.returnValue(of({})); + const unclaimSpy = spyOn(fixture.componentInstance.claim, 'emit'); + + const button = fixture.nativeElement.querySelector('button'); + button.click(); + fixture.detectChanges(); + await fixture.whenStable(); + + expect(unclaimSpy).toHaveBeenCalledWith(fixture.componentInstance.taskId); + }); +}); + +describe('Claim Task Directive validation errors', () => { + + @Component({ + selector: 'adf-claim-no-fields-validation-component', + template: '' + }) + class ClaimTestMissingInputDirectiveComponent { } + + @Component({ + selector: 'adf-claim-no-taskid-validation-component', + template: '' + }) + class ClaimTestMissingTaskIdDirectiveComponent { } + + let fixture: ComponentFixture; + + setupTestBed({ + imports: [ + ProcessTestingModule + ], + declarations: [ + ClaimTestMissingTaskIdDirectiveComponent, + ClaimTestMissingInputDirectiveComponent + ] + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ClaimTestMissingInputDirectiveComponent); + }); + + it('should throw error when missing input', () => { + fixture = TestBed.createComponent(ClaimTestMissingInputDirectiveComponent); + + expect(() => fixture.detectChanges()).toThrowError(); + }); + + it('should throw error when taskId is not set', () => { + fixture = TestBed.createComponent(ClaimTestMissingTaskIdDirectiveComponent); + + expect( () => fixture.detectChanges()).toThrowError('Attribute taskId is required'); + }); +}); diff --git a/lib/process-services/src/lib/task-list/components/task-form/claim-task.directive.ts b/lib/process-services/src/lib/task-list/components/task-form/claim-task.directive.ts new file mode 100644 index 0000000000..d2bdcd7ffa --- /dev/null +++ b/lib/process-services/src/lib/task-list/components/task-form/claim-task.directive.ts @@ -0,0 +1,89 @@ +/*! + * @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 { + Directive, + Input, + Output, + EventEmitter, + HostListener +} from '@angular/core'; +import { TaskListService } from '../../services/tasklist.service'; +import { LogService } from '@alfresco/adf-core'; + +@Directive({ + // tslint:disable-next-line: directive-selector + selector: '[adf-claim-task]' +}) +export class ClaimTaskDirective { + /** (Required) The id of the task. */ + @Input() + taskId: string; + + /** Emitted when the task is claimed. */ + @Output() + success: EventEmitter = new EventEmitter(); + + /** Emitted when the task cannot be claimed. */ + @Output() + error: EventEmitter = new EventEmitter(); + + invalidParams: string[] = []; + + constructor( + private taskListService: TaskListService, + private logService: LogService) {} + + ngOnInit() { + this.validateInputs(); + } + + validateInputs() { + if (!this.isTaskValid()) { + this.invalidParams.push('taskId'); + } + + if (this.invalidParams.length) { + throw new Error( + `Attribute ${this.invalidParams.join(', ')} is required` + ); + } + } + + isTaskValid(): boolean { + return this.taskId && this.taskId.length > 0; + } + + @HostListener('click') + async onClick() { + try { + this.claimTask(); + } catch (error) { + this.error.emit(error); + } + } + + private async claimTask() { + await this.taskListService.claimTask(this.taskId).subscribe( + () => { + this.logService.info('Task claimed'); + this.success.emit(this.taskId); + }, + error => this.error.emit(error) + ); + } +} diff --git a/lib/process-services/src/lib/task-list/components/task-form/task-form.component.html b/lib/process-services/src/lib/task-list/components/task-form/task-form.component.html index b51dec7261..3ba824ba04 100644 --- a/lib/process-services/src/lib/task-list/components/task-form/task-form.component.html +++ b/lib/process-services/src/lib/task-list/components/task-form/task-form.component.html @@ -16,6 +16,10 @@ (formError)='onFormError($event)' (error)='onError($event)' (executeOutcome)='onFormExecuteOutcome($event)'> + + + + + @@ -66,6 +71,23 @@ + + + + +

diff --git a/lib/process-services/src/lib/task-list/components/task-form/task-form.component.spec.ts b/lib/process-services/src/lib/task-list/components/task-form/task-form.component.spec.ts index d109016e1a..a14c149544 100644 --- a/lib/process-services/src/lib/task-list/components/task-form/task-form.component.spec.ts +++ b/lib/process-services/src/lib/task-list/components/task-form/task-form.component.spec.ts @@ -37,11 +37,15 @@ import { standaloneTaskWithoutForm, completedStandaloneTaskWithoutForm, claimableTaskDetailsMock, - initiatorCanCompleteTaskDetailsMock + initiatorCanCompleteTaskDetailsMock, + taskDetailsWithOutCandidateGroup, + claimedTaskDetailsMock, + claimedByGroupMemberMock } from '../../../mock/task/task-details.mock'; import { TaskDetailsModel } from '../../models/task-details.model'; import { ProcessTestingModule } from '../../../testing/process.testing.module'; import { TranslateModule } from '@ngx-translate/core'; +import { By } from '@angular/platform-browser'; describe('TaskFormComponent', () => { let component: TaskFormComponent; @@ -495,4 +499,125 @@ describe('TaskFormComponent', () => { expect(validationForm.textContent).toBe('check_circle'); }); }); + + describe('Claim/Unclaim buttons', () => { + + it('should display the claim button if no assignee', async() => { + getTaskDetailsSpy.and.returnValue(of(claimableTaskDetailsMock)); + + component.taskId = 'mock-task-id'; + fixture.detectChanges(); + await fixture.whenStable(); + + const claimButton = fixture.debugElement.query(By.css('[data-automation-id="adf-task-form-claim-button"]')); + expect(claimButton.nativeElement.innerText).toBe('ADF_TASK_LIST.DETAILS.BUTTON.CLAIM'); + }); + + it('should not display the claim/requeue button if the task is not claimable ', async() => { + getTaskDetailsSpy.and.returnValue(of(taskDetailsWithOutCandidateGroup)); + + component.taskId = 'mock-task-id'; + fixture.detectChanges(); + + await fixture.whenStable(); + const claimButton = fixture.debugElement.query(By.css('[data-automation-id="adf-task-form-claim-button"]')); + const unclaimButton = fixture.debugElement.query(By.css('[data-automation-id="adf-task-form-unclaim-button"]')); + + expect(component.isTaskClaimable()).toBe(false); + expect(component.isTaskClaimedByCandidateMember()).toBe(false); + expect(unclaimButton).toBeNull(); + expect(claimButton).toBeNull(); + }); + + it('should display the claim button if the task is claimable', async() => { + getTaskDetailsSpy.and.returnValue(of(claimableTaskDetailsMock)); + + component.taskId = 'mock-task-id'; + fixture.detectChanges(); + await fixture.whenStable(); + + const claimButton = fixture.debugElement.query(By.css('[data-automation-id="adf-task-form-claim-button"]')); + + expect(component.isTaskClaimable()).toBe(true); + expect(claimButton.nativeElement.innerText).toBe('ADF_TASK_LIST.DETAILS.BUTTON.CLAIM'); + }); + + it('should display the release button if task is claimed by the current logged-in user', async() => { + getBpmLoggedUserSpy.and.returnValue(of(claimedTaskDetailsMock.assignee)); + getTaskDetailsSpy.and.returnValue(of(claimedTaskDetailsMock)); + + component.taskId = 'mock-task-id'; + fixture.detectChanges(); + await fixture.whenStable(); + + const unclaimButton = fixture.debugElement.query(By.css('[data-automation-id="adf-task-form-unclaim-button"]')); + + expect(component.isTaskClaimedByCandidateMember()).toBe(true); + expect(unclaimButton.nativeElement.innerText).toBe('ADF_TASK_LIST.DETAILS.BUTTON.UNCLAIM'); + }); + + it('should not display the release button to logged in user if task is claimed by other candidate member', async() => { + getTaskDetailsSpy.and.returnValue(of(claimedByGroupMemberMock)); + + component.taskId = 'mock-task-id'; + fixture.detectChanges(); + await fixture.whenStable(); + + const unclaimButton = fixture.debugElement.query(By.css('[data-automation-id="adf-task-form-unclaim-button"]')); + + expect(component.isTaskClaimedByCandidateMember()).toBe(false); + expect(unclaimButton).toBeNull(); + }); + + it('should not display the release button if the task is completed', async() => { + getTaskDetailsSpy.and.returnValue(of(completedTaskDetailsMock)); + + component.taskId = 'mock-task-id'; + fixture.detectChanges(); + await fixture.whenStable(); + + const claimButton = fixture.debugElement.query(By.css('[data-automation-id="adf-task-form-claim-button"]')); + const unclaimButton = fixture.debugElement.query(By.css('[data-automation-id="adf-task-form-unclaim-button"]')); + + expect(claimButton).toBeNull(); + expect(unclaimButton).toBeNull(); + }); + + it('should emit taskClaimed when task is claimed', (done) => { + spyOn(taskListService, 'claimTask').and.returnValue(of({})); + getTaskDetailsSpy.and.returnValue(of(claimableTaskDetailsMock)); + + component.taskId = 'mock-task-id'; + + component.taskClaimed.subscribe((taskId) => { + expect(taskId).toEqual(component.taskId); + done(); + }); + + component.ngOnInit(); + fixture.detectChanges(); + + const claimBtn = fixture.debugElement.query(By.css('[adf-claim-task]')); + claimBtn.nativeElement.click(); + }); + + it('should emit taskUnClaimed when task is unclaimed', (done) => { + spyOn(taskListService, 'unclaimTask').and.returnValue(of({})); + getBpmLoggedUserSpy.and.returnValue(of(claimedTaskDetailsMock.assignee)); + getTaskDetailsSpy.and.returnValue(of(claimedTaskDetailsMock)); + + component.taskId = 'mock-task-id'; + + component.taskUnclaimed.subscribe((taskId: string) => { + expect(taskId).toEqual(component.taskId); + done(); + }); + + component.ngOnInit(); + fixture.detectChanges(); + + const unclaimBtn = fixture.debugElement.query(By.css('[adf-unclaim-task]')); + unclaimBtn.nativeElement.click(); + }); + }); }); diff --git a/lib/process-services/src/lib/task-list/components/task-form/task-form.component.ts b/lib/process-services/src/lib/task-list/components/task-form/task-form.component.ts index b53caf4ee3..77dca180fc 100644 --- a/lib/process-services/src/lib/task-list/components/task-form/task-form.component.ts +++ b/lib/process-services/src/lib/task-list/components/task-form/task-form.component.ts @@ -117,6 +117,14 @@ export class TaskFormComponent implements OnInit { @Output() cancel = new EventEmitter(); + /** Emitted when the task is claimed. */ + @Output() + taskClaimed = new EventEmitter(); + + /** Emitted when the task is unclaimed (ie, requeued).. */ + @Output() + taskUnclaimed = new EventEmitter(); + taskDetails: TaskDetailsModel; currentLoggedUser: UserRepresentation; loading: boolean = false; @@ -278,4 +286,28 @@ export class TaskFormComponent implements OnInit { getCompletedTaskTranslatedMessage(): Observable { return this.translationService.get('ADF_TASK_FORM.COMPLETED_TASK.TITLE', { taskName: this.taskDetails.name }); } + + isCandidateMember(): boolean { + return this.taskDetails.managerOfCandidateGroup || this.taskDetails.memberOfCandidateGroup || this.taskDetails.memberOfCandidateUsers; + } + + isTaskClaimable(): boolean { + return this.isCandidateMember() && !this.isAssigned(); + } + + isTaskClaimedByCandidateMember(): boolean { + return this.isCandidateMember() && this.isAssignedToMe() && !this.isCompletedTask(); + } + + reloadTask() { + this.loadTask(this.taskId); + } + + onClaimTask(taskId: string) { + this.taskClaimed.emit(taskId); + } + + onUnclaimTask(taskId: string) { + this.taskUnclaimed.emit(taskId); + } } diff --git a/lib/process-services/src/lib/task-list/components/task-form/unclaim-task.directive.spec.ts b/lib/process-services/src/lib/task-list/components/task-form/unclaim-task.directive.spec.ts new file mode 100644 index 0000000000..43bd1d48df --- /dev/null +++ b/lib/process-services/src/lib/task-list/components/task-form/unclaim-task.directive.spec.ts @@ -0,0 +1,126 @@ +/*! + * @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, Output, EventEmitter } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { setupTestBed } from '@alfresco/adf-core'; +import { of } from 'rxjs'; +import { TaskListService } from '../../services/tasklist.service'; +import { ProcessTestingModule } from '../../../testing/process.testing.module'; + +describe('UnclaimTaskDirective', () => { + + @Component({ + selector: 'adf-unclaim-test-component', + template: '' + }) + class TestComponent { + taskId = 'test1234'; + @Output() + unclaim: EventEmitter = new EventEmitter(); + + onUnclaim(event) { + this.unclaim.emit(event); + } + } + + let fixture: ComponentFixture; + let taskListService: TaskListService; + + setupTestBed({ + imports: [ + ProcessTestingModule + ], + declarations: [ + TestComponent + ] + }); + + beforeEach(() => { + taskListService = TestBed.get(TaskListService); + fixture = TestBed.createComponent(TestComponent); + fixture.detectChanges(); + }); + + it('Should be able to call unclaim task service', () => { + const claimTaskSpy = spyOn(taskListService, 'unclaimTask').and.returnValue(of({})); + + const button = fixture.nativeElement.querySelector('button'); + button.click(); + + expect(claimTaskSpy).toHaveBeenCalledWith(fixture.componentInstance.taskId); + }); + + it('Should be able to catch success event on click of unclaim button', async() => { + spyOn(taskListService, 'unclaimTask').and.returnValue(of({})); + const unclaimSpy = spyOn(fixture.componentInstance.unclaim, 'emit'); + + const button = fixture.nativeElement.querySelector('button'); + button.click(); + fixture.detectChanges(); + await fixture.whenStable(); + + expect(unclaimSpy).toHaveBeenCalledWith(fixture.componentInstance.taskId); + }); +}); + +describe('Claim Task Directive validation errors', () => { + + @Component({ + selector: 'adf-unclaim-no-fields-validation-component', + template: '' + }) + class ClaimTestMissingInputDirectiveComponent { + + } + + @Component({ + selector: 'adf-claim-no-taskid-validation-component', + template: '' + }) + class ClaimTestMissingTaskIdDirectiveComponent { + + } + + let fixture: ComponentFixture; + + setupTestBed({ + imports: [ + ProcessTestingModule + ], + declarations: [ + ClaimTestMissingTaskIdDirectiveComponent, + ClaimTestMissingInputDirectiveComponent + ] + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ClaimTestMissingInputDirectiveComponent); + }); + + it('should throw error when missing input', () => { + fixture = TestBed.createComponent(ClaimTestMissingInputDirectiveComponent); + + expect(() => fixture.detectChanges()).toThrowError(); + }); + + it('should throw error when taskId is not set', () => { + fixture = TestBed.createComponent(ClaimTestMissingTaskIdDirectiveComponent); + + expect( () => fixture.detectChanges()).toThrowError('Attribute taskId is required'); + }); +}); diff --git a/lib/process-services/src/lib/task-list/components/task-form/unclaim-task.directive.ts b/lib/process-services/src/lib/task-list/components/task-form/unclaim-task.directive.ts new file mode 100644 index 0000000000..57f1812c0b --- /dev/null +++ b/lib/process-services/src/lib/task-list/components/task-form/unclaim-task.directive.ts @@ -0,0 +1,88 @@ +/*! + * @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 { + Directive, + HostListener, + Input, + Output, + EventEmitter +} from '@angular/core'; +import { TaskListService } from '../../services/tasklist.service'; +import { LogService } from '@alfresco/adf-core'; + +@Directive({ + // tslint:disable-next-line: directive-selector + selector: '[adf-unclaim-task]' +}) +export class UnclaimTaskDirective { + /** (Required) The id of the task. */ + @Input() + taskId: string; + + /** Emitted when the task is released. */ + @Output() + success: EventEmitter = new EventEmitter(); + + /** Emitted when the task cannot be released. */ + @Output() + error: EventEmitter = new EventEmitter(); + + invalidParams: string[] = []; + + constructor( + private taskListService: TaskListService, + private logService: LogService) {} + + ngOnInit() { + this.validateInputs(); + } + + validateInputs() { + if (!this.isTaskValid()) { + this.invalidParams.push('taskId'); + } + if (this.invalidParams.length) { + throw new Error( + `Attribute ${this.invalidParams.join(', ')} is required` + ); + } + } + + isTaskValid(): boolean { + return this.taskId && this.taskId.length > 0; + } + + @HostListener('click') + async onClick() { + try { + this.unclaimTask(); + } catch (error) { + this.error.emit(error); + } + } + + private async unclaimTask() { + await this.taskListService.unclaimTask(this.taskId).subscribe( + () => { + this.logService.info('Task unclaimed'); + this.success.emit(this.taskId); + }, + error => this.error.emit(error) + ); + } +} diff --git a/lib/process-services/src/lib/task-list/components/task-header.component.html b/lib/process-services/src/lib/task-list/components/task-header.component.html index 4246928719..d6c2879caf 100644 --- a/lib/process-services/src/lib/task-list/components/task-header.component.html +++ b/lib/process-services/src/lib/task-list/components/task-header.component.html @@ -3,10 +3,26 @@ - - - diff --git a/lib/process-services/src/lib/task-list/components/task-header.component.spec.ts b/lib/process-services/src/lib/task-list/components/task-header.component.spec.ts index fc5186dda7..e401bb3caa 100644 --- a/lib/process-services/src/lib/task-list/components/task-header.component.spec.ts +++ b/lib/process-services/src/lib/task-list/components/task-header.component.spec.ts @@ -136,6 +136,30 @@ describe('TaskHeaderComponent', () => { describe('Claiming', () => { + it('should be able display the claim/release button if showClaimRelease set to true', async(() => { + component.taskDetails = new TaskDetailsModel(claimableTaskDetailsMock); + component.showClaimRelease = true; + component.refreshData(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + const claimButton = fixture.debugElement.query(By.css('[data-automation-id="header-claim-button"]')); + expect(claimButton.nativeElement.innerText).toBe('ADF_TASK_LIST.DETAILS.BUTTON.CLAIM'); + }); + })); + + it('should not be able display the claim/release button if showClaimRelease set to false', async(() => { + component.taskDetails = new TaskDetailsModel(claimableTaskDetailsMock); + component.showClaimRelease = false; + component.refreshData(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + const claimButton = fixture.debugElement.query(By.css('[data-automation-id="header-claim-button"]')); + expect(claimButton).toBeNull(); + }); + })); + it('should display the claim button if no assignee', async(() => { component.taskDetails = new TaskDetailsModel(claimableTaskDetailsMock); @@ -227,38 +251,37 @@ describe('TaskHeaderComponent', () => { }); })); - it('should call the service unclaim method on un-claiming', async(() => { - spyOn(service, 'unclaimTask').and.returnValue(of(true)); - component.taskDetails = new TaskDetailsModel(claimedTaskDetailsMock); - component.refreshData(); + it('should emit claim event when task is claimed', (done) => { + spyOn(service, 'claimTask').and.returnValue(of({})); + component.taskDetails = claimableTaskDetailsMock; + + component.claim.subscribe((taskId) => { + expect(taskId).toEqual(component.taskDetails.id); + done(); + }); + + component.ngOnInit(); fixture.detectChanges(); - fixture.whenStable().then(() => { - const unclaimButton = fixture.debugElement.query(By.css('[data-automation-id="header-unclaim-button"]')); - unclaimButton.triggerEventHandler('click', {}); + const claimBtn = fixture.debugElement.query(By.css('[adf-claim-task]')); + claimBtn.nativeElement.click(); + }); - expect(service.unclaimTask).toHaveBeenCalledWith('91'); + it('should emit unclaim event when task is unclaimed', (done) => { + spyOn(service, 'unclaimTask').and.returnValue(of({})); + component.taskDetails = claimedTaskDetailsMock; + + component.unclaim.subscribe((taskId: string) => { + expect(taskId).toEqual(component.taskDetails.id); + done(); }); - })); - it('should trigger the unclaim event on successful un-claiming', async(() => { - let unclaimed: boolean = false; - spyOn(service, 'unclaimTask').and.returnValue(of(true)); - component.taskDetails = new TaskDetailsModel(claimedTaskDetailsMock); - component.refreshData(); + component.ngOnInit(); fixture.detectChanges(); - fixture.whenStable().then(() => { - component.unclaim.subscribe(() => { - unclaimed = true; - }); - - const unclaimButton = fixture.debugElement.query(By.css('[data-automation-id="header-unclaim-button"]')); - unclaimButton.triggerEventHandler('click', {}); - - expect(unclaimed).toBeTruthy(); - }); - })); + const unclaimBtn = fixture.debugElement.query(By.css('[adf-unclaim-task]')); + unclaimBtn.nativeElement.click(); + }); it('should display due date', async(() => { component.taskDetails.dueDate = new Date('2016-11-03'); diff --git a/lib/process-services/src/lib/task-list/components/task-header.component.ts b/lib/process-services/src/lib/task-list/components/task-header.component.ts index 15202a428f..d9b3aed822 100644 --- a/lib/process-services/src/lib/task-list/components/task-header.component.ts +++ b/lib/process-services/src/lib/task-list/components/task-header.component.ts @@ -23,12 +23,10 @@ import { CardViewMapItemModel, CardViewTextItemModel, CardViewBaseItemModel, - LogService, TranslationService, AppConfigService } from '@alfresco/adf-core'; import { TaskDetailsModel } from '../models/task-details.model'; -import { TaskListService } from './../services/tasklist.service'; import { TaskDescriptionValidator } from '../validators/task-description.validator'; @Component({ @@ -46,6 +44,10 @@ export class TaskHeaderComponent implements OnChanges, OnInit { @Input() taskDetails: TaskDetailsModel; + /** Toggles display of the claim/release button. */ + @Input() + showClaimRelease = true; + /** Emitted when the task is claimed. */ @Output() claim: EventEmitter = new EventEmitter(); @@ -62,10 +64,8 @@ export class TaskHeaderComponent implements OnChanges, OnInit { dateFormat: string; dateLocale: string; - constructor(private activitiTaskService: TaskListService, - private bpmUserService: BpmUserService, + constructor(private bpmUserService: BpmUserService, private translationService: TranslationService, - private logService: LogService, private appConfig: AppConfigService) { this.dateFormat = this.appConfig.get('dateValues.defaultDateFormat'); this.dateLocale = this.appConfig.get('dateValues.defaultDateLocale'); @@ -281,28 +281,12 @@ export class TaskHeaderComponent implements OnChanges, OnInit { return (this.taskDetails && this.taskDetails.isCompleted()) ? 'Completed' : 'Running'; } - /** - * Claim task - * - * @param taskId - */ - claimTask(taskId: string) { - this.activitiTaskService.claimTask(taskId).subscribe(() => { - this.logService.info('Task claimed'); - this.claim.emit(taskId); - }); + onClaimTask(taskId: string) { + this.claim.emit(taskId); } - /** - * Unclaim task - * - * @param taskId - */ - unclaimTask(taskId: string) { - this.activitiTaskService.unclaimTask(taskId).subscribe(() => { - this.logService.info('Task unclaimed'); - this.unclaim.emit(taskId); - }); + onUnclaimTask(taskId: string) { + this.unclaim.emit(taskId); } /** diff --git a/lib/process-services/src/lib/task-list/public-api.ts b/lib/process-services/src/lib/task-list/public-api.ts index a921856032..997b6f79f3 100644 --- a/lib/process-services/src/lib/task-list/public-api.ts +++ b/lib/process-services/src/lib/task-list/public-api.ts @@ -21,6 +21,8 @@ export * from './components/task-header.component'; export * from './components/no-task-detail-template.directive'; export * from './components/task-filters.component'; export * from './components/task-form/task-form.component'; +export * from './components/task-form/claim-task.directive'; +export * from './components/task-form/unclaim-task.directive'; export * from './components/task-details.component'; export * from './components/task-audit.directive'; export * from './components/start-task.component'; diff --git a/lib/process-services/src/lib/task-list/task-list.module.ts b/lib/process-services/src/lib/task-list/task-list.module.ts index 76eaae9156..c9ba630ba2 100644 --- a/lib/process-services/src/lib/task-list/task-list.module.ts +++ b/lib/process-services/src/lib/task-list/task-list.module.ts @@ -38,6 +38,8 @@ import { TaskListComponent } from './components/task-list.component'; import { TaskStandaloneComponent } from './components/task-standalone.component'; import { AttachFormComponent } from './components/attach-form.component'; import { FormModule } from '../form/form.module'; +import { ClaimTaskDirective } from './components/task-form/claim-task.directive'; +import { UnclaimTaskDirective } from './components/task-form/unclaim-task.directive'; @NgModule({ imports: [ @@ -63,7 +65,9 @@ import { FormModule } from '../form/form.module'; TaskHeaderComponent, StartTaskComponent, TaskStandaloneComponent, - AttachFormComponent + AttachFormComponent, + ClaimTaskDirective, + UnclaimTaskDirective ], exports: [ NoTaskDetailsTemplateDirective, @@ -76,7 +80,9 @@ import { FormModule } from '../form/form.module'; TaskHeaderComponent, StartTaskComponent, TaskStandaloneComponent, - AttachFormComponent + AttachFormComponent, + ClaimTaskDirective, + UnclaimTaskDirective ] }) export class TaskListModule {