Skip to content

Commit

Permalink
AAE-24927 add ability to style form widget - header (#10173)
Browse files Browse the repository at this point in the history
* 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 styles for header

* AAE-24927 remove redundand prop
  • Loading branch information
kathrine0 committed Sep 5, 2024
1 parent 5d5c1ac commit 166325d
Show file tree
Hide file tree
Showing 12 changed files with 264 additions and 42 deletions.
20 changes: 1 addition & 19 deletions lib/core/src/lib/form/components/form-renderer.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,7 @@
[id]="'field-' + currentRootElement?.id + '-container'"
class="adf-container-widget"
[hidden]="!currentRootElement?.isVisible">
<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()"
mat-icon-button
class="mdl-button--icon"
(click)="onExpanderClicked(currentRootElement)">
<mat-icon>{{ currentRootElement?.isExpanded ? 'expand_more' : 'expand_less' }}</mat-icon>
</button>
<span (click)="onExpanderClicked(currentRootElement)"
role="button"
tabindex="0"
(keyup.enter)="onExpanderClicked(currentRootElement)"
[id]="'container-header-label-' + currentRootElement?.id">
{{ currentRootElement.name | translate }}
</span>
</h4>
</div>

<adf-header-widget [element]="currentRootElement"></adf-header-widget>
<div *ngIf="currentRootElement?.form?.enableFixedSpace; else fixingTemplate">
<div class="adf-grid-list"
[ngStyle]="{ 'grid-template-columns': 'repeat(' + getNumberOfColumns(currentRootElement) + ', 1fr)' }"
Expand Down
14 changes: 0 additions & 14 deletions lib/core/src/lib/form/components/form-renderer.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,6 @@
display: none;
}

.adf-container-widget__header-text {
border-bottom: 1px solid rgba(0, 0, 0, 0.87);
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;
}
}

.adf-field-list {
padding: 0;
list-style-type: none;
Expand Down
10 changes: 3 additions & 7 deletions lib/core/src/lib/form/components/form-renderer.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ 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';
import { HeaderWidgetComponent } from './widgets/header/header.widget';

@Component({
selector: 'adf-form-renderer',
Expand Down Expand Up @@ -57,7 +58,8 @@ import { FieldStylePipe } from '../pipes/field-style.pipe';
JsonPipe,
UpperCasePipe,
FieldStylePipe,
NgClass
NgClass,
HeaderWidgetComponent
],
encapsulation: ViewEncapsulation.None
})
Expand Down Expand Up @@ -103,12 +105,6 @@ export class FormRendererComponent<T> implements OnInit, OnDestroy {
return this.formDefinition.tabs.filter((tab) => tab.isVisible);
}

onExpanderClicked(content: ContainerModel) {
if (content?.isCollapsible()) {
content.isExpanded = !content.isExpanded;
}
}

