mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
AAE-29424 Screens (#10499)
* poc * updated unit tests * removed obsolete service, updated interface * passing data to created component, removed obsolete files * [AAE-29424] applied pr comments * [AAE-29424] updated import to avoid circular dependency error * [AAE-29424] updated styles to avoid visual bug * [AAE-29424] added self closing tags
This commit is contained in:
parent
872fb16b62
commit
bb036cbf6e
@ -0,0 +1 @@
|
|||||||
|
<div #container></div>
|
@ -0,0 +1,53 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TaskScreenCloudComponent } from './screen-cloud.component';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { ScreenRenderingService } from '../../../services/public-api';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-cloud-test-component',
|
||||||
|
template: `<div class="adf-cloud-test-container">test component</div>`,
|
||||||
|
imports: [CommonModule],
|
||||||
|
standalone: true
|
||||||
|
})
|
||||||
|
class TestComponent {}
|
||||||
|
|
||||||
|
describe('TaskScreenCloudComponent', () => {
|
||||||
|
let fixture: ComponentFixture<TaskScreenCloudComponent>;
|
||||||
|
let screenRenderingService: ScreenRenderingService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [TaskScreenCloudComponent, TestComponent]
|
||||||
|
});
|
||||||
|
fixture = TestBed.createComponent(TaskScreenCloudComponent);
|
||||||
|
screenRenderingService = TestBed.inject(ScreenRenderingService);
|
||||||
|
screenRenderingService.register({ ['test']: () => TestComponent });
|
||||||
|
fixture.componentRef.setInput('screenId', 'test');
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create custom component instance', () => {
|
||||||
|
const dynamicComponent = fixture.debugElement.query(By.css('.adf-cloud-test-container'));
|
||||||
|
expect(dynamicComponent).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,62 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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 { CommonModule } from '@angular/common';
|
||||||
|
import { Component, ComponentRef, inject, Input, OnInit, ViewChild, ViewContainerRef } from '@angular/core';
|
||||||
|
import { ScreenRenderingService } from '../../../services/public-api';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-cloud-task-screen',
|
||||||
|
standalone: true,
|
||||||
|
imports: [CommonModule],
|
||||||
|
template: '<div #container></div>'
|
||||||
|
})
|
||||||
|
export class TaskScreenCloudComponent implements OnInit {
|
||||||
|
/** Task id to fetch corresponding form and values. */
|
||||||
|
@Input() taskId: string;
|
||||||
|
/** App id to fetch corresponding form and values. */
|
||||||
|
@Input()
|
||||||
|
appName: string = '';
|
||||||
|
/** Screen id to fetch corresponding screen widget. */
|
||||||
|
@Input()
|
||||||
|
screenId: string = '';
|
||||||
|
/** Toggle readonly state of the task. */
|
||||||
|
@Input()
|
||||||
|
readOnly = false;
|
||||||
|
|
||||||
|
@ViewChild('container', { read: ViewContainerRef, static: true })
|
||||||
|
container: ViewContainerRef;
|
||||||
|
componentRef: ComponentRef<any>;
|
||||||
|
|
||||||
|
private readonly screenRenderingService = inject(ScreenRenderingService);
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (this.screenId) {
|
||||||
|
const componentType = this.screenRenderingService.resolveComponentType({ type: this.screenId });
|
||||||
|
this.componentRef = this.container.createComponent(componentType);
|
||||||
|
if (this.taskId) {
|
||||||
|
this.componentRef.setInput('taskId', this.taskId);
|
||||||
|
}
|
||||||
|
if (this.appName) {
|
||||||
|
this.componentRef.setInput('appName', this.appName);
|
||||||
|
}
|
||||||
|
if (this.screenId) {
|
||||||
|
this.componentRef.setInput('screenId', this.screenId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,13 +15,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export * from './user-preference-cloud.service';
|
export * from './base-cloud.service';
|
||||||
export * from './local-preference-cloud.service';
|
|
||||||
export * from './cloud-token.service';
|
export * from './cloud-token.service';
|
||||||
|
export * from './form-fields.interfaces';
|
||||||
|
export * from './local-preference-cloud.service';
|
||||||
export * from './notification-cloud.service';
|
export * from './notification-cloud.service';
|
||||||
export * from './preference-cloud.interface';
|
export * from './preference-cloud.interface';
|
||||||
export * from './form-fields.interfaces';
|
export * from './screen-rendering.service';
|
||||||
export * from './base-cloud.service';
|
|
||||||
export * from './task-list-cloud.service.interface';
|
export * from './task-list-cloud.service.interface';
|
||||||
|
export * from './user-preference-cloud.service';
|
||||||
export * from './variable-mapper.sevice';
|
export * from './variable-mapper.sevice';
|
||||||
export * from './web-socket.service';
|
export * from './web-socket.service';
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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 { TestBed } from '@angular/core/testing';
|
||||||
|
import { ScreenRenderingService } from './screen-rendering.service';
|
||||||
|
|
||||||
|
describe('ScreenRenderingService', () => {
|
||||||
|
let service: ScreenRenderingService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(ScreenRenderingService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,24 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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 { DynamicComponentMapper } from '@alfresco/adf-core';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class ScreenRenderingService extends DynamicComponentMapper {}
|
@ -1,73 +0,0 @@
|
|||||||
<div class="adf-task-form-cloud-container" *ngIf="!loading; else loadingTemplate">
|
|
||||||
<adf-cloud-form #adfCloudForm *ngIf="hasForm(); else withoutForm"
|
|
||||||
[appName]="appName"
|
|
||||||
[appVersion]="taskDetails.appVersion"
|
|
||||||
[taskId]="taskId"
|
|
||||||
[showTitle]="showTitle"
|
|
||||||
[processInstanceId]="taskDetails.processInstanceId"
|
|
||||||
[readOnly]="isReadOnly()"
|
|
||||||
[showRefreshButton]="showRefreshButton"
|
|
||||||
[showValidationIcon]="showValidationIcon"
|
|
||||||
[showCompleteButton]="canCompleteTask()"
|
|
||||||
[showSaveButton]="canCompleteTask()"
|
|
||||||
[displayModeConfigurations]="displayModeConfigurations"
|
|
||||||
[fieldValidators]="fieldValidators"
|
|
||||||
(formSaved)="onFormSaved($event)"
|
|
||||||
(formCompleted)="onFormCompleted($event)"
|
|
||||||
(formError)="onError($event)"
|
|
||||||
(error)="onError($event)"
|
|
||||||
(formContentClicked)="onFormContentClicked($event)"
|
|
||||||
(executeOutcome)="onFormExecuteOutcome($event)"
|
|
||||||
(displayModeOn)="onDisplayModeOn($event)"
|
|
||||||
(displayModeOff)="onDisplayModeOff($event)">
|
|
||||||
<adf-cloud-form-custom-outcomes>
|
|
||||||
<ng-template [ngTemplateOutlet]="taskFormCloudButtons">
|
|
||||||
</ng-template>
|
|
||||||
</adf-cloud-form-custom-outcomes>
|
|
||||||
</adf-cloud-form>
|
|
||||||
|
|
||||||
<ng-template #withoutForm>
|
|
||||||
<mat-card appearance="outlined" class="adf-task-form-container">
|
|
||||||
<mat-card-header *ngIf="showTitle">
|
|
||||||
<mat-card-title>
|
|
||||||
<h4>
|
|
||||||
<span class="adf-form-title">
|
|
||||||
{{ taskDetails?.name || 'FORM.FORM_RENDERER.NAMELESS_TASK' | translate }}
|
|
||||||
</span>
|
|
||||||
</h4>
|
|
||||||
</mat-card-title>
|
|
||||||
</mat-card-header>
|
|
||||||
<mat-card-content>
|
|
||||||
<adf-empty-content
|
|
||||||
[icon]="'description'"
|
|
||||||
[title]="'ADF_CLOUD_TASK_FORM.EMPTY_FORM.TITLE'"
|
|
||||||
[subtitle]="'ADF_CLOUD_TASK_FORM.EMPTY_FORM.SUBTITLE'" />
|
|
||||||
</mat-card-content>
|
|
||||||
<mat-card-actions class="adf-task-form-actions" align="end">
|
|
||||||
<ng-template [ngTemplateOutlet]="taskFormCloudButtons">
|
|
||||||
</ng-template>
|
|
||||||
<button mat-button *ngIf="canCompleteTask()" adf-cloud-complete-task [appName]="appName"
|
|
||||||
[taskId]="taskId" (success)="onCompleteTask()" (error)="onError($event)" color="primary" id="adf-form-complete">
|
|
||||||
{{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.COMPLETE' | translate}}
|
|
||||||
</button>
|
|
||||||
</mat-card-actions>
|
|
||||||
</mat-card>
|
|
||||||
</ng-template>
|
|
||||||
<ng-template #taskFormCloudButtons>
|
|
||||||
<button mat-button *ngIf="showCancelButton" id="adf-cloud-cancel-task" (click)="onCancelClick()">
|
|
||||||
{{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CANCEL' | translate}}
|
|
||||||
</button>
|
|
||||||
<button mat-button *ngIf="canClaimTask()" adf-cloud-claim-task [appName]="appName" [taskId]="taskId"
|
|
||||||
(success)="onClaimTask()" (error)="onError($event)">
|
|
||||||
{{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CLAIM' | translate}}
|
|
||||||
</button>
|
|
||||||
<button mat-button *ngIf="canUnclaimTask()" adf-cloud-unclaim-task [appName]="appName" [taskId]="taskId"
|
|
||||||
(success)="onUnclaimTask()" (error)="onError($event)">
|
|
||||||
{{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.UNCLAIM' | translate}}
|
|
||||||
</button>
|
|
||||||
</ng-template>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ng-template #loadingTemplate>
|
|
||||||
<mat-spinner class="adf-task-form-cloud-spinner" />
|
|
||||||
</ng-template>
|
|
@ -0,0 +1,39 @@
|
|||||||
|
<div class="adf-task-form-cloud-container">
|
||||||
|
<adf-cloud-form
|
||||||
|
#adfCloudForm
|
||||||
|
[appName]="appName"
|
||||||
|
[appVersion]="taskDetails.appVersion"
|
||||||
|
[taskId]="taskId"
|
||||||
|
[showTitle]="showTitle"
|
||||||
|
[processInstanceId]="taskDetails.processInstanceId"
|
||||||
|
[readOnly]="isReadOnly()"
|
||||||
|
[showRefreshButton]="showRefreshButton"
|
||||||
|
[showValidationIcon]="showValidationIcon"
|
||||||
|
[showCompleteButton]="canCompleteTask()"
|
||||||
|
[showSaveButton]="canCompleteTask()"
|
||||||
|
[displayModeConfigurations]="displayModeConfigurations"
|
||||||
|
[fieldValidators]="fieldValidators"
|
||||||
|
(formSaved)="onFormSaved($event)"
|
||||||
|
(formCompleted)="onFormCompleted($event)"
|
||||||
|
(formError)="onError($event)"
|
||||||
|
(error)="onError($event)"
|
||||||
|
(formContentClicked)="onFormContentClicked($event)"
|
||||||
|
(executeOutcome)="onFormExecuteOutcome($event)"
|
||||||
|
(displayModeOn)="onDisplayModeOn($event)"
|
||||||
|
(displayModeOff)="onDisplayModeOff($event)"
|
||||||
|
>
|
||||||
|
<adf-cloud-form-custom-outcomes>
|
||||||
|
<adf-cloud-user-task-cloud-buttons
|
||||||
|
[appName]="appName"
|
||||||
|
[canClaimTask]="canClaimTask()"
|
||||||
|
[canUnclaimTask]="canUnclaimTask()"
|
||||||
|
[showCancelButton]="showCancelButton"
|
||||||
|
[taskId]="taskId"
|
||||||
|
(cancelClick)="onCancelClick()"
|
||||||
|
(claimTask)="onClaimTask()"
|
||||||
|
(unclaimTask)="onUnclaimTask()"
|
||||||
|
(error)="onError($event)"
|
||||||
|
/>
|
||||||
|
</adf-cloud-form-custom-outcomes>
|
||||||
|
</adf-cloud-form>
|
||||||
|
</div>
|
@ -29,23 +29,4 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-cloud-spinner {
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
adf-cloud-task-form {
|
|
||||||
.adf-task-form-cloud-spinner {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -0,0 +1,282 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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 { FORM_FIELD_VALIDATORS, FormModel, FormOutcomeEvent, FormOutcomeModel } from '@alfresco/adf-core';
|
||||||
|
import { FormCustomOutcomesComponent } from '@alfresco/adf-process-services-cloud';
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
import { FormCloudComponent } from '../../../../form/components/form-cloud.component';
|
||||||
|
import { DisplayModeService } from '../../../../form/services/display-mode.service';
|
||||||
|
import { IdentityUserService } from '../../../../people/services/identity-user.service';
|
||||||
|
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
|
||||||
|
import { TaskCloudService } from '../../../services/task-cloud.service';
|
||||||
|
import {
|
||||||
|
TASK_ASSIGNED_STATE,
|
||||||
|
TASK_CLAIM_PERMISSION,
|
||||||
|
TASK_CREATED_STATE,
|
||||||
|
TASK_RELEASE_PERMISSION,
|
||||||
|
TASK_VIEW_PERMISSION,
|
||||||
|
TaskDetailsCloudModel
|
||||||
|
} from '../../../start-task/models/task-details-cloud.model';
|
||||||
|
import { MockFormFieldValidator } from '../../mocks/task-form-cloud.mock';
|
||||||
|
import { UserTaskCloudButtonsComponent } from '../user-task-cloud-buttons/user-task-cloud-buttons.component';
|
||||||
|
import { TaskFormCloudComponent } from './task-form-cloud.component';
|
||||||
|
|
||||||
|
const taskDetails: TaskDetailsCloudModel = {
|
||||||
|
appName: 'simple-app',
|
||||||
|
appVersion: 1,
|
||||||
|
assignee: 'admin.adf',
|
||||||
|
completedDate: null,
|
||||||
|
createdDate: new Date(1555419255340),
|
||||||
|
description: null,
|
||||||
|
formKey: null,
|
||||||
|
id: 'bd6b1741-6046-11e9-80f0-0a586460040d',
|
||||||
|
name: 'Task1',
|
||||||
|
owner: 'admin.adf',
|
||||||
|
standalone: false,
|
||||||
|
status: TASK_ASSIGNED_STATE,
|
||||||
|
permissions: [TASK_VIEW_PERMISSION]
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('TaskFormCloudComponent', () => {
|
||||||
|
let taskCloudService: TaskCloudService;
|
||||||
|
let identityUserService: IdentityUserService;
|
||||||
|
let getCurrentUserSpy: jasmine.Spy;
|
||||||
|
let component: TaskFormCloudComponent;
|
||||||
|
let fixture: ComponentFixture<TaskFormCloudComponent>;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [ProcessServiceCloudTestingModule],
|
||||||
|
declarations: [FormCloudComponent, UserTaskCloudButtonsComponent, FormCustomOutcomesComponent]
|
||||||
|
});
|
||||||
|
taskDetails.status = TASK_ASSIGNED_STATE;
|
||||||
|
taskDetails.permissions = [TASK_VIEW_PERMISSION];
|
||||||
|
taskDetails.standalone = false;
|
||||||
|
|
||||||
|
identityUserService = TestBed.inject(IdentityUserService);
|
||||||
|
getCurrentUserSpy = spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue({ username: 'admin.adf' });
|
||||||
|
taskCloudService = TestBed.inject(TaskCloudService);
|
||||||
|
fixture = TestBed.createComponent(TaskFormCloudComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
fixture.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Claim/Unclaim buttons', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
spyOn(component, 'hasCandidateUsers').and.returnValue(true);
|
||||||
|
fixture.componentRef.setInput('taskDetails', taskDetails);
|
||||||
|
component.taskId = 'task1';
|
||||||
|
component.showCancelButton = true;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not show release button for standalone task', () => {
|
||||||
|
taskDetails.permissions = [TASK_RELEASE_PERMISSION];
|
||||||
|
taskDetails.standalone = true;
|
||||||
|
fixture.detectChanges();
|
||||||
|
const canUnclaimTask = component.canUnclaimTask();
|
||||||
|
|
||||||
|
expect(canUnclaimTask).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not show claim button for standalone task', () => {
|
||||||
|
taskDetails.status = TASK_CREATED_STATE;
|
||||||
|
taskDetails.permissions = [TASK_CLAIM_PERMISSION];
|
||||||
|
taskDetails.standalone = true;
|
||||||
|
fixture.detectChanges();
|
||||||
|
const canClaimTask = component.canClaimTask();
|
||||||
|
|
||||||
|
expect(canClaimTask).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show release button when task is assigned to one of the candidate users', () => {
|
||||||
|
taskDetails.permissions = [TASK_RELEASE_PERMISSION];
|
||||||
|
fixture.detectChanges();
|
||||||
|
const canUnclaimTask = component.canUnclaimTask();
|
||||||
|
|
||||||
|
expect(canUnclaimTask).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not show unclaim button when status is ASSIGNED but assigned to different person', () => {
|
||||||
|
getCurrentUserSpy.and.returnValue({});
|
||||||
|
fixture.detectChanges();
|
||||||
|
const canUnclaimTask = component.canUnclaimTask();
|
||||||
|
|
||||||
|
expect(canUnclaimTask).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not show unclaim button when status is not ASSIGNED', () => {
|
||||||
|
taskDetails.status = undefined;
|
||||||
|
fixture.detectChanges();
|
||||||
|
const canUnclaimTask = component.canUnclaimTask();
|
||||||
|
|
||||||
|
expect(canUnclaimTask).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not show unclaim button when status is ASSIGNED and permissions not include RELEASE', () => {
|
||||||
|
taskDetails.status = TASK_ASSIGNED_STATE;
|
||||||
|
taskDetails.permissions = [TASK_VIEW_PERMISSION];
|
||||||
|
fixture.detectChanges();
|
||||||
|
const canUnclaimTask = component.canUnclaimTask();
|
||||||
|
|
||||||
|
expect(canUnclaimTask).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show claim button when status is CREATED and permission includes CLAIM', () => {
|
||||||
|
taskDetails.status = TASK_CREATED_STATE;
|
||||||
|
taskDetails.permissions = [TASK_CLAIM_PERMISSION];
|
||||||
|
fixture.detectChanges();
|
||||||
|
const canClaimTask = component.canClaimTask();
|
||||||
|
|
||||||
|
expect(canClaimTask).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not show claim button when status is not CREATED', () => {
|
||||||
|
taskDetails.status = undefined;
|
||||||
|
fixture.detectChanges();
|
||||||
|
const canClaimTask = component.canClaimTask();
|
||||||
|
|
||||||
|
expect(canClaimTask).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not show claim button when status is CREATED and permission not includes CLAIM', () => {
|
||||||
|
taskDetails.status = TASK_CREATED_STATE;
|
||||||
|
taskDetails.permissions = [TASK_VIEW_PERMISSION];
|
||||||
|
fixture.detectChanges();
|
||||||
|
const canClaimTask = component.canClaimTask();
|
||||||
|
|
||||||
|
expect(canClaimTask).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Inputs', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture.componentRef.setInput('taskDetails', taskDetails);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not show complete/claim/unclaim buttons when readOnly=true', () => {
|
||||||
|
component.appName = 'app1';
|
||||||
|
component.taskId = 'task1';
|
||||||
|
component.readOnly = true;
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const canShowCompleteBtn = component.canCompleteTask();
|
||||||
|
expect(canShowCompleteBtn).toBe(false);
|
||||||
|
|
||||||
|
const canClaimTask = component.canClaimTask();
|
||||||
|
expect(canClaimTask).toBe(false);
|
||||||
|
|
||||||
|
const canUnclaimTask = component.canUnclaimTask();
|
||||||
|
expect(canUnclaimTask).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should append additional field validators to the default ones when provided', () => {
|
||||||
|
const mockFirstCustomFieldValidator = new MockFormFieldValidator();
|
||||||
|
const mockSecondCustomFieldValidator = new MockFormFieldValidator();
|
||||||
|
fixture.componentRef.setInput('fieldValidators', [mockFirstCustomFieldValidator, mockSecondCustomFieldValidator]);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.fieldValidators).toEqual([...FORM_FIELD_VALIDATORS, mockFirstCustomFieldValidator, mockSecondCustomFieldValidator]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use default field validators when no additional validators are provided', () => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.fieldValidators).toEqual([...FORM_FIELD_VALIDATORS]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Events', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture.componentRef.setInput('taskDetails', taskDetails);
|
||||||
|
component.appName = 'app1';
|
||||||
|
component.taskId = 'task1';
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit cancelClick when cancel button is clicked', async () => {
|
||||||
|
spyOn(component.cancelClick, 'emit').and.stub();
|
||||||
|
component.onCancelClick();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.cancelClick.emit).toHaveBeenCalledOnceWith('task1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit taskClaimed when task is claimed', async () => {
|
||||||
|
spyOn(taskCloudService, 'claimTask').and.returnValue(of({}));
|
||||||
|
spyOn(component, 'hasCandidateUsers').and.returnValue(true);
|
||||||
|
spyOn(component.taskClaimed, 'emit').and.stub();
|
||||||
|
taskDetails.status = TASK_CREATED_STATE;
|
||||||
|
taskDetails.permissions = [TASK_CLAIM_PERMISSION];
|
||||||
|
component.onClaimTask();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.taskClaimed.emit).toHaveBeenCalledOnceWith('task1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit error when error occurs', async () => {
|
||||||
|
spyOn(component.error, 'emit').and.stub();
|
||||||
|
component.onError({});
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
|
||||||
|
expect(component.error.emit).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit an executeOutcome event when form outcome executed', () => {
|
||||||
|
const executeOutcomeSpy: jasmine.Spy = spyOn(component.executeOutcome, 'emit');
|
||||||
|
component.onFormExecuteOutcome(new FormOutcomeEvent(new FormOutcomeModel(new FormModel())));
|
||||||
|
|
||||||
|
expect(executeOutcomeSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit displayModeOn when display mode is turned on', async () => {
|
||||||
|
spyOn(component.displayModeOn, 'emit').and.stub();
|
||||||
|
component.onDisplayModeOn(DisplayModeService.DEFAULT_DISPLAY_MODE_CONFIGURATIONS[0]);
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
|
||||||
|
expect(component.displayModeOn.emit).toHaveBeenCalledWith(DisplayModeService.DEFAULT_DISPLAY_MODE_CONFIGURATIONS[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit displayModeOff when display mode is turned on', async () => {
|
||||||
|
spyOn(component.displayModeOff, 'emit').and.stub();
|
||||||
|
component.onDisplayModeOff(DisplayModeService.DEFAULT_DISPLAY_MODE_CONFIGURATIONS[0]);
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
|
||||||
|
expect(component.displayModeOff.emit).toHaveBeenCalledWith(DisplayModeService.DEFAULT_DISPLAY_MODE_CONFIGURATIONS[0]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call children cloud task form change display mode when changing the display mode', () => {
|
||||||
|
const displayMode = 'displayMode';
|
||||||
|
component.taskDetails = { ...taskDetails, formKey: 'some-form' };
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.adfCloudForm).toBeDefined();
|
||||||
|
|
||||||
|
const switchToDisplayModeSpy = spyOn(component.adfCloudForm, 'switchToDisplayMode');
|
||||||
|
component.switchToDisplayMode(displayMode);
|
||||||
|
|
||||||
|
expect(switchToDisplayModeSpy).toHaveBeenCalledOnceWith(displayMode);
|
||||||
|
});
|
||||||
|
});
|
@ -16,13 +16,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
|
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
|
||||||
import { FormCloudService } from '../../../form/public-api';
|
import { FormCloudService } from '../../../../form/public-api';
|
||||||
import { TaskCloudService } from '../../services/task-cloud.service';
|
import { TaskCloudService } from '../../../services/task-cloud.service';
|
||||||
import { TaskFormModule } from '../task-form.module';
|
import { TaskFormModule } from '../../task-form.module';
|
||||||
import { TaskFormCloudComponent } from './task-form-cloud.component';
|
import { TaskFormCloudComponent } from './task-form-cloud.component';
|
||||||
import { TaskCloudServiceMock } from '../../mock/task-cloud.service.mock';
|
import { TaskCloudServiceMock } from '../../../mock/task-cloud.service.mock';
|
||||||
import { FormCloudServiceMock } from '../../../form/mocks/form-cloud.service.mock';
|
import { FormCloudServiceMock } from '../../../../form/mocks/form-cloud.service.mock';
|
||||||
import { ProcessServicesCloudStoryModule } from '../../../testing/process-services-cloud-story.module';
|
import { ProcessServicesCloudStoryModule } from '../../../../testing/process-services-cloud-story.module';
|
||||||
import { importProvidersFrom } from '@angular/core';
|
import { importProvidersFrom } from '@angular/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -37,9 +37,7 @@ export default {
|
|||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
applicationConfig({
|
applicationConfig({
|
||||||
providers: [
|
providers: [importProvidersFrom(ProcessServicesCloudStoryModule)]
|
||||||
importProvidersFrom(ProcessServicesCloudStoryModule)
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
argTypes: {
|
argTypes: {
|
@ -15,28 +15,15 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
|
||||||
Component,
|
|
||||||
DestroyRef,
|
|
||||||
EventEmitter,
|
|
||||||
inject,
|
|
||||||
Input,
|
|
||||||
OnChanges,
|
|
||||||
OnInit,
|
|
||||||
Output,
|
|
||||||
SimpleChanges,
|
|
||||||
ViewChild,
|
|
||||||
ViewEncapsulation
|
|
||||||
} from '@angular/core';
|
|
||||||
import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model';
|
|
||||||
import { TaskCloudService } from '../../services/task-cloud.service';
|
|
||||||
import { ContentLinkModel, FORM_FIELD_VALIDATORS, FormFieldValidator, FormModel, FormOutcomeEvent, FormRenderingService } from '@alfresco/adf-core';
|
import { ContentLinkModel, FORM_FIELD_VALIDATORS, FormFieldValidator, FormModel, FormOutcomeEvent, FormRenderingService } from '@alfresco/adf-core';
|
||||||
import { AttachFileCloudWidgetComponent } from '../../../form/components/widgets/attach-file/attach-file-cloud-widget.component';
|
import { Component, EventEmitter, Input, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||||
import { DropdownCloudWidgetComponent } from '../../../form/components/widgets/dropdown/dropdown-cloud.widget';
|
import { FormCloudComponent } from '../../../../form/components/form-cloud.component';
|
||||||
import { DateCloudWidgetComponent } from '../../../form/components/widgets/date/date-cloud.widget';
|
import { AttachFileCloudWidgetComponent } from '../../../../form/components/widgets/attach-file/attach-file-cloud-widget.component';
|
||||||
import { FormCloudDisplayModeConfiguration } from '../../../services/form-fields.interfaces';
|
import { DateCloudWidgetComponent } from '../../../../form/components/widgets/date/date-cloud.widget';
|
||||||
import { FormCloudComponent } from '../../../form/components/form-cloud.component';
|
import { DropdownCloudWidgetComponent } from '../../../../form/components/widgets/dropdown/dropdown-cloud.widget';
|
||||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
import { FormCloudDisplayModeConfiguration } from '../../../../services/form-fields.interfaces';
|
||||||
|
import { TaskCloudService } from '../../../services/task-cloud.service';
|
||||||
|
import { TaskDetailsCloudModel } from '../../../start-task/models/task-details-cloud.model';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-cloud-task-form',
|
selector: 'adf-cloud-task-form',
|
||||||
@ -44,11 +31,19 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|||||||
styleUrls: ['./task-form-cloud.component.scss'],
|
styleUrls: ['./task-form-cloud.component.scss'],
|
||||||
encapsulation: ViewEncapsulation.None
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class TaskFormCloudComponent implements OnInit, OnChanges {
|
export class TaskFormCloudComponent implements OnInit {
|
||||||
/** App id to fetch corresponding form and values. */
|
/** App id to fetch corresponding form and values. */
|
||||||
@Input()
|
@Input()
|
||||||
appName: string = '';
|
appName: string = '';
|
||||||
|
|
||||||
|
/**Candidates users*/
|
||||||
|
@Input()
|
||||||
|
candidateUsers: string[] = [];
|
||||||
|
|
||||||
|
/**Candidates groups */
|
||||||
|
@Input()
|
||||||
|
candidateGroups: string[] = [];
|
||||||
|
|
||||||
/** Task id to fetch corresponding form and values. */
|
/** Task id to fetch corresponding form and values. */
|
||||||
@Input()
|
@Input()
|
||||||
taskId: string;
|
taskId: string;
|
||||||
@ -87,6 +82,10 @@ export class TaskFormCloudComponent implements OnInit, OnChanges {
|
|||||||
@Input()
|
@Input()
|
||||||
fieldValidators: FormFieldValidator[];
|
fieldValidators: FormFieldValidator[];
|
||||||
|
|
||||||
|
/** Task details. */
|
||||||
|
@Input()
|
||||||
|
taskDetails: TaskDetailsCloudModel;
|
||||||
|
|
||||||
/** Emitted when the form is saved. */
|
/** Emitted when the form is saved. */
|
||||||
@Output()
|
@Output()
|
||||||
formSaved = new EventEmitter<FormModel>();
|
formSaved = new EventEmitter<FormModel>();
|
||||||
@ -126,12 +125,6 @@ export class TaskFormCloudComponent implements OnInit, OnChanges {
|
|||||||
@Output()
|
@Output()
|
||||||
executeOutcome = new EventEmitter<FormOutcomeEvent>();
|
executeOutcome = new EventEmitter<FormOutcomeEvent>();
|
||||||
|
|
||||||
/**
|
|
||||||
* Emitted when a task is loaded`.
|
|
||||||
*/
|
|
||||||
@Output()
|
|
||||||
onTaskLoaded = new EventEmitter<TaskDetailsCloudModel>(); /* eslint-disable-line */
|
|
||||||
|
|
||||||
/** Emitted when a display mode configuration is turned on. */
|
/** Emitted when a display mode configuration is turned on. */
|
||||||
@Output()
|
@Output()
|
||||||
displayModeOn = new EventEmitter<FormCloudDisplayModeConfiguration>();
|
displayModeOn = new EventEmitter<FormCloudDisplayModeConfiguration>();
|
||||||
@ -143,15 +136,8 @@ export class TaskFormCloudComponent implements OnInit, OnChanges {
|
|||||||
@ViewChild('adfCloudForm', { static: false })
|
@ViewChild('adfCloudForm', { static: false })
|
||||||
adfCloudForm: FormCloudComponent;
|
adfCloudForm: FormCloudComponent;
|
||||||
|
|
||||||
taskDetails: TaskDetailsCloudModel;
|
|
||||||
|
|
||||||
candidateUsers: string[] = [];
|
|
||||||
candidateGroups: string[] = [];
|
|
||||||
|
|
||||||
loading: boolean = false;
|
loading: boolean = false;
|
||||||
|
|
||||||
private readonly destroyRef = inject(DestroyRef);
|
|
||||||
|
|
||||||
constructor(private taskCloudService: TaskCloudService, private formRenderingService: FormRenderingService) {
|
constructor(private taskCloudService: TaskCloudService, private formRenderingService: FormRenderingService) {
|
||||||
this.formRenderingService.setComponentTypeResolver('upload', () => AttachFileCloudWidgetComponent, true);
|
this.formRenderingService.setComponentTypeResolver('upload', () => AttachFileCloudWidgetComponent, true);
|
||||||
this.formRenderingService.setComponentTypeResolver('dropdown', () => DropdownCloudWidgetComponent, true);
|
this.formRenderingService.setComponentTypeResolver('dropdown', () => DropdownCloudWidgetComponent, true);
|
||||||
@ -160,46 +146,12 @@ export class TaskFormCloudComponent implements OnInit, OnChanges {
|
|||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.initFieldValidators();
|
this.initFieldValidators();
|
||||||
|
|
||||||
if (this.appName === '' && this.taskId) {
|
|
||||||
this.loadTask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges) {
|
|
||||||
const appName = changes['appName'];
|
|
||||||
if (appName && appName.currentValue !== appName.previousValue && this.taskId) {
|
|
||||||
this.loadTask();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const taskId = changes['taskId'];
|
|
||||||
if (taskId?.currentValue && this.appName) {
|
|
||||||
this.loadTask();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private initFieldValidators() {
|
private initFieldValidators() {
|
||||||
this.fieldValidators = this.fieldValidators ? [...FORM_FIELD_VALIDATORS, ...this.fieldValidators] : [...FORM_FIELD_VALIDATORS];
|
this.fieldValidators = this.fieldValidators ? [...FORM_FIELD_VALIDATORS, ...this.fieldValidators] : [...FORM_FIELD_VALIDATORS];
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadTask() {
|
|
||||||
this.loading = true;
|
|
||||||
this.taskCloudService
|
|
||||||
.getTaskById(this.appName, this.taskId)
|
|
||||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
||||||
.subscribe((details) => {
|
|
||||||
this.taskDetails = details;
|
|
||||||
this.loading = false;
|
|
||||||
this.onTaskLoaded.emit(this.taskDetails);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.taskCloudService.getCandidateUsers(this.appName, this.taskId).subscribe((users) => (this.candidateUsers = users || []));
|
|
||||||
|
|
||||||
this.taskCloudService.getCandidateGroups(this.appName, this.taskId).subscribe((groups) => (this.candidateGroups = groups || []));
|
|
||||||
}
|
|
||||||
|
|
||||||
hasForm(): boolean {
|
hasForm(): boolean {
|
||||||
return this.taskDetails && !!this.taskDetails.formKey;
|
return this.taskDetails && !!this.taskDetails.formKey;
|
||||||
}
|
}
|
||||||
@ -212,6 +164,10 @@ export class TaskFormCloudComponent implements OnInit, OnChanges {
|
|||||||
return !this.readOnly && this.taskCloudService.canClaimTask(this.taskDetails) && this.hasCandidateUsersOrGroups();
|
return !this.readOnly && this.taskCloudService.canClaimTask(this.taskDetails) && this.hasCandidateUsersOrGroups();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
canUnclaimTask(): boolean {
|
||||||
|
return !this.readOnly && this.taskCloudService.canUnclaimTask(this.taskDetails) && this.hasCandidateUsersOrGroups();
|
||||||
|
}
|
||||||
|
|
||||||
hasCandidateUsers(): boolean {
|
hasCandidateUsers(): boolean {
|
||||||
return this.candidateUsers.length !== 0;
|
return this.candidateUsers.length !== 0;
|
||||||
}
|
}
|
||||||
@ -224,26 +180,19 @@ export class TaskFormCloudComponent implements OnInit, OnChanges {
|
|||||||
return this.hasCandidateUsers() || this.hasCandidateGroups();
|
return this.hasCandidateUsers() || this.hasCandidateGroups();
|
||||||
}
|
}
|
||||||
|
|
||||||
canUnclaimTask(): boolean {
|
|
||||||
return !this.readOnly && this.taskCloudService.canUnclaimTask(this.taskDetails) && this.hasCandidateUsersOrGroups();
|
|
||||||
}
|
|
||||||
|
|
||||||
isReadOnly(): boolean {
|
isReadOnly(): boolean {
|
||||||
return this.readOnly || !this.taskCloudService.canCompleteTask(this.taskDetails);
|
return this.readOnly || !this.taskCloudService.canCompleteTask(this.taskDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
onCompleteTask() {
|
onCompleteTask() {
|
||||||
this.loadTask();
|
|
||||||
this.taskCompleted.emit(this.taskId);
|
this.taskCompleted.emit(this.taskId);
|
||||||
}
|
}
|
||||||
|
|
||||||
onClaimTask() {
|
onClaimTask() {
|
||||||
this.loadTask();
|
|
||||||
this.taskClaimed.emit(this.taskId);
|
this.taskClaimed.emit(this.taskId);
|
||||||
}
|
}
|
||||||
|
|
||||||
onUnclaimTask() {
|
onUnclaimTask() {
|
||||||
this.loadTask();
|
|
||||||
this.taskUnclaimed.emit(this.taskId);
|
this.taskUnclaimed.emit(this.taskId);
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
|||||||
|
<button
|
||||||
|
*ngIf="showCancelButton"
|
||||||
|
mat-button
|
||||||
|
id="adf-cloud-cancel-task"
|
||||||
|
(click)="onCancelClick()"
|
||||||
|
>
|
||||||
|
{{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CANCEL' | translate}}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
*ngIf="canClaimTask"
|
||||||
|
adf-cloud-claim-task
|
||||||
|
class="adf-user-task-cloud-claim-btn"
|
||||||
|
mat-button
|
||||||
|
[appName]="appName"
|
||||||
|
[taskId]="taskId"
|
||||||
|
(success)="onClaimTask()"
|
||||||
|
(error)="onError($event)"
|
||||||
|
>
|
||||||
|
{{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CLAIM' | translate}}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
*ngIf="canUnclaimTask"
|
||||||
|
adf-cloud-unclaim-task
|
||||||
|
class="adf-user-task-cloud-unclaim-btn"
|
||||||
|
mat-button
|
||||||
|
[appName]="appName"
|
||||||
|
[taskId]="taskId"
|
||||||
|
(success)="onUnclaimTask()"
|
||||||
|
(error)="onError($event)"
|
||||||
|
>
|
||||||
|
{{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.UNCLAIM' | translate}}
|
||||||
|
</button>
|
@ -0,0 +1,130 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { UserTaskCloudButtonsComponent } from './user-task-cloud-buttons.component';
|
||||||
|
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
||||||
|
import { HarnessLoader } from '@angular/cdk/testing';
|
||||||
|
import { MatButtonHarness } from '@angular/material/button/testing';
|
||||||
|
import { NoopTranslateModule } from '@alfresco/adf-core';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { DebugElement } from '@angular/core';
|
||||||
|
import { ProcessServiceCloudTestingModule } from 'lib/process-services-cloud/src/lib/testing/process-service-cloud.testing.module';
|
||||||
|
import { TaskCloudService } from '@alfresco/adf-process-services-cloud';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
|
||||||
|
describe('UserTaskCloudButtonsComponent', () => {
|
||||||
|
let component: UserTaskCloudButtonsComponent;
|
||||||
|
let fixture: ComponentFixture<UserTaskCloudButtonsComponent>;
|
||||||
|
let loader: HarnessLoader;
|
||||||
|
let debugElement: DebugElement;
|
||||||
|
let taskCloudService: TaskCloudService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [NoopTranslateModule, ProcessServiceCloudTestingModule],
|
||||||
|
declarations: [UserTaskCloudButtonsComponent]
|
||||||
|
});
|
||||||
|
fixture = TestBed.createComponent(UserTaskCloudButtonsComponent);
|
||||||
|
debugElement = fixture.debugElement;
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
loader = TestbedHarnessEnvironment.loader(fixture);
|
||||||
|
taskCloudService = TestBed.inject(TaskCloudService);
|
||||||
|
|
||||||
|
fixture.componentRef.setInput('appName', 'app-test');
|
||||||
|
fixture.componentRef.setInput('taskId', 'task1');
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show cancel button', async () => {
|
||||||
|
fixture.componentRef.setInput('showCancelButton', false);
|
||||||
|
let cancelButton: MatButtonHarness = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '#adf-cloud-cancel-task' }));
|
||||||
|
|
||||||
|
expect(cancelButton).toBeNull();
|
||||||
|
|
||||||
|
fixture.componentRef.setInput('showCancelButton', true);
|
||||||
|
fixture.detectChanges();
|
||||||
|
cancelButton = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '#adf-cloud-cancel-task' }));
|
||||||
|
|
||||||
|
expect(cancelButton).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit onCancelClick when cancel button clicked', async () => {
|
||||||
|
const cancelClickSpy = spyOn(component.cancelClick, 'emit');
|
||||||
|
fixture.componentRef.setInput('showCancelButton', true);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const cancelButton: MatButtonHarness = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '#adf-cloud-cancel-task' }));
|
||||||
|
await cancelButton.click();
|
||||||
|
expect(cancelClickSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show claim button', async () => {
|
||||||
|
let claimButton: MatButtonHarness = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '.adf-user-task-cloud-claim-btn' }));
|
||||||
|
|
||||||
|
expect(claimButton).toBeNull();
|
||||||
|
|
||||||
|
fixture.componentRef.setInput('canClaimTask', true);
|
||||||
|
fixture.detectChanges();
|
||||||
|
claimButton = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '.adf-user-task-cloud-claim-btn' }));
|
||||||
|
|
||||||
|
expect(claimButton).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit claimTask when claim button clicked', async () => {
|
||||||
|
spyOn(taskCloudService, 'claimTask').and.returnValue(of({}));
|
||||||
|
fixture.componentRef.setInput('canClaimTask', true);
|
||||||
|
spyOn(component.claimTask, 'emit').and.stub();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const claimButton = debugElement.query(By.css('[adf-cloud-claim-task]'));
|
||||||
|
expect(claimButton).toBeTruthy();
|
||||||
|
|
||||||
|
claimButton.triggerEventHandler('click', {});
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
|
||||||
|
expect(component.claimTask.emit).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show unclaim button', async () => {
|
||||||
|
let unclaimButton: MatButtonHarness = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '.adf-user-task-cloud-unclaim-btn' }));
|
||||||
|
|
||||||
|
expect(unclaimButton).toBeNull();
|
||||||
|
|
||||||
|
fixture.componentRef.setInput('canUnclaimTask', true);
|
||||||
|
fixture.detectChanges();
|
||||||
|
unclaimButton = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '.adf-user-task-cloud-unclaim-btn' }));
|
||||||
|
|
||||||
|
expect(unclaimButton).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit unclaim when button clicked', async () => {
|
||||||
|
spyOn(taskCloudService, 'unclaimTask').and.returnValue(of({}));
|
||||||
|
fixture.componentRef.setInput('canUnclaimTask', true);
|
||||||
|
spyOn(component.unclaimTask, 'emit').and.stub();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const unclaimButton = debugElement.query(By.css('[adf-cloud-unclaim-task]'));
|
||||||
|
expect(unclaimButton).toBeTruthy();
|
||||||
|
unclaimButton.triggerEventHandler('click', {});
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
|
||||||
|
expect(component.unclaimTask.emit).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,71 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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, EventEmitter, Input, Output } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-cloud-user-task-cloud-buttons',
|
||||||
|
styles: ['button { margin-right: 8px; }'],
|
||||||
|
templateUrl: './user-task-cloud-buttons.component.html'
|
||||||
|
})
|
||||||
|
export class UserTaskCloudButtonsComponent {
|
||||||
|
/** App id to fetch corresponding form and values. */
|
||||||
|
@Input()
|
||||||
|
appName: string = '';
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
canClaimTask: boolean;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
canUnclaimTask: boolean;
|
||||||
|
|
||||||
|
/** Task id to fetch corresponding form and values. */
|
||||||
|
@Input()
|
||||||
|
taskId: string;
|
||||||
|
|
||||||
|
/** Toggle rendering of the `Cancel` button. */
|
||||||
|
@Input()
|
||||||
|
showCancelButton = true;
|
||||||
|
|
||||||
|
/** Emitted when any error occurs. */
|
||||||
|
@Output() error = new EventEmitter<any>();
|
||||||
|
|
||||||
|
/** Emitted when the cancel button is clicked. */
|
||||||
|
@Output() cancelClick = new EventEmitter<any>();
|
||||||
|
|
||||||
|
/** Emitted when the task is claimed. */
|
||||||
|
@Output() claimTask = new EventEmitter<any>();
|
||||||
|
|
||||||
|
/** Emitted when the task is unclaimed. */
|
||||||
|
@Output() unclaimTask = new EventEmitter<any>();
|
||||||
|
|
||||||
|
onError(data: any): void {
|
||||||
|
this.error.emit(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
onUnclaimTask(): void {
|
||||||
|
this.unclaimTask.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
onClaimTask(): void {
|
||||||
|
this.claimTask.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
onCancelClick(): void {
|
||||||
|
this.cancelClick.emit();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,92 @@
|
|||||||
|
<div class="adf-user-task-cloud-container">
|
||||||
|
<div *ngIf="!loading; else loadingTemplate">
|
||||||
|
<ng-container [ngSwitch]="taskType">
|
||||||
|
<ng-container *ngSwitchCase="taskTypeEnum.Form">
|
||||||
|
<adf-cloud-task-form
|
||||||
|
#adfCloudTaskForm
|
||||||
|
[appName]="appName"
|
||||||
|
[candidateUsers]="candidateUsers"
|
||||||
|
[candidateGroups]="candidateGroups"
|
||||||
|
[displayModeConfigurations]="displayModeConfigurations"
|
||||||
|
[fieldValidators]="fieldValidators"
|
||||||
|
[showValidationIcon]="showValidationIcon"
|
||||||
|
[showTitle]="showTitle"
|
||||||
|
[taskId]="taskId"
|
||||||
|
[taskDetails]="taskDetails"
|
||||||
|
(cancelClick)="onCancelForm()"
|
||||||
|
(executeOutcome)="onExecuteOutcome($event)"
|
||||||
|
(error)="onError($event)"
|
||||||
|
(formSaved)="onFormSaved()"
|
||||||
|
(formContentClicked)="onFormContentClicked($event)"
|
||||||
|
(taskCompleted)="onCompleteTaskForm()"
|
||||||
|
(taskClaimed)="onClaimTask()"
|
||||||
|
(taskUnclaimed)="onTaskUnclaimed()"
|
||||||
|
/>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngSwitchCase="taskTypeEnum.Screen">
|
||||||
|
<adf-cloud-task-screen
|
||||||
|
[taskId]="taskId"
|
||||||
|
[appName]="appName"
|
||||||
|
[screenId]="screenId"
|
||||||
|
/>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngSwitchCase="taskTypeEnum.None">
|
||||||
|
<mat-card appearance="outlined" class="adf-task-form-container">
|
||||||
|
<mat-card-header *ngIf="showTitle">
|
||||||
|
<mat-card-title>
|
||||||
|
<h4>
|
||||||
|
<span class="adf-form-title">
|
||||||
|
{{ taskDetails?.name || 'FORM.FORM_RENDERER.NAMELESS_TASK' | translate }}
|
||||||
|
</span>
|
||||||
|
</h4>
|
||||||
|
</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content>
|
||||||
|
<adf-empty-content
|
||||||
|
[icon]="'description'"
|
||||||
|
[title]="'ADF_CLOUD_TASK_FORM.EMPTY_FORM.TITLE'"
|
||||||
|
[subtitle]="'ADF_CLOUD_TASK_FORM.EMPTY_FORM.SUBTITLE'" />
|
||||||
|
</mat-card-content>
|
||||||
|
<mat-card-actions class="adf-task-form-actions" align="end">
|
||||||
|
<ng-template [ngTemplateOutlet]="taskFormCloudButtons">
|
||||||
|
</ng-template>
|
||||||
|
<button
|
||||||
|
*ngIf="canCompleteTask()"
|
||||||
|
mat-button
|
||||||
|
adf-cloud-complete-task
|
||||||
|
[appName]="appName"
|
||||||
|
[taskId]="taskId"
|
||||||
|
(success)="onCompleteTask()"
|
||||||
|
(error)="onError($event)"
|
||||||
|
color="primary"
|
||||||
|
id="adf-form-complete"
|
||||||
|
>
|
||||||
|
{{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.COMPLETE' | translate}}
|
||||||
|
</button>
|
||||||
|
</mat-card-actions>
|
||||||
|
</mat-card>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-template #loadingTemplate>
|
||||||
|
<mat-spinner class="adf-user-task-cloud-spinner" />
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template #taskFormCloudButtons>
|
||||||
|
<adf-cloud-user-task-cloud-buttons
|
||||||
|
[appName]="appName"
|
||||||
|
[canClaimTask]="canClaimTask()"
|
||||||
|
[canUnclaimTask]="canUnclaimTask()"
|
||||||
|
[showCancelButton]="showCancelButton"
|
||||||
|
[taskId]="taskId"
|
||||||
|
(cancelClick)="onCancelClick()"
|
||||||
|
(claimTask)="onClaimTask()"
|
||||||
|
(unclaimTask)="onUnclaimTask()"
|
||||||
|
(error)="onError($event)"
|
||||||
|
/>
|
||||||
|
</ng-template>
|
@ -0,0 +1,13 @@
|
|||||||
|
.adf-user-task-cloud-container {
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-user-task-cloud-spinner {
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
@ -15,29 +15,28 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { DebugElement, SimpleChange } from '@angular/core';
|
import { NoopTranslateModule } from '@alfresco/adf-core';
|
||||||
import { By } from '@angular/platform-browser';
|
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { FORM_FIELD_VALIDATORS, FormModel, FormOutcomeEvent, FormOutcomeModel } from '@alfresco/adf-core';
|
|
||||||
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
|
||||||
import { TaskFormCloudComponent } from './task-form-cloud.component';
|
|
||||||
import {
|
import {
|
||||||
TaskDetailsCloudModel,
|
|
||||||
TASK_ASSIGNED_STATE,
|
TASK_ASSIGNED_STATE,
|
||||||
TASK_CLAIM_PERMISSION,
|
TASK_CLAIM_PERMISSION,
|
||||||
TASK_CREATED_STATE,
|
TASK_CREATED_STATE,
|
||||||
TASK_RELEASE_PERMISSION,
|
TASK_RELEASE_PERMISSION,
|
||||||
TASK_VIEW_PERMISSION
|
TASK_VIEW_PERMISSION,
|
||||||
} from '../../start-task/models/task-details-cloud.model';
|
TaskCloudService,
|
||||||
import { TaskCloudService } from '../../services/task-cloud.service';
|
TaskDetailsCloudModel,
|
||||||
import { IdentityUserService } from '../../../people/services/identity-user.service';
|
TaskFormCloudComponent
|
||||||
|
} from '@alfresco/adf-process-services-cloud';
|
||||||
import { HarnessLoader } from '@angular/cdk/testing';
|
import { HarnessLoader } from '@angular/cdk/testing';
|
||||||
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
||||||
|
import { SimpleChange } from '@angular/core';
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { MatButtonHarness } from '@angular/material/button/testing';
|
||||||
|
import { MatCardHarness } from '@angular/material/card/testing';
|
||||||
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
|
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
|
||||||
import { DisplayModeService } from '../../../form/services/display-mode.service';
|
import { ProcessServiceCloudTestingModule } from 'lib/process-services-cloud/src/lib/testing/process-service-cloud.testing.module';
|
||||||
import { FormCloudComponent } from '../../../form/components/form-cloud.component';
|
import { of } from 'rxjs';
|
||||||
import { MockFormFieldValidator } from '../mocks/task-form-cloud.mock';
|
import { IdentityUserService } from '../../../../people/services/identity-user.service';
|
||||||
|
import { UserTaskCloudComponent } from './user-task-cloud.component';
|
||||||
|
|
||||||
const taskDetails: TaskDetailsCloudModel = {
|
const taskDetails: TaskDetailsCloudModel = {
|
||||||
appName: 'simple-app',
|
appName: 'simple-app',
|
||||||
@ -54,265 +53,259 @@ const taskDetails: TaskDetailsCloudModel = {
|
|||||||
permissions: [TASK_VIEW_PERMISSION]
|
permissions: [TASK_VIEW_PERMISSION]
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('TaskFormCloudComponent', () => {
|
describe('UserTaskCloudComponent', () => {
|
||||||
let loader: HarnessLoader;
|
let component: UserTaskCloudComponent;
|
||||||
|
let fixture: ComponentFixture<UserTaskCloudComponent>;
|
||||||
let taskCloudService: TaskCloudService;
|
let taskCloudService: TaskCloudService;
|
||||||
let identityUserService: IdentityUserService;
|
|
||||||
|
|
||||||
let getTaskSpy: jasmine.Spy;
|
let getTaskSpy: jasmine.Spy;
|
||||||
let getCurrentUserSpy: jasmine.Spy;
|
let getCurrentUserSpy: jasmine.Spy;
|
||||||
let debugElement: DebugElement;
|
let loader: HarnessLoader;
|
||||||
|
let identityUserService: IdentityUserService;
|
||||||
let component: TaskFormCloudComponent;
|
|
||||||
let fixture: ComponentFixture<TaskFormCloudComponent>;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [ProcessServiceCloudTestingModule],
|
imports: [NoopTranslateModule, ProcessServiceCloudTestingModule],
|
||||||
declarations: [FormCloudComponent]
|
declarations: [UserTaskCloudComponent, TaskFormCloudComponent]
|
||||||
});
|
});
|
||||||
taskDetails.status = TASK_ASSIGNED_STATE;
|
fixture = TestBed.createComponent(UserTaskCloudComponent);
|
||||||
taskDetails.permissions = [TASK_VIEW_PERMISSION];
|
|
||||||
taskDetails.standalone = false;
|
|
||||||
|
|
||||||
identityUserService = TestBed.inject(IdentityUserService);
|
|
||||||
getCurrentUserSpy = spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue({ username: 'admin.adf' });
|
|
||||||
taskCloudService = TestBed.inject(TaskCloudService);
|
|
||||||
getTaskSpy = spyOn(taskCloudService, 'getTaskById').and.returnValue(of(taskDetails));
|
|
||||||
spyOn(taskCloudService, 'getCandidateGroups').and.returnValue(of([]));
|
|
||||||
spyOn(taskCloudService, 'getCandidateUsers').and.returnValue(of([]));
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(TaskFormCloudComponent);
|
|
||||||
debugElement = fixture.debugElement;
|
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
loader = TestbedHarnessEnvironment.loader(fixture);
|
loader = TestbedHarnessEnvironment.loader(fixture);
|
||||||
});
|
taskCloudService = TestBed.inject(TaskCloudService);
|
||||||
|
identityUserService = TestBed.inject(IdentityUserService);
|
||||||
|
|
||||||
afterEach(() => {
|
getTaskSpy = spyOn(taskCloudService, 'getTaskById').and.returnValue(of(taskDetails));
|
||||||
fixture.destroy();
|
getCurrentUserSpy = spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue({ username: 'admin.adf' });
|
||||||
|
spyOn(taskCloudService, 'getCandidateGroups').and.returnValue(of([]));
|
||||||
|
spyOn(taskCloudService, 'getCandidateUsers').and.returnValue(of([]));
|
||||||
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Complete button', () => {
|
describe('Complete button', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
component.taskId = 'task1';
|
fixture.componentRef.setInput('showCompleteButton', true);
|
||||||
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
|
fixture.componentRef.setInput('appName', 'app1');
|
||||||
|
fixture.componentRef.setInput('taskId', 'task1');
|
||||||
|
getTaskSpy.and.returnValue(of({ ...taskDetails }));
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show complete button when status is ASSIGNED', () => {
|
it('should show complete button when status is ASSIGNED', async () => {
|
||||||
const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]'));
|
const completeButton = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '#adf-form-complete' }));
|
||||||
expect(completeBtn.nativeElement).toBeDefined();
|
|
||||||
expect(completeBtn.nativeElement.innerText.trim()).toEqual('ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.COMPLETE');
|
expect(completeButton).not.toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not show complete button when status is ASSIGNED but assigned to a different person', () => {
|
it('should not show complete button when status is ASSIGNED but assigned to a different person', async () => {
|
||||||
getCurrentUserSpy.and.returnValue({});
|
getCurrentUserSpy.and.returnValue({});
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
const completeButton = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '#adf-form-complete' }));
|
||||||
|
|
||||||
const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]'));
|
expect(completeButton).toBeNull();
|
||||||
expect(completeBtn).toBeNull();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not show complete button when showCompleteButton=false', () => {
|
it('should not show complete button when showCompleteButton=false', async () => {
|
||||||
component.showCompleteButton = false;
|
fixture.componentRef.setInput('showCompleteButton', false);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
const completeButton = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '#adf-form-complete' }));
|
||||||
|
|
||||||
const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]'));
|
expect(completeButton).toBeNull();
|
||||||
expect(completeBtn).toBeNull();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Claim/Unclaim buttons', () => {
|
describe('Claim/Unclaim buttons', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyOn(component, 'hasCandidateUsers').and.returnValue(true);
|
spyOn(component, 'hasCandidateUsers').and.returnValue(true);
|
||||||
|
component.taskDetails = taskDetails;
|
||||||
|
fixture.componentRef.setInput('appName', 'app1');
|
||||||
|
fixture.componentRef.setInput('taskId', 'task1');
|
||||||
getTaskSpy.and.returnValue(of(taskDetails));
|
getTaskSpy.and.returnValue(of(taskDetails));
|
||||||
component.taskId = 'task1';
|
|
||||||
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not show release button for standalone task', () => {
|
it('should not show release button for standalone task', async () => {
|
||||||
taskDetails.permissions = [TASK_RELEASE_PERMISSION];
|
component.taskDetails.permissions = [TASK_RELEASE_PERMISSION];
|
||||||
taskDetails.standalone = true;
|
component.taskDetails.standalone = true;
|
||||||
getTaskSpy.and.returnValue(of(taskDetails));
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
const unclaimBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '[adf-cloud-unclaim-task]' }));
|
||||||
|
|
||||||
const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]'));
|
|
||||||
expect(unclaimBtn).toBeNull();
|
expect(unclaimBtn).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not show claim button for standalone task', () => {
|
it('should not show claim button for standalone task', async () => {
|
||||||
taskDetails.status = TASK_CREATED_STATE;
|
component.taskDetails.status = TASK_CREATED_STATE;
|
||||||
taskDetails.permissions = [TASK_CLAIM_PERMISSION];
|
component.taskDetails.permissions = [TASK_CLAIM_PERMISSION];
|
||||||
taskDetails.standalone = true;
|
component.taskDetails.standalone = true;
|
||||||
getTaskSpy.and.returnValue(of(taskDetails));
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
const claimBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '[adf-cloud-claim-task]' }));
|
||||||
|
|
||||||
const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]'));
|
|
||||||
expect(claimBtn).toBeNull();
|
expect(claimBtn).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show release button when task is assigned to one of the candidate users', () => {
|
it('should show release button when task is assigned to one of the candidate users', async () => {
|
||||||
taskDetails.permissions = [TASK_RELEASE_PERMISSION];
|
component.taskDetails = { ...taskDetails, standalone: false, status: TASK_ASSIGNED_STATE, permissions: [TASK_RELEASE_PERMISSION] };
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
const unclaimBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '[adf-cloud-unclaim-task]' }));
|
||||||
|
expect(unclaimBtn).not.toBeNull();
|
||||||
|
|
||||||
const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]'));
|
const unclaimBtnLabel = await unclaimBtn.getText();
|
||||||
expect(unclaimBtn.nativeElement).toBeDefined();
|
expect(unclaimBtnLabel).toEqual('ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.UNCLAIM');
|
||||||
expect(unclaimBtn.nativeElement.innerText.trim()).toEqual('ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.UNCLAIM');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not show unclaim button when status is ASSIGNED but assigned to different person', () => {
|
it('should not show unclaim button when status is ASSIGNED but assigned to different person', async () => {
|
||||||
getCurrentUserSpy.and.returnValue({});
|
getCurrentUserSpy.and.returnValue({});
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
const unclaimBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '[adf-cloud-unclaim-task]' }));
|
||||||
|
|
||||||
const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]'));
|
|
||||||
expect(unclaimBtn).toBeNull();
|
expect(unclaimBtn).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not show unclaim button when status is not ASSIGNED', () => {
|
it('should not show unclaim button when status is not ASSIGNED', async () => {
|
||||||
taskDetails.status = undefined;
|
component.taskDetails.status = undefined;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
const unclaimBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '[adf-cloud-unclaim-task]' }));
|
||||||
|
|
||||||
const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]'));
|
|
||||||
expect(unclaimBtn).toBeNull();
|
expect(unclaimBtn).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not show unclaim button when status is ASSIGNED and permissions not include RELEASE', () => {
|
it('should not show unclaim button when status is ASSIGNED and permissions not include RELEASE', async () => {
|
||||||
taskDetails.status = TASK_ASSIGNED_STATE;
|
component.taskDetails.status = TASK_ASSIGNED_STATE;
|
||||||
taskDetails.permissions = [TASK_VIEW_PERMISSION];
|
component.taskDetails.permissions = [TASK_VIEW_PERMISSION];
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
const unclaimBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '[adf-cloud-unclaim-task]' }));
|
||||||
|
|
||||||
const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]'));
|
|
||||||
expect(unclaimBtn).toBeNull();
|
expect(unclaimBtn).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show claim button when status is CREATED and permission includes CLAIM', () => {
|
it('should show claim button when status is CREATED and permission includes CLAIM', async () => {
|
||||||
taskDetails.status = TASK_CREATED_STATE;
|
component.taskDetails.standalone = false;
|
||||||
taskDetails.permissions = [TASK_CLAIM_PERMISSION];
|
component.taskDetails.status = TASK_CREATED_STATE;
|
||||||
|
component.taskDetails.permissions = [TASK_CLAIM_PERMISSION];
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]'));
|
const claimBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '[adf-cloud-claim-task]' }));
|
||||||
expect(claimBtn.nativeElement).toBeDefined();
|
expect(claimBtn).not.toBeNull();
|
||||||
expect(claimBtn.nativeElement.innerText.trim()).toEqual('ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CLAIM');
|
|
||||||
|
const claimBtnLabel = await claimBtn.getText();
|
||||||
|
expect(claimBtnLabel).toEqual('ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CLAIM');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not show claim button when status is not CREATED', () => {
|
it('should not show claim button when status is not CREATED', async () => {
|
||||||
taskDetails.status = undefined;
|
component.taskDetails.status = undefined;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
const claimBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '[adf-cloud-claim-task]' }));
|
||||||
|
|
||||||
const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]'));
|
|
||||||
expect(claimBtn).toBeNull();
|
expect(claimBtn).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not show claim button when status is CREATED and permission not includes CLAIM', () => {
|
it('should not show claim button when status is CREATED and permission not includes CLAIM', async () => {
|
||||||
taskDetails.status = TASK_CREATED_STATE;
|
component.taskDetails.status = TASK_CREATED_STATE;
|
||||||
taskDetails.permissions = [TASK_VIEW_PERMISSION];
|
component.taskDetails.permissions = [TASK_VIEW_PERMISSION];
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
const claimBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '[adf-cloud-claim-task]' }));
|
||||||
|
|
||||||
const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]'));
|
|
||||||
expect(claimBtn).toBeNull();
|
expect(claimBtn).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Cancel button', () => {
|
describe('Cancel button', () => {
|
||||||
it('should show cancel button by default', () => {
|
beforeEach(() => {
|
||||||
component.appName = 'app1';
|
fixture.componentRef.setInput('appName', 'app1');
|
||||||
component.taskId = 'task1';
|
fixture.componentRef.setInput('taskId', 'task1');
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const cancelBtn = debugElement.query(By.css('#adf-cloud-cancel-task'));
|
|
||||||
expect(cancelBtn.nativeElement).toBeDefined();
|
|
||||||
expect(cancelBtn.nativeElement.innerText.trim()).toEqual('ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CANCEL');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not show cancel button when showCancelButton=false', () => {
|
it('should show cancel button by default', async () => {
|
||||||
component.appName = 'app1';
|
const cancelBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '#adf-cloud-cancel-task' }));
|
||||||
component.taskId = 'task1';
|
expect(cancelBtn).toBeDefined();
|
||||||
component.showCancelButton = false;
|
|
||||||
|
|
||||||
|
const cancelBtnLabel = await cancelBtn.getText();
|
||||||
|
expect(cancelBtnLabel).toEqual('ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CANCEL');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not show cancel button when showCancelButton=false', async () => {
|
||||||
|
fixture.componentRef.setInput('showCancelButton', false);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
const cancelBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '#adf-cloud-cancel-task' }));
|
||||||
|
|
||||||
const cancelBtn = debugElement.query(By.css('#adf-cloud-cancel-task'));
|
|
||||||
expect(cancelBtn).toBeNull();
|
expect(cancelBtn).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Inputs', () => {
|
describe('Inputs', () => {
|
||||||
it('should not show complete/claim/unclaim buttons when readOnly=true', () => {
|
it('should not show complete/claim/unclaim buttons when readOnly=true', async () => {
|
||||||
component.appName = 'app1';
|
getTaskSpy.and.returnValue(of(taskDetails));
|
||||||
component.taskId = 'task1';
|
fixture.componentRef.setInput('appName', 'app1');
|
||||||
component.readOnly = true;
|
fixture.componentRef.setInput('taskId', 'task1');
|
||||||
|
fixture.componentRef.setInput('readOnly', true);
|
||||||
|
fixture.componentRef.setInput('showCancelButton', true);
|
||||||
|
component.getTaskType();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
|
||||||
const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]'));
|
const completeBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '[adf-cloud-complete-task]' }));
|
||||||
expect(completeBtn).toBeNull();
|
expect(completeBtn).toBeNull();
|
||||||
|
|
||||||
const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]'));
|
const claimBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '[adf-cloud-claim-task]' }));
|
||||||
expect(claimBtn).toBeNull();
|
expect(claimBtn).toBeNull();
|
||||||
|
|
||||||
const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]'));
|
const unclaimBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '[adf-cloud-unclaim-task]' }));
|
||||||
expect(unclaimBtn).toBeNull();
|
expect(unclaimBtn).toBeNull();
|
||||||
|
|
||||||
const cancelBtn = debugElement.query(By.css('#adf-cloud-cancel-task'));
|
const cancelBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '#adf-cloud-cancel-task' }));
|
||||||
expect(cancelBtn.nativeElement).toBeDefined();
|
expect(cancelBtn).toBeDefined();
|
||||||
expect(cancelBtn.nativeElement.innerText.trim()).toEqual('ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CANCEL');
|
|
||||||
|
const cancelBtnLabel = await cancelBtn.getText();
|
||||||
|
expect(cancelBtnLabel).toEqual('ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CANCEL');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should load data when appName changes', () => {
|
it('should load data when appName changes', () => {
|
||||||
component.taskId = 'task1';
|
component.taskId = 'task1';
|
||||||
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
|
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
|
||||||
|
|
||||||
expect(getTaskSpy).toHaveBeenCalled();
|
expect(getTaskSpy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should load data when taskId changes', () => {
|
it('should load data when taskId changes', () => {
|
||||||
component.appName = 'app1';
|
component.appName = 'app1';
|
||||||
component.ngOnChanges({ taskId: new SimpleChange(null, 'task1', false) });
|
component.ngOnChanges({ taskId: new SimpleChange(null, 'task1', false) });
|
||||||
|
|
||||||
expect(getTaskSpy).toHaveBeenCalled();
|
expect(getTaskSpy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not load data when appName changes and taskId is not defined', () => {
|
it('should not load data when appName changes and taskId is not defined', async () => {
|
||||||
|
fixture.componentRef.setInput('taskId', null);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.taskId).toBeNull();
|
||||||
|
|
||||||
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
|
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
|
||||||
|
await fixture.whenStable();
|
||||||
|
|
||||||
expect(getTaskSpy).not.toHaveBeenCalled();
|
expect(getTaskSpy).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not load data when taskId changes and appName is not defined', () => {
|
it('should not load data when taskId changes and appName is not defined', async () => {
|
||||||
component.ngOnChanges({ taskId: new SimpleChange(null, 'task1', false) });
|
component.ngOnChanges({ taskId: new SimpleChange(null, 'task1', false) });
|
||||||
|
|
||||||
expect(getTaskSpy).not.toHaveBeenCalled();
|
expect(getTaskSpy).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should append additional field validators to the default ones when provided', () => {
|
|
||||||
const mockFirstCustomFieldValidator = new MockFormFieldValidator();
|
|
||||||
const mockSecondCustomFieldValidator = new MockFormFieldValidator();
|
|
||||||
|
|
||||||
component.fieldValidators = [mockFirstCustomFieldValidator, mockSecondCustomFieldValidator];
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(component.fieldValidators).toEqual([...FORM_FIELD_VALIDATORS, mockFirstCustomFieldValidator, mockSecondCustomFieldValidator]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should use default field validators when no additional validators are provided', () => {
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(component.fieldValidators).toEqual([...FORM_FIELD_VALIDATORS]);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Events', () => {
|
describe('Events', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
component.appName = 'app1';
|
fixture.componentRef.setInput('appName', 'app1');
|
||||||
component.taskId = 'task1';
|
fixture.componentRef.setInput('taskId', 'task1');
|
||||||
|
fixture.componentRef.setInput('showCancelButton', true);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit cancelClick when cancel button is clicked', async () => {
|
it('should emit cancelClick when cancel button is clicked', async () => {
|
||||||
spyOn(component.cancelClick, 'emit').and.stub();
|
spyOn(component.cancelClick, 'emit').and.stub();
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const cancelBtn = debugElement.query(By.css('#adf-cloud-cancel-task'));
|
const cancelBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '#adf-cloud-cancel-task' }));
|
||||||
cancelBtn.triggerEventHandler('click', {});
|
await cancelBtn.click();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
|
|
||||||
@ -320,14 +313,13 @@ describe('TaskFormCloudComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should emit taskCompleted when task is completed', async () => {
|
it('should emit taskCompleted when task is completed', async () => {
|
||||||
|
component.taskDetails.status = TASK_ASSIGNED_STATE;
|
||||||
spyOn(taskCloudService, 'completeTask').and.returnValue(of({}));
|
spyOn(taskCloudService, 'completeTask').and.returnValue(of({}));
|
||||||
spyOn(component.taskCompleted, 'emit').and.stub();
|
spyOn(component.taskCompleted, 'emit').and.stub();
|
||||||
|
|
||||||
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
|
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
const completeBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '[adf-cloud-complete-task]' }));
|
||||||
const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]'));
|
await completeBtn.click();
|
||||||
completeBtn.triggerEventHandler('click', {});
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
|
|
||||||
@ -344,8 +336,9 @@ describe('TaskFormCloudComponent', () => {
|
|||||||
|
|
||||||
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
|
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]'));
|
|
||||||
claimBtn.triggerEventHandler('click', {});
|
const claimBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '[adf-cloud-claim-task]' }));
|
||||||
|
await claimBtn.click();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
|
|
||||||
@ -354,7 +347,6 @@ describe('TaskFormCloudComponent', () => {
|
|||||||
|
|
||||||
it('should emit error when error occurs', async () => {
|
it('should emit error when error occurs', async () => {
|
||||||
spyOn(component.error, 'emit').and.stub();
|
spyOn(component.error, 'emit').and.stub();
|
||||||
|
|
||||||
component.onError({});
|
component.onError({});
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
@ -365,13 +357,16 @@ describe('TaskFormCloudComponent', () => {
|
|||||||
it('should reload when task is completed', async () => {
|
it('should reload when task is completed', async () => {
|
||||||
spyOn(taskCloudService, 'completeTask').and.returnValue(of({}));
|
spyOn(taskCloudService, 'completeTask').and.returnValue(of({}));
|
||||||
const reloadSpy = spyOn(component, 'ngOnChanges').and.callThrough();
|
const reloadSpy = spyOn(component, 'ngOnChanges').and.callThrough();
|
||||||
|
component.taskDetails.status = TASK_ASSIGNED_STATE;
|
||||||
|
|
||||||
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
|
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]'));
|
|
||||||
|
|
||||||
completeBtn.nativeElement.click();
|
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
|
|
||||||
|
const completeBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '[adf-cloud-complete-task]' }));
|
||||||
|
await completeBtn.click();
|
||||||
|
await fixture.whenStable();
|
||||||
|
|
||||||
expect(reloadSpy).toHaveBeenCalled();
|
expect(reloadSpy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -385,10 +380,11 @@ describe('TaskFormCloudComponent', () => {
|
|||||||
|
|
||||||
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
|
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]'));
|
|
||||||
|
|
||||||
claimBtn.nativeElement.click();
|
const claimBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '[adf-cloud-claim-task]' }));
|
||||||
|
await claimBtn.click();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
|
|
||||||
expect(reloadSpy).toHaveBeenCalled();
|
expect(reloadSpy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -403,10 +399,10 @@ describe('TaskFormCloudComponent', () => {
|
|||||||
|
|
||||||
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
|
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]'));
|
const unclaimBtn = await loader.getHarnessOrNull(MatButtonHarness.with({ selector: '[adf-cloud-unclaim-task]' }));
|
||||||
|
await unclaimBtn.click();
|
||||||
unclaimBtn.nativeElement.click();
|
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
|
|
||||||
expect(reloadSpy).toHaveBeenCalled();
|
expect(reloadSpy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -424,14 +420,6 @@ describe('TaskFormCloudComponent', () => {
|
|||||||
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
|
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit an executeOutcome event when form outcome executed', () => {
|
|
||||||
const executeOutcomeSpy: jasmine.Spy = spyOn(component.executeOutcome, 'emit');
|
|
||||||
|
|
||||||
component.onFormExecuteOutcome(new FormOutcomeEvent(new FormOutcomeModel(new FormModel())));
|
|
||||||
|
|
||||||
expect(executeOutcomeSpy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should emit onTaskLoaded on initial load of component', () => {
|
it('should emit onTaskLoaded on initial load of component', () => {
|
||||||
component.appName = '';
|
component.appName = '';
|
||||||
spyOn(component.onTaskLoaded, 'emit');
|
spyOn(component.onTaskLoaded, 'emit');
|
||||||
@ -440,69 +428,44 @@ describe('TaskFormCloudComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(component.onTaskLoaded.emit).toHaveBeenCalledWith(taskDetails);
|
expect(component.onTaskLoaded.emit).toHaveBeenCalledWith(taskDetails);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should emit displayModeOn when display mode is turned on', async () => {
|
it('should display task name as title on no form template if showTitle is true', async () => {
|
||||||
spyOn(component.displayModeOn, 'emit').and.stub();
|
fixture.componentRef.setInput('appName', 'app1');
|
||||||
|
fixture.componentRef.setInput('taskId', 'task1');
|
||||||
component.onDisplayModeOn(DisplayModeService.DEFAULT_DISPLAY_MODE_CONFIGURATIONS[0]);
|
component.taskDetails = { ...taskDetails };
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
|
||||||
|
|
||||||
expect(component.displayModeOn.emit).toHaveBeenCalledWith(DisplayModeService.DEFAULT_DISPLAY_MODE_CONFIGURATIONS[0]);
|
const noFormTemplateTitle = await loader.getHarnessOrNull(MatCardHarness);
|
||||||
|
const noFormTemplateTitleText = await noFormTemplateTitle.getTitleText();
|
||||||
|
|
||||||
|
expect(noFormTemplateTitleText).toEqual('Task1');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit displayModeOff when display mode is turned on', async () => {
|
it('should display default name as title on no form template if the task name empty/undefined', async () => {
|
||||||
spyOn(component.displayModeOff, 'emit').and.stub();
|
fixture.componentRef.setInput('appName', 'app1');
|
||||||
|
fixture.componentRef.setInput('taskId', 'mock-task-id');
|
||||||
component.onDisplayModeOff(DisplayModeService.DEFAULT_DISPLAY_MODE_CONFIGURATIONS[0]);
|
|
||||||
fixture.detectChanges();
|
|
||||||
await fixture.whenStable();
|
|
||||||
|
|
||||||
expect(component.displayModeOff.emit).toHaveBeenCalledWith(DisplayModeService.DEFAULT_DISPLAY_MODE_CONFIGURATIONS[0]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display task name as title on no form template if showTitle is true', () => {
|
|
||||||
component.taskId = taskDetails.id;
|
|
||||||
|
|
||||||
fixture.detectChanges();
|
|
||||||
const noFormTemplateTitle = debugElement.query(By.css('.adf-form-title'));
|
|
||||||
|
|
||||||
expect(noFormTemplateTitle.nativeElement.innerText).toEqual('Task1');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display default name as title on no form template if the task name empty/undefined', () => {
|
|
||||||
const mockTaskDetailsWithOutName = { id: 'mock-task-id', name: null, formKey: null };
|
const mockTaskDetailsWithOutName = { id: 'mock-task-id', name: null, formKey: null };
|
||||||
getTaskSpy.and.returnValue(of(mockTaskDetailsWithOutName));
|
getTaskSpy.and.returnValue(of(mockTaskDetailsWithOutName));
|
||||||
component.taskId = 'mock-task-id';
|
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const noFormTemplateTitle = debugElement.query(By.css('.adf-form-title'));
|
const matCard = await loader.getHarnessOrNull(MatCardHarness);
|
||||||
|
const noFormTemplateTitle = await matCard.getTitleText();
|
||||||
|
|
||||||
expect(noFormTemplateTitle.nativeElement.innerText).toEqual('FORM.FORM_RENDERER.NAMELESS_TASK');
|
expect(noFormTemplateTitle).toEqual('FORM.FORM_RENDERER.NAMELESS_TASK');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not display no form title if showTitle is set to false', () => {
|
it('should not display no form title if showTitle is set to false', async () => {
|
||||||
component.taskId = taskDetails.id;
|
fixture.componentRef.setInput('appName', 'app1');
|
||||||
|
fixture.componentRef.setInput('taskId', 'task1');
|
||||||
|
fixture.componentRef.setInput('showTitle', false);
|
||||||
component.showTitle = false;
|
component.showTitle = false;
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const noFormTemplateTitle = debugElement.query(By.css('.adf-form-title'));
|
const matCard = await loader.getHarnessOrNull(MatCardHarness);
|
||||||
|
expect(matCard).toBeDefined();
|
||||||
|
|
||||||
expect(noFormTemplateTitle).toBeNull();
|
const noFormTemplateTitleText = await matCard.getTitleText();
|
||||||
});
|
expect(noFormTemplateTitleText).toBe('');
|
||||||
|
|
||||||
it('should call children cloud task form change display mode when changing the display mode', () => {
|
|
||||||
const displayMode = 'displayMode';
|
|
||||||
component.taskDetails = { ...taskDetails, formKey: 'some-form' };
|
|
||||||
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(component.adfCloudForm).toBeDefined();
|
|
||||||
const switchToDisplayModeSpy = spyOn(component.adfCloudForm, 'switchToDisplayMode');
|
|
||||||
|
|
||||||
component.switchToDisplayMode(displayMode);
|
|
||||||
|
|
||||||
expect(switchToDisplayModeSpy).toHaveBeenCalledOnceWith(displayMode);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
@ -0,0 +1,253 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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 { ContentLinkModel, FormFieldValidator, FormModel, FormOutcomeEvent } from '@alfresco/adf-core';
|
||||||
|
import { Component, DestroyRef, EventEmitter, inject, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core';
|
||||||
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
|
import { FormCloudDisplayModeConfiguration } from '../../../../services/form-fields.interfaces';
|
||||||
|
import { TaskCloudService } from '../../../services/task-cloud.service';
|
||||||
|
import { TaskDetailsCloudModel } from '../../../start-task/models/task-details-cloud.model';
|
||||||
|
import { TaskFormCloudComponent } from '../task-form-cloud/task-form-cloud.component';
|
||||||
|
|
||||||
|
const TaskTypes = {
|
||||||
|
Form: 'form',
|
||||||
|
Screen: 'screen',
|
||||||
|
None: ''
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
type TaskTypesType = (typeof TaskTypes)[keyof typeof TaskTypes];
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-cloud-user-task',
|
||||||
|
templateUrl: './user-task-cloud.component.html',
|
||||||
|
styleUrls: ['./user-task-cloud.component.scss']
|
||||||
|
})
|
||||||
|
export class UserTaskCloudComponent implements OnInit, OnChanges {
|
||||||
|
@ViewChild('adfCloudTaskForm')
|
||||||
|
adfCloudTaskForm: TaskFormCloudComponent;
|
||||||
|
|
||||||
|
/** App id to fetch corresponding form and values. */
|
||||||
|
@Input()
|
||||||
|
appName: string = '';
|
||||||
|
|
||||||
|
/** The available display configurations for the form */
|
||||||
|
@Input()
|
||||||
|
displayModeConfigurations: FormCloudDisplayModeConfiguration[];
|
||||||
|
|
||||||
|
/** FormFieldValidator allow to provide additional validators to the form field. */
|
||||||
|
@Input()
|
||||||
|
fieldValidators: FormFieldValidator[];
|
||||||
|
|
||||||
|
/** Toggle readonly state of the task. */
|
||||||
|
@Input()
|
||||||
|
readOnly = false;
|
||||||
|
|
||||||
|
/** Toggle rendering of the `Cancel` button. */
|
||||||
|
@Input()
|
||||||
|
showCancelButton = true;
|
||||||
|
|
||||||
|
/** Toggle rendering of the `Complete` button. */
|
||||||
|
@Input()
|
||||||
|
showCompleteButton = true;
|
||||||
|
|
||||||
|
/** Toggle rendering of the form title. */
|
||||||
|
@Input()
|
||||||
|
showTitle: boolean = true;
|
||||||
|
|
||||||
|
/** Toggle rendering of the `Validation` icon. */
|
||||||
|
@Input()
|
||||||
|
showValidationIcon = true;
|
||||||
|
|
||||||
|
/** Task id to fetch corresponding form and values. */
|
||||||
|
@Input()
|
||||||
|
taskId: string;
|
||||||
|
|
||||||
|
/** Emitted when the cancel button is clicked. */
|
||||||
|
@Output()
|
||||||
|
cancelClick = new EventEmitter<string>();
|
||||||
|
|
||||||
|
/** Emitted when any error occurs. */
|
||||||
|
@Output()
|
||||||
|
error = new EventEmitter<any>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted when any outcome is executed. Default behaviour can be prevented
|
||||||
|
* via `event.preventDefault()`.
|
||||||
|
*/
|
||||||
|
@Output()
|
||||||
|
executeOutcome = new EventEmitter<FormOutcomeEvent>();
|
||||||
|
|
||||||
|
/** Emitted when form content is clicked. */
|
||||||
|
@Output()
|
||||||
|
formContentClicked: EventEmitter<ContentLinkModel> = new EventEmitter();
|
||||||
|
|
||||||
|
/** Emitted when the form is saved. */
|
||||||
|
@Output()
|
||||||
|
formSaved = new EventEmitter<FormModel>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted when a task is loaded`.
|
||||||
|
*/
|
||||||
|
@Output()
|
||||||
|
onTaskLoaded = new EventEmitter<TaskDetailsCloudModel>(); /* eslint-disable-line */
|
||||||
|
|
||||||
|
/** Emitted when the task is claimed. */
|
||||||
|
@Output()
|
||||||
|
taskClaimed = new EventEmitter<string>();
|
||||||
|
|
||||||
|
/** Emitted when the task is unclaimed. */
|
||||||
|
@Output()
|
||||||
|
taskUnclaimed = new EventEmitter<string>();
|
||||||
|
|
||||||
|
/** Emitted when the task is completed. */
|
||||||
|
@Output()
|
||||||
|
taskCompleted = new EventEmitter<string>();
|
||||||
|
|
||||||
|
candidateUsers: string[] = [];
|
||||||
|
candidateGroups: string[] = [];
|
||||||
|
loading: boolean = false;
|
||||||
|
screenId: string;
|
||||||
|
taskDetails: TaskDetailsCloudModel;
|
||||||
|
taskType: TaskTypesType;
|
||||||
|
taskTypeEnum = TaskTypes;
|
||||||
|
|
||||||
|
private taskCloudService: TaskCloudService = inject(TaskCloudService);
|
||||||
|
private readonly destroyRef = inject(DestroyRef);
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
|
const appName = changes['appName'];
|
||||||
|
if (appName && appName.currentValue !== appName.previousValue && this.taskId) {
|
||||||
|
this.loadTask();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const taskId = changes['taskId'];
|
||||||
|
if (taskId?.currentValue && this.appName) {
|
||||||
|
this.loadTask();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (this.appName === '' && this.taskId) {
|
||||||
|
this.loadTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
canClaimTask(): boolean {
|
||||||
|
return !this.readOnly && this.taskCloudService.canClaimTask(this.taskDetails) && this.hasCandidateUsersOrGroups();
|
||||||
|
}
|
||||||
|
|
||||||
|
canCompleteTask(): boolean {
|
||||||
|
return this.showCompleteButton && !this.readOnly && this.taskCloudService.canCompleteTask(this.taskDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
canUnclaimTask(): boolean {
|
||||||
|
return !this.readOnly && this.taskCloudService.canUnclaimTask(this.taskDetails) && this.hasCandidateUsersOrGroups();
|
||||||
|
}
|
||||||
|
|
||||||
|
getTaskType(): void {
|
||||||
|
if (this.taskDetails && !!this.taskDetails.formKey && this.taskDetails.formKey.includes(this.taskTypeEnum.Form)) {
|
||||||
|
this.taskType = this.taskTypeEnum.Form;
|
||||||
|
} else if (this.taskDetails && !!this.taskDetails.formKey && this.taskDetails.formKey.includes(this.taskTypeEnum.Screen)) {
|
||||||
|
this.taskType = this.taskTypeEnum.Screen;
|
||||||
|
const screenId = this.taskDetails.formKey.replace(this.taskTypeEnum.Screen + '-', '');
|
||||||
|
this.screenId = screenId;
|
||||||
|
} else {
|
||||||
|
this.taskType = this.taskTypeEnum.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hasCandidateUsers(): boolean {
|
||||||
|
return this.candidateUsers.length !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasCandidateGroups(): boolean {
|
||||||
|
return this.candidateGroups.length !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasCandidateUsersOrGroups(): boolean {
|
||||||
|
return this.hasCandidateUsers() || this.hasCandidateGroups();
|
||||||
|
}
|
||||||
|
|
||||||
|
onCancelForm(): void {
|
||||||
|
this.cancelClick.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
onCancelClick(): void {
|
||||||
|
this.cancelClick.emit(this.taskId);
|
||||||
|
}
|
||||||
|
|
||||||
|
onClaimTask(): void {
|
||||||
|
this.loadTask();
|
||||||
|
this.taskClaimed.emit(this.taskId);
|
||||||
|
}
|
||||||
|
|
||||||
|
onCompleteTask(): void {
|
||||||
|
this.loadTask();
|
||||||
|
this.taskCompleted.emit(this.taskId);
|
||||||
|
}
|
||||||
|
|
||||||
|
onCompleteTaskForm(): void {
|
||||||
|
this.taskCompleted.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
onError(data: any): void {
|
||||||
|
this.error.emit(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
onExecuteOutcome(outcome: FormOutcomeEvent): void {
|
||||||
|
this.executeOutcome.emit(outcome);
|
||||||
|
}
|
||||||
|
onFormContentClicked(content: ContentLinkModel): void {
|
||||||
|
this.formContentClicked.emit(content);
|
||||||
|
}
|
||||||
|
onFormSaved(): void {
|
||||||
|
this.formSaved.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
onTaskUnclaimed(): void {
|
||||||
|
this.taskUnclaimed.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
onUnclaimTask(): void {
|
||||||
|
this.loadTask();
|
||||||
|
this.taskUnclaimed.emit(this.taskId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private loadTask(): void {
|
||||||
|
this.loading = true;
|
||||||
|
this.taskCloudService
|
||||||
|
.getTaskById(this.appName, this.taskId)
|
||||||
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe((details) => {
|
||||||
|
this.taskDetails = details;
|
||||||
|
this.getTaskType();
|
||||||
|
this.loading = false;
|
||||||
|
this.onTaskLoaded.emit(this.taskDetails);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.taskCloudService.getCandidateUsers(this.appName, this.taskId).subscribe((users) => (this.candidateUsers = users || []));
|
||||||
|
this.taskCloudService.getCandidateGroups(this.appName, this.taskId).subscribe((groups) => (this.candidateGroups = groups || []));
|
||||||
|
}
|
||||||
|
|
||||||
|
public switchToDisplayMode(newDisplayMode?: string): void {
|
||||||
|
if (this.adfCloudTaskForm) {
|
||||||
|
this.adfCloudTaskForm.switchToDisplayMode(newDisplayMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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 { EventEmitter } from '@angular/core';
|
||||||
|
|
||||||
|
export interface UserTaskCustomUi {
|
||||||
|
appName: string;
|
||||||
|
taskId: string;
|
||||||
|
screenId: string;
|
||||||
|
error: EventEmitter<any>;
|
||||||
|
cancelClick: EventEmitter<string>;
|
||||||
|
taskClaimed: EventEmitter<string>;
|
||||||
|
taskUnclaimed: EventEmitter<string>;
|
||||||
|
taskCompleted: EventEmitter<string>;
|
||||||
|
}
|
@ -15,6 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export * from './components/task-form-cloud.component';
|
export * from './components/task-form-cloud/task-form-cloud.component';
|
||||||
|
export * from './components/user-task-cloud/user-task-cloud.component';
|
||||||
|
|
||||||
export * from './task-form.module';
|
export * from './task-form.module';
|
||||||
|
@ -20,23 +20,15 @@ import { CommonModule } from '@angular/common';
|
|||||||
import { MaterialModule } from '../../material.module';
|
import { MaterialModule } from '../../material.module';
|
||||||
import { FormCloudModule } from '../../form/form-cloud.module';
|
import { FormCloudModule } from '../../form/form-cloud.module';
|
||||||
import { TaskDirectiveModule } from '../directives/task-directive.module';
|
import { TaskDirectiveModule } from '../directives/task-directive.module';
|
||||||
|
import { TaskFormCloudComponent } from './components/task-form-cloud/task-form-cloud.component';
|
||||||
import { TaskFormCloudComponent } from './components/task-form-cloud.component';
|
|
||||||
import { CoreModule } from '@alfresco/adf-core';
|
import { CoreModule } from '@alfresco/adf-core';
|
||||||
|
import { TaskScreenCloudComponent } from '../../screen/components/screen-cloud/screen-cloud.component';
|
||||||
|
import { UserTaskCloudComponent } from './components/user-task-cloud/user-task-cloud.component';
|
||||||
|
import { UserTaskCloudButtonsComponent } from './components/user-task-cloud-buttons/user-task-cloud-buttons.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [CoreModule, CommonModule, MaterialModule, FormCloudModule, TaskDirectiveModule, TaskScreenCloudComponent],
|
||||||
CoreModule,
|
declarations: [TaskFormCloudComponent, UserTaskCloudComponent, UserTaskCloudButtonsComponent],
|
||||||
CommonModule,
|
exports: [TaskFormCloudComponent, UserTaskCloudComponent]
|
||||||
MaterialModule,
|
|
||||||
FormCloudModule,
|
|
||||||
TaskDirectiveModule
|
|
||||||
],
|
|
||||||
declarations: [
|
|
||||||
TaskFormCloudComponent
|
|
||||||
],
|
|
||||||
exports: [
|
|
||||||
TaskFormCloudComponent
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
export class TaskFormModule { }
|
export class TaskFormModule {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user