AAE-30336 Screens updates (#10619)

* [AAE-30336] updated interface and removed buttons

* [AAE-30336] added fullscreen support for dynamic component

* [AAE-30336] fullscreen feature and css fix

* [AAE-30336] fixed wrong subscription, removed obsolete code

* [AAE-30336] removed obsolete variable

* [AAE-30336] updated unit test and model

* [AAE-30336] updated documentation and comments
This commit is contained in:
tomasz hanaj
2025-02-05 15:18:11 +01:00
committed by GitHub
parent a1a3f97ec8
commit 8e3bd154ed
12 changed files with 397 additions and 32 deletions

View File

@@ -1,8 +1,5 @@
<mat-card>
<mat-card-content [ngStyle]="{'position':'relative'}">
<div #container></div>
<mat-card-content [ngStyle]="{'position':'relative'}" >
<ng-container #container />
</mat-card-content>
<mat-card-actions align="end">
<ng-content select="[buttons]"></ng-content>
</mat-card-actions>
</mat-card>

View File

@@ -17,7 +17,7 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CommonModule } from '@angular/common';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { By } from '@angular/platform-browser';
import { ScreenRenderingService } from '../../../services/public-api';
import { TaskScreenCloudComponent } from './screen-cloud.component';
@@ -36,37 +36,45 @@ import { TaskScreenCloudComponent } from './screen-cloud.component';
})
class TestComponent {
@Input() taskId = '';
@Input() screenId = '';
@Output() taskCompleted = new EventEmitter();
displayMode: string;
onComplete() {
this.taskCompleted.emit();
}
switchToDisplayMode(newDisplayMode?: string) {
this.displayMode = newDisplayMode;
}
}
@Component({
selector: 'adf-cloud-test-actions-component',
template: `
<adf-cloud-task-screen [taskId]="'1'" [appName]="'app-name-test'" [screenId]="'test'" (taskCompleted)="onTaskCompleted()">
<div buttons class="adf-cloud-test-buttons">
<button>Test</button>
</div>
</adf-cloud-task-screen>
`,
template: ` <adf-cloud-task-screen [taskId]="'1'" [appName]="'app-name-test'" [screenId]="'test'" (taskCompleted)="onTaskCompleted()" /> `,
imports: [CommonModule, TaskScreenCloudComponent],
standalone: true
})
class TestWrapperComponent {
@Input() screenId = '';
@ViewChild('adfCloudTaskScreen') adfCloudTaskScreen: TaskScreenCloudComponent;
onTaskCompleted() {}
switchToDisplayMode(newDisplayMode?: string): void {
if (this.adfCloudTaskScreen) {
this.adfCloudTaskScreen.switchToDisplayMode(newDisplayMode);
}
}
}
describe('TaskScreenCloudComponent', () => {
let fixture: ComponentFixture<TestWrapperComponent>;
let screenRenderingService: ScreenRenderingService;
let component: TestWrapperComponent;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TaskScreenCloudComponent, TestComponent, TestWrapperComponent]
});
fixture = TestBed.createComponent(TestWrapperComponent);
component = fixture.componentInstance;
screenRenderingService = TestBed.inject(ScreenRenderingService);
screenRenderingService.register({ ['test']: () => TestComponent });
fixture.componentRef.setInput('screenId', 'test');
@@ -78,11 +86,6 @@ describe('TaskScreenCloudComponent', () => {
expect(dynamicComponent).toBeTruthy();
});
it('should project content into component', async () => {
const projectedContent = fixture.debugElement.query(By.css('.adf-cloud-test-buttons'));
expect(projectedContent).toBeTruthy();
});
it('should set input property for dynamic component', () => {
const inputValueFromDynamicComponent = fixture.debugElement.query(By.css('.adf-cloud-test-container-taskId'));
expect((inputValueFromDynamicComponent.nativeElement as HTMLElement).textContent).toBe('1');
@@ -97,4 +100,13 @@ describe('TaskScreenCloudComponent', () => {
(btnComplete.nativeElement as HTMLButtonElement).click();
expect(onTaskCompletedSpy).toHaveBeenCalled();
});
it('should call switchToDisplayMode on dynamic component', () => {
const taskScreenCloudComponentSpy = jasmine.createSpyObj('TaskScreenCloudComponent', ['switchToDisplayMode']);
component.adfCloudTaskScreen = taskScreenCloudComponentSpy;
component.switchToDisplayMode();
fixture.detectChanges();
expect(component.adfCloudTaskScreen.switchToDisplayMode).toHaveBeenCalled();
});
});

View File

