AAE-24927 Add ability to style form widgets (#10171)

* AAE-25211 form styling PoC

* AAE-25211 poc

* AAE-25211 revert cloud form service

* AAE-24927 display text schema

* AAE-24927 radio button styles

* AAE-24927 header styles

* AAE-24927 style pipes

* AAE-24927 remove redundand field

* remove redundand comment

* fix build error

* remove space from protractor test
This commit is contained in:
Kasia Biernat-Kluba 2024-09-05 10:58:36 +02:00 committed by GitHub
parent a86b23f8a1
commit 5d5c1ac527
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 672 additions and 48 deletions

View File

@ -145,7 +145,7 @@ describe('Form widgets', () => {
});
it('[C272783] Should display displayText and displayValue in form', async () => {
const expected0 = ' ' + formInstance.getWidgetBy('id', appFields.displayText_id).value;
const expected0 = formInstance.getWidgetBy('id', appFields.displayText_id).value;
const expected1 = (formInstance.getWidgetBy('id', appFields.displayValue_id).value as string) || 'Display value';
const expected2 = (formInstance.getWidgetBy('id', appFields.displayValue_id).value as string) || '';

View File

@ -1,6 +1,7 @@
<div [id]="'field-' + field?.id + '-container'"
[style.visibility]="!field?.isVisible ? 'hidden' : 'visible'"
[style.display]="!field?.isVisible ? 'none' : 'block'"
[style]="field | adfFieldStyle"
[class.adf-focus]="focus"
(focusin)="focusToggle()"
(focusout)="focusToggle()">

View File

@ -20,6 +20,7 @@ import {
Component,
ComponentFactory,
ComponentRef,
inject,
Input,
NgModule,
OnDestroy,
@ -30,7 +31,8 @@ import {
} from '@angular/core';
import { FormRenderingService } from '../../services/form-rendering.service';
import { WidgetVisibilityService } from '../../services/widget-visibility.service';
import { FormFieldModel } from '../widgets';
import { FormFieldModel } from '../widgets/core/form-field.model';
import { FieldStylePipe } from '../../pipes/field-style.pipe';
declare const adf: any;
@ -38,7 +40,8 @@ declare const adf: any;
selector: 'adf-form-field',
standalone: true,
templateUrl: './form-field.component.html',
encapsulation: ViewEncapsulation.None
encapsulation: ViewEncapsulation.None,
imports: [FieldStylePipe]
})
export class FormFieldComponent implements OnInit, OnDestroy {
@ViewChild('container', { read: ViewContainerRef, static: true })
@ -57,7 +60,9 @@ export class FormFieldComponent implements OnInit, OnDestroy {
focus: boolean = false;
constructor(private formRenderingService: FormRenderingService, private visibilityService: WidgetVisibilityService, private compiler: Compiler) {}
private readonly formRenderingService = inject(FormRenderingService);
private readonly visibilityService = inject(WidgetVisibilityService);
private readonly compiler = inject(Compiler);
ngOnInit() {
const w: any = window;

View File

@ -21,7 +21,7 @@
[id]="'field-' + currentRootElement?.id + '-container'"
class="adf-container-widget"
[hidden]="!currentRootElement?.isVisible">
<div [hidden]="!currentRootElement?.isGroup()" class="adf-container-widget__header">
<div [hidden]="!currentRootElement?.isGroup()" [style]="currentRootElement | adfFieldStyle" class="adf-container-widget__header">
<h4 class="adf-container-widget__header-text" id="container-header"
[class.adf-collapsible]="currentRootElement?.isCollapsible()">
<button *ngIf="currentRootElement?.isCollapsible()"

View File

@ -11,6 +11,9 @@
padding-bottom: 10px;
cursor: default;
user-select: none;
font-size: var(--adf-header-font-size);
font-weight: var(--adf-header-font-weight);
color: var(--adf-header-color);
&.adf-collapsible {
cursor: pointer;

View File

@ -28,6 +28,7 @@ import { FormService } from '../services/form.service';
import { FormFieldComponent } from './form-field/form-field.component';
import { FORM_FIELD_MODEL_RENDER_MIDDLEWARE, FormFieldModelRenderMiddleware } from './middlewares/middleware';
import { ContainerModel, FormFieldModel, FormModel, TabModel } from './widgets';
import { FieldStylePipe } from '../pipes/field-style.pipe';
@Component({
selector: 'adf-form-renderer',
@ -55,6 +56,7 @@ import { ContainerModel, FormFieldModel, FormModel, TabModel } from './widgets';
FormsModule,
JsonPipe,
UpperCasePipe,
FieldStylePipe,
NgClass
],
encapsulation: ViewEncapsulation.None

View File

@ -93,6 +93,7 @@ export class FormFieldModel extends FormWidgetModel {
variableConfig: VariableConfig;
schemaDefinition: DataColumn[];
externalProperty?: string;
style?: string;
// container model members
numberOfColumns: number = 1;
@ -221,6 +222,7 @@ export class FormFieldModel extends FormWidgetModel {
this.precision = json.precision;
this.externalProperty = json.externalProperty;
this._value = this.parseValue(json);
this.style = json.style;
if (json.placeholder && json.placeholder !== '' && json.placeholder !== 'null') {
this.placeholder = json.placeholder;

View File

@ -15,15 +15,15 @@
* limitations under the License.
*/
/* eslint-disable @angular-eslint/component-selector */
/* eslint-disable @angular-eslint/component-selector */
export abstract class FormWidgetModel {
readonly fieldType: string;
readonly id: string;
readonly name: string;
readonly type: string;
readonly tab: string;
readonly style?: string;
readonly form: any;
readonly json: any;
@ -40,6 +40,7 @@ export abstract class FormWidgetModel {
this.type = json.type;
this.tab = json.tab;
this.field = json.field;
this.style = json.style;
}
}
}

View File

@ -33,6 +33,7 @@ import { UploadWidgetContentLinkModel } from './upload-widget-content-link.model
import { FormValidationService } from '../../../services/form-validation-service.interface';
import { ProcessFormModel } from './process-form-model.interface';
import { WidgetTypeEnum, WidgetVisibilityModel } from '../../../models/widget-visibility.model';
import { ThemeModel } from './theme.model';
export interface ConfirmMessage {
show: boolean;
@ -58,6 +59,7 @@ export interface FormRepresentationModel {
fields?: any[];
};
displayMode: string;
theme?: ThemeModel;
}
export class FormModel implements ProcessFormModel {
static UNSET_TASK_NAME: string = 'Nameless task';
@ -85,6 +87,7 @@ export class FormModel implements ProcessFormModel {
outcomes: FormOutcomeModel[] = [];
fieldValidators: FormFieldValidator[] = [...FORM_FIELD_VALIDATORS];
customFieldTemplates: FormFieldTemplates = {};
theme?: ThemeModel;
className: string;
readOnly = false;
@ -116,6 +119,7 @@ export class FormModel implements ProcessFormModel {
this.enableFixedSpace = enableFixedSpace;
this.confirmMessage = json.confirmMessage || {};
this.displayMode = json.displayMode;
this.theme = json.theme;
this.tabs = (json.tabs || []).map((tabJson) => new TabModel(this, tabJson));

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
/* eslint-disable @angular-eslint/component-selector */
/* eslint-disable @angular-eslint/component-selector */
export * from './form-field-metadata';
export * from './form-values';
@ -44,3 +44,5 @@ export * from './form-field-file-source';
export * from './form-field-rule';
export * from './form-field-utils';
export * from './form-field-variable-options';
export * from './widget-schema.model';
export * from './theme.model';

View File

@ -0,0 +1,50 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export type FormThemeVariable = '--adf-form-label-font-size' | '--adf-form-label-font-weight' | '--adf-form-label-color';
export type ReadonlyTextThemeVariable = '--adf-readonly-text-font-size' | '--adf-readonly-text-font-weight' | '--adf-readonly-text-color';
export type HeaderThemeVariable = '--adf-header-font-size' | '--adf-header-font-weight' | '--adf-header-color';
export type RadioButtonsThemeVariable = '--adf-radio-buttons-font-size' | '--adf-radio-buttons-font-weight' | '--adf-radio-buttons-color';
export type SupportedWidgetType = 'radio-buttons' | 'group' | 'readonly-text';
export interface ThemeModel {
form?: {
[variable in FormThemeVariable]?: string;
};
widgets?: {
['readonly-text']?: {
[styleName: string]: {
[variable in ReadonlyTextThemeVariable]?: string;
};
};
['group']?: {
[styleName: string]: {
[variable in HeaderThemeVariable]?: string;
};
};
['radio-buttons']?: {
[styleName: string]: {
[variable in RadioButtonsThemeVariable]?: string;
};
};
};
defaults?: {
[widgetType in SupportedWidgetType]?: string;
};
}

View File

@ -0,0 +1,38 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { FormThemeVariable } from './theme.model';
export type WidgetStylePropertySelector = 'number' | 'options' | 'colorOptions';
export interface WidgetSchemaModel<TFieldVariable = string, TFormVariable = FormThemeVariable> {
themeProperties: WidgetSchemaThemeProperty<TFieldVariable, TFormVariable>[];
}
export interface WidgetSchemaThemeProperty<TFieldVariable, TFormVariable = FormThemeVariable> {
name: string;
cssPropertyName: string;
fieldVariableName: TFieldVariable;
formVariableName: TFormVariable;
type: WidgetStylePropertySelector;
options?: {
name: string;
value: string;
}[];
unit?: string;
defaultValue: string;
}

View File

@ -0,0 +1,89 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ReadonlyTextThemeVariable } from '../core/theme.model';
import { WidgetSchemaModel } from '../core/widget-schema.model';
export const displayTextSchema: WidgetSchemaModel<ReadonlyTextThemeVariable> = {
themeProperties: [
{
name: 'FORM.FIELD_STYLE.FONT_SIZE',
cssPropertyName: 'font-size',
fieldVariableName: '--adf-readonly-text-font-size',
formVariableName: '--adf-form-label-font-size',
type: 'number',
unit: 'px',
defaultValue: '16px'
},
{
name: 'FORM.FIELD_STYLE.FONT_WEIGHT',
cssPropertyName: 'font-weight',
fieldVariableName: '--adf-readonly-text-font-weight',
formVariableName: '--adf-form-label-font-weight',
type: 'options',
options: [
{
name: 'FORM.FIELD_STYLE.REGULAR',
value: 'normal'
},
{
name: 'FORM.FIELD_STYLE.BOLD',
value: 'bold'
}
],
defaultValue: 'normal'
},
{
name: 'FORM.FIELD_STYLE.FONT_COLOR',
cssPropertyName: 'color',
fieldVariableName: '--adf-readonly-text-color',
formVariableName: '--adf-form-label-color',
type: 'colorOptions',
options: [
{
name: 'FORM.FIELD_STYLE.SYSTEM_COLOR',
value: 'inherit'
},
{
name: 'FORM.FIELD_STYLE.BLACK',
value: '#000000'
},
{
name: 'FORM.FIELD_STYLE.GREY',
value: '#9CA3AF'
},
{
name: 'FORM.FIELD_STYLE.RED',
value: '#DA1500'
},
{
name: 'FORM.FIELD_STYLE.GREEN',
value: '#04A003'
},
{
name: 'FORM.FIELD_STYLE.BLUE',
value: '#0A60CE'
},
{
name: 'FORM.FIELD_STYLE.YELLOW',
value: '#FACC15'
}
],
defaultValue: 'inherit'
}
]
};

View File

@ -1,3 +1 @@
<div [title]="field.tooltip" class="adf-display-text-widget {{ field.className }}">
{{ field.value | translate }}
</div>
<div [title]="field.tooltip" [class]="'adf-display-text-widget '+ field.className">{{ field.value | translate }}</div>

View File

@ -1,3 +1,6 @@
.adf-display-text-widget {
white-space: pre-wrap;
font-size: var(--adf-readonly-text-font-size, var(--adf-form-label-font-size, var(--theme-body-1-font-size)));
font-weight: var(--adf-readonly-text-font-weight, var(--adf-form-label-font-weight, var(--theme-font-weight)));
color: var(--adf-readonly-text-color, var(--adf-form-label-color, var(--theme-text-color)));
}

View File

@ -0,0 +1,19 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './display-text.schema';
export * from './display-text.widget';

View File

@ -44,7 +44,6 @@ export * from './decimal/decimal.component';
export * from './checkbox/checkbox.widget';
export * from './multiline-text/multiline-text.widget';
export * from './hyperlink/hyperlink.widget';
export * from './display-text/display-text.widget';
export * from './date/date.widget';
export * from './amount/amount.widget';
export * from './error/error.component';
@ -53,6 +52,9 @@ export * from './json/json.widget';
export * from './base-viewer/base-viewer.widget';
export * from './text/text-mask.component';
// widgets with schema
export * from './display-text';
export const WIDGET_DIRECTIVES: any[] = [
UnknownWidgetComponent,
TextWidgetComponent,
@ -70,6 +72,4 @@ export const WIDGET_DIRECTIVES: any[] = [
BaseViewerWidgetComponent
];
export const MASK_DIRECTIVE: any[] = [
InputMaskDirective
];
export const MASK_DIRECTIVE: any[] = [InputMaskDirective];

View File

@ -0,0 +1,100 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { FieldStylePipe } from '../pipes/field-style.pipe';
import { FormFieldModel } from '../components/widgets/core/form-field.model';
import { ThemeModel } from '../components/widgets/core/theme.model';
const mockTheme: ThemeModel = {
widgets: {
'readonly-text': {
'my-custom-display-text': {
'--adf-readonly-text-font-size': '12px',
'--adf-readonly-text-font-weight': 'normal',
'--adf-readonly-text-color': '#000000'
},
'my-custom-display-text2': {
'--adf-readonly-text-font-size': '15px',
'--adf-readonly-text-color': 'green'
}
},
'radio-buttons': {
'my-custom-radio-buttons2': {
'--adf-radio-buttons-font-size': '15px',
'--adf-radio-buttons-font-weight': 'normal',
'--adf-radio-buttons-color': 'green'
}
}
}
};
describe('FieldStylePipe', () => {
let pipe: FieldStylePipe;
beforeEach(() => {
pipe = new FieldStylePipe();
});
it('should return styles as a string', () => {
const field: Partial<FormFieldModel> = {
type: 'readonly-text',
form: {
theme: mockTheme
},
style: 'my-custom-display-text'
};
const result = pipe.transform(field as FormFieldModel);
expect(result).toEqual('--adf-readonly-text-font-size: 12px;--adf-readonly-text-font-weight: normal;--adf-readonly-text-color: #000000');
});
it('should return empty string when style name is not provided', () => {
const field: Partial<FormFieldModel> = {
type: 'readonly-text',
form: {
theme: mockTheme
}
};
const result = pipe.transform(field as FormFieldModel);
expect(result).toEqual('');
});
it('should return empty string when style name is not defined', () => {
const field: Partial<FormFieldModel> = {
type: 'readonly-text',
form: {
theme: mockTheme
},
style: 'not-defined-style'
};
const result = pipe.transform(field as FormFieldModel);
expect(result).toEqual('');
});
it('should return empty string when theme is not defined', () => {
const field: Partial<FormFieldModel> = {
type: 'readonly-text',
form: {},
style: 'my-custom-display-text'
};
const result = pipe.transform(field as FormFieldModel);
expect(result).toEqual('');
});
});

View File

@ -0,0 +1,38 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Pipe, PipeTransform } from '@angular/core';
import { FormFieldModel } from '../components/widgets/core/form-field.model';
@Pipe({
name: 'adfFieldStyle',
standalone: true
})
export class FieldStylePipe implements PipeTransform {
transform(field: FormFieldModel): string {
const theme = field.form?.theme?.widgets[field.type];
const style = field.style && theme?.[field.style];
return style ? this.flattenStyles(style) : '';
}
private flattenStyles(styles: { [key: string]: string }): string {
return Object.entries(styles)
.map(([key, value]) => `${key}: ${value}`)
.join(';');
}
}

View File

@ -0,0 +1,47 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { FormStylePipe } from './form-style.pipe';
import { ThemeModel } from '../components/widgets/core/theme.model';
describe('FormStylePipe', () => {
let pipe: FormStylePipe;
beforeEach(() => {
pipe = new FormStylePipe();
});
it('should transform form theme into styles', () => {
const formTheme: ThemeModel = {
form: {
'--adf-form-label-font-size': '16px',
'--adf-form-label-color': 'black',
'--adf-form-label-font-weight': 'bold'
}
};
const result = pipe.transform(formTheme);
expect(result).toEqual('--adf-form-label-font-size: 16px;--adf-form-label-color: black;--adf-form-label-font-weight: bold');
});
it('should return an empty string if form theme is undefined', () => {
const result = pipe.transform(undefined);
expect(result).toEqual('');
});
});

View File

@ -0,0 +1,36 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Pipe, PipeTransform } from '@angular/core';
import { ThemeModel } from '../components/widgets/core/theme.model';
@Pipe({
name: 'adfFormStyle',
standalone: true
})
export class FormStylePipe implements PipeTransform {
transform(formTheme?: ThemeModel): string {
const theme = formTheme?.form;
return theme ? this.flattenStyles(theme) : '';
}
private flattenStyles(styles: { [key: string]: string }): string {
return Object.entries(styles)
.map(([key, value]) => `${key}: ${value}`)
.join(';');
}
}

View File

@ -0,0 +1,19 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './field-style.pipe';
export * from './form-style.pipe';

View File

@ -29,6 +29,8 @@ export * from './services/form.service';
export * from './services/form-validation-service.interface';
export * from './services/widget-visibility.service';
export * from './pipes';
export * from './events';
export * from './form-base.module';

View File

@ -70,6 +70,20 @@
},
"FORM_RENDERER": {
"NAMELESS_TASK": "Nameless task"
},
"FIELD_STYLE": {
"FONT_SIZE": "Font size",
"FONT_WEIGHT": "Font weight",
"FONT_COLOR": "Font color",
"REGULAR": "Regular",
"BOLD": "Bold",
"SYSTEM_COLOR": "System color",
"BLACK": "Black",
"GREY": "Grey",
"RED": "Red",
"GREEN": "Green",
"BLUE": "Blue",
"YELLOW": "Yellow"
}
},
"CORE": {

View File

@ -31,20 +31,17 @@
--theme-primary-color: mat.get-color-from-palette($primary),
--theme-primary-color-default-contrast: mat.get-color-from-palette($primary, default-contrast),
--theme-header-text-color: mat.get-color-from-palette($primary, default-contrast),
--adf-theme-primary-50:mat.get-color-from-palette($primary, 50),
--adf-theme-primary-100:mat.get-color-from-palette($primary, 100),
--adf-theme-primary-300:mat.get-color-from-palette($primary, 300),
--adf-theme-primary-900:mat.get-color-from-palette($primary, 900),
--adf-theme-primary-50: mat.get-color-from-palette($primary, 50),
--adf-theme-primary-100: mat.get-color-from-palette($primary, 100),
--adf-theme-primary-300: mat.get-color-from-palette($primary, 300),
--adf-theme-primary-900: mat.get-color-from-palette($primary, 900),
--theme-warn-color: mat.get-color-from-palette($warn),
--theme-warn-color-a700: mat.get-color-from-palette($warn, A700),
--theme-warn-color-default-contrast: mat.get-color-from-palette($warn, default-contrast),
--theme-accent-color: mat.get-color-from-palette($accent),
--theme-accent-color-a200: mat.get-color-from-palette($accent, A200),
--theme-accent-color-default-contrast: mat.get-color-from-palette($accent, default-contrast),
--theme-accent-500:mat.get-color-from-palette($accent, 500),
--theme-accent-500: mat.get-color-from-palette($accent, 500),
--adf-theme-foreground-base-color: mat.get-color-from-palette($foreground, base),
--adf-theme-foreground-base-color-065: mat.get-color-from-palette($foreground, base, 0.65),
--adf-theme-foreground-base-color-045: mat.get-color-from-palette($foreground, base, 0.45),
@ -63,7 +60,6 @@
--adf-theme-foreground-text-color-025: mat.get-color-from-palette($foreground, text, 0.25),
--adf-theme-foreground-text-color-014: mat.get-color-from-palette($foreground, text, 0.14),
--adf-theme-foreground-text-color-007: mat.get-color-from-palette($foreground, text, 0.07),
--adf-theme-background-card-color: mat.get-color-from-palette($background, card),
--adf-theme-background-card-color-087: mat.get-color-from-palette($background, card, 0.87),
--theme-background-color: mat.get-color-from-palette($background, background),
@ -72,9 +68,9 @@
--adf-theme-background-selected-button-color: mat.get-color-from-palette($background, selected-button),
--adf-theme-background-status-bar-color: mat.get-color-from-palette($background, status-bar),
--adf-theme-background-unselected-chip-color: mat.get-color-from-palette($background, unselected-chip),
// typography
--theme-font-family: mat.font-family($typography),
--theme-font-weight: normal,
--theme-body-1-font-size: mat.font-size($typography, body-2),
--theme-body-2-font-size: mat.font-size($typography, subtitle-2),
--theme-body-1-line-height: mat.line-height($typography, body-2),
@ -88,17 +84,14 @@
--theme-button-font-size: mat.font-size($typography, button),
--theme-headline-font-size: mat.font-size($typography, headline-5),
--theme-headline-line-height: mat.line-height($typography, headline-5),
--theme-adf-icon-1-font-size: map-get($custom-css-variables, 'theme-adf-icon-1-font-size'),
--theme-adf-picture-1-font-size: map-get($custom-css-variables, 'theme-adf-picture-1-font-size'),
--theme-adf-task-footer-font-size: map-get($custom-css-variables, 'theme-adf-task-footer-font-size'),
--theme-adf-task-title-font-size: map-get($custom-css-variables, 'theme-adf-task-title-font-size'),
// specific colors
--adf-theme-mat-grey-color-a200: mat.get-color-from-palette(mat.$grey-palette, A200),
--adf-theme-mat-grey-color-a400: mat.get-color-from-palette(mat.$grey-palette, A400),
--adf-theme-mat-grey-color-50: mat.get-color-from-palette(mat.$grey-palette, 50),
// spacing
--adf-theme-spacing: map-get($custom-css-variables, 'theme-adf-spacing')
);

View File

@ -3,7 +3,7 @@
</ng-content>
</div>
<div *ngIf="hasForm()" class="adf-cloud-form-container adf-cloud-form-{{displayMode?.toLowerCase() || 'inline'}}-container">
<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>

View File

@ -15,7 +15,19 @@
* limitations under the License.
*/
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, OnDestroy, HostListener, OnInit, ChangeDetectorRef } from '@angular/core';
import {
Component,
EventEmitter,
Input,
OnChanges,
Output,
SimpleChanges,
OnDestroy,
HostListener,
OnInit,
ChangeDetectorRef,
inject
} from '@angular/core';
import { Observable, of, forkJoin, Subject, Subscription } from 'rxjs';
import { switchMap, takeUntil, map, filter } from 'rxjs/operators';
import {
@ -123,16 +135,17 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
readonly id: string;
displayMode: FormCloudDisplayMode;
style: string = '';
constructor(
protected formCloudService: FormCloudService,
protected formService: FormService,
private dialog: MatDialog,
protected visibilityService: WidgetVisibilityService,
private readonly displayModeService: DisplayModeService,
private spinnerService: FormCloudSpinnerService,
private readonly changeDetector: ChangeDetectorRef
) {
protected formCloudService = inject(FormCloudService);
protected formService = inject(FormService);
protected visibilityService = inject(WidgetVisibilityService);
protected dialog = inject(MatDialog);
protected spinnerService = inject(FormCloudSpinnerService);
protected displayModeService = inject(DisplayModeService);
protected changeDetector = inject(ChangeDetectorRef);
constructor() {
super();
this.spinnerService.initSpinnerHandling(this.onDestroy$);
@ -419,6 +432,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
this.displayMode,
this.displayModeConfigurations
);
this.displayModeOn.emit(this.displayModeService.findConfiguration(this.displayMode, this.displayModeConfigurations));
}

View File

@ -0,0 +1,19 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './radio-buttons-cloud.schema';
export * from './radio-buttons-cloud.widget';

View File

@ -0,0 +1,88 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { WidgetSchemaModel, RadioButtonsThemeVariable } from '@alfresco/adf-core';
export const displayTextSchema: WidgetSchemaModel<RadioButtonsThemeVariable> = {
themeProperties: [
{
name: 'FORM.FIELD_STYLE.FONT_SIZE',
cssPropertyName: 'font-size',
fieldVariableName: '--adf-radio-buttons-font-size',
formVariableName: '--adf-form-label-font-size',
type: 'number',
unit: 'px',
defaultValue: '16px'
},
{
name: 'FORM.FIELD_STYLE.FONT_WEIGHT',
cssPropertyName: 'font-weight',
fieldVariableName: '--adf-radio-buttons-font-weight',
formVariableName: '--adf-form-label-font-weight',
type: 'options',
options: [
{
name: 'FORM.FIELD_STYLE.REGULAR',
value: 'normal'
},
{
name: 'FORM.FIELD_STYLE.BOLD',
value: 'bold'
}
],
defaultValue: 'normal'
},
{
name: 'FORM.FIELD_STYLE.FONT_COLOR',
cssPropertyName: 'color',
fieldVariableName: '--adf-radio-buttons-color',
formVariableName: '--adf-form-label-color',
type: 'colorOptions',
options: [
{
name: 'FORM.FIELD_STYLE.SYSTEM_COLOR',
value: 'inherit'
},
{
name: 'FORM.FIELD_STYLE.BLACK',
value: '#000000'
},
{
name: 'FORM.FIELD_STYLE.GREY',
value: '#9CA3AF'
},
{
name: 'FORM.FIELD_STYLE.RED',
value: '#DA1500'
},
{
name: 'FORM.FIELD_STYLE.GREEN',
value: '#04A003'
},
{
name: 'FORM.FIELD_STYLE.BLUE',
value: '#0A60CE'
},
{
name: 'FORM.FIELD_STYLE.YELLOW',
value: '#FACC15'
}
],
defaultValue: 'inherit'
}
]
};

View File

@ -1,4 +1,12 @@
.adf {
&-radio-buttons-widget-cloud {
.adf-label {
font-size: var(--adf-radio-buttons-font-size, var(--adf-form-label-font-size, var(--theme-caption-font-size)));
font-weight: var(--adf-radio-buttons-font-weight, var(--adf-form-label-font-weight, var(--theme-font-weight)));
color: var(--adf-radio-buttons-color, var(--adf-form-label-color, var(--adf-theme-foreground-secondary-text-color)));
}
}
&-radio-button-container {
margin-bottom: 15px;
display: flex;

View File

@ -17,7 +17,7 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CoreModule, FormatSpacePipe, TOOLBAR_DIRECTIVES } from '@alfresco/adf-core';
import { CoreModule, FormatSpacePipe, TOOLBAR_DIRECTIVES, FormStylePipe } from '@alfresco/adf-core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MaterialModule } from '../material.module';
import { FormCloudComponent } from './components/form-cloud.component';
@ -65,7 +65,8 @@ import { FormCloudSpinnerService } from './services/spinner/form-cloud-spinner.s
FormatSpacePipe,
AlfrescoViewerComponent,
...CONTENT_UPLOAD_DIRECTIVES,
...CONTENT_METADATA_DIRECTIVES
...CONTENT_METADATA_DIRECTIVES,
FormStylePipe
],
declarations: [
FormCloudComponent,

View File

@ -29,10 +29,12 @@ export * from './components/widgets/dropdown/dropdown-cloud.widget';
export * from './components/widgets/group/group-cloud.widget';
export * from './components/widgets/people/people-cloud.widget';
export * from './components/widgets/properties-viewer/properties-viewer.widget';
export * from './components/widgets/radio-buttons/radio-buttons-cloud.widget';
export * from './components/widgets/file-viewer/file-viewer.widget';
export * from './components/widgets/display-rich-text/display-rich-text.widget';
// widgets with schema
export * from './components/widgets/radio-buttons';
export * from './services/content-cloud-node-selector.service';
export * from './services/form-cloud.service';
export * from './services/form-definition-selector-cloud.service';

View File

@ -35,6 +35,19 @@ export interface FormTab {
visibilityCondition: VisibilityCondition | null;
}
export interface FormTheme {
form: {
[key: string]: string;
};
widgets: {
[key: string]: {
[key: string]: {
[key: string]: string;
};
};
};
}
export interface FormOutcome {
id: string;
name: string;
@ -46,6 +59,7 @@ export interface FormDefinition {
outcomes: FormOutcome[];
metadata: any;
variables: any[];
theme?: FormTheme;
}
export interface Container {
@ -59,8 +73,19 @@ export interface Container {
};
}
export type FormFieldRepresentation = (DateField | DateTimeField | TextField | AttachFileField | DropDownField |
RadioField | TypeaheadField | PeopleField | AmountField | NumberField | CheckboxField | HyperlinkField);
export type FormFieldRepresentation =
| DateField
| DateTimeField
| TextField
| AttachFileField
| DropDownField
| RadioField
| TypeaheadField
| PeopleField
| AmountField
| NumberField
| CheckboxField
| HyperlinkField;
export interface AttachFileField extends FormField {
required: boolean;
@ -125,6 +150,7 @@ export interface FormField {
[anyKey: string]: any;
};
visibilityCondition: null | VisibilityCondition;
style?: string;
}
export interface FormOption {
@ -241,21 +267,21 @@ export interface FormCloudDisplayModeConfigurationOptions {
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;
};
}