mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
AAE-20480 Full Screen User Task Forms (#9341)
* AAE-20480 Full Screen User Task Forms * AAE-20480 Attend review comments * AAE-20480 Remove leftovers * AAE-20480 Enable changing the display mode from task-form-cloud * AAE-20480 Fix fullscreen mode header * AAE-20480 Fix review comments * AAE-20480 Allow hiding the full screen toolbar by configuration * AAE-20480 Add review comments * AAE-20480 Create display mode service
This commit is contained in:
@@ -95,6 +95,7 @@ The template defined inside `empty-form` will be shown when no form definition i
|
|||||||
| showTitle | `boolean` | true | Toggle rendering of the form title. |
|
| showTitle | `boolean` | true | Toggle rendering of the form title. |
|
||||||
| showValidationIcon | `boolean` | true | Toggle rendering of the validation icon next to the form title. |
|
| showValidationIcon | `boolean` | true | Toggle rendering of the validation icon next to the form title. |
|
||||||
| taskId | `string` | | Task id to fetch corresponding form and values. |
|
| taskId | `string` | | Task id to fetch corresponding form and values. |
|
||||||
|
| displayModeConfigurations | [`FormCloudDisplayModeConfiguration`](../../../lib/process-services-cloud/src/lib/services/form-fields.interfaces.ts)`[]` | | The available display configurations for the form |
|
||||||
|
|
||||||
### Events
|
### Events
|
||||||
|
|
||||||
@@ -108,6 +109,8 @@ The template defined inside `empty-form` will be shown when no form definition i
|
|||||||
| formError | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormFieldModel`](../../core/models/form-field.model.md)`[]>` | Emitted when the supplied form values have a validation error. |
|
| formError | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormFieldModel`](../../core/models/form-field.model.md)`[]>` | Emitted when the supplied form values have a validation error. |
|
||||||
| formLoaded | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormModel`](../../../lib/core/src/lib/form/components/widgets/core/form.model.ts)`>` | Emitted when the form is loaded or reloaded. |
|
| formLoaded | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormModel`](../../../lib/core/src/lib/form/components/widgets/core/form.model.ts)`>` | Emitted when the form is loaded or reloaded. |
|
||||||
| formSaved | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormModel`](../../../lib/core/src/lib/form/components/widgets/core/form.model.ts)`>` | Emitted when the form is submitted with the `Save` or custom outcomes. |
|
| formSaved | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormModel`](../../../lib/core/src/lib/form/components/widgets/core/form.model.ts)`>` | Emitted when the form is submitted with the `Save` or custom outcomes. |
|
||||||
|
| displayModeOn | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloudDisplayModeConfiguration`](../../../lib/process-services-cloud/src/lib/services/form-fields.interfaces.ts)`>` | Emitted when a display mode configuration is turned on. |
|
||||||
|
| displayModeOff | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloudDisplayModeConfiguration`](../../../lib/process-services-cloud/src/lib/services/form-fields.interfaces.ts)`>` | Emitted when a display mode configuration is turned off. |
|
||||||
|
|
||||||
## Details
|
## Details
|
||||||
|
|
||||||
@@ -160,6 +163,41 @@ For an existing Task both the form and its values will be fetched and displayed.
|
|||||||
|
|
||||||
In this case, only the form definition will be fetched.
|
In this case, only the form definition will be fetched.
|
||||||
|
|
||||||
|
#### Enabling fullscreen display for the form
|
||||||
|
|
||||||
|
Provide a `displayModeConfiguration` array object containing the fullscreen configuration. You can use the configuration provided in the [`DisplayModeService`](../../../lib/process-services-cloud/src/lib/form/services/display-mode.service.ts) as a static member `DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS`, or configure your own if you want to customise the options for the fullscreen display mode.
|
||||||
|
|
||||||
|
**MyView.component.html**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<button (click)="adfCloudForm.switchToDisplayMode('fullScreen')">Full screen</button>
|
||||||
|
|
||||||
|
<adf-cloud-form #adfCloudForm
|
||||||
|
[appName]="appName"
|
||||||
|
[taskId]="selectedTask?.id"
|
||||||
|
[showTitle]="false"
|
||||||
|
[showRefreshButton]="false"
|
||||||
|
[showValidationIcon]="false"
|
||||||
|
[displayModeConfigurations]="displayConfigurations">
|
||||||
|
</adf-cloud-form>
|
||||||
|
```
|
||||||
|
|
||||||
|
**MyView.component.ts**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { DisplayModeService } from '@alfresco/adf-process-services-cloud';
|
||||||
|
|
||||||
|
export class MyView {
|
||||||
|
|
||||||
|
get displayConfigurations() {
|
||||||
|
return DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
When the `displayModeConfigurations` contains the configuration for the fullscreen display, in the header of the form, a button to switch to fullscreen is displayed. Keep in mind that the header of the form is visible only if any of the parameters `showTitle`, `showRefreshButton`or `showValidationIcon` is `true`, but it is also possible to switch to the fullscreen display using a button that you can place wherever you want as shown in the previous example.
|
||||||
|
|
||||||
### Controlling outcome execution behaviour
|
### Controlling outcome execution behaviour
|
||||||
|
|
||||||
In unusual circumstances, you may need to take complete control of form outcome execution.
|
In unusual circumstances, you may need to take complete control of form outcome execution.
|
||||||
|
@@ -43,6 +43,7 @@ Save and Complete buttons get disabled when at least one of the form's inputs ar
|
|||||||
| showTitle | `boolean` | true | Toggle rendering of the form title. |
|
| showTitle | `boolean` | true | Toggle rendering of the form title. |
|
||||||
| showValidationIcon | `boolean` | true | Toggle rendering of the `Validation` icon. |
|
| showValidationIcon | `boolean` | true | Toggle rendering of the `Validation` icon. |
|
||||||
| taskId | `string` | | Task id to fetch corresponding form and values. |
|
| taskId | `string` | | Task id to fetch corresponding form and values. |
|
||||||
|
| displayModeConfigurations | [`FormCloudDisplayModeConfiguration`](../../../lib/process-services-cloud/src/lib/services/form-fields.interfaces.ts)`[]` | | The available display configurations for the form |
|
||||||
|
|
||||||
### Events
|
### Events
|
||||||
|
|
||||||
@@ -58,6 +59,43 @@ Save and Complete buttons get disabled when at least one of the form's inputs ar
|
|||||||
| taskClaimed | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<string>` | Emitted when the task is claimed. |
|
| taskClaimed | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<string>` | Emitted when the task is claimed. |
|
||||||
| taskCompleted | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<string>` | Emitted when the task is completed. |
|
| taskCompleted | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<string>` | Emitted when the task is completed. |
|
||||||
| taskUnclaimed | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<string>` | Emitted when the task is unclaimed. |
|
| taskUnclaimed | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<string>` | Emitted when the task is unclaimed. |
|
||||||
|
| displayModeOn | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloudDisplayModeConfiguration`](../../../lib/process-services-cloud/src/lib/services/form-fields.interfaces.ts)`>` | Emitted when a display mode configuration is turned on. |
|
||||||
|
| displayModeOff | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloudDisplayModeConfiguration`](../../../lib/process-services-cloud/src/lib/services/form-fields.interfaces.ts)`>` | Emitted when a display mode configuration is turned off. |
|
||||||
|
|
||||||
|
#### Enabling fullscreen display for the form of the task
|
||||||
|
|
||||||
|
Provide a `displayModeConfiguration` array object containing the fullscreen configuration. You can use the configuration provided in the [`DisplayModeService`](../../../lib/process-services-cloud/src/lib/form/services/display-mode.service.ts) as a static member `DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS`, or configure your own if you want to customise the options for the fullscreen display mode.
|
||||||
|
|
||||||
|
**MyView.component.html**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<button (click)="adfCloudTaskForm.switchToDisplayMode('fullScreen')">Full screen</button>
|
||||||
|
|
||||||
|
<adf-cloud-task-form #adfCloudTaskForm
|
||||||
|
[appName]="appName"
|
||||||
|
[taskId]="selectedTask?.id"
|
||||||
|
[showTitle]="false"
|
||||||
|
[showRefreshButton]="false"
|
||||||
|
[showValidationIcon]="false"
|
||||||
|
[displayModeConfigurations]="displayConfigurations">
|
||||||
|
</adf-cloud-task-form>
|
||||||
|
```
|
||||||
|
|
||||||
|
**MyView.component.ts**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { DisplayModeService } from '@alfresco/adf-process-services-cloud';
|
||||||
|
|
||||||
|
export class MyView {
|
||||||
|
|
||||||
|
get displayConfigurations() {
|
||||||
|
return DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
When the `displayModeConfigurations` contains the configuration for the fullscreen display, in the header of the form, a button to switch to fullscreen is displayed. Keep in mind that the header of the form is visible only if any of the parameters `showTitle`, `showRefreshButton`or `showValidationIcon` is `true`, but it is also possible to switch to the fullscreen display using a button that you can place wherever you want as shown in the previous example.
|
||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
|
@@ -57,6 +57,7 @@ export interface FormRepresentationModel {
|
|||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
fields?: any[];
|
fields?: any[];
|
||||||
};
|
};
|
||||||
|
displayMode: string;
|
||||||
}
|
}
|
||||||
export class FormModel implements ProcessFormModel {
|
export class FormModel implements ProcessFormModel {
|
||||||
static UNSET_TASK_NAME: string = 'Nameless task';
|
static UNSET_TASK_NAME: string = 'Nameless task';
|
||||||
@@ -72,6 +73,7 @@ export class FormModel implements ProcessFormModel {
|
|||||||
readonly processDefinitionId: string;
|
readonly processDefinitionId: string;
|
||||||
readonly selectedOutcome: string;
|
readonly selectedOutcome: string;
|
||||||
readonly enableFixedSpace: boolean;
|
readonly enableFixedSpace: boolean;
|
||||||
|
readonly displayMode: any;
|
||||||
|
|
||||||
fieldsCache: FormFieldModel[] = [];
|
fieldsCache: FormFieldModel[] = [];
|
||||||
|
|
||||||
@@ -113,6 +115,7 @@ export class FormModel implements ProcessFormModel {
|
|||||||
this.processVariables = json.processVariables || [];
|
this.processVariables = json.processVariables || [];
|
||||||
this.enableFixedSpace = enableFixedSpace;
|
this.enableFixedSpace = enableFixedSpace;
|
||||||
this.confirmMessage = json.confirmMessage || {};
|
this.confirmMessage = json.confirmMessage || {};
|
||||||
|
this.displayMode = json.displayMode;
|
||||||
|
|
||||||
this.tabs = (json.tabs || []).map((tabJson) => new TabModel(this, tabJson));
|
this.tabs = (json.tabs || []).map((tabJson) => new TabModel(this, tabJson));
|
||||||
|
|
||||||
|
@@ -3,8 +3,36 @@
|
|||||||
</ng-content>
|
</ng-content>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="hasForm()" class="adf-form-container">
|
<div *ngIf="hasForm()" class="adf-cloud-form-container adf-cloud-form-{{displayMode?.toLowerCase() || 'inline'}}-container">
|
||||||
<mat-card class="adf-form-container-card">
|
<div class="adf-cloud-form-content"
|
||||||
|
[cdkTrapFocus]="displayMode === 'fullScreen'"
|
||||||
|
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" [matTooltip]="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'"
|
||||||
|
[matTooltip]="'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 [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-header *ngIf="showTitle || showRefreshButton || showValidationIcon">
|
||||||
<mat-card-title>
|
<mat-card-title>
|
||||||
<h4>
|
<h4>
|
||||||
@@ -15,18 +43,22 @@
|
|||||||
<i id="adf-invalid-form-icon" class="material-icons adf-invalid-color">error</i>
|
<i id="adf-invalid-form-icon" class="material-icons adf-invalid-color">error</i>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="showRefreshButton" class="adf-form-reload-button">
|
<div *ngIf="displayMode !== 'fullScreen' && findDisplayConfiguration('fullScreen')" class="adf-cloud-form-fullscreen-button">
|
||||||
<button mat-icon-button (click)="onRefreshClicked()">
|
<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" [matTooltip]="'ADF_VIEWER.ACTIONS.FULLSCREEN' | translate">
|
||||||
|
<button mat-icon-button (click)="onRefreshClicked()" [attr.aria-label]="'ADF_VIEWER.ACTIONS.FULLSCREEN' | translate">
|
||||||
<mat-icon>refresh</mat-icon>
|
<mat-icon>refresh</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<span *ngIf="isTitleEnabled()" class="adf-form-title" [matTooltip]="form.taskName">
|
<span *ngIf="isTitleEnabled()" class="adf-cloud-form-title" [matTooltip]="form.taskName">
|
||||||
{{form.taskName}}
|
{{form.taskName}}
|
||||||
<ng-container *ngIf="!form.taskName">
|
<ng-container *ngIf="!form.taskName">
|
||||||
{{'FORM.FORM_RENDERER.NAMELESS_TASK' | translate}}
|
{{'FORM.FORM_RENDERER.NAMELESS_TASK' | translate}}
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
</h4>
|
</h4>
|
||||||
</mat-card-title>
|
</mat-card-title>
|
||||||
</mat-card-header>
|
</mat-card-header>
|
||||||
@@ -45,5 +77,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
|
</div>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
@@ -0,0 +1,100 @@
|
|||||||
|
/* cspell: disable-next-line */
|
||||||
|
/* stylelint-disable scss/at-extend-no-missing-placeholder */
|
||||||
|
.adf-full-screen {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: var(--adf-theme-background-card-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-cloud-form {
|
||||||
|
&-container {
|
||||||
|
.adf-cloud-form-content {
|
||||||
|
@extend .adf-full-screen;
|
||||||
|
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: column;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fullscreen-container {
|
||||||
|
.adf-cloud-form-content {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 100000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-inline-container {
|
||||||
|
@extend .adf-full-screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-toolbar {
|
||||||
|
/* stylelint-disable-next-line selector-class-pattern */
|
||||||
|
.mat-toolbar {
|
||||||
|
background-color: var(--adf-theme-background-card-color-087);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fullscreen-button {
|
||||||
|
position: absolute;
|
||||||
|
right: 70px;
|
||||||
|
top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__display-name {
|
||||||
|
font-size: var(--theme-subheading-2-font-size);
|
||||||
|
opacity: 0.87;
|
||||||
|
line-height: 1.5;
|
||||||
|
letter-spacing: -0.4px;
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
font-stretch: normal;
|
||||||
|
max-width: 400px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
color: var(--adf-theme-foreground-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__form-title {
|
||||||
|
text-align: center;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-content-card {
|
||||||
|
padding: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.adf-cloud-form-content-card-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
mat-card-content {
|
||||||
|
height: 100%;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-card-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-sidebars {
|
||||||
|
display: flex;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
|
||||||
|
adf-viewer-render {
|
||||||
|
order: 1;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -52,9 +52,12 @@ import {
|
|||||||
} from '../mocks/cloud-form.mock';
|
} from '../mocks/cloud-form.mock';
|
||||||
import { FormCloudRepresentation } from '../models/form-cloud-representation.model';
|
import { FormCloudRepresentation } from '../models/form-cloud-representation.model';
|
||||||
import { FormCloudService } from '../services/form-cloud.service';
|
import { FormCloudService } from '../services/form-cloud.service';
|
||||||
import { CloudFormRenderingService } from './cloud-form-rendering.service';
|
import { DisplayModeService } from '../services/display-mode.service';
|
||||||
import { FormCloudComponent } from './form-cloud.component';
|
import { FormCloudComponent } from './form-cloud.component';
|
||||||
import { ProcessServicesCloudModule } from '../../process-services-cloud.module';
|
import { ProcessServicesCloudModule } from '../../process-services-cloud.module';
|
||||||
|
import { MatButtonHarness } from '@angular/material/button/testing';
|
||||||
|
import { FormCloudDisplayMode } from '../../services/form-fields.interfaces';
|
||||||
|
import { CloudFormRenderingService } from './cloud-form-rendering.service';
|
||||||
|
|
||||||
const mockOauth2Auth: any = {
|
const mockOauth2Auth: any = {
|
||||||
oauth2Auth: {
|
oauth2Auth: {
|
||||||
@@ -71,6 +74,7 @@ describe('FormCloudComponent', () => {
|
|||||||
let matDialog: MatDialog;
|
let matDialog: MatDialog;
|
||||||
let visibilityService: WidgetVisibilityService;
|
let visibilityService: WidgetVisibilityService;
|
||||||
let formRenderingService: CloudFormRenderingService;
|
let formRenderingService: CloudFormRenderingService;
|
||||||
|
let displayModeService: DisplayModeService;
|
||||||
let documentRootLoader: HarnessLoader;
|
let documentRootLoader: HarnessLoader;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -111,6 +115,7 @@ describe('FormCloudComponent', () => {
|
|||||||
|
|
||||||
formRenderingService = TestBed.inject(CloudFormRenderingService);
|
formRenderingService = TestBed.inject(CloudFormRenderingService);
|
||||||
formCloudService = TestBed.inject(FormCloudService);
|
formCloudService = TestBed.inject(FormCloudService);
|
||||||
|
displayModeService = TestBed.inject(DisplayModeService);
|
||||||
|
|
||||||
matDialog = TestBed.inject(MatDialog);
|
matDialog = TestBed.inject(MatDialog);
|
||||||
|
|
||||||
@@ -1140,6 +1145,224 @@ describe('FormCloudComponent', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Full screen', async () => {
|
||||||
|
|
||||||
|
let displayModeOnSpy: jasmine.Spy;
|
||||||
|
let displayModeOffSpy: jasmine.Spy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for loading the form in the tests
|
||||||
|
*
|
||||||
|
* @param form The form model to be loaded
|
||||||
|
*/
|
||||||
|
async function loadForm(form?: any): Promise<void> {
|
||||||
|
formComponent.ngOnChanges({ form: { currentValue: formComponent.parseForm(form || {}), firstChange: true, isFirstChange: () => true, previousValue: undefined } });
|
||||||
|
await fixture.whenStable();
|
||||||
|
fixture.detectChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
displayModeOnSpy = spyOn(formComponent.displayModeOn, 'emit').and.stub();
|
||||||
|
displayModeOffSpy = spyOn(formComponent.displayModeOff, 'emit').and.stub();
|
||||||
|
spyOn(displayModeService, 'getDefaultDisplayModeConfigurations').and.callFake(() => DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS);
|
||||||
|
|
||||||
|
formComponent.taskId = 'any';
|
||||||
|
formComponent.appName = 'any';
|
||||||
|
formComponent.showRefreshButton = false;
|
||||||
|
formComponent.showTitle = false;
|
||||||
|
formComponent.showValidationIcon = false;
|
||||||
|
|
||||||
|
await loadForm();
|
||||||
|
|
||||||
|
displayModeOnSpy.calls.reset();
|
||||||
|
displayModeOffSpy.calls.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit display mode turned on wit the inline configuration', async () => {
|
||||||
|
await loadForm();
|
||||||
|
|
||||||
|
expect(displayModeOnSpy).toHaveBeenCalledWith(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not be in fullScreen mode by default', () => {
|
||||||
|
const fullScreenModeContainer = fixture.debugElement.query(By.css('.adf-cloud-form-container.adf-cloud-form-fullscreen-container'));
|
||||||
|
const inlineModeContainer = fixture.debugElement.query(By.css('.adf-cloud-form-container.adf-cloud-form-inline-container'));
|
||||||
|
expect(fullScreenModeContainer).toBeNull();
|
||||||
|
expect(inlineModeContainer).not.toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be in fullScreen mode if it is forced', async () => {
|
||||||
|
await loadForm({ displayMode: FormCloudDisplayMode.fullScreen });
|
||||||
|
|
||||||
|
const fullScreenModeContainer = fixture.debugElement.query(By.css('.adf-cloud-form-container.adf-cloud-form-fullscreen-container'));
|
||||||
|
const inlineModeContainer = fixture.debugElement.query(By.css('.adf-cloud-form-container.adf-cloud-form-inline-container'));
|
||||||
|
expect(fullScreenModeContainer).not.toBeNull();
|
||||||
|
expect(inlineModeContainer).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display full screen button on header when header is displayed an not in fullScreen mode', () => {
|
||||||
|
formComponent.showTitle = true;
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const fullScreenButton = fixture.debugElement.query(By.css('.adf-cloud-form-fullscreen-button'));
|
||||||
|
expect(fullScreenButton).not.toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set fullScreen mode on clicking on the full screen button', async () => {
|
||||||
|
formComponent.showTitle = true;
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const fullScreenButton = await documentRootLoader.getHarness(
|
||||||
|
MatButtonHarness.with({ selector: `[data-automation-id="adf-cloud-form-fullscreen-button"]` })
|
||||||
|
);
|
||||||
|
await fullScreenButton.click();
|
||||||
|
|
||||||
|
await fixture.whenStable();
|
||||||
|
|
||||||
|
expect(formComponent.displayMode).toBe(FormCloudDisplayMode.fullScreen);
|
||||||
|
expect(displayModeOffSpy).toHaveBeenCalledWith(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[0]);
|
||||||
|
expect(displayModeOnSpy).toHaveBeenCalledWith(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not display full screen button on header when header is displayed but in fullScreen mode', async () => {
|
||||||
|
formComponent.showTitle = true;
|
||||||
|
await loadForm({ displayMode: FormCloudDisplayMode.fullScreen });
|
||||||
|
|
||||||
|
const fullScreenButton = fixture.debugElement.query(By.css('.adf-cloud-form-fullscreen-button'));
|
||||||
|
expect(fullScreenButton).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not display full screen button when header is not displayed', () => {
|
||||||
|
const fullScreenButton = fixture.debugElement.query(By.css('.adf-cloud-form-fullscreen-button'));
|
||||||
|
expect(fullScreenButton).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set the styles for the card', () => {
|
||||||
|
const fullScreenCard = fixture.debugElement.query(By.css('.adf-cloud-form-content-card'));
|
||||||
|
expect(fullScreenCard).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set fullScreen mode from the form service notification', () => {
|
||||||
|
DisplayModeService.changeDisplayMode({ displayMode: FormCloudDisplayMode.fullScreen, id: formComponent.id });
|
||||||
|
|
||||||
|
expect(displayModeOffSpy).toHaveBeenCalledWith(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[0]);
|
||||||
|
expect(displayModeOnSpy).toHaveBeenCalledWith(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[1]);
|
||||||
|
expect(formComponent.displayMode).toBe(FormCloudDisplayMode.fullScreen);
|
||||||
|
|
||||||
|
displayModeOnSpy.calls.reset();
|
||||||
|
displayModeOffSpy.calls.reset();
|
||||||
|
|
||||||
|
DisplayModeService.changeDisplayMode({ displayMode: FormCloudDisplayMode.inline, id: formComponent.id });
|
||||||
|
|
||||||
|
expect(displayModeOffSpy).toHaveBeenCalledWith(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[1]);
|
||||||
|
expect(displayModeOnSpy).toHaveBeenCalledWith(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[0]);
|
||||||
|
expect(formComponent.displayMode).toBe(FormCloudDisplayMode.inline);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not change the display mode when the notification change is from a different id', () => {
|
||||||
|
DisplayModeService.changeDisplayMode({ displayMode: FormCloudDisplayMode.fullScreen, id: formComponent.id });
|
||||||
|
|
||||||
|
expect(formComponent.displayMode).toBe(FormCloudDisplayMode.fullScreen);
|
||||||
|
expect(displayModeOffSpy).toHaveBeenCalledWith(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[0]);
|
||||||
|
expect(displayModeOnSpy).toHaveBeenCalledWith(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[1]);
|
||||||
|
|
||||||
|
displayModeOnSpy.calls.reset();
|
||||||
|
displayModeOffSpy.calls.reset();
|
||||||
|
|
||||||
|
DisplayModeService.changeDisplayMode({ displayMode: FormCloudDisplayMode.inline, id: 'otherId' });
|
||||||
|
expect(displayModeOffSpy).not.toHaveBeenCalled();
|
||||||
|
expect(displayModeOnSpy).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
expect(formComponent.displayMode).toBe(FormCloudDisplayMode.fullScreen);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('fullScreen Mode', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await loadForm({ displayMode: FormCloudDisplayMode.fullScreen });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit display mode turned on wit the fullScreen configuration', () => {
|
||||||
|
expect(displayModeOnSpy).toHaveBeenCalledWith(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display the toolbar with the nameless task title when the task name is not provided and toolbar is enabled', () => {
|
||||||
|
const cloudFormToolbarDisplayName: HTMLSpanElement = fixture.debugElement.nativeElement.querySelector('.adf-cloud-form__display-name');
|
||||||
|
expect(cloudFormToolbarDisplayName).not.toBeNull();
|
||||||
|
expect(cloudFormToolbarDisplayName.textContent.trim()).toEqual('Nameless task');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display the toolbar with the task title when the task name is provided and toolbar is enabled', async () => {
|
||||||
|
const taskName = 'task-name';
|
||||||
|
|
||||||
|
await loadForm({ displayMode: FormCloudDisplayMode.fullScreen, taskName });
|
||||||
|
|
||||||
|
const cloudFormToolbarDisplayName: HTMLSpanElement = fixture.debugElement.nativeElement.querySelector('.adf-cloud-form__display-name');
|
||||||
|
expect(cloudFormToolbarDisplayName).not.toBeNull();
|
||||||
|
expect(cloudFormToolbarDisplayName.textContent.trim()).toEqual(taskName);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not display the toolbar with the task title when the toolbar option is disabled', async () => {
|
||||||
|
formComponent.displayModeConfigurations = [
|
||||||
|
{
|
||||||
|
displayMode: FormCloudDisplayMode.fullScreen,
|
||||||
|
options: {
|
||||||
|
onCompleteTask: () => { },
|
||||||
|
onDisplayModeOff: () => { },
|
||||||
|
onDisplayModeOn: () => { },
|
||||||
|
onSaveTask: () => { },
|
||||||
|
displayToolbar: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
await loadForm({ displayMode: FormCloudDisplayMode.fullScreen });
|
||||||
|
|
||||||
|
const cloudFormToolbar: HTMLSpanElement = fixture.debugElement.nativeElement.querySelector('.adf-cloud-form-toolbar');
|
||||||
|
expect(cloudFormToolbar).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set the styles for the card', () => {
|
||||||
|
const fullScreenCard = fixture.debugElement.query(By.css('.adf-cloud-form-content-card'));
|
||||||
|
expect(fullScreenCard).not.toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should close fullScreen when close button is clicked', async () => {
|
||||||
|
displayModeOnSpy.calls.reset();
|
||||||
|
displayModeOffSpy.calls.reset();
|
||||||
|
|
||||||
|
const closeButton = await documentRootLoader.getHarness(
|
||||||
|
MatButtonHarness.with({ selector: `[data-automation-id="adf-cloud-form-close-button"]` })
|
||||||
|
);
|
||||||
|
await closeButton.click();
|
||||||
|
|
||||||
|
await fixture.whenStable();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(formComponent.displayMode).toEqual(FormCloudDisplayMode.inline);
|
||||||
|
expect(displayModeOffSpy).toHaveBeenCalledWith(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[1]);
|
||||||
|
expect(displayModeOnSpy).toHaveBeenCalledWith(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should close fullScreen when completing the task', () => {
|
||||||
|
const formRenderingServiceOnCompleteTaskSpy = spyOn(displayModeService, 'onCompleteTask').and.callThrough();
|
||||||
|
const onCompleteTaskSpy = spyOn(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[1].options, 'onCompleteTask').and.callThrough();
|
||||||
|
const formRenderingServiceChangeDisplayModeSpy = spyOn(DisplayModeService, 'changeDisplayMode').and.callThrough();
|
||||||
|
|
||||||
|
displayModeOnSpy.calls.reset();
|
||||||
|
displayModeOffSpy.calls.reset();
|
||||||
|
|
||||||
|
formComponent.completeTaskForm();
|
||||||
|
|
||||||
|
expect(formRenderingServiceOnCompleteTaskSpy).toHaveBeenCalledOnceWith(formComponent.id, FormCloudDisplayMode.fullScreen, DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS);
|
||||||
|
expect(onCompleteTaskSpy).toHaveBeenCalledOnceWith(formComponent.id);
|
||||||
|
expect(formRenderingServiceChangeDisplayModeSpy).toHaveBeenCalledOnceWith({ id: formComponent.id, displayMode: FormCloudDisplayMode.inline });
|
||||||
|
expect(displayModeOffSpy).toHaveBeenCalledOnceWith(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[1]);
|
||||||
|
expect(displayModeOnSpy).toHaveBeenCalledOnceWith(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[0]);
|
||||||
|
expect(formComponent.displayMode).toBe(FormCloudDisplayMode.inline);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Multilingual Form', () => {
|
describe('Multilingual Form', () => {
|
||||||
|
@@ -15,9 +15,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, OnDestroy, HostListener } from '@angular/core';
|
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, OnDestroy, HostListener, OnInit } from '@angular/core';
|
||||||
import { Observable, of, forkJoin, Subject, Subscription } from 'rxjs';
|
import { Observable, of, forkJoin, Subject, Subscription } from 'rxjs';
|
||||||
import { switchMap, takeUntil, map } from 'rxjs/operators';
|
import { switchMap, takeUntil, map, filter } from 'rxjs/operators';
|
||||||
import {
|
import {
|
||||||
FormBaseComponent,
|
FormBaseComponent,
|
||||||
FormFieldModel,
|
FormFieldModel,
|
||||||
@@ -38,12 +38,16 @@ import { TaskVariableCloud } from '../models/task-variable-cloud.model';
|
|||||||
import { TaskDetailsCloudModel } from '../../task/start-task/models/task-details-cloud.model';
|
import { TaskDetailsCloudModel } from '../../task/start-task/models/task-details-cloud.model';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { ConfirmDialogComponent } from '@alfresco/adf-content-services';
|
import { ConfirmDialogComponent } from '@alfresco/adf-content-services';
|
||||||
|
import { v4 as uuidGeneration } from 'uuid';
|
||||||
|
import { FormCloudDisplayMode, FormCloudDisplayModeConfiguration } from '../../services/form-fields.interfaces';
|
||||||
|
import { DisplayModeService } from '../public-api';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-cloud-form',
|
selector: 'adf-cloud-form',
|
||||||
templateUrl: './form-cloud.component.html'
|
templateUrl: './form-cloud.component.html',
|
||||||
|
styleUrls: ['./form-cloud.component.scss']
|
||||||
})
|
})
|
||||||
export class FormCloudComponent extends FormBaseComponent implements OnChanges, OnDestroy {
|
export class FormCloudComponent extends FormBaseComponent implements OnChanges, OnInit, OnDestroy {
|
||||||
/** App name to fetch corresponding form and values. */
|
/** App name to fetch corresponding form and values. */
|
||||||
@Input()
|
@Input()
|
||||||
appName: string = '';
|
appName: string = '';
|
||||||
@@ -76,6 +80,12 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
|
|||||||
@Input()
|
@Input()
|
||||||
fieldValidators: FormFieldValidator[] = [...FORM_FIELD_VALIDATORS];
|
fieldValidators: FormFieldValidator[] = [...FORM_FIELD_VALIDATORS];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The available display configurations for the form
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
displayModeConfigurations: FormCloudDisplayModeConfiguration[];
|
||||||
|
|
||||||
/** Emitted when the form is submitted with the `Save` or custom outcomes. */
|
/** Emitted when the form is submitted with the `Save` or custom outcomes. */
|
||||||
@Output()
|
@Output()
|
||||||
formSaved = new EventEmitter<FormModel>();
|
formSaved = new EventEmitter<FormModel>();
|
||||||
@@ -96,19 +106,32 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
|
|||||||
@Output()
|
@Output()
|
||||||
formContentClicked = new EventEmitter<ContentLinkModel>();
|
formContentClicked = new EventEmitter<ContentLinkModel>();
|
||||||
|
|
||||||
|
/** Emitted when a display mode configuration is turned on. */
|
||||||
|
@Output()
|
||||||
|
displayModeOn = new EventEmitter<FormCloudDisplayModeConfiguration>();
|
||||||
|
|
||||||
|
/** Emitted when a display mode configuration is turned off. */
|
||||||
|
@Output()
|
||||||
|
displayModeOff = new EventEmitter<FormCloudDisplayModeConfiguration>();
|
||||||
|
|
||||||
protected subscriptions: Subscription[] = [];
|
protected subscriptions: Subscription[] = [];
|
||||||
nodeId: string;
|
nodeId: string;
|
||||||
formCloudRepresentationJSON: any;
|
formCloudRepresentationJSON: any;
|
||||||
|
|
||||||
protected onDestroy$ = new Subject<boolean>();
|
protected onDestroy$ = new Subject<boolean>();
|
||||||
|
|
||||||
|
readonly id: string;
|
||||||
|
displayMode: FormCloudDisplayMode;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected formCloudService: FormCloudService,
|
protected formCloudService: FormCloudService,
|
||||||
protected formService: FormService,
|
protected formService: FormService,
|
||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
protected visibilityService: WidgetVisibilityService
|
protected visibilityService: WidgetVisibilityService,
|
||||||
|
private readonly displayModeService: DisplayModeService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
this.id = uuidGeneration();
|
||||||
|
|
||||||
this.formService.formContentClicked.pipe(takeUntil(this.onDestroy$)).subscribe((content) => {
|
this.formService.formContentClicked.pipe(takeUntil(this.onDestroy$)).subscribe((content) => {
|
||||||
if (content instanceof UploadWidgetContentLinkModel) {
|
if (content instanceof UploadWidgetContentLinkModel) {
|
||||||
@@ -166,6 +189,36 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
|
|||||||
this.refreshFormData();
|
this.refreshFormData();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const formRepresentation = changes['form'];
|
||||||
|
if (formRepresentation?.currentValue) {
|
||||||
|
this.form = formRepresentation.currentValue;
|
||||||
|
this.onFormLoaded(this.form);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
DisplayModeService.displayMode$
|
||||||
|
.pipe(
|
||||||
|
filter(change => change.id === this.id),
|
||||||
|
takeUntil(this.onDestroy$)
|
||||||
|
).subscribe((displayModeChange) => {
|
||||||
|
const oldDisplayMode = this.displayMode;
|
||||||
|
this.displayMode = displayModeChange.displayMode;
|
||||||
|
|
||||||
|
const oldDisplayModeConfiguration = this.displayModeService.findConfiguration(oldDisplayMode, this.displayModeConfigurations);
|
||||||
|
const newDisplayModeConfiguration = this.displayModeService.findConfiguration(displayModeChange.displayMode, this.displayModeConfigurations);
|
||||||
|
|
||||||
|
if (oldDisplayModeConfiguration?.displayMode !== newDisplayModeConfiguration?.displayMode) {
|
||||||
|
if (oldDisplayModeConfiguration) {
|
||||||
|
this.displayModeOff.emit(oldDisplayModeConfiguration);
|
||||||
|
}
|
||||||
|
if (newDisplayModeConfiguration) {
|
||||||
|
this.displayModeOn.emit(newDisplayModeConfiguration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -264,6 +317,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
|
|||||||
},
|
},
|
||||||
(error) => this.onTaskSavedError(error)
|
(error) => this.onTaskSavedError(error)
|
||||||
);
|
);
|
||||||
|
this.displayModeService.onSaveTask(this.id, this.displayMode, this.displayModeConfigurations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,6 +338,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
|
|||||||
} else {
|
} else {
|
||||||
this.completeForm(outcome);
|
this.completeForm(outcome);
|
||||||
}
|
}
|
||||||
|
this.displayModeService.onCompleteTask(this.id, this.displayMode, this.displayModeConfigurations);
|
||||||
}
|
}
|
||||||
|
|
||||||
private completeForm(outcome?: string) {
|
private completeForm(outcome?: string) {
|
||||||
@@ -342,6 +397,9 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected onFormLoaded(form: FormModel) {
|
protected onFormLoaded(form: FormModel) {
|
||||||
|
this.displayModeConfigurations = this.displayModeService.getDisplayModeConfigurations(this.displayModeConfigurations);
|
||||||
|
this.displayMode = this.displayModeService.switchToDisplayMode(this.id, this.form.json.displayMode, this.displayMode, this.displayModeConfigurations);
|
||||||
|
this.displayModeOn.emit(this.displayModeService.findConfiguration(this.displayMode, this.displayModeConfigurations));
|
||||||
this.formLoaded.emit(form);
|
this.formLoaded.emit(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,4 +440,12 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
|
|||||||
this.onDestroy$.next(true);
|
this.onDestroy$.next(true);
|
||||||
this.onDestroy$.complete();
|
this.onDestroy$.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switchToDisplayMode(newDisplayMode?: string) {
|
||||||
|
this.displayModeService.switchToDisplayMode(this.id, FormCloudDisplayMode[newDisplayMode], this.displayMode, this.displayModeConfigurations);
|
||||||
|
}
|
||||||
|
|
||||||
|
findDisplayConfiguration(displayMode?: string): FormCloudDisplayModeConfiguration {
|
||||||
|
return this.displayModeService.findConfiguration(FormCloudDisplayMode[displayMode], this.displayModeConfigurations);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { CoreModule } from '@alfresco/adf-core';
|
import { CoreModule, ToolbarModule } from '@alfresco/adf-core';
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { MaterialModule } from '../material.module';
|
import { MaterialModule } from '../material.module';
|
||||||
import { FormCloudComponent } from './components/form-cloud.component';
|
import { FormCloudComponent } from './components/form-cloud.component';
|
||||||
@@ -41,6 +41,7 @@ import { FilePropertiesTableCloudComponent } from './components/widgets/attach-f
|
|||||||
import { FileViewerWidgetComponent } from './components/widgets/file-viewer/file-viewer.widget';
|
import { FileViewerWidgetComponent } from './components/widgets/file-viewer/file-viewer.widget';
|
||||||
import { DisplayRichTextWidgetComponent } from './components/widgets/display-rich-text/display-rich-text.widget';
|
import { DisplayRichTextWidgetComponent } from './components/widgets/display-rich-text/display-rich-text.widget';
|
||||||
import { RichTextEditorModule } from '../rich-text-editor';
|
import { RichTextEditorModule } from '../rich-text-editor';
|
||||||
|
import { A11yModule } from '@angular/cdk/a11y';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -55,7 +56,9 @@ import { RichTextEditorModule } from '../rich-text-editor';
|
|||||||
ContentMetadataModule,
|
ContentMetadataModule,
|
||||||
UploadModule,
|
UploadModule,
|
||||||
AlfrescoViewerModule,
|
AlfrescoViewerModule,
|
||||||
RichTextEditorModule
|
RichTextEditorModule,
|
||||||
|
ToolbarModule,
|
||||||
|
A11yModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
FormCloudComponent,
|
FormCloudComponent,
|
||||||
|
@@ -38,5 +38,6 @@ export * from './services/form-cloud.service';
|
|||||||
export * from './services/form-definition-selector-cloud.service';
|
export * from './services/form-definition-selector-cloud.service';
|
||||||
export * from './services/content-cloud-node-selector.service';
|
export * from './services/content-cloud-node-selector.service';
|
||||||
export * from './services/process-cloud-content.service';
|
export * from './services/process-cloud-content.service';
|
||||||
|
export * from './services/display-mode.service';
|
||||||
|
|
||||||
export * from './form-cloud.module';
|
export * from './form-cloud.module';
|
||||||
|
@@ -0,0 +1,164 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2023 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 { FormCloudDisplayMode, FormCloudDisplayModeConfiguration } from '../../services/form-fields.interfaces';
|
||||||
|
import { DisplayModeService } from './display-mode.service';
|
||||||
|
|
||||||
|
describe('DisplayModeService', () => {
|
||||||
|
|
||||||
|
let service: DisplayModeService;
|
||||||
|
let displayModeOnSpy: jasmine.Spy;
|
||||||
|
let displayModeOffSpy: jasmine.Spy;
|
||||||
|
let completeTaskSpy: jasmine.Spy;
|
||||||
|
let saveTaskSpy: jasmine.Spy;
|
||||||
|
let changeDisplayModeSpy: jasmine.Spy;
|
||||||
|
const formId = 'id';
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
service = new DisplayModeService();
|
||||||
|
|
||||||
|
spyOn(service, 'getDefaultDisplayModeConfigurations').and.callFake(() => DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS);
|
||||||
|
displayModeOnSpy = spyOn(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[1].options, 'onDisplayModeOn');
|
||||||
|
displayModeOffSpy = spyOn(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[1].options, 'onDisplayModeOff');
|
||||||
|
completeTaskSpy = spyOn(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[1].options, 'onCompleteTask');
|
||||||
|
saveTaskSpy = spyOn(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS[1].options, 'onSaveTask');
|
||||||
|
changeDisplayModeSpy = spyOn(DisplayModeService, 'changeDisplayMode');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the default display mode configurations when no available configurations are provided', () => {
|
||||||
|
expect(service.getDisplayModeConfigurations()).toBe(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS);
|
||||||
|
expect(service.getDisplayModeConfigurations(null)).toBe(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS);
|
||||||
|
expect(service.getDisplayModeConfigurations([])).toBe(DisplayModeService.IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the provided display mode configurations when available configurations are provided', () => {
|
||||||
|
const availableConfigurations: FormCloudDisplayModeConfiguration[] = [
|
||||||
|
{
|
||||||
|
displayMode: FormCloudDisplayMode.fullScreen
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(service.getDisplayModeConfigurations(availableConfigurations)).toBe(availableConfigurations);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the default display mode when no display mode is provided', () => {
|
||||||
|
expect(service.getDisplayMode()).toBe(DisplayModeService.DEFAULT_DISPLAY_MODE);
|
||||||
|
expect(service.getDisplayMode(null)).toBe(DisplayModeService.DEFAULT_DISPLAY_MODE);
|
||||||
|
});
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the provided display mode when display mode is provided', () => {
|
||||||
|
expect(service.getDisplayMode(FormCloudDisplayMode.fullScreen)).toBe(FormCloudDisplayMode.fullScreen);
|
||||||
|
});
|
||||||
|
|
||||||
|
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(FormCloudDisplayMode.fullScreen, [{ displayMode: FormCloudDisplayMode.inline }])).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the display mode on function in the configuration when it is found', () => {
|
||||||
|
service.onDisplayModeOn(formId, FormCloudDisplayMode.fullScreen);
|
||||||
|
|
||||||
|
expect(displayModeOnSpy).toHaveBeenCalledWith(formId);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not call the on display mode on function in the configuration when it is not found', () => {
|
||||||
|
service.onDisplayModeOff(formId, FormCloudDisplayMode.inline);
|
||||||
|
|
||||||
|
expect(displayModeOnSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the display mode off function in the configuration when it is found', () => {
|
||||||
|
service.onDisplayModeOff(formId, FormCloudDisplayMode.fullScreen);
|
||||||
|
|
||||||
|
expect(displayModeOffSpy).toHaveBeenCalledWith(formId);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not call the on display mode off function in the configuration when it is not found', () => {
|
||||||
|
service.onDisplayModeOff(formId, FormCloudDisplayMode.inline);
|
||||||
|
|
||||||
|
expect(displayModeOffSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the complete task function in the configuration when it is found', () => {
|
||||||
|
service.onCompleteTask(formId, FormCloudDisplayMode.fullScreen);
|
||||||
|
|
||||||
|
expect(completeTaskSpy).toHaveBeenCalledWith(formId);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not call the complete task function in the configuration when it is not found', () => {
|
||||||
|
service.onCompleteTask(formId, FormCloudDisplayMode.inline);
|
||||||
|
|
||||||
|
expect(completeTaskSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the save task function in the configuration when it is found', () => {
|
||||||
|
service.onSaveTask(formId, FormCloudDisplayMode.fullScreen);
|
||||||
|
|
||||||
|
expect(saveTaskSpy).toHaveBeenCalledWith(formId);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not call the save task function in the configuration when it is not found', () => {
|
||||||
|
service.onSaveTask(formId, FormCloudDisplayMode.inline);
|
||||||
|
|
||||||
|
expect(saveTaskSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the provided display mode when calling the switchToDisplayMode and display exists in configuration', () => {
|
||||||
|
expect(service.switchToDisplayMode(formId, FormCloudDisplayMode.fullScreen)).toBe(FormCloudDisplayMode.fullScreen);
|
||||||
|
expect(changeDisplayModeSpy).toHaveBeenCalledWith({ id: formId, displayMode: FormCloudDisplayMode.fullScreen });
|
||||||
|
});
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
|
||||||
|
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(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(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(changeDisplayModeSpy).not.toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the display mode off when switching the display mode and the old display mode is provided and it provides the off method', () => {
|
||||||
|
expect(service.switchToDisplayMode(formId, FormCloudDisplayMode.inline, FormCloudDisplayMode.fullScreen)).toBe(FormCloudDisplayMode.inline);
|
||||||
|
expect(displayModeOffSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the display mode on when switching the display mode and the new display mode provides the on method', () => {
|
||||||
|
expect(service.switchToDisplayMode(formId, FormCloudDisplayMode.fullScreen)).toBe(FormCloudDisplayMode.fullScreen);
|
||||||
|
expect(displayModeOnSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,147 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2023 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 { Injectable } from '@angular/core';
|
||||||
|
import { Observable, Subject } from 'rxjs';
|
||||||
|
import { FormCloudDisplayMode, FormCloudDisplayModeChange, FormCloudDisplayModeConfiguration } from '../../services/form-fields.interfaces';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class DisplayModeService {
|
||||||
|
public static readonly DEFAULT_DISPLAY_MODE_CONFIGURATIONS: FormCloudDisplayModeConfiguration[] = [
|
||||||
|
{
|
||||||
|
displayMode: FormCloudDisplayMode.inline,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
public static readonly IMPLEMENTED_DISPLAY_MODE_CONFIGURATIONS: FormCloudDisplayModeConfiguration[] = [
|
||||||
|
...DisplayModeService.DEFAULT_DISPLAY_MODE_CONFIGURATIONS,
|
||||||
|
{
|
||||||
|
displayMode: FormCloudDisplayMode.fullScreen,
|
||||||
|
options: {
|
||||||
|
onDisplayModeOn: () => { },
|
||||||
|
onDisplayModeOff: (id: string) => DisplayModeService.changeDisplayMode({ displayMode: FormCloudDisplayMode.inline, id }),
|
||||||
|
onCompleteTask: (id: string) => DisplayModeService.changeDisplayMode({ displayMode: FormCloudDisplayMode.inline, id }),
|
||||||
|
onSaveTask: () => { },
|
||||||
|
displayToolbar: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
public static readonly DEFAULT_DISPLAY_MODE: FormCloudDisplayMode = FormCloudDisplayMode.inline;
|
||||||
|
|
||||||
|
private static readonly displayMode = new Subject<FormCloudDisplayModeChange>();
|
||||||
|
|
||||||
|
static readonly displayMode$: Observable<FormCloudDisplayModeChange> = DisplayModeService.displayMode.asObservable();
|
||||||
|
|
||||||
|
static changeDisplayMode(change: FormCloudDisplayModeChange) {
|
||||||
|
DisplayModeService.displayMode.next(change);
|
||||||
|
}
|
||||||
|
|
||||||
|
getDefaultDisplayModeConfigurations(): FormCloudDisplayModeConfiguration[] {
|
||||||
|
return DisplayModeService.DEFAULT_DISPLAY_MODE_CONFIGURATIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDisplayModeConfigurations(availableConfigurations?: FormCloudDisplayModeConfiguration[]): FormCloudDisplayModeConfiguration[] {
|
||||||
|
if (availableConfigurations && availableConfigurations.length > 0) {
|
||||||
|
return availableConfigurations;
|
||||||
|
} else {
|
||||||
|
return this.getDefaultDisplayModeConfigurations();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getDisplayMode(displayMode?: FormCloudDisplayMode, availableConfigurations?: FormCloudDisplayModeConfiguration[]): FormCloudDisplayMode {
|
||||||
|
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);
|
||||||
|
} else {
|
||||||
|
return DisplayModeService.DEFAULT_DISPLAY_MODE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
findConfiguration(displayMode?: FormCloudDisplayMode, availableConfigurations?: FormCloudDisplayModeConfiguration[]): FormCloudDisplayModeConfiguration {
|
||||||
|
return this.getDisplayModeConfigurations(availableConfigurations).find(config => config.displayMode === displayMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
onCompleteTask(id?: string, displayMode?: FormCloudDisplayMode, availableConfigurations?: FormCloudDisplayModeConfiguration[]) {
|
||||||
|
const configuration = this.findConfiguration(displayMode, availableConfigurations);
|
||||||
|
|
||||||
|
if (configuration?.options?.onCompleteTask) {
|
||||||
|
configuration.options.onCompleteTask(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSaveTask(id?: string, displayMode?: FormCloudDisplayMode, availableConfigurations?: FormCloudDisplayModeConfiguration[]) {
|
||||||
|
const configuration = this.findConfiguration(displayMode, availableConfigurations);
|
||||||
|
|
||||||
|
if (configuration?.options?.onSaveTask) {
|
||||||
|
configuration.options.onSaveTask(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onDisplayModeOff(id?: string, displayMode?: FormCloudDisplayMode, availableConfigurations?: FormCloudDisplayModeConfiguration[]) {
|
||||||
|
const configuration = this.findConfiguration(displayMode, availableConfigurations);
|
||||||
|
|
||||||
|
if (configuration?.options?.onDisplayModeOff) {
|
||||||
|
configuration.options.onDisplayModeOff(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onDisplayModeOn(id?: string, displayMode?: FormCloudDisplayMode, availableConfigurations?: FormCloudDisplayModeConfiguration[]) {
|
||||||
|
const configuration = this.findConfiguration(displayMode, availableConfigurations);
|
||||||
|
|
||||||
|
if (configuration?.options?.onDisplayModeOn) {
|
||||||
|
configuration.options.onDisplayModeOn(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switchToDisplayMode(
|
||||||
|
id?: string,
|
||||||
|
newDisplayMode?: FormCloudDisplayMode,
|
||||||
|
oldDisplayMode?: FormCloudDisplayMode,
|
||||||
|
availableConfigurations?: FormCloudDisplayModeConfiguration[]
|
||||||
|
): FormCloudDisplayMode {
|
||||||
|
const oldConfiguration = this.findConfiguration(oldDisplayMode, availableConfigurations);
|
||||||
|
const newConfiguration = this.findConfiguration(newDisplayMode, availableConfigurations);
|
||||||
|
|
||||||
|
if (oldConfiguration?.displayMode !== newConfiguration?.displayMode) {
|
||||||
|
if (oldConfiguration) {
|
||||||
|
this.onDisplayModeOff(id, oldDisplayMode, availableConfigurations);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newConfiguration) {
|
||||||
|
DisplayModeService.changeDisplayMode({ id, displayMode: newConfiguration.displayMode });
|
||||||
|
this.onDisplayModeOn(id, newDisplayMode, availableConfigurations);
|
||||||
|
return newConfiguration.displayMode;
|
||||||
|
} else {
|
||||||
|
const displayMode = this.getDisplayMode(newDisplayMode, availableConfigurations);
|
||||||
|
DisplayModeService.changeDisplayMode({ id, displayMode });
|
||||||
|
this.onDisplayModeOn(id, displayMode, availableConfigurations);
|
||||||
|
return displayMode;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return oldConfiguration?.displayMode || this.getDisplayMode(oldDisplayMode, availableConfigurations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -26,6 +26,7 @@ export interface FormRepresentation {
|
|||||||
version?: number;
|
version?: number;
|
||||||
formDefinition?: FormDefinition;
|
formDefinition?: FormDefinition;
|
||||||
standAlone?: boolean;
|
standAlone?: boolean;
|
||||||
|
displayMode?: FormCloudDisplayMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FormTab {
|
export interface FormTab {
|
||||||
@@ -233,3 +234,28 @@ export enum FormFieldType {
|
|||||||
displayText = 'readonly-text',
|
displayText = 'readonly-text',
|
||||||
fileViewer = 'file-viewer'
|
fileViewer = 'file-viewer'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FormCloudDisplayModeConfigurationOptions {
|
||||||
|
onCompleteTask(id?: string): void;
|
||||||
|
onSaveTask(id?: string): void;
|
||||||
|
onDisplayModeOn(id?: string): void;
|
||||||
|
onDisplayModeOff(id?: string): void;
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface FormCloudDisplayModeConfiguration {
|
||||||
|
displayMode: FormCloudDisplayMode;
|
||||||
|
options?: FormCloudDisplayModeConfigurationOptions;
|
||||||
|
default?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-shadow
|
||||||
|
export enum FormCloudDisplayMode {
|
||||||
|
inline = 'inline',
|
||||||
|
fullScreen = 'fullScreen'
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface FormCloudDisplayModeChange {
|
||||||
|
displayMode: FormCloudDisplayMode;
|
||||||
|
id?: string;
|
||||||
|
};
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<div *ngIf="!loading; else loadingTemplate">
|
<div *ngIf="!loading; else loadingTemplate">
|
||||||
<adf-cloud-form *ngIf="hasForm(); else withoutForm"
|
<adf-cloud-form #adfCloudForm *ngIf="hasForm(); else withoutForm"
|
||||||
[appName]="appName"
|
[appName]="appName"
|
||||||
[appVersion]="taskDetails.appVersion"
|
[appVersion]="taskDetails.appVersion"
|
||||||
[taskId]="taskId"
|
[taskId]="taskId"
|
||||||
@@ -10,12 +10,15 @@
|
|||||||
[showValidationIcon]="showValidationIcon"
|
[showValidationIcon]="showValidationIcon"
|
||||||
[showCompleteButton]="canCompleteTask()"
|
[showCompleteButton]="canCompleteTask()"
|
||||||
[showSaveButton]="canCompleteTask()"
|
[showSaveButton]="canCompleteTask()"
|
||||||
|
[displayModeConfigurations]="displayModeConfigurations"
|
||||||
(formSaved)="onFormSaved($event)"
|
(formSaved)="onFormSaved($event)"
|
||||||
(formCompleted)="onFormCompleted($event)"
|
(formCompleted)="onFormCompleted($event)"
|
||||||
(formError)="onError($event)"
|
(formError)="onError($event)"
|
||||||
(error)="onError($event)"
|
(error)="onError($event)"
|
||||||
(formContentClicked)="onFormContentClicked($event)"
|
(formContentClicked)="onFormContentClicked($event)"
|
||||||
(executeOutcome)="onFormExecuteOutcome($event)">
|
(executeOutcome)="onFormExecuteOutcome($event)"
|
||||||
|
(displayModeOn)="onDisplayModeOn($event)"
|
||||||
|
(displayModeOff)="onDisplayModeOff($event)">
|
||||||
<adf-cloud-form-custom-outcomes>
|
<adf-cloud-form-custom-outcomes>
|
||||||
<ng-template [ngTemplateOutlet]="taskFormCloudButtons">
|
<ng-template [ngTemplateOutlet]="taskFormCloudButtons">
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
@@ -36,6 +36,8 @@ import { IdentityUserService } from '../../../people/services/identity-user.serv
|
|||||||
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 { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
|
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
|
||||||
|
import { DisplayModeService } from '../../../form/services/display-mode.service';
|
||||||
|
import { FormCloudComponent } from '../../../form/components/form-cloud.component';
|
||||||
|
|
||||||
const taskDetails: TaskDetailsCloudModel = {
|
const taskDetails: TaskDetailsCloudModel = {
|
||||||
appName: 'simple-app',
|
appName: 'simple-app',
|
||||||
@@ -66,7 +68,8 @@ describe('TaskFormCloudComponent', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule]
|
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule],
|
||||||
|
declarations: [FormCloudComponent]
|
||||||
});
|
});
|
||||||
taskDetails.status = TASK_ASSIGNED_STATE;
|
taskDetails.status = TASK_ASSIGNED_STATE;
|
||||||
taskDetails.permissions = [TASK_VIEW_PERMISSION];
|
taskDetails.permissions = [TASK_VIEW_PERMISSION];
|
||||||
@@ -421,6 +424,26 @@ 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 () => {
|
||||||
|
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 display task name as title on no form template if showTitle is true', () => {
|
it('should display task name as title on no form template if showTitle is true', () => {
|
||||||
@@ -452,4 +475,18 @@ describe('TaskFormCloudComponent', () => {
|
|||||||
|
|
||||||
expect(noFormTemplateTitle).toBeNull();
|
expect(noFormTemplateTitle).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, OnInit, ViewEncapsulation, OnDestroy } from '@angular/core';
|
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, OnInit, ViewEncapsulation, OnDestroy, ViewChild } from '@angular/core';
|
||||||
import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model';
|
import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model';
|
||||||
import { TaskCloudService } from '../../services/task-cloud.service';
|
import { TaskCloudService } from '../../services/task-cloud.service';
|
||||||
import { FormRenderingService, FormModel, ContentLinkModel, FormOutcomeEvent } from '@alfresco/adf-core';
|
import { FormRenderingService, FormModel, ContentLinkModel, FormOutcomeEvent } from '@alfresco/adf-core';
|
||||||
@@ -24,6 +24,8 @@ import { DropdownCloudWidgetComponent } from '../../../form/components/widgets/d
|
|||||||
import { DateCloudWidgetComponent } from '../../../form/components/widgets/date/date-cloud.widget';
|
import { DateCloudWidgetComponent } from '../../../form/components/widgets/date/date-cloud.widget';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
|
import { FormCloudDisplayModeConfiguration } from '../../../services/form-fields.interfaces';
|
||||||
|
import { FormCloudComponent } from '../../../form/components/form-cloud.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-cloud-task-form',
|
selector: 'adf-cloud-task-form',
|
||||||
@@ -64,6 +66,12 @@ export class TaskFormCloudComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
@Input()
|
@Input()
|
||||||
readOnly = false;
|
readOnly = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The available display configurations for the form
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
displayModeConfigurations: FormCloudDisplayModeConfiguration[];
|
||||||
|
|
||||||
/** Emitted when the form is saved. */
|
/** Emitted when the form is saved. */
|
||||||
@Output()
|
@Output()
|
||||||
formSaved = new EventEmitter<FormModel>();
|
formSaved = new EventEmitter<FormModel>();
|
||||||
@@ -109,6 +117,17 @@ export class TaskFormCloudComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
@Output()
|
@Output()
|
||||||
onTaskLoaded = new EventEmitter<TaskDetailsCloudModel>(); /* eslint-disable-line */
|
onTaskLoaded = new EventEmitter<TaskDetailsCloudModel>(); /* eslint-disable-line */
|
||||||
|
|
||||||
|
/** Emitted when a display mode configuration is turned on. */
|
||||||
|
@Output()
|
||||||
|
displayModeOn = new EventEmitter<FormCloudDisplayModeConfiguration>();
|
||||||
|
|
||||||
|
/** Emitted when a display mode configuration is turned off. */
|
||||||
|
@Output()
|
||||||
|
displayModeOff = new EventEmitter<FormCloudDisplayModeConfiguration>();
|
||||||
|
|
||||||
|
@ViewChild('adfCloudForm', { static: false })
|
||||||
|
adfCloudForm: FormCloudComponent;
|
||||||
|
|
||||||
taskDetails: TaskDetailsCloudModel;
|
taskDetails: TaskDetailsCloudModel;
|
||||||
|
|
||||||
candidateUsers: string[] = [];
|
candidateUsers: string[] = [];
|
||||||
@@ -231,6 +250,18 @@ export class TaskFormCloudComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
this.executeOutcome.emit(outcome);
|
this.executeOutcome.emit(outcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switchToDisplayMode(newDisplayMode?: string) {
|
||||||
|
this.adfCloudForm.switchToDisplayMode(newDisplayMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
onDisplayModeOn(displayModeConfiguration: FormCloudDisplayModeConfiguration){
|
||||||
|
this.displayModeOn.emit(displayModeConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
onDisplayModeOff(displayModeConfiguration: FormCloudDisplayModeConfiguration){
|
||||||
|
this.displayModeOff.emit(displayModeConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.onDestroy$.next(true);
|
this.onDestroy$.next(true);
|
||||||
this.onDestroy$.complete();
|
this.onDestroy$.complete();
|
||||||
|
Reference in New Issue
Block a user