[ADF-4409] ADF for Activiti Community - Be able to claim/release/complete task (#4677)

* Be able to claim/release/complete task for community
Be able to start a task/process
Fix unsubscribe on destroy

* Fix the construnctor
This commit is contained in:
Maurizio Vitale
2019-05-02 14:30:38 +02:00
committed by GitHub
parent 9298e6762f
commit e88e0d9b45
12 changed files with 62 additions and 41 deletions

View File

@@ -10,6 +10,7 @@
<adf-cloud-task-list <adf-cloud-task-list
fxFlex fxFlex
class="adf-cloud-layout-overflow" class="adf-cloud-layout-overflow"
[appName]="''"
[processInstanceId]="processInstanceId" [processInstanceId]="processInstanceId"
(rowClick)="onRowClick($event)" (rowClick)="onRowClick($event)"
#taskCloud> #taskCloud>

View File

@@ -1,4 +1,5 @@
<adf-cloud-start-task <adf-cloud-start-task
[appName]="''"
(error)="openSnackMessage($event)" (error)="openSnackMessage($event)"
(success)="onStartTaskSuccess()" (success)="onStartTaskSuccess()"
(cancel)="onCancelStartTask()"> (cancel)="onCancelStartTask()">

View File

@@ -19,7 +19,8 @@ import { SimpleChange, DebugElement, CUSTOM_ELEMENTS_SCHEMA, Component } from '@
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { Observable, of, throwError } from 'rxjs'; import { Observable, of, throwError } from 'rxjs';
import { FormFieldModel, FormFieldTypes, FormService, FormOutcomeEvent, FormOutcomeModel, LogService, WidgetVisibilityService, setupTestBed } from '@alfresco/adf-core'; import { FormFieldModel, FormFieldTypes, FormService, FormOutcomeEvent, FormOutcomeModel, LogService, WidgetVisibilityService,
setupTestBed, AppConfigService } from '@alfresco/adf-core';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module'; import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { FormCloudService } from '../services/form-cloud.service'; import { FormCloudService } from '../services/form-cloud.service';
import { FormCloudComponent } from './form-cloud.component'; import { FormCloudComponent } from './form-cloud.component';
@@ -38,7 +39,7 @@ describe('FormCloudComponent', () => {
logService = new LogService(null); logService = new LogService(null);
visibilityService = new WidgetVisibilityService(null, logService); visibilityService = new WidgetVisibilityService(null, logService);
spyOn(visibilityService, 'refreshVisibility').and.stub(); spyOn(visibilityService, 'refreshVisibility').and.stub();
formCloudService = new FormCloudService(null, null, logService); formCloudService = new FormCloudService(null, new AppConfigService(null), logService);
formService = new FormService(null, null, logService); formService = new FormService(null, null, logService);
formComponent = new FormCloudComponent(formCloudService, formService, null, visibilityService); formComponent = new FormCloudComponent(formCloudService, formService, null, visibilityService);
}); });

View File