@@ -19,7 +19,7 @@ import { CommonModule } from '@angular/common';
import { Component, ComponentRef, DestroyRef, EventEmitter, inject, Input, OnInit, Output, ViewChild, ViewContainerRef } from '@angular/core';
import { ScreenRenderingService } from '../../../services/public-api';
import { MatCardModule } from '@angular/material/card';
import { UserTaskCustomUi } from './screen-cloud.interface';
import { UserTaskCustomUi } from '../../models/screen-cloud.model';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
@@ -30,17 +30,36 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
})
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()
taskId: string;
/** App name to fetch data for dynamic component. */
@Input()
appName: string = '';
/** Screen id to fetch corresponding screen widget. */
/** Boolean informing if a task can be claimed. */
@Input()
canClaimTask: boolean;
/** Boolean informing if a task can be unclaimed. */
@Input()
canUnclaimTask: boolean;
@Input()
showCancelButton: boolean;
/** Screen id to create dynamic component. */
@Input()
screenId: string = '';
/** Process Instance Id to fetch corresponding data. */
@Input()
processInstanceId: string = '';
/** Name of the task. */
@Input()
taskName: string = '';
/** Toggle readonly state of the task. */
@Input()
readOnly = false;
@@ -57,12 +76,23 @@ export class TaskScreenCloudComponent implements OnInit {
@Output()
error = new EventEmitter<any>();
/** Emitted when the task is cancelled. */
@Output()
cancelTask = 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>();
@ViewChild('container', { read: ViewContainerRef, static: true })
container: ViewContainerRef;
private destroyRef = inject(DestroyRef);
componentRef: ComponentRef<UserTaskCustomUi>;
private readonly screenRenderingService = inject(ScreenRenderingService);
ngOnInit() {
@@ -94,6 +124,15 @@ export class TaskScreenCloudComponent implements OnInit {
if (this.taskName && Object.prototype.hasOwnProperty.call(this.componentRef.instance, 'taskName')) {
this.componentRef.setInput('taskName', this.taskName);
}
if (this.canClaimTask && Object.prototype.hasOwnProperty.call(this.componentRef.instance, 'canClaimTask')) {
this.componentRef.setInput('canClaimTask', this.canClaimTask);
}
if (this.canUnclaimTask && Object.prototype.hasOwnProperty.call(this.componentRef.instance, 'canUnclaimTask')) {
this.componentRef.setInput('canUnclaimTask', this.canUnclaimTask);
}
if (this.showCancelButton && Object.prototype.hasOwnProperty.call(this.componentRef.instance, 'showCancelButton')) {
this.componentRef.setInput('showCancelButton', this.showCancelButton);
}
}
subscribeToOutputs() {
@@ -106,5 +145,21 @@ export class TaskScreenCloudComponent implements OnInit {
if (this.componentRef.instance?.error) {
this.componentRef.instance.error.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data) => this.error.emit(data));
}
if (this.componentRef.instance?.claimTask) {
this.componentRef.instance.claimTask.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data) => this.claimTask.emit(data));
}
if (this.componentRef.instance?.unclaimTask) {
this.componentRef.instance.unclaimTask.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data) => this.unclaimTask.emit(data));
}
if (this.componentRef.instance?.cancelTask) {
this.componentRef.instance.cancelTask.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data) => this.cancelTask.emit(data));
}
}
switchToDisplayMode(newDisplayMode?: string) {
if (this.componentRef?.instance?.switchToDisplayMode) {
this.componentRef.instance.switchToDisplayMode(newDisplayMode);
}
}
}

View File

@@ -18,12 +18,19 @@
import { EventEmitter } from '@angular/core';
export interface UserTaskCustomUi {
appName: string;
canClaimTask: boolean;
canUnclaimTask: boolean;
processInstanceId: string;
taskName: string;
appName: string;
taskId: string;
screenId: string;
showCancelButton: boolean;
cancelTask: EventEmitter<any>;
claimTask: EventEmitter<any>;
error: EventEmitter<any>;
switchToDisplayMode?: (newDisplayMode?: string) => void;
taskCompleted: EventEmitter<string>;
taskSaved: EventEmitter<string>;
error: EventEmitter<any>;
unclaimTask: EventEmitter<any>;
}

View File

@@ -0,0 +1,18 @@
/*!
* @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.
*/
export * from './models/screen-cloud.model';

View File

@@ -34,9 +34,11 @@ export class UserTaskCloudButtonsComponent {
@Input()
appName: string = '';
/** Boolean informing if a task can be claimed. */
@Input()
canClaimTask: boolean;
/** Boolean informing if a task can be unclaimed. */
@Input()
canUnclaimTask: boolean;

View File

@@ -26,18 +26,23 @@
<ng-container *ngSwitchCase="taskTypeEnum.Screen">
<adf-cloud-task-screen
#adfCloudTaskScreen
[appName]="appName"
[screenId]="screenId"
[taskId]="taskId"
[taskName]="taskDetails.name"
[canClaimTask]="canClaimTask()"
[canUnclaimTask]="canUnclaimTask()"
[processInstanceId]="taskDetails.processInstanceId"
[screenId]="screenId"
[showCancelButton]="showCancelButton"
[taskName]="taskDetails.name"
[taskId]="taskId"
(cancelTask)="onCancelClick()"
(claimTask)="onClaimTask()"
(error)="onError($event)"
(taskCompleted)="onCompleteTask()"
(taskSaved)="onFormSaved()"
>
<ng-template [ngTemplateOutlet]="taskFormCloudButtons" buttons>
</ng-template>
</adf-cloud-task-screen>
(unclaimTask)="onUnclaimTask()"
/>
</ng-container>
<ng-container *ngSwitchCase="taskTypeEnum.None">

View File

@@ -61,6 +61,9 @@ export class UserTaskCloudComponent implements OnInit, OnChanges {
@ViewChild('adfCloudTaskForm')
adfCloudTaskForm: TaskFormCloudComponent;
@ViewChild('adfCloudTaskScreen')
adfCloudTaskScreen: TaskScreenCloudComponent;
/** App id to fetch corresponding form and values. */
@Input()
appName: string = '';
@@ -270,5 +273,8 @@ export class UserTaskCloudComponent implements OnInit, OnChanges {
if (this.adfCloudTaskForm) {
this.adfCloudTaskForm.switchToDisplayMode(newDisplayMode);
}
if (this.adfCloudTaskScreen) {
this.adfCloudTaskScreen.switchToDisplayMode(newDisplayMode);
}
}
}

View File

@@ -24,6 +24,7 @@ export * from './lib/people/public-api';
export * from './lib/form/public-api';
export * from './lib/services/public-api';
export * from './lib/rich-text-editor/public-api';
export * from './lib/screen/public-api';
export * from './lib/types';
export * from './lib/common/index';