AAE-26142 Allow standalone form display configuration (#10244)

This commit is contained in:
Pablo Martinez 2024-10-01 10:55:59 +02:00 committed by GitHub
parent 86765b90e3
commit 1b5eaa0fa1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 160 additions and 116 deletions

View File

@ -3,89 +3,94 @@
</ng-content>
</div>
<div *ngIf="hasForm()" class="adf-cloud-form-container adf-cloud-form-{{displayMode?.toLowerCase() || 'inline'}}-container" [style]="form.theme | adfFormStyle">
<div class="adf-cloud-form-content"
[cdkTrapFocus]="displayMode === 'fullScreen'"
cdkTrapFocusAutoCapture>
<div
*ngIf="hasForm()"
class="adf-cloud-form-container adf-cloud-form-{{displayConfiguration?.options?.fullscreen ? 'fullscreen' : 'inline'}}-container"
[style]="form.theme | adfFormStyle">
<div class="adf-cloud-form-content"
[cdkTrapFocus]="displayConfiguration?.options?.trapFocus"
cdkTrapFocusAutoCapture>
<adf-toolbar class="adf-cloud-form-toolbar" *ngIf="displayMode === 'fullScreen' && findDisplayConfiguration('fullScreen')?.options?.displayToolbar">
<div class="adf-cloud-form__form-title">
<span class="adf-cloud-form__display-name" [title]="form.taskName">
{{form.taskName}}
<ng-container *ngIf="!form.taskName">
{{'FORM.FORM_RENDERER.NAMELESS_TASK' | translate}}
</ng-container>
</span>
</div>
<adf-toolbar class="adf-cloud-form-toolbar" *ngIf="displayConfiguration?.options?.displayToolbar">
<div class="adf-cloud-form__form-title">
<span class="adf-cloud-form__display-name" [title]="form.taskName">
{{form.taskName}}
<ng-container *ngIf="!form.taskName">
{{'FORM.FORM_RENDERER.NAMELESS_TASK' | translate}}
</ng-container>
</span>
</div>
<adf-toolbar-divider></adf-toolbar-divider>
<button class="adf-cloud-form-close-button"
data-automation-id="adf-toolbar-right-back"
[attr.aria-label]="'ADF_VIEWER.ACTIONS.CLOSE' | translate"
[attr.data-automation-id]="'adf-cloud-form-close-button'"
[title]="'ADF_VIEWER.ACTIONS.CLOSE' | translate"
mat-icon-button
title="{{ 'ADF_VIEWER.ACTIONS.CLOSE' | translate }}"
(click)="switchToDisplayMode()">
<mat-icon>close</mat-icon>
</button>
</adf-toolbar>
<mat-card appearance="outlined" [class.adf-cloud-form-content-card]="displayMode === 'fullScreen'">
<div class="adf-cloud-form-content-card-container">
<mat-card-header *ngIf="showTitle || showRefreshButton || showValidationIcon">
<mat-card-title>
<h4>
<div *ngIf="showValidationIcon" class="adf-form-validation-button">
<i id="adf-valid-form-icon" class="material-icons"
*ngIf="form.isValid; else no_valid_form">check_circle</i>
<ng-template #no_valid_form>
<i id="adf-invalid-form-icon" class="material-icons adf-invalid-color">error</i>
</ng-template>
</div>
<div *ngIf="displayMode !== 'fullScreen' && findDisplayConfiguration('fullScreen')" class="adf-cloud-form-fullscreen-button">
<button mat-icon-button (click)="switchToDisplayMode('fullScreen')" [attr.data-automation-id]="'adf-cloud-form-fullscreen-button'">
<mat-icon>fullscreen</mat-icon>
</button>
</div>
<div *ngIf="showRefreshButton" class="adf-cloud-form-reload-button" [title]="'ADF_VIEWER.ACTIONS.FULLSCREEN' | translate">
<button mat-icon-button (click)="onRefreshClicked()" [attr.aria-label]="'ADF_VIEWER.ACTIONS.FULLSCREEN' | translate">
<mat-icon>refresh</mat-icon>
</button>
</div>
<span *ngIf="isTitleEnabled()" class="adf-cloud-form-title" [title]="form.taskName"
>{{form.taskName}}
<ng-container *ngIf="!form.taskName">
{{'FORM.FORM_RENDERER.NAMELESS_TASK' | translate}}
</ng-container>
</span>
</h4>
</mat-card-title>
</mat-card-header>
<mat-card-content class="adf-form-container-card-content">
<adf-form-renderer
[formDefinition]="form"
[readOnly]="readOnly"
>
</adf-form-renderer>
</mat-card-content>
<mat-card-actions *ngIf="form.hasOutcomes()" class="adf-form-mat-card-actions" align="end">
<ng-content select="adf-cloud-form-custom-outcomes"></ng-content>
<ng-container *ngFor="let outcome of form.outcomes">
<adf-toolbar-divider *ngIf="displayConfiguration?.options?.displayCloseButton"></adf-toolbar-divider>
<button
*ngIf="outcome.isVisible"
[id]="'adf-form-'+ outcome.name | formatSpace"
[color]="getColorForOutcome(outcome.name)"
mat-button
[disabled]="!isOutcomeButtonEnabled(outcome)"
[class.adf-form-hide-button]="!isOutcomeButtonVisible(outcome, form.readOnly)"
(click)="onOutcomeClicked(outcome)"
>
{{outcome.name | translate | uppercase }}
*ngIf="displayConfiguration?.options?.displayCloseButton"
class="adf-cloud-form-close-button"
data-automation-id="adf-toolbar-right-back"
[attr.aria-label]="'ADF_VIEWER.ACTIONS.CLOSE' | translate"
[attr.data-automation-id]="'adf-cloud-form-close-button'"
[title]="'ADF_VIEWER.ACTIONS.CLOSE' | translate"
mat-icon-button
title="{{ 'ADF_VIEWER.ACTIONS.CLOSE' | translate }}"
(click)="switchToDisplayMode()">
<mat-icon>close</mat-icon>
</button>
</ng-container>
</mat-card-actions>
</div>
</mat-card>
</div>
</adf-toolbar>
<mat-card appearance="outlined" [class.adf-cloud-form-content-card]="displayConfiguration?.options?.fullscreen">
<div class="adf-cloud-form-content-card-container">
<mat-card-header *ngIf="showTitle || showRefreshButton || showValidationIcon">
<mat-card-title>
<h4>
<div *ngIf="showValidationIcon" class="adf-form-validation-button">
<i id="adf-valid-form-icon" class="material-icons"
*ngIf="form.isValid; else no_valid_form">check_circle</i>
<ng-template #no_valid_form>
<i id="adf-invalid-form-icon" class="material-icons adf-invalid-color">error</i>
</ng-template>
</div>
<div *ngIf="!displayConfiguration?.options?.fullscreen && findDisplayConfiguration('fullScreen')" class="adf-cloud-form-fullscreen-button">
<button mat-icon-button (click)="switchToDisplayMode('fullScreen')" [attr.data-automation-id]="'adf-cloud-form-fullscreen-button'">
<mat-icon>fullscreen</mat-icon>
</button>
</div>
<div *ngIf="showRefreshButton" class="adf-cloud-form-reload-button" [title]="'ADF_VIEWER.ACTIONS.FULLSCREEN' | translate">
<button mat-icon-button (click)="onRefreshClicked()" [attr.aria-label]="'ADF_VIEWER.ACTIONS.FULLSCREEN' | translate">
<mat-icon>refresh</mat-icon>
</button>
</div>
<span *ngIf="isTitleEnabled()" class="adf-cloud-form-title" [title]="form.taskName"
>{{form.taskName}}
<ng-container *ngIf="!form.taskName">
{{'FORM.FORM_RENDERER.NAMELESS_TASK' | translate}}
</ng-container>
</span>
</h4>
</mat-card-title>
</mat-card-header>
<mat-card-content class="adf-form-container-card-content">
<adf-form-renderer
[formDefinition]="form"
[readOnly]="readOnly"
>
</adf-form-renderer>
</mat-card-content>
<mat-card-actions *ngIf="form.hasOutcomes()" class="adf-form-mat-card-actions" align="end">
<ng-content select="adf-cloud-form-custom-outcomes"></ng-content>
<ng-container *ngFor="let outcome of form.outcomes">
<button
*ngIf="outcome.isVisible"
[id]="'adf-form-'+ outcome.name | formatSpace"
[color]="getColorForOutcome(outcome.name)"
mat-button
[disabled]="!isOutcomeButtonEnabled(outcome)"
[class.adf-form-hide-button]="!isOutcomeButtonVisible(outcome, form.readOnly)"
(click)="onOutcomeClicked(outcome)"
>
{{outcome.name | translate | uppercase }}
</button>
</ng-container>
</mat-card-actions>
</div>
</mat-card>
</div>
</div>

View File

@ -1362,7 +1362,7 @@ describe('FormCloudComponent', () => {
await loadForm({ displayMode: FormCloudDisplayMode.fullScreen });
});
it('should emit display mode turned on wit the fullScreen configuration', () => {
it('should emit display mode turned on with the fullScreen configuration', () => {
expect(displayModeOnSpy).toHaveBeenCalledWith(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[1]);
});

View File

@ -134,7 +134,8 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
protected onDestroy$ = new Subject<boolean>();
readonly id: string;
displayMode: FormCloudDisplayMode;
displayMode: string;
displayConfiguration: FormCloudDisplayModeConfiguration = DisplayModeService.DEFAULT_DISPLAY_MODE_CONFIGURATIONS[0];
style: string = '';
protected formCloudService = inject(FormCloudService);
@ -241,6 +242,8 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
this.displayModeOn.emit(newDisplayModeConfiguration);
}
}
this.displayConfiguration = newDisplayModeConfiguration;
});
}
@ -433,7 +436,9 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
this.displayModeConfigurations
);
this.displayModeOn.emit(this.displayModeService.findConfiguration(this.displayMode, this.displayModeConfigurations));
this.displayConfiguration = this.displayModeService.findConfiguration(this.displayMode, this.displayModeConfigurations);
this.displayModeOn.emit(this.displayConfiguration);
}
this.changeDetector.detectChanges();