getNumberOfColumns(content: ContainerModel): number {
return (content.json?.numberOfColumns || 1) > (content.columns?.length || 1)
? content.json?.numberOfColumns || 1
Expand Down
8 changes: 7 additions & 1 deletion lib/core/src/lib/form/components/widgets/core/theme.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@
* limitations under the License.
*/

export type FormThemeVariable = '--adf-form-label-font-size' | '--adf-form-label-font-weight' | '--adf-form-label-color';
export type FormThemeVariable =
| '--adf-form-label-font-size'
| '--adf-form-label-font-weight'
| '--adf-form-label-color'
| '--adf-header-font-size'
| '--adf-header-font-weight'
| '--adf-header-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';
Expand Down
89 changes: 89 additions & 0 deletions lib/core/src/lib/form/components/widgets/header/header.schema.ts
Original file line number Diff line number Diff line change
@@ -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 { HeaderThemeVariable } from '../core/theme.model';
import { WidgetSchemaModel } from '../core/widget-schema.model';

export const headerSchema: WidgetSchemaModel<HeaderThemeVariable> = {
themeProperties: [
{
name: 'FORM.FIELD_STYLE.FONT_SIZE',
cssPropertyName: 'font-size',
fieldVariableName: '--adf-header-font-size',
formVariableName: '--adf-header-font-size',
type: 'number',
unit: 'px',
defaultValue: '16px'
},
{
name: 'FORM.FIELD_STYLE.FONT_WEIGHT',
cssPropertyName: 'font-weight',
fieldVariableName: '--adf-header-font-weight',
formVariableName: '--adf-header-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-header-color',
formVariableName: '--adf-header-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'
}
]
};
18 changes: 18 additions & 0 deletions lib/core/src/lib/form/components/widgets/header/header.widget.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<div [hidden]="!element?.isGroup()" [style]="element | adfFieldStyle" class="adf-container-widget-header">
<h4 class="adf-container-widget-header__text" id="container-header"
[class.adf-collapsible]="element?.isCollapsible()">
<button *ngIf="element?.isCollapsible()"
mat-icon-button
class="mdl-button--icon"
(click)="onExpanderClicked(element)">
<mat-icon>{{ element?.isExpanded ? 'expand_more' : 'expand_less' }}</mat-icon>
</button>
<span (click)="onExpanderClicked(element)"
role="button"
tabindex="0"
(keyup.enter)="onExpanderClicked(element)"
[id]="'container-header-label-' + element?.id">
{{ element.name | translate }}
</span>
</h4>
</div>
13 changes: 13 additions & 0 deletions lib/core/src/lib/form/components/widgets/header/header.widget.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.adf-container-widget-header__text {
border-bottom: 1px solid rgba(0, 0, 0, 0.87);
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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { ContainerModel } from '../core/container.model';
import { FormFieldTypes } from '../core/form-field-types';
import { FormFieldModel } from '../core/form-field.model';
import { HeaderWidgetComponent } from './header.widget';

describe('HeaderWidgetComponent', () => {
let component: HeaderWidgetComponent;
let fixture: ComponentFixture<HeaderWidgetComponent>;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [HeaderWidgetComponent, TranslateModule.forRoot()]
}).compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(HeaderWidgetComponent);
component = fixture.componentInstance;
fixture.componentRef.setInput(
'element',
new ContainerModel(
new FormFieldModel(
{
onFormFieldChanged: () => {}
},
{
type: FormFieldTypes.GROUP,
name: 'test-name',
id: 'test-id',
params: { allowCollapse: true }
}
)
)
);
fixture.detectChanges();
});

it('should render the header widget template', () => {
const nativeElement = fixture.nativeElement;
expect(nativeElement.querySelector('.adf-container-widget-header')).toBeTruthy();
expect(nativeElement.querySelector('#container-header-label-test-id').textContent.trim()).toEqual('test-name');
});

it('should call onExpanderClicked method when expander is clicked', () => {
spyOn(component, 'onExpanderClicked');
const expander = fixture.nativeElement.querySelector('#container-header-label-test-id');
expander.click();
expect(component.onExpanderClicked).toHaveBeenCalled();
});
});
42 changes: 42 additions & 0 deletions lib/core/src/lib/form/components/widgets/header/header.widget.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { Component, Input, ViewEncapsulation } from '@angular/core';
import { ContainerModel } from '../core/container.model';
import { FieldStylePipe } from './../../../pipes/field-style.pipe';
import { MatIconModule } from '@angular/material/icon';
import { NgIf } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button';

@Component({
selector: 'adf-header-widget',
templateUrl: './header.widget.html',
styleUrls: ['./header.widget.scss'],
standalone: true,
encapsulation: ViewEncapsulation.None,
imports: [FieldStylePipe, MatIconModule, MatButtonModule, TranslateModule, NgIf]
})
export class HeaderWidgetComponent {
@Input() element: ContainerModel;

onExpanderClicked(content: ContainerModel) {
if (content?.isCollapsible()) {
content.isExpanded = !content.isExpanded;
}
}
}
19 changes: 19 additions & 0 deletions lib/core/src/lib/form/components/widgets/header/index.ts
Original file line number Diff line number Diff line change
@@ -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 './header.schema';
export * from './header.widget';
1 change: 1 addition & 0 deletions lib/core/src/lib/form/components/widgets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export * from './text/text-mask.component';

// widgets with schema
export * from './display-text';
export * from './header';

export const WIDGET_DIRECTIVES: any[] = [
UnknownWidgetComponent,
Expand Down
3 changes: 2 additions & 1 deletion lib/core/src/lib/form/pipes/field-style.pipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@

import { Pipe, PipeTransform } from '@angular/core';
import { FormFieldModel } from '../components/widgets/core/form-field.model';
import { ContainerModel } from '../components/widgets/core/container.model';

@Pipe({
name: 'adfFieldStyle',
standalone: true
})
export class FieldStylePipe implements PipeTransform {
transform(field: FormFieldModel): string {
transform(field: FormFieldModel | ContainerModel): string {
const theme = field.form?.theme?.widgets[field.type];
const style = field.style && theme?.[field.style];

Expand Down

0 comments on commit 166325d

Please sign in to comment.