@@ -17,14 +17,14 @@
import { FormCloudService } from '../services/form-cloud.service'; import { FormCloudService } from '../services/form-cloud.service';
import { FormCloud } from './form-cloud.model'; import { FormCloud } from './form-cloud.model';
import { TabModel, FormFieldModel, ContainerModel, FormOutcomeModel, FormFieldTypes } from '@alfresco/adf-core'; import { TabModel, FormFieldModel, ContainerModel, FormOutcomeModel, FormFieldTypes, AppConfigService } from '@alfresco/adf-core';
describe('FormCloud', () => { describe('FormCloud', () => {
let formCloudService: FormCloudService; let formCloudService: FormCloudService;
beforeEach(() => { beforeEach(() => {
formCloudService = new FormCloudService(null, null, null); formCloudService = new FormCloudService(null, new AppConfigService(null), null);
}); });
it('should store original json', () => { it('should store original json', () => {

View File

@@ -23,18 +23,22 @@ import { TaskDetailsCloudModel } from '../../task/start-task/models/task-details
import { SaveFormRepresentation, CompleteFormRepresentation } from '@alfresco/js-api'; import { SaveFormRepresentation, CompleteFormRepresentation } from '@alfresco/js-api';
import { FormCloud } from '../models/form-cloud.model'; import { FormCloud } from '../models/form-cloud.model';
import { TaskVariableCloud } from '../models/task-variable-cloud.model'; import { TaskVariableCloud } from '../models/task-variable-cloud.model';
import { BaseCloudService } from '../../services/base-cloud.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class FormCloudService { export class FormCloudService extends BaseCloudService {
contentTypes = ['application/json']; accepts = ['application/json']; returnType = Object; contentTypes = ['application/json']; accepts = ['application/json']; returnType = Object;
constructor( constructor(
private apiService: AlfrescoApiService, private apiService: AlfrescoApiService,
private appConfigService: AppConfigService, private appConfigService: AppConfigService,
private logService: LogService private logService: LogService
) {} ) {
super();
this.contextRoot = this.appConfigService.get('bpmHost', '');
}
/** /**
* Gets the form definition of a task. * Gets the form definition of a task.
@@ -245,15 +249,15 @@ export class FormCloudService {
} }
private buildGetTaskUrl(appName: string, taskId: string): string { private buildGetTaskUrl(appName: string, taskId: string): string {
return `${this.appConfigService.get('bpmHost')}/${appName}/query/v1/tasks/${taskId}`; return `${this.getBasePath(appName)}/query/v1/tasks/${taskId}`;
} }
private buildGetFormUrl(appName: string, formId: string): string { private buildGetFormUrl(appName: string, formId: string): string {
return `${this.appConfigService.get('bpmHost')}/${appName}/form/v1/forms/${formId}`; return `${this.getBasePath(appName)}/form/v1/forms/${formId}`;
} }
private buildSaveFormUrl(appName: string, formId: string): string { private buildSaveFormUrl(appName: string, formId: string): string {
return `${this.appConfigService.get('bpmHost')}/${appName}/form/v1/forms/${formId}/save`; return `${this.getBasePath(appName)}/form/v1/forms/${formId}/save`;
} }
private buildUploadUrl(nodeId: string): string { private buildUploadUrl(nodeId: string): string {
@@ -261,15 +265,15 @@ export class FormCloudService {
} }
private buildSubmitFormUrl(appName: string, formId: string): string { private buildSubmitFormUrl(appName: string, formId: string): string {
return `${this.appConfigService.get('bpmHost')}/${appName}/form/v1/forms/${formId}/submit`; return `${this.getBasePath(appName)}/form/v1/forms/${formId}/submit`;
} }
private buildGetTaskVariablesUrl(appName: string, taskId: string): string { private buildGetTaskVariablesUrl(appName: string, taskId: string): string {
return `${this.appConfigService.get('bpmHost')}/${appName}/query/v1/tasks/${taskId}/variables`; return `${this.getBasePath(appName)}/query/v1/tasks/${taskId}/variables`;
} }
private buildFolderTask(appName: string, taskId: string): string { private buildFolderTask(appName: string, taskId: string): string {
return `${this.appConfigService.get('bpmHost')}/${appName}/process-storage/v1/folders/tasks/${taskId}`; return `${this.getBasePath(appName)}/process-storage/v1/folders/tasks/${taskId}`;
} }
private handleError(error: any) { private handleError(error: any) {

View File

@@ -20,13 +20,13 @@ import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-
import { catchError, map } from 'rxjs/operators'; import { catchError, map } from 'rxjs/operators';
import { FormDefinitionSelectorCloudModel } from '../models/form-definition-selector-cloud.model'; import { FormDefinitionSelectorCloudModel } from '../models/form-definition-selector-cloud.model';
import { from, Observable, throwError } from 'rxjs'; import { from, Observable, throwError } from 'rxjs';
import { BaseCloudService } from '../../services/base-cloud.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class FormDefinitionSelectorCloudService { export class FormDefinitionSelectorCloudService extends BaseCloudService {
contextRoot: string;
contentTypes = ['application/json']; contentTypes = ['application/json'];
accepts = ['application/json']; accepts = ['application/json'];
returnType = Object; returnType = Object;
@@ -34,6 +34,7 @@ export class FormDefinitionSelectorCloudService {
constructor(private apiService: AlfrescoApiService, constructor(private apiService: AlfrescoApiService,
private appConfigService: AppConfigService, private appConfigService: AppConfigService,
private logService: LogService) { private logService: LogService) {
super();
this.contextRoot = this.appConfigService.get('bpmHost', ''); this.contextRoot = this.appConfigService.get('bpmHost', '');
} }
@@ -65,7 +66,7 @@ export class FormDefinitionSelectorCloudService {
} }
private buildGetFormsUrl(appName: string): any { private buildGetFormsUrl(appName: string): any {
return `${this.appConfigService.get('bpmHost')}/${appName}/form/v1/forms`; return `${this.getBasePath(appName)}/form/v1/forms`;
} }
private handleError(error: any) { private handleError(error: any) {

View File

@@ -67,7 +67,7 @@ export class ClaimTaskDirective implements OnInit {
} }
isAppValid(): boolean { isAppValid(): boolean {
return this.appName && this.appName.length > 0; return (this.appName && this.appName.length > 0) || (this.appName === '');
} }
@HostListener('click') @HostListener('click')

View File

@@ -64,7 +64,7 @@ export class CompleteTaskDirective implements OnInit {
} }
isAppValid(): boolean { isAppValid(): boolean {
return this.appName && this.appName.length > 0; return (this.appName && this.appName.length > 0) || (this.appName === '');
} }
@HostListener('click') @HostListener('click')

View File

@@ -65,7 +65,7 @@ export class UnClaimTaskDirective implements OnInit {
} }
isAppValid(): boolean { isAppValid(): boolean {
return this.appName && this.appName.length > 0; return (this.appName && this.appName.length > 0) || (this.appName === '');
} }
@HostListener('click') @HostListener('click')

View File

@@ -48,21 +48,26 @@ export class TaskCloudService extends BaseCloudService {
* @returns Details of the task that was completed * @returns Details of the task that was completed
*/ */
completeTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> { completeTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> {
const queryUrl = this.buildCompleteTaskUrl(appName, taskId); if ((appName || appName === '') && taskId) {
const bodyParam = { 'payloadType': 'CompleteTaskPayload' }; const queryUrl = this.buildCompleteTaskUrl(appName, taskId);
const pathParams = {}, queryParams = {}, headerParams = {}, const bodyParam = { 'payloadType': 'CompleteTaskPayload' };
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; const pathParams = {}, queryParams = {}, headerParams = {},
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return from( return from(
this.apiService this.apiService
.getInstance() .getInstance()
.oauth2Auth.callCustomApi( .oauth2Auth.callCustomApi(
queryUrl, 'POST', pathParams, queryParams, queryUrl, 'POST', pathParams, queryParams,
headerParams, formParams, bodyParam, headerParams, formParams, bodyParam,
contentTypes, accepts, null, null) contentTypes, accepts, null, null)
).pipe( ).pipe(
catchError((err) => this.handleError(err)) catchError((err) => this.handleError(err))
); );
} else {
this.logService.error('AppName and TaskId are mandatory for complete a task');
return throwError('AppName/TaskId not configured');
}
} }
/** /**
@@ -102,7 +107,7 @@ export class TaskCloudService extends BaseCloudService {
* @returns Details of the claimed task * @returns Details of the claimed task
*/ */
claimTask(appName: string, taskId: string, assignee: string): Observable<TaskDetailsCloudModel> { claimTask(appName: string, taskId: string, assignee: string): Observable<TaskDetailsCloudModel> {
if (appName && taskId) { if ((appName || appName === '') && taskId) {
const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/claim?assignee=${assignee}`; const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/claim?assignee=${assignee}`;
return from(this.apiService.getInstance() return from(this.apiService.getInstance()
.oauth2Auth.callCustomApi(queryUrl, 'POST', .oauth2Auth.callCustomApi(queryUrl, 'POST',
@@ -129,7 +134,7 @@ export class TaskCloudService extends BaseCloudService {
* @returns Details of the task that was unclaimed * @returns Details of the task that was unclaimed
*/ */
unclaimTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> { unclaimTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> {
if (appName && taskId) { if ((appName || appName === '') && taskId) {
const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/release`; const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/release`;
return from(this.apiService.getInstance() return from(this.apiService.getInstance()
.oauth2Auth.callCustomApi(queryUrl, 'POST', .oauth2Auth.callCustomApi(queryUrl, 'POST',
@@ -184,7 +189,7 @@ export class TaskCloudService extends BaseCloudService {
* @returns Updated task details * @returns Updated task details
*/ */
updateTask(appName: string, taskId: string, updatePayload: any): Observable<TaskDetailsCloudModel> { updateTask(appName: string, taskId: string, updatePayload: any): Observable<TaskDetailsCloudModel> {
if (appName && taskId) { if ((appName || appName === '') && taskId) {
updatePayload.payloadType = 'UpdateTaskPayload'; updatePayload.payloadType = 'UpdateTaskPayload';
const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}`; const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}`;

View File

@@ -98,7 +98,7 @@ export class TaskFormCloudComponent implements OnChanges {
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
const appName = changes['appName']; const appName = changes['appName'];
if (appName && appName.currentValue && this.taskId) { if (appName && (appName.currentValue || appName.currentValue === '' ) && this.taskId) {
this.loadTask(); this.loadTask();
return; return;
} }

View File

@@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { Component, Input, OnInit, EventEmitter, Output } from '@angular/core'; import { Component, Input, OnInit, EventEmitter, Output, OnDestroy } from '@angular/core';
import { import {
CardViewDateItemModel, CardViewDateItemModel,
CardViewItem, CardViewItem,
@@ -29,13 +29,14 @@ import {
import { TaskDetailsCloudModel, TaskStatusEnum } from '../../start-task/models/task-details-cloud.model'; import { TaskDetailsCloudModel, TaskStatusEnum } from '../../start-task/models/task-details-cloud.model';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { TaskCloudService } from '../../services/task-cloud.service'; import { TaskCloudService } from '../../services/task-cloud.service';
import { Subscription } from 'rxjs';
@Component({ @Component({
selector: 'adf-cloud-task-header', selector: 'adf-cloud-task-header',
templateUrl: './task-header-cloud.component.html', templateUrl: './task-header-cloud.component.html',
styleUrls: ['./task-header-cloud.component.scss'] styleUrls: ['./task-header-cloud.component.scss']
}) })
export class TaskHeaderCloudComponent implements OnInit { export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
/** (Required) The name of the application. */ /** (Required) The name of the application. */
@Input() @Input()
@@ -58,6 +59,8 @@ export class TaskHeaderCloudComponent implements OnInit {
inEdit: boolean = false; inEdit: boolean = false;
parentTaskName: string; parentTaskName: string;
private subscriptions: Subscription[] = [];
constructor( constructor(
private taskCloudService: TaskCloudService, private taskCloudService: TaskCloudService,
private translationService: TranslationService, private translationService: TranslationService,
@@ -71,11 +74,11 @@ export class TaskHeaderCloudComponent implements OnInit {
this.loadTaskDetailsById(this.appName, this.taskId); this.loadTaskDetailsById(this.appName, this.taskId);
} }
this.cardViewUpdateService.itemUpdated$.subscribe(this.updateTaskDetails.bind(this)); this.subscriptions.push(this.cardViewUpdateService.itemUpdated$.subscribe(this.updateTaskDetails.bind(this)));
} }
loadTaskDetailsById(appName: string, taskId: string): any { loadTaskDetailsById(appName: string, taskId: string): any {
this.taskCloudService.getTaskById(appName, taskId).subscribe( this.subscriptions.push(this.taskCloudService.getTaskById(appName, taskId).subscribe(
(taskDetails) => { (taskDetails) => {
this.taskDetails = taskDetails; this.taskDetails = taskDetails;
if (this.taskDetails.parentTaskId) { if (this.taskDetails.parentTaskId) {
@@ -83,7 +86,7 @@ export class TaskHeaderCloudComponent implements OnInit {
} else { } else {
this.refreshData(); this.refreshData();
} }
}); }));
} }
private initDefaultProperties() { private initDefaultProperties() {
@@ -244,4 +247,9 @@ export class TaskHeaderCloudComponent implements OnInit {
onCompletedTask(event: any) { onCompletedTask(event: any) {
this.goBack(); this.goBack();
} }
ngOnDestroy() {
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
this.subscriptions = [];
}
} }