mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ADF-4128] ProcessCloud - add complete task directive (#4364)
* [ADF-4128] ProcessCloud - add complete task directive * [ADF-4128] ProcessCloud - fix completion functionality and add documentation * [ADF-4128] ProcessCloud - PR changes * [ADF-4128] ProcessCloud - lint * [ADF-4148] ProcessServicesCloud - change layout * [ADF-4128] fix PR changes * [ADF-4128] - refractor complete task directive * [ADF-4128] - fix lint * [ADF-4128] - PR changes * [ADF-4128] - replace isCompleted method from service with model method * [ADF-4128] fix unit tests * [ADF-4128] - change travis yml * [ADF-4128] - fix travis.yml * [ADF-4128] - travis lint
This commit is contained in:
committed by
Eugenio Romano
parent
e586ee17d5
commit
791051edee
@@ -64,7 +64,7 @@ import { ContentModule } from '@alfresco/adf-content-services';
|
|||||||
import { InsightsModule } from '@alfresco/adf-insights';
|
import { InsightsModule } from '@alfresco/adf-insights';
|
||||||
import { ProcessModule } from '@alfresco/adf-process-services';
|
import { ProcessModule } from '@alfresco/adf-process-services';
|
||||||
import { AuthBearerInterceptor } from './services';
|
import { AuthBearerInterceptor } from './services';
|
||||||
import { ProcessServicesCloudModule, GroupCloudModule } from '@alfresco/adf-process-services-cloud';
|
import { ProcessServicesCloudModule, GroupCloudModule, TaskDirectiveModule } from '@alfresco/adf-process-services-cloud';
|
||||||
import { TreeViewSampleComponent } from './components/tree-view/tree-view-sample.component';
|
import { TreeViewSampleComponent } from './components/tree-view/tree-view-sample.component';
|
||||||
import { CloudLayoutComponent } from './components/app-layout/cloud/cloud-layout.component';
|
import { CloudLayoutComponent } from './components/app-layout/cloud/cloud-layout.component';
|
||||||
import { AppsCloudDemoComponent } from './components/app-layout/cloud/apps-cloud-demo.component';
|
import { AppsCloudDemoComponent } from './components/app-layout/cloud/apps-cloud-demo.component';
|
||||||
@@ -102,7 +102,9 @@ import { NestedMenuPositionDirective } from './components/app-layout/cloud/direc
|
|||||||
ThemePickerModule,
|
ThemePickerModule,
|
||||||
ChartsModule,
|
ChartsModule,
|
||||||
MonacoEditorModule.forRoot(),
|
MonacoEditorModule.forRoot(),
|
||||||
GroupCloudModule
|
ProcessServicesCloudModule,
|
||||||
|
GroupCloudModule,
|
||||||
|
TaskDirectiveModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
|
|
||||||
<button data-automation-id="go-back" mat-icon-button (click)="onGoBack()">
|
|
||||||
<mat-icon>arrow_back</mat-icon> Go Back
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<h4 data-automation-id="task-details-header">Simple page to show the taskId: {{ taskId }} of the app: {{ appName }}</h4>
|
<h4 data-automation-id="task-details-header">Simple page to show the taskId: {{ taskId }} of the app: {{ appName }}</h4>
|
||||||
|
|
||||||
<adf-cloud-task-header
|
<div class="adf-task-detail-container">
|
||||||
[appName]="appName"
|
<div class="adf-task-control">
|
||||||
[taskId]="taskId"
|
<button mat-button (click)="goBack()">Cancel</button>
|
||||||
[readOnly]="readOnly">
|
<button mat-button color="primary" *ngIf="canCompleteTask()" adf-cloud-complete-task [appName]="appName" [taskId]="taskId"
|
||||||
</adf-cloud-task-header>
|
(success)="onCompletedTask($event)">{{ 'ADF_TASK_LIST.DETAILS.BUTTON.COMPLETE' | translate }}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<adf-cloud-task-header class="adf-demop-card-container" [appName]="appName" [taskId]="taskId" [readOnly]="readOnly">
|
||||||
|
</adf-cloud-task-header>
|
||||||
|
|
||||||
|
</div>
|
@@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
.adf {
|
||||||
|
|
||||||
|
&-task-detail-container {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-task-tiitle {
|
||||||
|
margin-left:15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-task-control {
|
||||||
|
width:70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-demop-card-container {
|
||||||
|
width:30%;
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -15,20 +15,26 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
import { TaskCloudService, TaskDetailsCloudModel } from '@alfresco/adf-process-services-cloud';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: './task-details-cloud-demo.component.html',
|
templateUrl: './task-details-cloud-demo.component.html',
|
||||||
styleUrls: ['./task-details-cloud-demo.component.scss']
|
styleUrls: ['./task-details-cloud-demo.component.scss']
|
||||||
})
|
})
|
||||||
export class TaskDetailsCloudDemoComponent {
|
export class TaskDetailsCloudDemoComponent implements OnInit {
|
||||||
|
|
||||||
|
taskDetails: TaskDetailsCloudModel;
|
||||||
taskId: string;
|
taskId: string;
|
||||||
appName: string;
|
appName: string;
|
||||||
readOnly = false;
|
readOnly = false;
|
||||||
|
|
||||||
constructor(private route: ActivatedRoute, private router: Router) {
|
constructor(
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private router: Router,
|
||||||
|
private taskCloudService: TaskCloudService
|
||||||
|
) {
|
||||||
this.route.params.subscribe((params) => {
|
this.route.params.subscribe((params) => {
|
||||||
this.taskId = params.taskId;
|
this.taskId = params.taskId;
|
||||||
});
|
});
|
||||||
@@ -37,8 +43,30 @@ export class TaskDetailsCloudDemoComponent {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onGoBack() {
|
ngOnInit() {
|
||||||
this.router.navigate([`/cloud/${this.appName}/`]);
|
this.loadTaskDetailsById(this.appName, this.taskId);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadTaskDetailsById(appName: string, taskId: string): any {
|
||||||
|
this.taskCloudService.getTaskById(appName, taskId).subscribe(
|
||||||
|
(taskDetails) => {
|
||||||
|
this.taskDetails = taskDetails;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
isTaskValid() {
|
||||||
|
return this.appName && this.taskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
canCompleteTask() {
|
||||||
|
return this.taskDetails && this.taskCloudService.canCompleteTask(this.taskDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
goBack() {
|
||||||
|
this.router.navigate([`/cloud/${this.appName}/`]);
|
||||||
|
}
|
||||||
|
|
||||||
|
onCompletedTask(evt: any) {
|
||||||
|
this.goBack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
26
docs/process-services-cloud/complete-task.directive.md
Normal file
26
docs/process-services-cloud/complete-task.directive.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
Title: Complete Cloud Task
|
||||||
|
Added: v3.1.0
|
||||||
|
Status: Experimental
|
||||||
|
Last reviewed: 2019-02-28
|
||||||
|
---
|
||||||
|
|
||||||
|
# [Complete task directive](../../lib/process-services-cloud/src/lib/task/task-header/directives/complete-task.directive.ts "Defined in complete-task.directive.ts")
|
||||||
|
|
||||||
|
Complete a task
|
||||||
|
|
||||||
|
## Basic Usage
|
||||||
|
|
||||||
|
```html
|
||||||
|
<button adf-cloud-complete-task [appName]="appName" [taskId]="taskId" (success)="onTaskCompleted()">Complete</button>
|
||||||
|
```
|
||||||
|
## Class members
|
||||||
|
|
||||||
|
### Properties
|
||||||
|
|
||||||
|
| Name | Type | Default value | Description |
|
||||||
|
| ---- | ---- | ------------- | ----------- |
|
||||||
|
| taskId | `string` | empty |(Required) The id of the task. |
|
||||||
|
| appName | `string` | empty | (Required) The name of the application. |
|
||||||
|
| success | `EventEmitter<any>` | empty | Emitted when the task is completed. |
|
||||||
|
| error | `EventEmitter<any>` | empty | Emitted when the task cannot be completed. |
|
57
docs/process-services-cloud/task-cloud.service.md
Normal file
57
docs/process-services-cloud/task-cloud.service.md
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
---
|
||||||
|
Title: Task Cloud Service
|
||||||
|
Added: v3.1.0
|
||||||
|
Status: Experimental
|
||||||
|
Last reviewed: 2019-02-28
|
||||||
|
---
|
||||||
|
|
||||||
|
# [Task Cloud Service](../../lib/process-services-cloud/src/lib/task/task-header/services/task-cloud.service.ts "Defined in task-cloud.service.ts")
|
||||||
|
|
||||||
|
Manage task cloud.
|
||||||
|
|
||||||
|
## Class members
|
||||||
|
|
||||||
|
### Methods
|
||||||
|
|
||||||
|
- **completeTask**(appName: `string`, taskId: `string`)<br/>
|
||||||
|
Complete a task
|
||||||
|
- _appName:_ `string` - Name of the app
|
||||||
|
- _taskId:_ `string` - ID of the task to complete
|
||||||
|
|
||||||
|
- **canCompleteTask**(taskDetails: [`TaskDetailsCloudModel`](../../lib/process-services-cloud/src/lib/task/start-filters/models/task-details-cloud.model.ts))<br/>
|
||||||
|
Validate if a task can be completed.
|
||||||
|
- _taskDetails:_ [`TaskDetailsCloudModel`](../../lib/process-services-cloud/src/lib/task/start-filters/models/task-details-cloud.model.ts) - Task details object
|
||||||
|
|
||||||
|
- **claimTask**(appName: `string`, taskId: `string`, assignee: `string`): `any`<br/>
|
||||||
|
Claims a task for an assignee.
|
||||||
|
- _appName:_ `string` - Name of the app
|
||||||
|
- _taskId:_ `string` - ID of the task to claim
|
||||||
|
- _assignee:_ `string` - User to assign the task to
|
||||||
|
- **Returns** `any` - Details of the claimed task
|
||||||
|
- **getTaskById**(appName: `string`, taskId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TaskDetailsCloudModel`](../../lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts)`>`<br/>
|
||||||
|
Gets details of a task.
|
||||||
|
- _appName:_ `string` - Name of the app
|
||||||
|
- _taskId:_ `string` - ID of the task whose details you want
|
||||||
|
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TaskDetailsCloudModel`](../../lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts)`>` - Task details
|
||||||
|
- **unclaimTask**(appName: `string`, taskId: `string`): `any`<br/>
|
||||||
|
Un-claims a task.
|
||||||
|
- _appName:_ `string` - Name of the app
|
||||||
|
- _taskId:_ `string` - ID of the task to unclaim
|
||||||
|
- **Returns** `any` - Details of the task that was unclaimed
|
||||||
|
- **updateTask**(appName: `string`, taskId: `string`, updatePayload: `any`): `any`<br/>
|
||||||
|
Updates the details (name, description, due date) for a task.
|
||||||
|
- _appName:_ `string` - Name of the app
|
||||||
|
- _taskId:_ `string` - ID of the task to update
|
||||||
|
- _updatePayload:_ `any` - Data to update the task
|
||||||
|
- **Returns** `any` - Updated task details
|
||||||
|
|
||||||
|
## Details
|
||||||
|
|
||||||
|
The methods work in much the same way as the equivalent methods in the
|
||||||
|
[Tasklist service](../process-services/tasklist.service.md)
|
||||||
|
but they use the cloud variants of the classes for return values. See the
|
||||||
|
[Tasklist service](../process-services/tasklist.service.md) page for usage examples.
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
- [Tasklist service](../process-services/tasklist.service.md)
|
@@ -0,0 +1,181 @@
|
|||||||
|
/*!
|
||||||
|
* @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, ViewChild, ContentChildren } from '@angular/core';
|
||||||
|
import { CompleteTaskDirective } from './complete-task.directive';
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { CoreModule, setupTestBed } from '@alfresco/adf-core';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
import { TaskCloudService } from '../task-header/services/task-cloud.service';
|
||||||
|
import { taskCompleteCloudMock } from '../task-header/mocks/fake-complete-task.mock';
|
||||||
|
|
||||||
|
describe('CompleteTaskDirective', () => {
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-test-component',
|
||||||
|
template: `<button adf-cloud-complete-task [taskId]='taskMock' [appName]='appNameMock' (success)="onCompleteTask($event)"></button>`
|
||||||
|
})
|
||||||
|
class TestComponent {
|
||||||
|
|
||||||
|
taskMock = 'test1234';
|
||||||
|
appNameMock = 'simple-app';
|
||||||
|
|
||||||
|
@ViewChild(CompleteTaskDirective)
|
||||||
|
completeTaskDirective: CompleteTaskDirective;
|
||||||
|
|
||||||
|
onCompleteTask(event: any) {
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let fixture: ComponentFixture<TestComponent>;
|
||||||
|
let taskCloudService: TaskCloudService;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
CoreModule.forRoot(),
|
||||||
|
RouterTestingModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
TestComponent,
|
||||||
|
CompleteTaskDirective
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
taskCloudService = TestBed.get(TaskCloudService);
|
||||||
|
fixture = TestBed.createComponent(TestComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should directive complete task', () => {
|
||||||
|
spyOn(taskCloudService, 'completeTask').and.returnValue(of(taskCompleteCloudMock));
|
||||||
|
const button = fixture.nativeElement.querySelector('button');
|
||||||
|
button.click();
|
||||||
|
expect(taskCloudService.completeTask).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Complete Task Directive validation errors', () => {
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-no-fields-validation-component',
|
||||||
|
template: '<button adf-cloud-complete-task (success)="onCompleteTask($event)"></button>'
|
||||||
|
})
|
||||||
|
class TestMissingInputDirectiveComponent {
|
||||||
|
|
||||||
|
appName = 'simple-app';
|
||||||
|
appNameUndefined = undefined;
|
||||||
|
appNameNull = null;
|
||||||
|
|
||||||
|
@ContentChildren(CompleteTaskDirective)
|
||||||
|
completeTaskValidationDirective: CompleteTaskDirective;
|
||||||
|
|
||||||
|
onCompleteTask(event: any) {
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-no-taskid-validation-component',
|
||||||
|
template: '<button adf-cloud-complete-task [appName]="appName" (success)="onCompleteTask($event)"></button>'
|
||||||
|
})
|
||||||
|
class TestMissingTaskIdDirectiveComponent {
|
||||||
|
|
||||||
|
appName = 'simple-app';
|
||||||
|
|
||||||
|
@ContentChildren(CompleteTaskDirective)
|
||||||
|
completeTaskValidationDirective: CompleteTaskDirective;
|
||||||
|
|
||||||
|
onCompleteTask(event: any) {
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-undefined-appname-component',
|
||||||
|
template: '<button adf-cloud-complete-task [taskId]="taskMock" [appName]="appNameUndefined" (success)="onCompleteTask($event)"></button>'
|
||||||
|
})
|
||||||
|
class TestInvalidAppNameUndefineddDirectiveComponent {
|
||||||
|
|
||||||
|
appName = 'simple-app';
|
||||||
|
taskMock = 'test1234';
|
||||||
|
|
||||||
|
@ContentChildren(CompleteTaskDirective)
|
||||||
|
completeTaskValidationDirective: CompleteTaskDirective;
|
||||||
|
|
||||||
|
onCompleteTask(event: any) {
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-null-appname-component',
|
||||||
|
template: '<button adf-cloud-complete-task [taskId]="taskMock" [appName]="appNameNull" (success)="onCompleteTask($event)"></button>'
|
||||||
|
})
|
||||||
|
class TestInvalidAppNameNulldDirectiveComponent {
|
||||||
|
|
||||||
|
appName = 'simple-app';
|
||||||
|
taskMock = 'test1234';
|
||||||
|
|
||||||
|
@ContentChildren(CompleteTaskDirective)
|
||||||
|
completeTaskValidationDirective: CompleteTaskDirective;
|
||||||
|
|
||||||
|
onCompleteTask(event: any) {
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let fixture: ComponentFixture<any>;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
CoreModule.forRoot(),
|
||||||
|
RouterTestingModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
TestMissingTaskIdDirectiveComponent,
|
||||||
|
TestInvalidAppNameUndefineddDirectiveComponent,
|
||||||
|
TestInvalidAppNameNulldDirectiveComponent,
|
||||||
|
TestMissingInputDirectiveComponent,
|
||||||
|
CompleteTaskDirective
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(TestMissingInputDirectiveComponent);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error when missing input', () => {
|
||||||
|
expect(() => fixture.detectChanges()).toThrowError();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error when taskId is not set', () => {
|
||||||
|
fixture = TestBed.createComponent(TestMissingTaskIdDirectiveComponent);
|
||||||
|
expect( () => fixture.detectChanges()).toThrowError('Attribute taskId is required');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error when appName is undefined', () => {
|
||||||
|
fixture = TestBed.createComponent(TestInvalidAppNameUndefineddDirectiveComponent);
|
||||||
|
expect( () => fixture.detectChanges()).toThrowError('Attribute appName is required');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error when appName is null', () => {
|
||||||
|
fixture = TestBed.createComponent(TestInvalidAppNameUndefineddDirectiveComponent);
|
||||||
|
expect( () => fixture.detectChanges()).toThrowError('Attribute appName is required');
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,82 @@
|
|||||||
|
/*!
|
||||||
|
* @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, HostListener, Output, EventEmitter, OnInit } from '@angular/core';
|
||||||
|
import { TaskCloudService } from '../task-header/services/task-cloud.service';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: '[adf-cloud-complete-task]'
|
||||||
|
})
|
||||||
|
export class CompleteTaskDirective implements OnInit {
|
||||||
|
|
||||||
|
/** (Required) The id of the task. */
|
||||||
|
@Input()
|
||||||
|
taskId: string;
|
||||||
|
|
||||||
|
/** (Required) The name of the application. */
|
||||||
|
@Input()
|
||||||
|
appName: string;
|
||||||
|
|
||||||
|
/** Emitted when the task is completed. */
|
||||||
|
@Output()
|
||||||
|
success: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
|
/** Emitted when the task cannot be completed. */
|
||||||
|
@Output()
|
||||||
|
error: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
|
invalidParams: string[] = [];
|
||||||
|
|
||||||
|
constructor(private taskListService: TaskCloudService) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.validateInputs();
|
||||||
|
}
|
||||||
|
|
||||||
|
validateInputs() {
|
||||||
|
|
||||||
|
if (!this.isTaskValid()) {
|
||||||
|
this.invalidParams.push('taskId');
|
||||||
|
}
|
||||||
|
if (!this.isAppValid()) {
|
||||||
|
this.invalidParams.push('appName');
|
||||||
|
}
|
||||||
|
if (this.invalidParams.length) {
|
||||||
|
throw new Error(`Attribute ${this.invalidParams.join(', ')} is required`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isTaskValid() {
|
||||||
|
return this.taskId && this.taskId.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
isAppValid() {
|
||||||
|
return this.appName && this.appName.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('click')
|
||||||
|
async onClick() {
|
||||||
|
try {
|
||||||
|
const result = await this.taskListService.completeTask(this.appName, this.taskId).toPromise();
|
||||||
|
if (result) {
|
||||||
|
this.success.emit(result);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.error.emit(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,29 @@
|
|||||||
|
/*!
|
||||||
|
* @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 { NgModule } from '@angular/core';
|
||||||
|
import { CompleteTaskDirective } from './complete-task.directive';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
CompleteTaskDirective
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
CompleteTaskDirective
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class TaskDirectiveModule { }
|
@@ -21,3 +21,4 @@ export * from './start-task/public-api';
|
|||||||
export * from './task-header/public-api';
|
export * from './task-header/public-api';
|
||||||
|
|
||||||
export * from './task-cloud.module';
|
export * from './task-cloud.module';
|
||||||
|
export * from './directives/task-directive.module';
|
||||||
|
@@ -36,7 +36,7 @@ export class TaskDetailsCloudModel {
|
|||||||
priority: number;
|
priority: number;
|
||||||
processDefinitionId: string;
|
processDefinitionId: string;
|
||||||
processInstanceId: string;
|
processInstanceId: string;
|
||||||
status: string;
|
status: TaskStatusEnum;
|
||||||
standAlone: boolean;
|
standAlone: boolean;
|
||||||
candidateUsers: string[];
|
candidateUsers: string[];
|
||||||
candidateGroups: string[];
|
candidateGroups: string[];
|
||||||
@@ -73,8 +73,21 @@ export class TaskDetailsCloudModel {
|
|||||||
this.memberOfCandidateUsers = obj.memberOfCandidateUsers || null;
|
this.memberOfCandidateUsers = obj.memberOfCandidateUsers || null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isCompleted() {
|
||||||
|
return this.status && this.status === TaskStatusEnum.COMPLETED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface StartTaskCloudResponseModel {
|
export interface StartTaskCloudResponseModel {
|
||||||
entry: TaskDetailsCloudModel;
|
entry: TaskDetailsCloudModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum TaskStatusEnum {
|
||||||
|
COMPLETED= 'COMPLETED',
|
||||||
|
DELETED = 'DELETED',
|
||||||
|
CREATED = 'CREATED',
|
||||||
|
ASSIGNED = 'ASSIGNED',
|
||||||
|
SUSPENDED = 'SUSPENDED',
|
||||||
|
CANCELLED = 'CANCELLED'
|
||||||
|
}
|
||||||
|
@@ -1,15 +1,20 @@
|
|||||||
<mat-card *ngIf="isTaskValid()" class="adf-card-container">
|
<h3 class="adf-task-tiitle">{{ taskDetails.name }}</h3>
|
||||||
<mat-card-content>
|
|
||||||
<adf-card-view
|
|
||||||
[properties]="properties"
|
|
||||||
[editable]="!isCompleted()">
|
|
||||||
</adf-card-view>
|
|
||||||
</mat-card-content>
|
|
||||||
|
|
||||||
<mat-card-actions class="adf-controls">
|
<div class="adf-task-header-container">
|
||||||
<button *ngIf="isTaskClaimedByCandidateMember()" mat-button data-automation-id="header-unclaim-button" id="unclaim-task" (click)="unclaimTask()" class="adf-claim-controls">{{ 'ADF_CLOUD_TASK_HEADER.BUTTON.UNCLAIM' | translate }}
|
<mat-card *ngIf="isTaskValid()" class="adf-card-container">
|
||||||
</button>
|
<mat-card-content>
|
||||||
<button *ngIf="isTaskClaimable()" mat-button data-automation-id="header-claim-button" id="claim-task" (click)="claimTask()" class="adf-claim-controls">{{ 'ADF_CLOUD_TASK_HEADER.BUTTON.CLAIM' | translate }}
|
<adf-card-view
|
||||||
</button>
|
[properties]="properties"
|
||||||
</mat-card-actions>
|
[editable]="!taskDetails.isCompleted()">
|
||||||
</mat-card>
|
</adf-card-view>
|
||||||
|
</mat-card-content>
|
||||||
|
|
||||||
|
<mat-card-actions class="adf-controls">
|
||||||
|
<button *ngIf="isTaskClaimedByCandidateMember()" mat-button data-automation-id="header-unclaim-button" id="unclaim-task" (click)="unclaimTask()" class="adf-claim-controls">{{ 'ADF_CLOUD_TASK_HEADER.BUTTON.UNCLAIM' | translate }}
|
||||||
|
</button>
|
||||||
|
<button *ngIf="isTaskClaimable()" mat-button data-automation-id="header-claim-button" id="claim-task" (click)="claimTask()" class="adf-claim-controls">{{ 'ADF_CLOUD_TASK_HEADER.BUTTON.CLAIM' | translate }}
|
||||||
|
</button>
|
||||||
|
</mat-card-actions>
|
||||||
|
</mat-card>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@@ -22,11 +22,6 @@
|
|||||||
&-claim-controls {
|
&-claim-controls {
|
||||||
color: rgb(131, 131, 131);
|
color: rgb(131, 131, 131);
|
||||||
}
|
}
|
||||||
|
|
||||||
&-card-container {
|
|
||||||
font-family: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and ($mat-small) {
|
@media screen and ($mat-small) {
|
||||||
@@ -36,5 +31,4 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -21,20 +21,22 @@ import { TaskHeaderCloudComponent } from './task-header-cloud.component';
|
|||||||
import { taskDetailsCloudMock } from '../mocks/task-details-cloud.mock';
|
import { taskDetailsCloudMock } from '../mocks/task-details-cloud.mock';
|
||||||
import { TaskHeaderCloudModule } from '../task-header-cloud.module';
|
import { TaskHeaderCloudModule } from '../task-header-cloud.module';
|
||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
import { TaskHeaderCloudService } from '../services/task-header-cloud.service';
|
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { TaskCloudService } from '../services/task-cloud.service';
|
||||||
|
|
||||||
describe('TaskHeaderComponent', () => {
|
describe('TaskHeaderCloudComponent', () => {
|
||||||
let component: TaskHeaderCloudComponent;
|
let component: TaskHeaderCloudComponent;
|
||||||
let fixture: ComponentFixture<TaskHeaderCloudComponent>;
|
let fixture: ComponentFixture<TaskHeaderCloudComponent>;
|
||||||
let service: TaskHeaderCloudService;
|
let service: TaskCloudService;
|
||||||
let appConfigService: AppConfigService;
|
let appConfigService: AppConfigService;
|
||||||
|
|
||||||
setupTestBed({
|
setupTestBed({
|
||||||
imports: [
|
imports: [
|
||||||
ProcessServiceCloudTestingModule,
|
ProcessServiceCloudTestingModule,
|
||||||
TaskHeaderCloudModule
|
TaskHeaderCloudModule,
|
||||||
|
RouterTestingModule
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -43,7 +45,7 @@ describe('TaskHeaderComponent', () => {
|
|||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
component.appName = 'myApp';
|
component.appName = 'myApp';
|
||||||
component.taskId = taskDetailsCloudMock.id;
|
component.taskId = taskDetailsCloudMock.id;
|
||||||
service = TestBed.get(TaskHeaderCloudService);
|
service = TestBed.get(TaskCloudService);
|
||||||
appConfigService = TestBed.get(AppConfigService);
|
appConfigService = TestBed.get(AppConfigService);
|
||||||
spyOn(service, 'getTaskById').and.returnValue(of(taskDetailsCloudMock));
|
spyOn(service, 'getTaskById').and.returnValue(of(taskDetailsCloudMock));
|
||||||
});
|
});
|
||||||
@@ -52,7 +54,7 @@ describe('TaskHeaderComponent', () => {
|
|||||||
component.appName = undefined;
|
component.appName = undefined;
|
||||||
component.taskId = undefined;
|
component.taskId = undefined;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(fixture.debugElement.children.length).toBe(0);
|
expect(fixture.debugElement.children.length).toBe(2);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should display assignee', async(() => {
|
it('should display assignee', async(() => {
|
||||||
|
@@ -25,10 +25,10 @@ import {
|
|||||||
AppConfigService,
|
AppConfigService,
|
||||||
UpdateNotification,
|
UpdateNotification,
|
||||||
CardViewUpdateService,
|
CardViewUpdateService,
|
||||||
StorageService
|
IdentityUserService
|
||||||
} from '@alfresco/adf-core';
|
} from '@alfresco/adf-core';
|
||||||
import { TaskHeaderCloudService } from '../services/task-header-cloud.service';
|
|
||||||
import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model';
|
import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model';
|
||||||
|
import { TaskCloudService } from '../services/task-cloud.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-cloud-task-header',
|
selector: 'adf-cloud-task-header',
|
||||||
@@ -64,11 +64,11 @@ export class TaskHeaderCloudComponent implements OnInit {
|
|||||||
private currentUser: string;
|
private currentUser: string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private taskHeaderCloudService: TaskHeaderCloudService,
|
private taskCloudService: TaskCloudService,
|
||||||
private translationService: TranslationService,
|
private translationService: TranslationService,
|
||||||
private appConfig: AppConfigService,
|
private appConfig: AppConfigService,
|
||||||
private cardViewUpdateService: CardViewUpdateService,
|
private cardViewUpdateService: CardViewUpdateService,
|
||||||
private storage: StorageService
|
private identityUserService: IdentityUserService
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@@ -79,12 +79,13 @@ export class TaskHeaderCloudComponent implements OnInit {
|
|||||||
|
|
||||||
this.cardViewUpdateService.itemUpdated$.subscribe(this.updateTaskDetails.bind(this));
|
this.cardViewUpdateService.itemUpdated$.subscribe(this.updateTaskDetails.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
loadCurrentBpmUserId(): any {
|
loadCurrentBpmUserId(): any {
|
||||||
this.currentUser = this.storage.getItem('USERNAME');
|
this.currentUser = this.identityUserService.getCurrentUserInfo().username;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadTaskDetailsById(appName: string, taskId: string): any {
|
loadTaskDetailsById(appName: string, taskId: string): any {
|
||||||
this.taskHeaderCloudService.getTaskById(appName, taskId).subscribe(
|
this.taskCloudService.getTaskById(appName, taskId).subscribe(
|
||||||
(taskDetails) => {
|
(taskDetails) => {
|
||||||
this.taskDetails = taskDetails;
|
this.taskDetails = taskDetails;
|
||||||
if (this.taskDetails.parentTaskId) {
|
if (this.taskDetails.parentTaskId) {
|
||||||
@@ -204,7 +205,7 @@ export class TaskHeaderCloudComponent implements OnInit {
|
|||||||
* @param updateNotification
|
* @param updateNotification
|
||||||
*/
|
*/
|
||||||
private updateTaskDetails(updateNotification: UpdateNotification) {
|
private updateTaskDetails(updateNotification: UpdateNotification) {
|
||||||
this.taskHeaderCloudService.updateTask(this.appName, this.taskId, updateNotification.changed)
|
this.taskCloudService.updateTask(this.appName, this.taskId, updateNotification.changed)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
(taskDetails) => {
|
(taskDetails) => {
|
||||||
this.taskDetails = taskDetails;
|
this.taskDetails = taskDetails;
|
||||||
@@ -214,7 +215,7 @@ export class TaskHeaderCloudComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private loadParentName(taskId) {
|
private loadParentName(taskId) {
|
||||||
this.taskHeaderCloudService.getTaskById(this.appName, taskId)
|
this.taskCloudService.getTaskById(this.appName, taskId)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
(taskDetails) => {
|
(taskDetails) => {
|
||||||
this.parentTaskName = taskDetails.name;
|
this.parentTaskName = taskDetails.name;
|
||||||
@@ -223,10 +224,6 @@ export class TaskHeaderCloudComponent implements OnInit {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
isCompleted() {
|
|
||||||
return this.taskDetails && this.taskDetails.status === 'completed';
|
|
||||||
}
|
|
||||||
|
|
||||||
isTaskClaimable(): boolean {
|
isTaskClaimable(): boolean {
|
||||||
return !this.hasAssignee() && this.isCandidateMember();
|
return !this.hasAssignee() && this.isCandidateMember();
|
||||||
}
|
}
|
||||||
@@ -240,7 +237,7 @@ export class TaskHeaderCloudComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isTaskClaimedByCandidateMember(): boolean {
|
isTaskClaimedByCandidateMember(): boolean {
|
||||||
return this.isCandidateMember() && this.isAssignedToCurrentUser() && !this.isCompleted();
|
return this.isCandidateMember() && this.isAssignedToCurrentUser() && !this.taskDetails.isCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
isAssignedToCurrentUser(): boolean {
|
isAssignedToCurrentUser(): boolean {
|
||||||
@@ -260,7 +257,7 @@ export class TaskHeaderCloudComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
claimTask() {
|
claimTask() {
|
||||||
this.taskHeaderCloudService.claimTask(this.appName, this.taskId, this.currentUser).subscribe(
|
this.taskCloudService.claimTask(this.appName, this.taskId, this.currentUser).subscribe(
|
||||||
(res: any) => {
|
(res: any) => {
|
||||||
this.loadTaskDetailsById(this.appName, this.taskId);
|
this.loadTaskDetailsById(this.appName, this.taskId);
|
||||||
this.claim.emit(this.taskId);
|
this.claim.emit(this.taskId);
|
||||||
@@ -268,7 +265,7 @@ export class TaskHeaderCloudComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unclaimTask() {
|
unclaimTask() {
|
||||||
this.taskHeaderCloudService.unclaimTask(this.appName, this.taskId).subscribe(
|
this.taskCloudService.unclaimTask(this.appName, this.taskId).subscribe(
|
||||||
() => {
|
() => {
|
||||||
this.loadTaskDetailsById(this.appName, this.taskId);
|
this.loadTaskDetailsById(this.appName, this.taskId);
|
||||||
this.unclaim.emit(this.taskId);
|
this.unclaim.emit(this.taskId);
|
||||||
|
@@ -0,0 +1,31 @@
|
|||||||
|
/*!
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const taskCompleteCloudMock = {
|
||||||
|
'entry': {
|
||||||
|
'appName': 'simple-app',
|
||||||
|
'appVersion': '',
|
||||||
|
'serviceName': 'simple-app-rb',
|
||||||
|
'serviceFullName': 'simple-app-rb',
|
||||||
|
'serviceType': 'runtime-bundle',
|
||||||
|
'serviceVersion': '',
|
||||||
|
'id': '68d54a8f',
|
||||||
|
'name': 'NXltAGmT',
|
||||||
|
'priority': 0,
|
||||||
|
'status': 'COMPLETED'
|
||||||
|
}
|
||||||
|
};
|
@@ -17,4 +17,6 @@
|
|||||||
|
|
||||||
export * from './components/task-header-cloud.component';
|
export * from './components/task-header-cloud.component';
|
||||||
|
|
||||||
|
export * from './services/task-cloud.service';
|
||||||
|
|
||||||
export * from './task-header-cloud.module';
|
export * from './task-header-cloud.module';
|
||||||
|
@@ -15,16 +15,42 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { async } from '@angular/core/testing';
|
import { async, TestBed } from '@angular/core/testing';
|
||||||
import { setupTestBed } from '@alfresco/adf-core';
|
import { setupTestBed, IdentityUserService, IdentityUserModel, AlfrescoApiServiceMock } from '@alfresco/adf-core';
|
||||||
import { AlfrescoApiServiceMock, LogService, AppConfigService, StorageService, CoreModule } from '@alfresco/adf-core';
|
import { LogService, AppConfigService, StorageService, CoreModule } from '@alfresco/adf-core';
|
||||||
|
import { TaskCloudService } from './task-cloud.service';
|
||||||
|
import { taskDetailsCloudMock } from '../mocks/task-details-cloud.mock';
|
||||||
|
import { taskCompleteCloudMock } from '../mocks/fake-complete-task.mock';
|
||||||
import { fakeTaskDetailsCloud } from '../mocks/fake-task-details-response.mock';
|
import { fakeTaskDetailsCloud } from '../mocks/fake-task-details-response.mock';
|
||||||
import { TaskHeaderCloudService } from './task-header-cloud.service';
|
|
||||||
|
|
||||||
describe('Task Header Cloud Service', () => {
|
describe('Task Cloud Service', () => {
|
||||||
|
|
||||||
let service: TaskHeaderCloudService;
|
let service: TaskCloudService;
|
||||||
let alfrescoApiMock: AlfrescoApiServiceMock;
|
let alfrescoApiMock: AlfrescoApiServiceMock;
|
||||||
|
let identityService: IdentityUserService;
|
||||||
|
let identityUserWithOutFirstNameMock = { firstName: null, lastName: 'fake-identity-last-name', email: 'fakeIdentity@email.com', username: 'superadminuser' };
|
||||||
|
let getCurrentUserInfoStub;
|
||||||
|
let fakeIdentityUser: IdentityUserModel = new IdentityUserModel(identityUserWithOutFirstNameMock);
|
||||||
|
|
||||||
|
function returnFakeTaskCompleteResults() {
|
||||||
|
return {
|
||||||
|
oauth2Auth: {
|
||||||
|
callCustomApi : () => {
|
||||||
|
return Promise.resolve(taskCompleteCloudMock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function returnFakeTaskCompleteResultsError() {
|
||||||
|
return {
|
||||||
|
oauth2Auth: {
|
||||||
|
callCustomApi : () => {
|
||||||
|
return Promise.reject(taskCompleteCloudMock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function returnFakeTaskDetailsResults() {
|
function returnFakeTaskDetailsResults() {
|
||||||
return {
|
return {
|
||||||
@@ -39,16 +65,53 @@ describe('Task Header Cloud Service', () => {
|
|||||||
setupTestBed({
|
setupTestBed({
|
||||||
imports: [
|
imports: [
|
||||||
CoreModule.forRoot()
|
CoreModule.forRoot()
|
||||||
]
|
],
|
||||||
|
providers: [IdentityUserService, LogService]
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
|
|
||||||
|
identityService = TestBed.get(IdentityUserService);
|
||||||
|
getCurrentUserInfoStub = spyOn(identityService, 'getCurrentUserInfo');
|
||||||
|
getCurrentUserInfoStub.and.returnValue(fakeIdentityUser);
|
||||||
alfrescoApiMock = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService() );
|
alfrescoApiMock = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService() );
|
||||||
service = new TaskHeaderCloudService(alfrescoApiMock,
|
service = new TaskCloudService(alfrescoApiMock,
|
||||||
new AppConfigService(null),
|
new AppConfigService(null),
|
||||||
new LogService(new AppConfigService(null)));
|
new LogService(new AppConfigService(null)),
|
||||||
|
identityService);
|
||||||
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should complete a task', (done) => {
|
||||||
|
const appName = 'simple-app';
|
||||||
|
const taskId = '68d54a8f';
|
||||||
|
spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskCompleteResults);
|
||||||
|
service.completeTask(appName, taskId).subscribe((res: any) => {
|
||||||
|
expect(res).toBeDefined();
|
||||||
|
expect(res).not.toBeNull();
|
||||||
|
expect(res.entry.appName).toBe('simple-app');
|
||||||
|
expect(res.entry.id).toBe('68d54a8f');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not complete a task', (done) => {
|
||||||
|
spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskCompleteResultsError);
|
||||||
|
const appName = 'simple-app';
|
||||||
|
const taskId = '68d54a8f';
|
||||||
|
|
||||||
|
service.completeTask(appName, taskId).toPromise().then( (res: any) => {
|
||||||
|
}, (error) => {
|
||||||
|
expect(error).toBeDefined();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should canCompleteTask', () => {
|
||||||
|
const canCompleteTaskResult = service.canCompleteTask(taskDetailsCloudMock);
|
||||||
|
expect(canCompleteTaskResult).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it('should return the task details when querying by id', (done) => {
|
it('should return the task details when querying by id', (done) => {
|
||||||
const appName = 'taskp-app';
|
const appName = 'taskp-app';
|
||||||
const taskId = '68d54a8f';
|
const taskId = '68d54a8f';
|
@@ -15,27 +15,69 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { AlfrescoApiService, LogService, AppConfigService } from '@alfresco/adf-core';
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable, from, throwError } from 'rxjs';
|
import { AlfrescoApiService, LogService, AppConfigService, IdentityUserService } from '@alfresco/adf-core';
|
||||||
|
import { from, throwError, Observable } from 'rxjs';
|
||||||
import { catchError, map } from 'rxjs/operators';
|
import { catchError, map } from 'rxjs/operators';
|
||||||
import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model';
|
import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class TaskHeaderCloudService {
|
export class TaskCloudService {
|
||||||
|
|
||||||
contextRoot: string;
|
contextRoot: string;
|
||||||
contentTypes = ['application/json'];
|
contentTypes = ['application/json'];
|
||||||
accepts = ['application/json'];
|
accepts = ['application/json'];
|
||||||
returnType = Object;
|
returnType = Object;
|
||||||
|
|
||||||
constructor(private alfrescoApiService: AlfrescoApiService,
|
constructor(
|
||||||
private appConfigService: AppConfigService,
|
private apiService: AlfrescoApiService,
|
||||||
private logService: LogService) {
|
private appConfigService: AppConfigService,
|
||||||
|
private logService: LogService,
|
||||||
|
private identityUserService: IdentityUserService
|
||||||
|
) {
|
||||||
this.contextRoot = this.appConfigService.get('bpmHost', '');
|
this.contextRoot = this.appConfigService.get('bpmHost', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Complete a task.
|
||||||
|
* @param appName Name of the app
|
||||||
|
* @param taskId ID of the task to complete
|
||||||
|
* @returns Details of the task that was completed
|
||||||
|
*/
|
||||||
|
completeTask(appName: string, taskId: string) {
|
||||||
|
const queryUrl = this.buildCompleteTaskUrl(appName, taskId);
|
||||||
|
const bodyParam = { 'payloadType': 'CompleteTaskPayload' };
|
||||||
|
const pathParams = {}, queryParams = {}, headerParams = {},
|
||||||
|
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
|
||||||
|
|
||||||
|
return from(
|
||||||
|
this.apiService
|
||||||
|
.getInstance()
|
||||||
|
.oauth2Auth.callCustomApi(
|
||||||
|
queryUrl, 'POST', pathParams, queryParams,
|
||||||
|
headerParams, formParams, bodyParam,
|
||||||
|
contentTypes, accepts, null, null)
|
||||||
|
).pipe(
|
||||||
|
catchError((err) => this.handleError(err))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate if a task can be completed.
|
||||||
|
* @param taskDetails task details object
|
||||||
|
* @returns Boolean value if the task can be completed
|
||||||
|
*/
|
||||||
|
canCompleteTask(taskDetails: TaskDetailsCloudModel): boolean {
|
||||||
|
const currentUser = this.identityUserService.getCurrentUserInfo().username;
|
||||||
|
return taskDetails.owner === currentUser && !taskDetails.isCompleted();
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildCompleteTaskUrl(appName: string, taskId: string): any {
|
||||||
|
return `${this.appConfigService.get('bpmHost')}/${appName}-rb/v1/tasks/${taskId}/complete`;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets details of a task.
|
* Gets details of a task.
|
||||||
* @param appName Name of the app
|
* @param appName Name of the app
|
||||||
@@ -46,7 +88,7 @@ export class TaskHeaderCloudService {
|
|||||||
if (appName && taskId) {
|
if (appName && taskId) {
|
||||||
|
|
||||||
let queryUrl = `${this.contextRoot}/${appName}-query/v1/tasks/${taskId}`;
|
let queryUrl = `${this.contextRoot}/${appName}-query/v1/tasks/${taskId}`;
|
||||||
return from(this.alfrescoApiService.getInstance()
|
return from(this.apiService.getInstance()
|
||||||
.oauth2Auth.callCustomApi(queryUrl, 'GET',
|
.oauth2Auth.callCustomApi(queryUrl, 'GET',
|
||||||
null, null, null,
|
null, null, null,
|
||||||
null, null,
|
null, null,
|
||||||
@@ -77,7 +119,7 @@ export class TaskHeaderCloudService {
|
|||||||
updatePayload.payloadType = 'UpdateTaskPayload';
|
updatePayload.payloadType = 'UpdateTaskPayload';
|
||||||
|
|
||||||
let queryUrl = `${this.contextRoot}/${appName}-rb/v1/tasks/${taskId}`;
|
let queryUrl = `${this.contextRoot}/${appName}-rb/v1/tasks/${taskId}`;
|
||||||
return from(this.alfrescoApiService.getInstance()
|
return from(this.apiService.getInstance()
|
||||||
.oauth2Auth.callCustomApi(queryUrl, 'PUT',
|
.oauth2Auth.callCustomApi(queryUrl, 'PUT',
|
||||||
null, null, null,
|
null, null, null,
|
||||||
null, updatePayload,
|
null, updatePayload,
|
||||||
@@ -106,7 +148,7 @@ export class TaskHeaderCloudService {
|
|||||||
if (appName && taskId) {
|
if (appName && taskId) {
|
||||||
|
|
||||||
let queryUrl = `${this.contextRoot}/${appName}-rb/v1/tasks/${taskId}/claim?assignee=${assignee}`;
|
let queryUrl = `${this.contextRoot}/${appName}-rb/v1/tasks/${taskId}/claim?assignee=${assignee}`;
|
||||||
return from(this.alfrescoApiService.getInstance()
|
return from(this.apiService.getInstance()
|
||||||
.oauth2Auth.callCustomApi(queryUrl, 'POST',
|
.oauth2Auth.callCustomApi(queryUrl, 'POST',
|
||||||
null, null, null,
|
null, null, null,
|
||||||
null, null,
|
null, null,
|
||||||
@@ -134,7 +176,7 @@ export class TaskHeaderCloudService {
|
|||||||
if (appName && taskId) {
|
if (appName && taskId) {
|
||||||
|
|
||||||
let queryUrl = `${this.contextRoot}/${appName}-rb/v1/tasks/${taskId}/release`;
|
let queryUrl = `${this.contextRoot}/${appName}-rb/v1/tasks/${taskId}/release`;
|
||||||
return from(this.alfrescoApiService.getInstance()
|
return from(this.apiService.getInstance()
|
||||||
.oauth2Auth.callCustomApi(queryUrl, 'POST',
|
.oauth2Auth.callCustomApi(queryUrl, 'POST',
|
||||||
null, null, null,
|
null, null, null,
|
||||||
null, null,
|
null, null,
|
@@ -20,7 +20,6 @@ import { CommonModule } from '@angular/common';
|
|||||||
import { MaterialModule } from '../../material.module';
|
import { MaterialModule } from '../../material.module';
|
||||||
import { DataTableModule, TemplateModule, CardViewModule, CoreModule } from '@alfresco/adf-core';
|
import { DataTableModule, TemplateModule, CardViewModule, CoreModule } from '@alfresco/adf-core';
|
||||||
import { TaskHeaderCloudComponent } from './components/task-header-cloud.component';
|
import { TaskHeaderCloudComponent } from './components/task-header-cloud.component';
|
||||||
import { TaskHeaderCloudService } from './services/task-header-cloud.service';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -36,9 +35,6 @@ import { TaskHeaderCloudService } from './services/task-header-cloud.service';
|
|||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
TaskHeaderCloudComponent
|
TaskHeaderCloudComponent
|
||||||
],
|
|
||||||
providers: [
|
|
||||||
TaskHeaderCloudService
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class TaskHeaderCloudModule { }
|
export class TaskHeaderCloudModule { }
|
||||||
|
Reference in New Issue
Block a user