View File

@ -19,7 +19,6 @@ import { FormCloudDisplayMode, FormCloudDisplayModeConfiguration } from '../../s
import { DisplayModeService } from './display-mode.service';
describe('DisplayModeService', () => {
let service: DisplayModeService;
let displayModeOnSpy: jasmine.Spy;
let displayModeOffSpy: jasmine.Spy;
@ -61,11 +60,18 @@ describe('DisplayModeService', () => {
});
it('should return the default display mode when no display mode does not exist in the configuration', () => {
expect(service.getDisplayMode('notExisting' as any)).toBe(DisplayModeService.DEFAULT_DISPLAY_MODE);
expect(service.getDisplayMode('notExisting' as any, [])).toBe(DisplayModeService.DEFAULT_DISPLAY_MODE);
expect(service.getDisplayMode('notExisting' as any, [{ displayMode: FormCloudDisplayMode.fullScreen }])).toBe(FormCloudDisplayMode.fullScreen);
expect(service.getDisplayMode('notExisting' as any, [{ displayMode: FormCloudDisplayMode.fullScreen }, { displayMode: FormCloudDisplayMode.inline }])).toBe(FormCloudDisplayMode.fullScreen);
expect(service.getDisplayMode('notExisting' as any, [{ displayMode: FormCloudDisplayMode.fullScreen, default: true }, { displayMode: FormCloudDisplayMode.inline }])).toBe(FormCloudDisplayMode.fullScreen);
expect(service.getDisplayMode('notExisting')).toBe(DisplayModeService.DEFAULT_DISPLAY_MODE);
expect(service.getDisplayMode('notExisting', [])).toBe(DisplayModeService.DEFAULT_DISPLAY_MODE);
expect(service.getDisplayMode('notExisting', [{ displayMode: FormCloudDisplayMode.fullScreen }])).toBe(FormCloudDisplayMode.fullScreen);
expect(
service.getDisplayMode('notExisting', [{ displayMode: FormCloudDisplayMode.fullScreen }, { displayMode: FormCloudDisplayMode.inline }])
).toBe(FormCloudDisplayMode.fullScreen);
expect(
service.getDisplayMode('notExisting', [
{ displayMode: FormCloudDisplayMode.fullScreen, default: true },
{ displayMode: FormCloudDisplayMode.inline }
])
).toBe(FormCloudDisplayMode.fullScreen);
});
it('should return the provided display mode when display mode is provided', () => {
@ -75,8 +81,10 @@ describe('DisplayModeService', () => {
it('should find the display configuration', () => {
expect(service.findConfiguration()).toBeUndefined();
expect(service.findConfiguration(FormCloudDisplayMode.fullScreen)).toBe(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[1]);
expect(service.findConfiguration('notExisting' as any)).toBeUndefined();
expect(service.findConfiguration(FormCloudDisplayMode.fullScreen, [{ displayMode: FormCloudDisplayMode.fullScreen }])).toEqual({ displayMode: FormCloudDisplayMode.fullScreen });
expect(service.findConfiguration('notExisting')).toBeUndefined();
expect(service.findConfiguration(FormCloudDisplayMode.fullScreen, [{ displayMode: FormCloudDisplayMode.fullScreen }])).toEqual({
displayMode: FormCloudDisplayMode.fullScreen
});
expect(service.findConfiguration(FormCloudDisplayMode.fullScreen, [{ displayMode: FormCloudDisplayMode.inline }])).toBeUndefined();
});
@ -134,21 +142,27 @@ describe('DisplayModeService', () => {
});
it('should return the default display mode when calling the switchToDisplayMode and display does not exist in configuration', () => {
expect(service.switchToDisplayMode(formId, 'notExisting' as any)).toBe(DisplayModeService.DEFAULT_DISPLAY_MODE);
expect(service.switchToDisplayMode(formId, 'notExisting')).toBe(DisplayModeService.DEFAULT_DISPLAY_MODE);
});
it('should not call the change display mode method when switchToDisplayMode and the mode to switch is the same as the old one', () => {
expect(service.switchToDisplayMode(formId, FormCloudDisplayMode.fullScreen, FormCloudDisplayMode.fullScreen)).toBe(FormCloudDisplayMode.fullScreen);
expect(service.switchToDisplayMode(formId, FormCloudDisplayMode.fullScreen, FormCloudDisplayMode.fullScreen)).toBe(
FormCloudDisplayMode.fullScreen
);
expect(changeDisplayModeSpy).not.toHaveBeenCalledWith();
});
it('should not call the change display mode method when switchToDisplayMode and the mode to switch does not exist and the previous mode was the default one', () => {
expect(service.switchToDisplayMode(formId, 'notExisting' as any, DisplayModeService.DEFAULT_DISPLAY_MODE)).toBe(DisplayModeService.DEFAULT_DISPLAY_MODE);
expect(service.switchToDisplayMode(formId, 'notExisting', DisplayModeService.DEFAULT_DISPLAY_MODE)).toBe(
DisplayModeService.DEFAULT_DISPLAY_MODE
);
expect(changeDisplayModeSpy).not.toHaveBeenCalledWith();
});
it('should not call the change display mode method when switchToDisplayMode and the mode to switch does not exist and the previous mode was not provided', () => {
expect(service.switchToDisplayMode(formId, 'notExisting' as any, DisplayModeService.DEFAULT_DISPLAY_MODE)).toBe(DisplayModeService.DEFAULT_DISPLAY_MODE);
expect(service.switchToDisplayMode(formId, 'notExisting', DisplayModeService.DEFAULT_DISPLAY_MODE)).toBe(
DisplayModeService.DEFAULT_DISPLAY_MODE
);
expect(changeDisplayModeSpy).not.toHaveBeenCalledWith();
});

View File

@ -35,11 +35,26 @@ export class DisplayModeService {
{
displayMode: FormCloudDisplayMode.fullScreen,
options: {
onDisplayModeOn: () => { },
onDisplayModeOn: () => {},
onDisplayModeOff: (id: string) => DisplayModeService.changeDisplayMode({ displayMode: FormCloudDisplayMode.inline, id }),
onCompleteTask: (id: string) => DisplayModeService.changeDisplayMode({ displayMode: FormCloudDisplayMode.inline, id }),
onSaveTask: () => { },
displayToolbar: true
onSaveTask: () => {},
fullscreen: true,
displayToolbar: true,
displayCloseButton: true,
trapFocus: true
}
},
{
displayMode: FormCloudDisplayMode.standalone,
options: {
onDisplayModeOn: () => {},
onDisplayModeOff: () => {},
onCompleteTask: () => {},
onSaveTask: () => {},
fullscreen: true,
displayToolbar: false,
trapFocus: true
}
}
];
@ -66,25 +81,25 @@ export class DisplayModeService {
}
}
getDisplayMode(displayMode?: FormCloudDisplayMode, availableConfigurations?: FormCloudDisplayModeConfiguration[]): FormCloudDisplayMode {
getDisplayMode(displayMode?: string, availableConfigurations?: FormCloudDisplayModeConfiguration[]): string {
const configuration = this.findConfiguration(displayMode, availableConfigurations);
if (configuration) {
return configuration.displayMode;
} else if (availableConfigurations && availableConfigurations.length > 0) {
return availableConfigurations.length === 1 ?
availableConfigurations[0].displayMode :
(availableConfigurations.find(config => config.default)?.displayMode || availableConfigurations[0].displayMode);
return availableConfigurations.length === 1
? availableConfigurations[0].displayMode
: availableConfigurations.find((config) => config.default)?.displayMode || availableConfigurations[0].displayMode;
} else {
return DisplayModeService.DEFAULT_DISPLAY_MODE;
}
}
findConfiguration(displayMode?: FormCloudDisplayMode, availableConfigurations?: FormCloudDisplayModeConfiguration[]): FormCloudDisplayModeConfiguration {
return this.getDisplayModeConfigurations(availableConfigurations).find(config => config.displayMode === displayMode);
findConfiguration(displayMode?: string, availableConfigurations?: FormCloudDisplayModeConfiguration[]): FormCloudDisplayModeConfiguration {
return this.getDisplayModeConfigurations(availableConfigurations).find((config) => config.displayMode === displayMode);
}
onCompleteTask(id?: string, displayMode?: FormCloudDisplayMode, availableConfigurations?: FormCloudDisplayModeConfiguration[]) {
onCompleteTask(id?: string, displayMode?: string, availableConfigurations?: FormCloudDisplayModeConfiguration[]) {
const configuration = this.findConfiguration(displayMode, availableConfigurations);
if (configuration?.options?.onCompleteTask) {
@ -92,7 +107,7 @@ export class DisplayModeService {
}
}
onSaveTask(id?: string, displayMode?: FormCloudDisplayMode, availableConfigurations?: FormCloudDisplayModeConfiguration[]) {
onSaveTask(id?: string, displayMode?: string, availableConfigurations?: FormCloudDisplayModeConfiguration[]) {
const configuration = this.findConfiguration(displayMode, availableConfigurations);
if (configuration?.options?.onSaveTask) {
@ -100,7 +115,7 @@ export class DisplayModeService {
}
}
onDisplayModeOff(id?: string, displayMode?: FormCloudDisplayMode, availableConfigurations?: FormCloudDisplayModeConfiguration[]) {
onDisplayModeOff(id?: string, displayMode?: string, availableConfigurations?: FormCloudDisplayModeConfiguration[]) {
const configuration = this.findConfiguration(displayMode, availableConfigurations);
if (configuration?.options?.onDisplayModeOff) {
@ -108,7 +123,7 @@ export class DisplayModeService {
}
}
onDisplayModeOn(id?: string, displayMode?: FormCloudDisplayMode, availableConfigurations?: FormCloudDisplayModeConfiguration[]) {
onDisplayModeOn(id?: string, displayMode?: string, availableConfigurations?: FormCloudDisplayModeConfiguration[]) {
const configuration = this.findConfiguration(displayMode, availableConfigurations);
if (configuration?.options?.onDisplayModeOn) {
@ -118,10 +133,10 @@ export class DisplayModeService {
switchToDisplayMode(
id?: string,
newDisplayMode?: FormCloudDisplayMode,
oldDisplayMode?: FormCloudDisplayMode,
newDisplayMode?: string,
oldDisplayMode?: string,
availableConfigurations?: FormCloudDisplayModeConfiguration[]
): FormCloudDisplayMode {
): string {
const oldConfiguration = this.findConfiguration(oldDisplayMode, availableConfigurations);
const newConfiguration = this.findConfiguration(newDisplayMode, availableConfigurations);

View File

@ -26,7 +26,7 @@ export interface FormRepresentation {
version?: number;
formDefinition?: FormDefinition;
standAlone?: boolean;
displayMode?: FormCloudDisplayMode;
displayMode?: string;
}
export interface FormTab {
@ -266,11 +266,15 @@ export interface FormCloudDisplayModeConfigurationOptions {
onSaveTask(id?: string): void;
onDisplayModeOn(id?: string): void;
onDisplayModeOff(id?: string): void;
fullscreen?: boolean;
displayToolbar?: boolean;
displayCloseButton?: boolean;
trapFocus?: boolean;
[key: string]: any;
}
export interface FormCloudDisplayModeConfiguration {
displayMode: FormCloudDisplayMode;
displayMode: string;
options?: FormCloudDisplayModeConfigurationOptions;
default?: boolean;
}
@ -278,10 +282,11 @@ export interface FormCloudDisplayModeConfiguration {
// eslint-disable-next-line no-shadow
export enum FormCloudDisplayMode {
inline = 'inline',
fullScreen = 'fullScreen'
fullScreen = 'fullScreen',
standalone = 'standalone'
}
export interface FormCloudDisplayModeChange {
displayMode: FormCloudDisplayMode;
displayMode: string;
id?: string;
}