[ACS-7377][ADF] Break Form dependency on Material Module (#9712)

* [ACS-7383] remove MaterialModule dependency, convert components to standalone

* [ACS-7383] remove MaterialModule dependency, convert components to standalone

* [ACS-7383] remove MaterialModule dependency, convert components to standalone

* [ACS-7383] update e2e tests

* [ACS-7383] update e2e tests

* [ACS-7383] update e2e tests
This commit is contained in:
tamaragruszka 2024-05-23 11:10:21 +02:00 committed by GitHub
parent 19fa86d1a1
commit 5f00acad68
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
57 changed files with 612 additions and 500 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

@ -15,11 +15,13 @@
* limitations under the License.
*/
import { FormOutcomeModel, FormFieldValidator, FormFieldModel, FormOutcomeEvent, FormModel } from './widgets';
import { EventEmitter, Input, Output, Directive } from '@angular/core';
import { Directive, EventEmitter, Input, Output } from '@angular/core';
import { ThemePalette } from '@angular/material/core';
import { FormFieldModel, FormFieldValidator, FormModel, FormOutcomeEvent, FormOutcomeModel } from './widgets';
@Directive()
@Directive({
standalone: true
})
// eslint-disable-next-line @angular-eslint/directive-class-suffix
export abstract class FormBaseComponent {
static SAVE_OUTCOME_ID: string = '$save';
@ -210,10 +212,14 @@ export abstract class FormBaseComponent {
}
abstract onRefreshClicked(): void;
abstract saveTaskForm(): void;
abstract completeTaskForm(outcome?: string): void;
protected abstract onTaskSaved(form: FormModel): void;
protected abstract storeFormAsMetadata(): void;
protected abstract onExecuteOutcome(outcome: FormOutcomeModel): boolean;
}

View File

@ -17,7 +17,8 @@
import { Directive } from '@angular/core';
/**
* Directive selectors without adf- prefix will be deprecated on 3.0.0
*/
@Directive({ selector: '[adf-form-custom-button], [form-custom-button]' }) export class StartFormCustomButtonDirective {}
@Directive({
selector: '[adf-form-custom-button]',
standalone: true
})
export class StartFormCustomButtonDirective {}

View File

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

View File

@ -16,12 +16,10 @@
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormRenderingService } from '../../services/form-rendering.service';
import { FormFieldModel, FormFieldTypes, FormModel } from '../widgets/core';
import { TextWidgetComponent, CheckboxWidgetComponent } from '../widgets';
import { FormFieldComponent } from './form-field.component';
import { FormBaseModule } from '../../form-base.module';
import { CoreTestingModule } from '../../../testing';
import { FormRenderingService } from '../../services/form-rendering.service';
import { CheckboxWidgetComponent, FormFieldModel, FormFieldTypes, FormModel, TextWidgetComponent } from '../widgets';
import { FormFieldComponent } from './form-field.component';
describe('FormFieldComponent', () => {
let fixture: ComponentFixture<FormFieldComponent>;
@ -32,7 +30,7 @@ describe('FormFieldComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule, FormBaseModule]
imports: [CoreTestingModule]
});
fixture = TestBed.createComponent(FormFieldComponent);
component = fixture.componentInstance;

View File

@ -28,27 +28,16 @@ import {
ViewContainerRef,
ViewEncapsulation
} from '@angular/core';
import { FormRenderingService } from '../../services/form-rendering.service';
import { WidgetVisibilityService } from '../../services/widget-visibility.service';
import { FormFieldModel } from '../widgets/core/form-field.model';
import { FormFieldModel } from '../widgets';
declare const adf: any;
@Component({
selector: 'adf-form-field',
template: `
<div
[id]="'field-' + field?.id + '-container'"
[style.visibility]="!field?.isVisible ? 'hidden' : 'visible'"
[style.display]="!field?.isVisible ? 'none' : 'block'"
[class.adf-focus]="focus"
(focusin)="focusToggle()"
(focusout)="focusToggle()"
>
<div #container></div>
</div>
`,
standalone: true,
templateUrl: './form-field.component.html',
encapsulation: ViewEncapsulation.None
})
export class FormFieldComponent implements OnInit, OnDestroy {
@ -109,6 +98,12 @@ export class FormFieldComponent implements OnInit, OnDestroy {
}
}
focusToggle() {
setTimeout(() => {
this.focus = !this.focus;
});
}
private getField(): FormFieldModel {
if (this.field?.params) {
const wrappedField = this.field.params.field;
@ -149,10 +144,4 @@ export class FormFieldComponent implements OnInit, OnDestroy {
return module.componentFactories.find((x) => x.componentType === decoratedCmp);
}
focusToggle() {
setTimeout(() => {
this.focus = !this.focus;
});
}
}

View File

@ -1,4 +1,5 @@
<div id="adf-form-renderer" class="{{ formDefinition.className }}" [ngClass]="{ 'adf-readonly-form': formDefinition.readOnly }">
<div id="adf-form-renderer" class="{{ formDefinition.className }}"
[ngClass]="{ 'adf-readonly-form': formDefinition.readOnly }">
<div *ngIf="formDefinition.hasTabs()">
<div *ngIf="hasTabs()" class="alfresco-tabs-widget">
<mat-tab-group>
@ -16,44 +17,36 @@
<ng-template #render let-fieldToRender="fieldToRender">
<div *ngFor="let currentRootElement of fieldToRender">
<div
*ngIf="currentRootElement.type === 'container' || currentRootElement.type === 'group'"
class="adf-container-widget"
[id]="'field-' + currentRootElement?.id + '-container'"
[hidden]="!currentRootElement?.isVisible"
>
<div *ngIf="currentRootElement.type === 'container' || currentRootElement.type === 'group'"
[id]="'field-' + currentRootElement?.id + '-container'"
class="adf-container-widget"
[hidden]="!currentRootElement?.isVisible">
<div [hidden]="!currentRootElement?.isGroup()" 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)"
>
<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
>
<span (click)="onExpanderClicked(currentRootElement)"
role="button"
tabindex="0"
(keyup.enter)="onExpanderClicked(currentRootElement)"
[id]="'container-header-label-' + currentRootElement?.id">
{{ currentRootElement.name | translate }}
</span>
</h4>
</div>
<div *ngIf="currentRootElement?.form?.enableFixedSpace; else fixingTemplate">
<div
class="adf-grid-list"
[ngStyle]="{ 'grid-template-columns': 'repeat(' + getNumberOfColumns(currentRootElement) + ', 1fr)' }"
*ngIf="currentRootElement?.isExpanded"
>
<div
class="adf-grid-list-item"
*ngFor="let field of getContainerFields(currentRootElement)"
[ngStyle]="{ 'grid-area': 'auto / auto / span ' + (field?.rowspan || 1) + ' / span ' + (field?.colspan || 1) }"
>
<div class="adf-grid-list"
[ngStyle]="{ 'grid-template-columns': 'repeat(' + getNumberOfColumns(currentRootElement) + ', 1fr)' }"
*ngIf="currentRootElement?.isExpanded">
<div class="adf-grid-list-item"
*ngFor="let field of getContainerFields(currentRootElement)"
[ngStyle]="{ 'grid-area': 'auto / auto / span ' + (field?.rowspan || 1) + ' / span ' + (field?.colspan || 1) }">
<adf-form-field *ngIf="field" [field]="field"></adf-form-field>
</div>
</div>
@ -61,11 +54,9 @@
<ng-template #fixingTemplate>
<section class="adf-grid-list-column-view" *ngIf="currentRootElement?.isExpanded">
<div
class="adf-grid-list-single-column"
*ngFor="let column of currentRootElement?.columns"
[style.width.%]="getColumnWith(currentRootElement)"
>
<div class="adf-grid-list-single-column"
*ngFor="let column of currentRootElement?.columns"
[style.width.%]="getColumnWith(currentRootElement)">
<div class="adf-grid-list-column-view-item" *ngFor="let field of column?.fields">
<adf-form-field *ngIf="field" [field]="field"></adf-form-field>
</div>

View File

@ -15,37 +15,36 @@
* limitations under the License.
*/
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CoreTestingModule } from '../../testing';
import { FormRulesManager } from '../models/form-rules.model';
import { FormRenderingService } from '../services/form-rendering.service';
import { FormService } from '../services/form.service';
import { FormRendererComponent } from './form-renderer.component';
import { FormBaseModule } from '../form-base.module';
import {
formDisplayValueVisibility,
formDisplayValueForm,
formDisplayValueCombinedVisibility,
formNumberWidgetVisibility,
formNumberTextJson,
formRequiredNumberWidget,
colspanForm,
numberNotRequiredForm,
numberMinMaxForm,
textWidgetVisibility,
numberWidgetVisibilityForm,
radioWidgetVisibilityForm,
customWidgetForm,
formDateVisibility,
customWidgetFormWithVisibility,
amountWidgetFormVisibilityMock,
checkboxWidgetFormVisibilityMock,
colspanForm,
customWidgetForm,
customWidgetFormWithVisibility,
dateWidgetFormVisibilityMock,
multilineWidgetFormVisibilityMock,
displayBigDecimalWidgetMock,
displayTextWidgetFormVisibilityMock,
displayBigDecimalWidgetMock
formDateVisibility,
formDisplayValueCombinedVisibility,
formDisplayValueForm,
formDisplayValueVisibility,
formNumberTextJson,
formNumberWidgetVisibility,
formRequiredNumberWidget,
multilineWidgetFormVisibilityMock,
numberMinMaxForm,
numberNotRequiredForm,
numberWidgetVisibilityForm,
radioWidgetVisibilityForm,
textWidgetVisibility
} from './mock/form-renderer.component.mock';
import { FormService } from '../services/form.service';
import { CoreTestingModule } from '../../testing';
import { FormRenderingService } from '../services/form-rendering.service';
import { TextWidgetComponent } from './widgets';
import { FormRulesManager } from '../models/form-rules.model';
const typeIntoInput = (targetInput: HTMLInputElement, message: string) => {
expect(targetInput).toBeTruthy('Expected input to set to be valid and not null');
@ -87,7 +86,7 @@ describe('Form Renderer Component', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule, FormBaseModule]
imports: [CoreTestingModule]
});
fixture = TestBed.createComponent(FormRendererComponent);
formRendererComponent = fixture.componentInstance;

View File

@ -15,15 +15,23 @@
* limitations under the License.
*/
import { Component, ViewEncapsulation, Input, OnDestroy, Injector, OnInit, Inject } from '@angular/core';
import { JsonPipe, NgClass, NgForOf, NgIf, NgStyle, NgTemplateOutlet } from '@angular/common';
import { Component, Inject, Injector, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { MatTabsModule } from '@angular/material/tabs';
import { TranslateModule } from '@ngx-translate/core';
import { FormRulesManager, formRulesManagerFactory } from '../models/form-rules.model';
import { FormModel } from './widgets/core/form.model';
import { ContainerModel, FormFieldModel, TabModel } from './widgets';
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';
@Component({
selector: 'adf-form-renderer',
standalone: true,
templateUrl: './form-renderer.component.html',
styleUrls: ['./form-renderer.component.scss'],
providers: [
@ -32,7 +40,21 @@ import { FORM_FIELD_MODEL_RENDER_MIDDLEWARE, FormFieldModelRenderMiddleware } fr
useFactory: formRulesManagerFactory,
deps: [Injector]
}
],
imports: [
NgIf,
MatTabsModule,
NgForOf,
NgTemplateOutlet,
TranslateModule,
MatButtonModule,
MatIconModule,
NgStyle,
FormFieldComponent,
MatSlideToggleModule,
FormsModule,
JsonPipe,
NgClass
],
encapsulation: ViewEncapsulation.None
})
@ -135,7 +157,7 @@ export class FormRendererComponent<T> implements OnInit, OnDestroy {
private runMiddlewareServices(): void {
const formFields = this.formDefinition.getFormFields();
formFields.forEach(field => {
formFields.forEach((field) => {
this.middlewareServices.forEach((middlewareService) => {
if (middlewareService.type === field.type) {
field = middlewareService.getParsedField(field);

View File

@ -1,14 +1,10 @@
<div
class="adf-inplace-input-container"
[ngClass]="{'adf-inplace-input-container-error': control.invalid && control.touched}"
>
<div class="adf-inplace-input-container"
[ngClass]="{'adf-inplace-input-container-error': control.invalid && control.touched}">
<mat-form-field class="adf-inplace-input-mat-form-field">
<input
matInput
[formControl]="control"
class="adf-inplace-input"
data-automation-id="adf-inplace-input"
>
<input matInput
[formControl]="control"
class="adf-inplace-input"
data-automation-id="adf-inplace-input">
<mat-label data-automation-id="adf-inplace-input-label">
<ng-content select="[label]"></ng-content>

View File

@ -17,7 +17,7 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UntypedFormControl } from '@angular/forms';
import { CoreTestingModule } from '../../../testing/core.testing.module';
import { CoreTestingModule } from '../../../testing';
import { InplaceFormInputComponent } from './inplace-form-input.component';
describe('InplaceFormInputComponent', () => {
@ -27,8 +27,7 @@ describe('InplaceFormInputComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [CoreTestingModule],
declarations: [InplaceFormInputComponent]
imports: [CoreTestingModule, InplaceFormInputComponent]
}).compileComponents();
});

View File

@ -15,17 +15,18 @@
* limitations under the License.
*/
import {
Component,
Input,
ViewEncapsulation
} from '@angular/core';
import { UntypedFormControl } from '@angular/forms';
import { NgClass } from '@angular/common';
import { Component, Input, ViewEncapsulation } from '@angular/core';
import { ReactiveFormsModule, UntypedFormControl } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
@Component({
selector: 'adf-inplace-form-input',
standalone: true,
templateUrl: './inplace-form-input.component.html',
styleUrls: ['./inplace-form-input.component.scss'],
imports: [MatFormFieldModule, ReactiveFormsModule, MatInputModule, NgClass],
encapsulation: ViewEncapsulation.None
})
export class InplaceFormInputComponent {

View File

@ -16,10 +16,11 @@
*/
import { InjectionToken } from '@angular/core';
import { FormFieldModel } from '../../components/widgets';
import { FormFieldModel } from '../widgets';
export interface FormFieldModelRenderMiddleware {
type: string;
getParsedField(field: FormFieldModel): FormFieldModel;
}

View File

@ -1,21 +1,33 @@
<div class="adf-amount-widget__container adf-amount-widget {{field.className}}"
[class.adf-invalid]="!field.isValid && isTouched()" [class.adf-readonly]="field.readOnly"
[class.adf-left-label-input-container]="field.leftLabels">
<div>
<label class="adf-label"
[class.adf-left-label]="field.leftLabels" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
</div>
<div>
<mat-form-field class="adf-amount-widget__input" [hideRequiredMarker]="true">
<span matPrefix class="adf-amount-widget__prefix-spacing">{{ currency }} &nbsp;</span>
<input matInput [matTooltip]="field.tooltip" matTooltipPosition="above" matTooltipShowDelay="1000"
class="adf-input" type="text" [id]="field.id" [required]="isRequired()"
[placeholder]="placeholder" [value]="field.value" [(ngModel)]="field.value"
(ngModelChange)="onFieldChanged(field)" [disabled]="field.readOnly"
(blur)="markAsTouched()">
</mat-form-field>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
</div>
</div>
<div class="adf-amount-widget__container adf-amount-widget {{ field.className }}"
[class.adf-invalid]="!field.isValid && isTouched()"
[class.adf-readonly]="field.readOnly"
[class.adf-left-label-input-container]="field.leftLabels">
<div>
<label class="adf-label"
[class.adf-left-label]="field.leftLabels"
[attr.for]="field.id">
{{ field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
</div>
<div>
<mat-form-field class="adf-amount-widget__input" [hideRequiredMarker]="true">
<span matPrefix class="adf-amount-widget__prefix-spacing">{{ currency }} &nbsp;</span>
<input matInput
[matTooltip]="field.tooltip"
matTooltipPosition="above"
[matTooltipShowDelay]="1000"
class="adf-input"
type="text"
[id]="field.id"
[required]="isRequired()"
[placeholder]="placeholder"
[value]="field.value"
[(ngModel)]="field.value"
(ngModelChange)="onFieldChanged(field)"
[disabled]="field.readOnly"
(blur)="markAsTouched()">
</mat-form-field>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
</div>
</div>

View File

@ -15,18 +15,15 @@
* limitations under the License.
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormFieldModel } from '../core/form-field.model';
import { AmountWidgetComponent, ADF_AMOUNT_SETTINGS } from './amount.widget';
import { FormBaseModule } from '../../../form-base.module';
import { FormFieldTypes } from '../core/form-field-types';
import { CoreTestingModule } from '../../../../testing/core.testing.module';
import { FormModel } from '../core/form.model';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatTooltipHarness } from '@angular/material/tooltip/testing';
import { MatInputHarness } from '@angular/material/input/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatFormFieldHarness } from '@angular/material/form-field/testing';
import { MatInputHarness } from '@angular/material/input/testing';
import { MatTooltipHarness } from '@angular/material/tooltip/testing';
import { CoreTestingModule } from '../../../../testing';
import { FormFieldModel, FormFieldTypes, FormModel } from '../core';
import { ADF_AMOUNT_SETTINGS, AmountWidgetComponent } from './amount.widget';
describe('AmountWidgetComponent', () => {
let loader: HarnessLoader;
@ -36,7 +33,7 @@ describe('AmountWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule, FormBaseModule]
imports: [CoreTestingModule]
});
fixture = TestBed.createComponent(AmountWidgetComponent);
widget = fixture.componentInstance;
@ -144,7 +141,7 @@ describe('AmountWidgetComponent - rendering', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule, FormBaseModule]
imports: [CoreTestingModule]
});
fixture = TestBed.createComponent(AmountWidgetComponent);
widget = fixture.componentInstance;
@ -203,7 +200,7 @@ describe('AmountWidgetComponent - rendering', () => {
expect(await field.getPrefixText()).toBe('$');
const widgetLabel = fixture.nativeElement.querySelector('label.adf-label');
expect(widgetLabel.textContent).toBe('Test Amount*');
expect(widgetLabel.textContent.trim()).toBe('Test Amount*');
expect(widget.field.isValid).toBe(false);
const input = await loader.getHarness(MatInputHarness);
@ -239,7 +236,7 @@ describe('AmountWidgetComponent - rendering', () => {
await fixture.whenStable();
const widgetLabel = fixture.nativeElement.querySelector('label.adf-label');
expect(widgetLabel.textContent).toBe('Test Amount*');
expect(widgetLabel.textContent.trim()).toBe('Test Amount*');
const field = await loader.getHarness(MatFormFieldHarness);
expect(await field.getPrefixText()).toBe('£');
@ -339,7 +336,7 @@ describe('AmountWidgetComponent settings', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule, FormBaseModule],
imports: [CoreTestingModule],
providers: [
{
provide: ADF_AMOUNT_SETTINGS,

View File

@ -17,8 +17,15 @@
/* eslint-disable @angular-eslint/component-selector */
import { NgIf } from '@angular/common';
import { Component, OnInit, ViewEncapsulation, InjectionToken, Inject, Optional } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { FormService } from '../../../services/form.service';
import { ErrorWidgetComponent } from '../error/error.component';
import { WidgetComponent } from '../widget.component';
export interface AmountWidgetSettings {
@ -29,6 +36,7 @@ export const ADF_AMOUNT_SETTINGS = new InjectionToken<AmountWidgetSettings>('adf
@Component({
selector: 'amount-widget',
standalone: true,
templateUrl: './amount.widget.html',
styleUrls: ['./amount.widget.scss'],
host: {
@ -42,6 +50,7 @@ export const ADF_AMOUNT_SETTINGS = new InjectionToken<AmountWidgetSettings>('adf
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
imports: [MatFormFieldModule, MatTooltipModule, MatInputModule, FormsModule, ErrorWidgetComponent, TranslateModule, NgIf],
encapsulation: ViewEncapsulation.None
})
export class AmountWidgetComponent extends WidgetComponent implements OnInit {

View File

@ -1,7 +1,13 @@
<div class="adf-base-viewer-widget {{field.className}}" [class.adf-invalid]="!field.isValid"
[class.adf-readonly]="field.readOnly">
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk"
*ngIf="isRequired()">*</span></label>
<adf-viewer [urlFile]="field.value.urlFile" [blobFile]="field.value.blobFile" [fileName]="field.value.fileName" [showViewer]="field.value?.blobFile || field.value?.urlFile" [allowGoBack]="false"></adf-viewer>
<div class="adf-base-viewer-widget {{ field.className }}"
[class.adf-invalid]="!field.isValid"
[class.adf-readonly]="field.readOnly">
<label class="adf-label" [attr.for]="field.id">
{{ field.name | translate }}
<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
<adf-viewer [urlFile]="field.value.urlFile"
[blobFile]="field.value.blobFile"
[fileName]="field.value.fileName"
[showViewer]="field.value?.blobFile || field.value?.urlFile"
[allowGoBack]="false"></adf-viewer>
<error-widget [error]="field.validationSummary"></error-widget>
</div>

View File

@ -15,12 +15,11 @@
* limitations under the License.
*/
import { FormModel } from '../core/form.model';
import { FormFieldModel } from '../core/form-field.model';
import { FormService } from '../../../services/form.service';
import { CoreTestingModule } from '../../../../testing/core.testing.module';
import { BaseViewerWidgetComponent } from './base-viewer.widget';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CoreTestingModule } from '../../../../testing';
import { FormService } from '../../../services/form.service';
import { FormFieldModel, FormModel } from '../core';
import { BaseViewerWidgetComponent } from './base-viewer.widget';
describe('BaseViewerWidgetComponent', () => {
const fakeForm = new FormModel();
@ -45,8 +44,7 @@ describe('BaseViewerWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule],
declarations: [BaseViewerWidgetComponent],
imports: [CoreTestingModule, BaseViewerWidgetComponent],
providers: [{ provide: FormService, useValue: formServiceStub }]
});

View File

@ -15,14 +15,19 @@
* limitations under the License.
*/
import { NgIf } from '@angular/common';
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { ViewerComponent } from '../../../../viewer';
import { FormService } from '../../../services/form.service';
import { ErrorWidgetComponent } from '../error/error.component';
import { WidgetComponent } from '../widget.component';
/* eslint-disable @angular-eslint/component-selector */
@Component({
selector: 'base-viewer-widget',
standalone: true,
templateUrl: './base-viewer.widget.html',
styleUrls: ['./base-viewer.widget.scss'],
host: {
@ -36,6 +41,7 @@ import { WidgetComponent } from '../widget.component';
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
imports: [NgIf, TranslateModule, ViewerComponent, ErrorWidgetComponent],
encapsulation: ViewEncapsulation.None
})
export class BaseViewerWidgetComponent extends WidgetComponent implements OnInit {

View File

@ -1,19 +1,19 @@
<div [ngClass]="field.className"
[class.adf-invalid]="!field.isValid && isTouched()">
<mat-checkbox
[id]="field.id"
color="primary"
[required]="isRequired()"
[disabled]="field.readOnly || readOnly"
[(ngModel)]="field.value"
(ngModelChange)="onFieldChanged(field)"
[matTooltip]="field.tooltip"
(click)="markAsTouched()"
matTooltipPosition="right"
matTooltipShowDelay="1000">
{{field.name | translate }}
<span class="adf-asterisk" *ngIf="isRequired()" >*</span>
<mat-checkbox [id]="field.id"
color="primary"
[required]="isRequired()"
[disabled]="field.readOnly || readOnly"
[(ngModel)]="field.value"
(ngModelChange)="onFieldChanged(field)"
[matTooltip]="field.tooltip"
(click)="markAsTouched()"
matTooltipPosition="right"
[matTooltipShowDelay]="1000">
{{ field.name | translate }}
<span class="adf-asterisk" *ngIf="isRequired()">*</span>
</mat-checkbox>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
</div>

View File

@ -15,21 +15,18 @@
* limitations under the License.
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormFieldTypes } from '../core/form-field-types';
import { FormFieldModel } from '../core/form-field.model';
import { FormModel } from '../core/form.model';
import { CheckboxWidgetComponent } from './checkbox.widget';
import { FormBaseModule } from '../../../form-base.module';
import { TranslateLoader } from '@ngx-translate/core';
import { TranslateLoaderService } from '../../../../translation/translate-loader.service';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { CoreTestingModule } from '../../../../testing';
import { MatTooltipModule } from '@angular/material/tooltip';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatCheckboxHarness } from '@angular/material/checkbox/testing';
import { MatTooltipModule } from '@angular/material/tooltip';
import { MatTooltipHarness } from '@angular/material/tooltip/testing';
import { TranslateLoader } from '@ngx-translate/core';
import { CoreTestingModule } from '../../../../testing';
import { TranslateLoaderService } from '../../../../translation';
import { FormFieldModel, FormFieldTypes, FormModel } from '../core';
import { CheckboxWidgetComponent } from './checkbox.widget';
describe('CheckboxWidgetComponent', () => {
let loader: HarnessLoader;
@ -39,7 +36,7 @@ describe('CheckboxWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule, FormBaseModule, MatCheckboxModule, MatTooltipModule],
imports: [CoreTestingModule, MatCheckboxModule, MatTooltipModule],
providers: [{ provide: TranslateLoader, useClass: TranslateLoaderService }]
});
fixture = TestBed.createComponent(CheckboxWidgetComponent);

View File

@ -17,12 +17,19 @@
/* eslint-disable @angular-eslint/component-selector, @angular-eslint/no-input-rename */
import { NgClass, NgIf } from '@angular/common';
import { Component, ViewEncapsulation } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { FormService } from '../../../services/form.service';
import { ErrorWidgetComponent } from '../error/error.component';
import { WidgetComponent } from '../widget.component';
@Component({
selector: 'checkbox-widget',
standalone: true,
templateUrl: './checkbox.widget.html',
host: {
'(click)': 'event($event)',
@ -35,6 +42,7 @@ import { WidgetComponent } from '../widget.component';
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
imports: [NgClass, MatCheckboxModule, FormsModule, TranslateModule, MatTooltipModule, ErrorWidgetComponent, NgIf],
encapsulation: ViewEncapsulation.None
})
export class CheckboxWidgetComponent extends WidgetComponent {

View File

@ -1,36 +1,47 @@
<div class="{{field.className}}" id="data-time-widget" [class.adf-invalid]="!field.isValid && isTouched()" [class.adf-left-label-input-container]="field.leftLabels">
<div class="{{ field.className }}"
id="data-time-widget"
[class.adf-invalid]="!field.isValid && isTouched()"
[class.adf-left-label-input-container]="field.leftLabels">
<div *ngIf="field.leftLabels">
<label class="adf-label adf-left-label" [attr.for]="field.id">{{field.name | translate }} ({{field.dateDisplayFormat}})<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
</div>
<label class="adf-label adf-left-label" [attr.for]="field.id">
{{ field.name | translate }} ({{ field.dateDisplayFormat }})<span class="adf-asterisk" *ngIf="isRequired()">*</span>
</label>
</div>
<div>
<mat-form-field class="adf-date-time-widget" [class.adf-left-label-input-datepicker]="field.leftLabels" [hideRequiredMarker]="true">
<label class="adf-label" *ngIf="!field.leftLabels" [attr.for]="field.id">{{field.name | translate }} ({{field.dateDisplayFormat}})<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
<mat-form-field class="adf-date-time-widget"
[class.adf-left-label-input-datepicker]="field.leftLabels"
[hideRequiredMarker]="true">
<label class="adf-label" *ngIf="!field.leftLabels" [attr.for]="field.id">
{{ field.name | translate }} ({{ field.dateDisplayFormat }})<span class="adf-asterisk" *ngIf="isRequired()">*</span>
</label>
<input matInput
[matDatetimepicker]="datetimePicker"
[id]="field.id"
[(ngModel)]="value"
[required]="isRequired()"
[disabled]="field.readOnly"
(change)="onValueChanged($event)"
(dateChange)="onDateChanged($event)"
(keydown.enter)="datetimePicker.open()"
[placeholder]="field.placeholder"
[matTooltip]="field.tooltip"
(blur)="markAsTouched()"
matTooltipPosition="above"
matTooltipShowDelay="1000"
[min]="minDate"
[max]="maxDate">
<mat-datetimepicker-toggle matSuffix [for]="datetimePicker" [disabled]="field.readOnly"></mat-datetimepicker-toggle>
[matDatetimepicker]="datetimePicker"
[id]="field.id"
[(ngModel)]="value"
[required]="isRequired()"
[disabled]="field.readOnly"
(change)="onValueChanged($event)"
(dateChange)="onDateChanged($event)"
(keydown.enter)="datetimePicker.open()"
[placeholder]="field.placeholder"
[matTooltip]="field.tooltip"
(blur)="markAsTouched()"
matTooltipPosition="above"
[matTooltipShowDelay]="1000"
[min]="minDate"
[max]="maxDate">
<mat-datetimepicker-toggle matSuffix [for]="datetimePicker"
[disabled]="field.readOnly"></mat-datetimepicker-toggle>
</mat-form-field>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
<mat-datetimepicker #datetimePicker
data-automation-id="adf-date-time-widget-picker"
type="datetime"
[touchUi]="true"
[timeInterval]="5"
[disabled]="field.readOnly">
data-automation-id="adf-date-time-widget-picker"
type="datetime"
[touchUi]="true"
[timeInterval]="5"
[disabled]="field.readOnly">
</mat-datetimepicker>
</div>
</div>

View File

@ -15,18 +15,15 @@
* limitations under the License.
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormFieldModel } from '../core/form-field.model';
import { FormModel } from '../core/form.model';
import { DateTimeWidgetComponent } from './date-time.widget';
import { CoreTestingModule } from '../../../../testing/core.testing.module';
import { MatTooltipModule } from '@angular/material/tooltip';
import { FormFieldTypes } from '../core/form-field-types';
import { DateFieldValidator, DateTimeFieldValidator } from '../core';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatTooltipHarness } from '@angular/material/tooltip/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatInputHarness } from '@angular/material/input/testing';
import { MatTooltipModule } from '@angular/material/tooltip';
import { MatTooltipHarness } from '@angular/material/tooltip/testing';
import { CoreTestingModule } from '../../../../testing';
import { DateFieldValidator, DateTimeFieldValidator, FormFieldModel, FormFieldTypes, FormModel } from '../core';
import { DateTimeWidgetComponent } from './date-time.widget';
describe('DateTimeWidgetComponent', () => {
let loader: HarnessLoader;

View File

@ -17,26 +17,42 @@
/* eslint-disable @angular-eslint/component-selector */
import { NgIf } from '@angular/common';
import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
import { DatetimeAdapter, MAT_DATETIME_FORMATS, MatDatetimepickerInputEvent } from '@mat-datetimepicker/core';
import { FormService } from '../../../services/form.service';
import { WidgetComponent } from '../widget.component';
import { ADF_DATE_FORMATS, AdfDateFnsAdapter } from '../../../../common/utils/date-fns-adapter';
import { ADF_DATETIME_FORMATS, AdfDateTimeFnsAdapter } from '../../../../common/utils/datetime-fns-adapter';
import { DateFnsUtils } from '../../../../common';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatTooltipModule } from '@angular/material/tooltip';
import { DatetimeAdapter, MAT_DATETIME_FORMATS, MatDatetimepickerInputEvent, MatDatetimepickerModule } from '@mat-datetimepicker/core';
import { TranslateModule } from '@ngx-translate/core';
import { isValid } from 'date-fns';
import { ADF_DATE_FORMATS, ADF_DATETIME_FORMATS, AdfDateFnsAdapter, AdfDateTimeFnsAdapter, DateFnsUtils } from '../../../../common';
import { FormService } from '../../../services/form.service';
import { ErrorWidgetComponent } from '../error/error.component';
import { WidgetComponent } from '../widget.component';
@Component({
selector: 'date-time-widget',
standalone: true,
providers: [
{ provide: MAT_DATE_FORMATS, useValue: ADF_DATE_FORMATS },
{ provide: MAT_DATETIME_FORMATS, useValue: ADF_DATETIME_FORMATS },
{ provide: DateAdapter, useClass: AdfDateFnsAdapter },
{ provide: DatetimeAdapter, useClass: AdfDateTimeFnsAdapter }
],
selector: 'date-time-widget',
templateUrl: './date-time.widget.html',
styleUrls: ['./date-time.widget.scss'],
imports: [
NgIf,
TranslateModule,
MatFormFieldModule,
MatInputModule,
MatDatetimepickerModule,
FormsModule,
MatTooltipModule,
ErrorWidgetComponent
],
encapsulation: ViewEncapsulation.None
})
export class DateTimeWidgetComponent extends WidgetComponent implements OnInit {
@ -46,9 +62,7 @@ export class DateTimeWidgetComponent extends WidgetComponent implements OnInit {
@Input()
value: any = null;
constructor(public formService: FormService,
private dateAdapter: DateAdapter<Date>,
private dateTimeAdapter: DatetimeAdapter<Date>) {
constructor(public formService: FormService, private dateAdapter: DateAdapter<Date>, private dateTimeAdapter: DatetimeAdapter<Date>) {
super(formService);
}

View File

@ -1,25 +1,28 @@
<div class="{{field.className}}" id="data-widget" [class.adf-invalid]="!field.isValid && isTouched()">
<div class="{{ field.className }}" id="data-widget" [class.adf-invalid]="!field.isValid && isTouched()">
<mat-form-field [floatLabel]="'always'" class="adf-date-widget">
<mat-label class="adf-label"
[id]="field.id + '-label'"
[attr.for]="field.id"
>{{field.name | translate }} ({{field.dateDisplayFormat}})</mat-label>
<input matInput [matDatepicker]="datePicker"
[id]="field.id"
[(ngModel)]="value"
[required]="field.required"
[placeholder]="field.placeholder"
[min]="minDate"
[max]="maxDate"
[disabled]="field.readOnly"
(dateChange)="onDateChange($event)"
(blur)="markAsTouched()">
[id]="field.id + '-label'"
[attr.for]="field.id">
{{ field.name | translate }} ({{ field.dateDisplayFormat }})
</mat-label>
<input matInput
[matDatepicker]="datePicker"
[id]="field.id"
[(ngModel)]="value"
[required]="field.required"
[placeholder]="field.placeholder"
[min]="minDate"
[max]="maxDate"
[disabled]="field.readOnly"
(dateChange)="onDateChange($event)"
(blur)="markAsTouched()">
<mat-datepicker-toggle matSuffix [for]="datePicker" [disabled]="field.readOnly"></mat-datepicker-toggle>
<mat-datepicker #datePicker
[startAt]="startAt"
[disabled]="field.readOnly">
[startAt]="startAt"
[disabled]="field.readOnly">
</mat-datepicker>
</mat-form-field>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
</div>

View File

@ -17,12 +17,9 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DateAdapter } from '@angular/material/core';
import { FormFieldModel } from '../core/form-field.model';
import { FormModel } from '../core/form.model';
import { CoreTestingModule } from '../../../../testing';
import { DateFieldValidator, FormFieldModel, FormFieldTypes, FormModel, MaxDateFieldValidator, MinDateFieldValidator } from '../core';
import { DateWidgetComponent } from './date.widget';
import { CoreTestingModule } from '../../../../testing/core.testing.module';
import { FormFieldTypes } from '../core/form-field-types';
import { DateFieldValidator, MaxDateFieldValidator, MinDateFieldValidator } from '../core/form-field-validator';
describe('DateWidgetComponent', () => {
let widget: DateWidgetComponent;

View File

@ -17,16 +17,23 @@
/* eslint-disable @angular-eslint/component-selector */
import { Component, OnInit, ViewEncapsulation, OnDestroy, Input } from '@angular/core';
import { NgIf } from '@angular/common';
import { Component, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
import { FormService } from '../../../services/form.service';
import { WidgetComponent } from '../widget.component';
import { MatDatepickerInputEvent, MatDatepickerModule } from '@angular/material/datepicker';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { TranslateModule } from '@ngx-translate/core';
import { Subject } from 'rxjs';
import { MatDatepickerInputEvent } from '@angular/material/datepicker';
import { ADF_DATE_FORMATS, AdfDateFnsAdapter } from '../../../../common/utils/date-fns-adapter';
import { ADF_DATE_FORMATS, AdfDateFnsAdapter } from '../../../../common';
import { FormService } from '../../../services/form.service';
import { ErrorWidgetComponent } from '../error/error.component';
import { WidgetComponent } from '../widget.component';
@Component({
selector: 'date-widget',
standalone: true,
providers: [
{ provide: MAT_DATE_FORMATS, useValue: ADF_DATE_FORMATS },
{ provide: DateAdapter, useClass: AdfDateFnsAdapter }
@ -43,6 +50,7 @@ import { ADF_DATE_FORMATS, AdfDateFnsAdapter } from '../../../../common/utils/da
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
imports: [MatFormFieldModule, TranslateModule, MatInputModule, MatDatepickerModule, FormsModule, ErrorWidgetComponent, NgIf],
encapsulation: ViewEncapsulation.None
})
export class DateWidgetComponent extends WidgetComponent implements OnInit, OnDestroy {

View File

@ -1,9 +1,7 @@
<div
class="adf-textfield adf-decimal-widget {{ field.className }}"
[class.adf-invalid]="!field.isValid && isTouched()"
[class.adf-readonly]="field.readOnly"
[class.adf-left-label-input-container]="field.leftLabels"
>
<div class="adf-textfield adf-decimal-widget {{ field.className }}"
[class.adf-invalid]="!field.isValid && isTouched()"
[class.adf-readonly]="field.readOnly"
[class.adf-left-label-input-container]="field.leftLabels">
<div *ngIf="field.leftLabels">
<label class="adf-label adf-left-label" [attr.for]="field.id">
{{ field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span>
@ -16,28 +14,25 @@
{{ field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span>
</label>
<input
matInput
class="adf-input"
type="text"
pattern="-?[0-9]*(\.[0-9]*)?"
[id]="field.id"
[required]="isRequired()"
[(ngModel)]="field.value"
(ngModelChange)="onFieldChanged(field)"
[disabled]="field.readOnly"
[placeholder]="field.placeholder"
[matTooltip]="field.tooltip"
(blur)="markAsTouched()"
matTooltipPosition="above"
matTooltipShowDelay="1000"
/>
<input matInput
class="adf-input"
type="text"
pattern="-?[0-9]*(\.[0-9]*)?"
[id]="field.id"
[required]="isRequired()"
[(ngModel)]="field.value"
(ngModelChange)="onFieldChanged(field)"
[disabled]="field.readOnly"
[placeholder]="field.placeholder"
[matTooltip]="field.tooltip"
(blur)="markAsTouched()"
matTooltipPosition="above"
[matTooltipShowDelay]="1000" />
</mat-form-field>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget
*ngIf="isInvalidFieldRequired() && isTouched()"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}">
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}">
</error-widget>
</div>
</div>

View File

@ -15,18 +15,17 @@
* limitations under the License.
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { HarnessLoader } from '@angular/cdk/testing';
import { DecimalWidgetComponent } from './decimal.component';
import { FormService } from '../../../services/form.service';
import { FormFieldModel, FormFieldTypes, FormModel } from '../core';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatInputModule } from '@angular/material/input';
import { MatInputHarness } from '@angular/material/input/testing';
import { MatTooltipHarness } from '@angular/material/tooltip/testing';
import { MatInputModule } from '@angular/material/input';
import { CoreTestingModule } from '../../../../testing';
import { FormsModule } from '@angular/forms';
import { FormService } from '../../../services/form.service';
import { FormFieldModel, FormFieldTypes, FormModel } from '../core';
import { DecimalWidgetComponent } from './decimal.component';
describe('DecimalComponent', () => {
let loader: HarnessLoader;
@ -36,8 +35,7 @@ describe('DecimalComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [CoreTestingModule, MatInputModule, FormsModule],
declarations: [DecimalWidgetComponent],
imports: [CoreTestingModule, MatInputModule, DecimalWidgetComponent],
providers: [FormService]
}).compileComponents();

View File

@ -15,12 +15,20 @@
* limitations under the License.
*/
import { NgIf } from '@angular/common';
import { Component, ViewEncapsulation } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { FormService } from '../../../services/form.service';
import { ErrorWidgetComponent } from '../error/error.component';
import { WidgetComponent } from '../widget.component';
@Component({
selector: 'adf-decimal',
standalone: true,
templateUrl: './decimal.component.html',
styleUrls: ['./decimal.component.scss'],
host: {
@ -34,6 +42,7 @@ import { WidgetComponent } from '../widget.component';
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
imports: [NgIf, TranslateModule, MatFormFieldModule, MatInputModule, FormsModule, MatTooltipModule, ErrorWidgetComponent],
encapsulation: ViewEncapsulation.None
})
export class DecimalWidgetComponent extends WidgetComponent {

View File

@ -1,2 +1,6 @@
<div [matTooltip]="field.tooltip" matTooltipPosition="above" matTooltipShowDelay="1000"
class="adf-display-text-widget {{field.className}}">{{field.value | translate}}</div>
<div [matTooltip]="field.tooltip"
matTooltipPosition="above"
[matTooltipShowDelay]="1000"
class="adf-display-text-widget {{ field.className }}">
{{ field.value | translate }}
</div>

View File

@ -15,14 +15,17 @@
* limitations under the License.
*/
/* eslint-disable @angular-eslint/component-selector */
/* eslint-disable @angular-eslint/component-selector */
import { Component, ViewEncapsulation } from '@angular/core';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { FormService } from '../../../services/form.service';
import { WidgetComponent } from '../widget.component';
@Component({
selector: 'display-text-widget',
standalone: true,
templateUrl: './display-text.widget.html',
styleUrls: ['./display-text.widget.scss'],
host: {
@ -36,12 +39,11 @@ import { WidgetComponent } from '../widget.component';
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
imports: [MatTooltipModule, TranslateModule],
encapsulation: ViewEncapsulation.None
})
export class DisplayTextWidgetComponent extends WidgetComponent {
constructor(public formService: FormService) {
super(formService);
super(formService);
}
}

View File

@ -1,10 +1,10 @@
<div class="adf-error-container">
<div *ngIf="error?.isActive()" [@transitionMessages]="subscriptAnimationState" class="adf-error">
<mat-icon class="adf-error-icon">error_outline</mat-icon>
<div class="adf-error-text">{{error.message | translate:translateParameters}}</div>
<div class="adf-error-text">{{ error.message | translate:translateParameters }}</div>
</div>
<div *ngIf="required" [@transitionMessages]="subscriptAnimationState" class="adf-error">
<mat-icon class="adf-error-icon">error_outline</mat-icon>
<div class="adf-error-text">{{required}}</div>
<div class="adf-error-text">{{ required }}</div>
</div>
</div>

View File

@ -17,28 +17,25 @@
import { SimpleChange, SimpleChanges } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ErrorWidgetComponent } from './error.component';
import { CoreTestingModule } from '../../../../testing';
import { ErrorMessageModel } from '../index';
import { ErrorMessageModel } from '../core';
import { ErrorWidgetComponent } from './error.component';
describe('ErrorWidgetComponent', () => {
let widget: ErrorWidgetComponent;
let fixture: ComponentFixture<ErrorWidgetComponent>;
let element: HTMLElement;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
CoreTestingModule
]
imports: [CoreTestingModule]
});
fixture = TestBed.createComponent(ErrorWidgetComponent);
widget = fixture.componentInstance;
element = fixture.nativeElement;
});
const errorMessage: string = 'fake-error';
const errorMessageModel: ErrorMessageModel = new ErrorMessageModel({message: errorMessage});
const errorMessageModel: ErrorMessageModel = new ErrorMessageModel({ message: errorMessage });
const errorChanges: SimpleChanges = {
error: new SimpleChange(errorMessageModel, errorMessageModel, false)
};

View File

@ -18,19 +18,29 @@
/* eslint-disable @angular-eslint/component-selector */
import { animate, state, style, transition, trigger } from '@angular/animations';
import { NgIf } from '@angular/common';
import { Component, Input, OnChanges, SimpleChanges, ViewEncapsulation } from '@angular/core';
import { ErrorMessageModel } from '../core';
import { MatIconModule } from '@angular/material/icon';
import { TranslateModule } from '@ngx-translate/core';
import { FormService } from '../../../services/form.service';
import { ErrorMessageModel } from '../core';
import { WidgetComponent } from '../widget.component';
@Component({
selector: 'error-widget',
standalone: true,
templateUrl: './error.component.html',
styleUrls: ['./error.component.scss'],
animations: [
trigger('transitionMessages', [
state('enter', style({ opacity: 1, transform: 'translateY(0%)' })),
transition('void => enter', [style({ opacity: 0, transform: 'translateY(-100%)' }), animate('300ms cubic-bezier(0.55, 0, 0.55, 0.2)')])
transition('void => enter', [
style({
opacity: 0,
transform: 'translateY(-100%)'
}),
animate('300ms cubic-bezier(0.55, 0, 0.55, 0.2)')
])
])
],
host: {
@ -44,6 +54,7 @@ import { WidgetComponent } from '../widget.component';
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
imports: [NgIf, MatIconModule, TranslateModule],
encapsulation: ViewEncapsulation.None
})
export class ErrorWidgetComponent extends WidgetComponent implements OnChanges {

View File

@ -1,7 +1,10 @@
<div class="adf-hyperlink-widget {{field.className}}">
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk"
*ngIf="isRequired()">*</span></label>
<div [matTooltip]="field.tooltip" matTooltipPosition="above" matTooltipShowDelay="1000">
<a [href]="linkUrl" target="_blank" rel="nofollow">{{linkText}}</a>
<label class="adf-label" [attr.for]="field.id">
{{ field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span>
</label>
<div [matTooltip]="field.tooltip"
matTooltipPosition="above"
[matTooltipShowDelay]="1000">
<a [href]="linkUrl" target="_blank" rel="nofollow">{{ linkText }}</a>
</div>
</div>

View File

@ -16,12 +16,10 @@
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormFieldTypes } from '../core/form-field-types';
import { FormFieldModel } from '../core/form-field.model';
import { FormModel } from '../core/form.model';
import { HyperlinkWidgetComponent } from './hyperlink.widget';
import { CoreTestingModule } from '../../../../testing';
import { MatTooltipModule } from '@angular/material/tooltip';
import { CoreTestingModule } from '../../../../testing';
import { FormFieldModel, FormFieldTypes, FormModel } from '../core';
import { HyperlinkWidgetComponent } from './hyperlink.widget';
describe('HyperlinkWidgetComponent', () => {
let widget: HyperlinkWidgetComponent;

View File

@ -17,13 +17,17 @@
/* eslint-disable @angular-eslint/component-selector */
import { NgIf } from '@angular/common';
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { FormService } from '../../../services/form.service';
import { WidgetComponent } from '../widget.component';
import { FormFieldModel } from '../core';
import { WidgetComponent } from '../widget.component';
@Component({
selector: 'hyperlink-widget',
standalone: true,
templateUrl: './hyperlink.widget.html',
styleUrls: ['./hyperlink.widget.scss'],
host: {
@ -37,10 +41,10 @@ import { FormFieldModel } from '../core';
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
imports: [TranslateModule, MatTooltipModule, NgIf],
encapsulation: ViewEncapsulation.None
})
export class HyperlinkWidgetComponent extends WidgetComponent implements OnInit {
static DEFAULT_HYPERLINK_URL: string = '#';
static DEFAULT_HYPERLINK_SCHEME: string = 'http://';

View File

@ -16,15 +16,15 @@
*/
import { Component, ViewEncapsulation } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatDialog } from '@angular/material/dialog';
import { EditJsonDialogComponent, EditJsonDialogSettings } from '../../../../dialogs';
import { FormService } from '../../../services/form.service';
import { WidgetComponent } from '../widget.component';
import { MatDialog } from '@angular/material/dialog';
import { EditJsonDialogSettings, EditJsonDialogComponent } from '../../../../dialogs/edit-json/edit-json.dialog';
@Component({
template: `
<button mat-raised-button color="primary" (click)="view()">json</button>
`,
standalone: true,
template: ` <button mat-raised-button color="primary" (click)="view()">json</button> `,
host: {
'(click)': 'event($event)',
'(blur)': 'event($event)',
@ -36,6 +36,7 @@ import { EditJsonDialogSettings, EditJsonDialogComponent } from '../../../../dia
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
imports: [MatButtonModule],
encapsulation: ViewEncapsulation.None
})
export class JsonWidgetComponent extends WidgetComponent {
@ -45,10 +46,7 @@ export class JsonWidgetComponent extends WidgetComponent {
view() {
const rawValue = this.field.value;
const value =
typeof rawValue === 'object'
? JSON.stringify(rawValue || {}, null, 2)
: rawValue;
const value = typeof rawValue === 'object' ? JSON.stringify(rawValue || {}, null, 2) : rawValue;
const settings: EditJsonDialogSettings = {
title: this.field.name,
@ -56,11 +54,10 @@ export class JsonWidgetComponent extends WidgetComponent {
value
};
this.dialog
.open(EditJsonDialogComponent, {
data: settings,
minWidth: '50%',
minHeight: '50%'
});
this.dialog.open(EditJsonDialogComponent, {
data: settings,
minWidth: '50%',
minHeight: '50%'
});
}
}

View File

@ -1,8 +1,12 @@
<div class="adf-multiline-text-widget {{field.className}}"
[class.adf-invalid]="!field.isValid && isTouched()" [class.adf-readonly]="field.readOnly">
<div class="adf-multiline-text-widget {{ field.className }}"
[class.adf-invalid]="!field.isValid && isTouched()"
[class.adf-readonly]="field.readOnly">
<mat-form-field floatPlaceholder="never" [hideRequiredMarker]="true">
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
<textarea matInput class="adf-input"
<label class="adf-label" [attr.for]="field.id">
{{ field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span>
</label>
<textarea matInput
class="adf-input"
[cdkTextareaAutosize]="true"
type="text"
rows="3"
@ -15,14 +19,16 @@
[matTooltip]="field.tooltip"
(blur)="markAsTouched()"
matTooltipPosition="above"
matTooltipShowDelay="1000">
[matTooltipShowDelay]="1000">
</textarea>
</mat-form-field>
<div *ngIf="field.maxLength > 0" class="adf-multiline-word-counter">
<span class="adf-multiline-word-counter-value">{{field?.value?.length || 0}}/{{field.maxLength}}</span>
<span class="adf-multiline-word-counter-value">{{ field?.value?.length || 0 }}/{{ field.maxLength }}</span>
</div>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget class="adf-multiline-required-message" *ngIf="isInvalidFieldRequired() && isTouched()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}">
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()"
class="adf-multiline-required-message"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}">
</error-widget>
</div>

View File

@ -15,16 +15,14 @@
* limitations under the License.
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MultilineTextWidgetComponentComponent } from './multiline-text.widget';
import { CoreTestingModule } from '../../../../testing/core.testing.module';
import { FormFieldModel } from '../core/form-field.model';
import { FormModel } from '../core/form.model';
import { FormFieldTypes } from '../core/form-field-types';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatInputHarness } from '@angular/material/input/testing';
import { MatTooltipHarness } from '@angular/material/tooltip/testing';
import { CoreTestingModule } from '../../../../testing';
import { FormFieldModel, FormFieldTypes, FormModel } from '../core';
import { MultilineTextWidgetComponentComponent } from './multiline-text.widget';
describe('MultilineTextWidgetComponentComponent', () => {
let loader: HarnessLoader;

View File

@ -17,12 +17,20 @@
/* eslint-disable @angular-eslint/component-selector */
import { NgIf } from '@angular/common';
import { Component, ViewEncapsulation } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { FormService } from '../../../services/form.service';
import { ErrorWidgetComponent } from '../error/error.component';
import { WidgetComponent } from '../widget.component';
@Component({
selector: 'multiline-text-widget',
standalone: true,
templateUrl: './multiline-text.widget.html',
styleUrls: ['./multiline-text.widget.scss'],
host: {
@ -36,12 +44,11 @@ import { WidgetComponent } from '../widget.component';
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
imports: [MatFormFieldModule, NgIf, TranslateModule, MatInputModule, FormsModule, MatTooltipModule, ErrorWidgetComponent],
encapsulation: ViewEncapsulation.None
})
export class MultilineTextWidgetComponentComponent extends WidgetComponent {
export class MultilineTextWidgetComponentComponent extends WidgetComponent {
constructor(public formService: FormService) {
super(formService);
}
}

View File

@ -1,28 +1,36 @@
<div class="adf-textfield adf-number-widget {{field.className}}"
[class.adf-invalid]="!field.isValid && isTouched()" [class.adf-readonly]="field.readOnly" [class.adf-left-label-input-container]="field.leftLabels">
<div class="adf-textfield adf-number-widget {{ field.className }}"
[class.adf-invalid]="!field.isValid && isTouched()"
[class.adf-readonly]="field.readOnly"
[class.adf-left-label-input-container]="field.leftLabels">
<div *ngIf="field.leftLabels">
<label class="adf-label adf-left-label" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
<label class="adf-label adf-left-label"
[attr.for]="field.id">
{{ field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span>
</label>
</div>
<div>
<mat-form-field [hideRequiredMarker]="true">
<label class="adf-label" *ngIf="!field.leftLabels" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
<label class="adf-label" *ngIf="!field.leftLabels" [attr.for]="field.id">
{{ field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span>
</label>
<input matInput
class="adf-input"
type="text"
pattern="-?[0-9]*(\.[0-9]+)?"
[id]="field.id"
[required]="isRequired()"
[value]="displayValue"
[(ngModel)]="field.value"
(ngModelChange)="onFieldChanged(field)"
[disabled]="field.readOnly"
[placeholder]="field.placeholder"
[matTooltip]="field.tooltip"
(blur)="markAsTouched()"
matTooltipPosition="above"
matTooltipShowDelay="1000">
class="adf-input"
type="text"
pattern="-?[0-9]*(\.[0-9]+)?"
[id]="field.id"
[required]="isRequired()"
[value]="displayValue"
[(ngModel)]="field.value"
(ngModelChange)="onFieldChanged(field)"
[disabled]="field.readOnly"
[placeholder]="field.placeholder"
[matTooltip]="field.tooltip"
(blur)="markAsTouched()"
matTooltipPosition="above"
[matTooltipShowDelay]="1000">
</mat-form-field>
<error-widget [error]="field.validationSummary" ></error-widget>
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
</div>
</div>

View File

@ -15,17 +15,16 @@
* limitations under the License.
*/
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatInputHarness } from '@angular/material/input/testing';
import { MatTooltipHarness } from '@angular/material/tooltip/testing';
import { CoreTestingModule } from '../../../../testing';
import { FormFieldModel, FormFieldTypes, FormModel } from '../core';
import { NumberWidgetComponent } from './number.widget';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatInputHarness } from '@angular/material/input/testing';
import { MatTooltipHarness } from '@angular/material/tooltip/testing';
describe('NumberWidgetComponent', () => {
let loader: HarnessLoader;
@ -35,7 +34,7 @@ describe('NumberWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule, MatInputModule, FormsModule, MatIconModule]
imports: [CoreTestingModule, MatInputModule, MatIconModule]
});
fixture = TestBed.createComponent(NumberWidgetComponent);
widget = fixture.componentInstance;

View File

@ -15,15 +15,23 @@
* limitations under the License.
*/
/* eslint-disable @angular-eslint/component-selector, @angular-eslint/no-input-rename */
/* eslint-disable @angular-eslint/component-selector, @angular-eslint/no-input-rename */
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
import { NgIf } from '@angular/common';
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { DecimalNumberPipe } from '../../../../pipes';
import { FormService } from '../../../services/form.service';
import { ErrorWidgetComponent } from '../error/error.component';
import { WidgetComponent } from '../widget.component';
import { DecimalNumberPipe } from '../../../../pipes/decimal-number.pipe';
@Component({
selector: 'number-widget',
standalone: true,
templateUrl: './number.widget.html',
styleUrls: ['./number.widget.scss'],
host: {
@ -37,15 +45,14 @@ import { DecimalNumberPipe } from '../../../../pipes/decimal-number.pipe';
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
imports: [NgIf, TranslateModule, MatFormFieldModule, MatInputModule, FormsModule, MatTooltipModule, ErrorWidgetComponent],
encapsulation: ViewEncapsulation.None
})
export class NumberWidgetComponent extends WidgetComponent implements OnInit {
displayValue: number;
constructor(public formService: FormService,
private decimalNumberPipe: DecimalNumberPipe) {
super(formService);
constructor(public formService: FormService, private decimalNumberPipe: DecimalNumberPipe) {
super(formService);
}
ngOnInit() {
@ -55,5 +62,4 @@ export class NumberWidgetComponent extends WidgetComponent implements OnInit {
this.displayValue = this.field.value;
}
}
}

View File

@ -31,6 +31,7 @@ export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
*/
@Directive({
selector: '[adf-text-mask], [textMask]',
standalone: true,
providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]
})
export class InputMaskDirective implements OnChanges, ControlValueAccessor {

View File

@ -1,28 +1,35 @@
<div class="adf-textfield adf-text-widget {{field.className}}"
[class.adf-invalid]="!field.isValid && isTouched()" [class.adf-readonly]="field.readOnly" [class.adf-left-label-input-container]="field.leftLabels">
<div *ngIf="field.leftLabels">
<label class="adf-label adf-left-label" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
</div>
<div>
<mat-form-field [hideRequiredMarker]="true">
<label class="adf-label" *ngIf="!field.leftLabels" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
<input matInput
class="adf-input"
type="text"
[id]="field.id"
[required]="isRequired()"
[value]="field.value"
[(ngModel)]="field.value"
(ngModelChange)="onFieldChanged(field)"
[disabled]="field.readOnly || readOnly"
[textMask]="{mask: mask, isReversed: isMaskReversed}"
[placeholder]="placeholder"
[matTooltip]="field.tooltip"
(blur)="markAsTouched()"
matTooltipPosition="above"
matTooltipShowDelay="1000">
</mat-form-field>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
</div>
</div>
<div class="adf-textfield adf-text-widget {{ field.className }}"
[class.adf-invalid]="!field.isValid && isTouched()"
[class.adf-readonly]="field.readOnly"
[class.adf-left-label-input-container]="field.leftLabels">
<div *ngIf="field.leftLabels">
<label class="adf-label adf-left-label" [attr.for]="field.id">
{{ field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span>
</label>
</div>
<div>
<mat-form-field [hideRequiredMarker]="true">
<label *ngIf="!field.leftLabels" class="adf-label" [attr.for]="field.id">
{{ field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span>
</label>
<input matInput
class="adf-input"
type="text"
[id]="field.id"
[required]="isRequired()"
[value]="field.value"
[(ngModel)]="field.value"
(ngModelChange)="onFieldChanged(field)"
[disabled]="field.readOnly || readOnly"
[textMask]="{mask: mask, isReversed: isMaskReversed}"
[placeholder]="placeholder"
[matTooltip]="field.tooltip"
(blur)="markAsTouched()"
matTooltipPosition="above"
[matTooltipShowDelay]="1000">
</mat-form-field>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
</div>
</div>

View File

@ -17,12 +17,21 @@
/* eslint-disable @angular-eslint/component-selector */
import { NgIf } from '@angular/common';
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { FormService } from '../../../services/form.service';
import { ErrorWidgetComponent } from '../error/error.component';
import { WidgetComponent } from '../widget.component';
import { InputMaskDirective } from './text-mask.component';
@Component({
selector: 'text-widget',
standalone: true,
templateUrl: './text.widget.html',
styleUrls: ['./text.widget.scss'],
host: {
@ -36,10 +45,10 @@ import { WidgetComponent } from '../widget.component';
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
imports: [NgIf, TranslateModule, MatFormFieldModule, MatInputModule, FormsModule, MatTooltipModule, ErrorWidgetComponent, InputMaskDirective],
encapsulation: ViewEncapsulation.None
})
export class TextWidgetComponent extends WidgetComponent implements OnInit {
mask: string;
placeholder: string;
isMaskReversed: boolean;
@ -51,7 +60,10 @@ export class TextWidgetComponent extends WidgetComponent implements OnInit {
ngOnInit() {
if (this.field.params) {
this.mask = this.field.params['inputMask'];
this.placeholder = this.field.params['inputMask'] && this.field.params['inputMaskPlaceholder'] ? this.field.params['inputMaskPlaceholder'] : this.field.placeholder;
this.placeholder =
this.field.params['inputMask'] && this.field.params['inputMaskPlaceholder']
? this.field.params['inputMaskPlaceholder']
: this.field.placeholder;
this.isMaskReversed = this.field.params['inputMaskReversed'] ? this.field.params['inputMaskReversed'] : false;
}
}

View File

@ -15,22 +15,24 @@
* limitations under the License.
*/
/* eslint-disable @angular-eslint/component-selector */
/* eslint-disable @angular-eslint/component-selector */
import { Component, ViewEncapsulation } from '@angular/core';
import { MatIconModule } from '@angular/material/icon';
import { MatListModule } from '@angular/material/list';
import { FormService } from '../../../services/form.service';
import { WidgetComponent } from '../widget.component';
@Component({
selector: 'unknown-widget',
standalone: true,
template: `
<mat-list class="adf-unknown-widget">
<mat-list-item>
<mat-icon class="mat-24">error_outline</mat-icon>
<span class="adf-unknown-text">Unknown type: {{field.type}}</span>
</mat-list-item>
</mat-list>
<mat-list class="adf-unknown-widget">
<mat-list-item>
<mat-icon class="mat-24">error_outline</mat-icon>
<span class="adf-unknown-text">Unknown type: {{ field.type }}</span>
</mat-list-item>
</mat-list>
`,
styleUrls: ['./unknown.widget.scss'],
host: {
@ -44,11 +46,11 @@ import { WidgetComponent } from '../widget.component';
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
imports: [MatListModule, MatIconModule],
encapsulation: ViewEncapsulation.None
})
export class UnknownWidgetComponent extends WidgetComponent {
constructor(public formService: FormService) {
super(formService);
super(formService);
}
}

View File

@ -16,12 +16,11 @@
*/
import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing';
import { FormFieldModel } from './core/form-field.model';
import { FormModel } from './core/form.model';
import { WidgetComponent } from './widget.component';
import { CoreTestingModule } from '../../../testing';
import { filter } from 'rxjs/operators';
import { FormRulesEvent } from '../../events/form-rules.event';
import { CoreTestingModule } from '../../../testing';
import { FormRulesEvent } from '../../events';
import { FormFieldModel, FormModel } from './core';
import { WidgetComponent } from './widget.component';
describe('WidgetComponent', () => {
let widget: WidgetComponent;

View File

@ -18,8 +18,7 @@
/* eslint-disable @angular-eslint/component-selector */
import { AfterViewInit, Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core';
import { FormFieldEvent } from '../../events/form-field.event';
import { FormRulesEvent } from '../../events/form-rules.event';
import { FormFieldEvent, FormRulesEvent } from '../../events';
import { FormService } from '../../services/form.service';
import { FormFieldModel } from './core';
@ -28,6 +27,7 @@ import { FormFieldModel } from './core';
*/
@Component({
selector: 'base-widget',
standalone: true,
template: '',
host: {
'(click)': 'event($event)',

View File

@ -15,56 +15,26 @@
* limitations under the License.
*/
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { NgModule } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { DataTableModule } from '../datatable/datatable.module';
import { PipeModule } from '../pipes/pipe.module';
import { HttpClientModule } from '@angular/common/http';
import { MaterialModule } from '../material.module';
import { MASK_DIRECTIVE, WIDGET_DIRECTIVES } from './components/widgets';
import { StartFormCustomButtonDirective } from './components/form-custom-button.directive';
import { FormFieldComponent } from './components/form-field/form-field.component';
import { WidgetComponent } from './components/widgets/widget.component';
import { MatDatetimepickerModule, MatNativeDatetimeModule } from '@mat-datetimepicker/core';
import { FormRendererComponent } from './components/form-renderer.component';
import { EditJsonDialogModule } from '../dialogs/edit-json/edit-json.dialog.module';
import { A11yModule } from '@angular/cdk/a11y';
import { ViewerModule } from '../viewer/viewer.module';
import { InplaceFormInputComponent } from './components/inplace-form-input/inplace-form-input.component';
import { FORM_FIELD_MODEL_RENDER_MIDDLEWARE } from './components/middlewares/middleware';
import { DecimalRenderMiddlewareService } from './components/middlewares/decimal-middleware.service';
import { FORM_FIELD_MODEL_RENDER_MIDDLEWARE } from './components/middlewares/middleware';
import { MASK_DIRECTIVE, WIDGET_DIRECTIVES, WidgetComponent } from './components/widgets';
@NgModule({
imports: [
CommonModule,
A11yModule,
DataTableModule,
HttpClientModule,
MaterialModule,
TranslateModule,
FormsModule,
ReactiveFormsModule,
PipeModule,
MatDatetimepickerModule,
MatNativeDatetimeModule,
EditJsonDialogModule,
ViewerModule
],
declarations: [
FormFieldComponent,
FormRendererComponent,
StartFormCustomButtonDirective,
...WIDGET_DIRECTIVES,
...MASK_DIRECTIVE,
WidgetComponent,
InplaceFormInputComponent
StartFormCustomButtonDirective,
InplaceFormInputComponent,
...WIDGET_DIRECTIVES,
...MASK_DIRECTIVE
],
declarations: [],
exports: [
FormFieldComponent,
FormRendererComponent,
@ -73,11 +43,12 @@ import { DecimalRenderMiddlewareService } from './components/middlewares/decimal
InplaceFormInputComponent,
WidgetComponent
],
providers: [{
provide: FORM_FIELD_MODEL_RENDER_MIDDLEWARE,
useClass: DecimalRenderMiddlewareService,
multi: true
}]
providers: [
{
provide: FORM_FIELD_MODEL_RENDER_MIDDLEWARE,
useClass: DecimalRenderMiddlewareService,
multi: true
}
]
})
export class FormBaseModule {
}
export class FormBaseModule {}

View File

@ -15,21 +15,20 @@
* limitations under the License.
*/
import { FormBaseModule } from '../form-base.module';
import { CoreTestingModule } from '../../testing';
import { ByPassFormRuleManager, FormRulesManager, formRulesManagerFactory, FORM_RULES_MANAGER } from './form-rules.model';
import { Injector } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { FormModel } from '../components/widgets/core/form.model';
import { FormRulesEvent } from '../events/form-rules.event';
import { FormEvent } from '../events/form.event';
import { FormService } from '../services/form.service';
import { getTestScheduler } from 'jasmine-marbles';
import { CoreTestingModule } from '../../testing';
import { FormModel } from '../components/widgets';
import { FormEvent, FormRulesEvent } from '../events';
import { FormService } from '../services/form.service';
import { ByPassFormRuleManager, FORM_RULES_MANAGER, FormRulesManager, formRulesManagerFactory } from './form-rules.model';
class CustomRuleManager extends FormRulesManager<any> {
protected getRules() {
return null;
}
protected handleRuleEvent(): void {
return;
}
@ -43,7 +42,7 @@ describe('Form Rules', () => {
describe('Injection token provided', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule, FormBaseModule],
imports: [CoreTestingModule],
providers: [
{
provide: FORM_RULES_MANAGER,
@ -108,7 +107,7 @@ describe('Form Rules', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule, FormBaseModule]
imports: [CoreTestingModule]
});
injector = TestBed.inject(Injector);
rulesManager = formRulesManagerFactory<any>(injector);

View File

@ -18,7 +18,7 @@
import { TestBed } from '@angular/core/testing';
import { formModelTabs } from '../../mock';
import { FormService } from './form.service';
import { CoreTestingModule } from '../../testing/core.testing.module';
import { CoreTestingModule } from '../../testing';
describe('Form service', () => {
let service: FormService;

View File

@ -331,7 +331,7 @@ describe('StartFormComponent', () => {
expect(dateElement).toBeDefined();
expect(selectElement).toBeDefined();
expect(translate.instant(inputLabelElement.textContent)).toBe('ClientName*');
expect(translate.instant(inputLabelElement.textContent.trim())).toBe('ClientName*');
expect(translate.instant(dateLabelElement.innerText)).toBe('BillDate (D-M-YYYY)');
expect(translate.instant(selectLabelElement.innerText)).toBe('ClaimType');
});

View File

@ -22,7 +22,6 @@ import { Logger } from '../../utils/logger';
import { materialLocators } from './material-locators';
export class DropdownPage {
dropDownElement: ElementFinder;
constructor(dropDownElement = $$(`div[class="${materialLocators.Select.arrow.wrapper.root}"]`).first()) {
@ -36,7 +35,9 @@ export class DropdownPage {
async selectOption(option: string): Promise<void> {
Logger.log(`Select dropdown option ${option}`);
const optionElement = element.all(by.cssContainingText(`${materialLocators.Option.root} span${materialLocators.Option.text.class}`, option)).first();
const optionElement = element
.all(by.cssContainingText(`${materialLocators.Option.root.trim()} span${materialLocators.Option.text.class}`, option))
.first();
await BrowserActions.click(optionElement);
await browser.waitForAngular();
}
@ -86,11 +87,15 @@ export class DropdownPage {
}
async checkOptionIsDisplayed(option: string): Promise<void> {
await BrowserVisibility.waitUntilElementIsVisible(element.all(by.cssContainingText(`${materialLocators.Option.root} span${materialLocators.Option.text.class}`, option)).first());
await BrowserVisibility.waitUntilElementIsVisible(
element.all(by.cssContainingText(`${materialLocators.Option.root} span${materialLocators.Option.text.class}`, option)).first()
);
}
async checkOptionIsNotDisplayed(option: string): Promise<void> {
await BrowserVisibility.waitUntilElementIsNotVisible(element.all(by.cssContainingText(`${materialLocators.Option.root} span${materialLocators.Option.text.class}`, option)).first());
await BrowserVisibility.waitUntilElementIsNotVisible(
element.all(by.cssContainingText(`${materialLocators.Option.root} span${materialLocators.Option.text.class}`, option)).first()
);
}
async selectDropdownOption(option: string): Promise<void> {