[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 () => { 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 expected1 = (formInstance.getWidgetBy('id', appFields.displayValue_id).value as string) || 'Display value';
const expected2 = (formInstance.getWidgetBy('id', appFields.displayValue_id).value as string) || ''; const expected2 = (formInstance.getWidgetBy('id', appFields.displayValue_id).value as string) || '';

View File

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

View File

@ -17,7 +17,8 @@
import { Directive } from '@angular/core'; import { Directive } from '@angular/core';
/** @Directive({
* Directive selectors without adf- prefix will be deprecated on 3.0.0 selector: '[adf-form-custom-button]',
*/ standalone: true
@Directive({ selector: '[adf-form-custom-button], [form-custom-button]' }) export class StartFormCustomButtonDirective {} })
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 { 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 { 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', () => { describe('FormFieldComponent', () => {
let fixture: ComponentFixture<FormFieldComponent>; let fixture: ComponentFixture<FormFieldComponent>;
@ -32,7 +30,7 @@ describe('FormFieldComponent', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [CoreTestingModule, FormBaseModule] imports: [CoreTestingModule]
}); });
fixture = TestBed.createComponent(FormFieldComponent); fixture = TestBed.createComponent(FormFieldComponent);
component = fixture.componentInstance; component = fixture.componentInstance;

View File

@ -28,27 +28,16 @@ import {
ViewContainerRef, ViewContainerRef,
ViewEncapsulation ViewEncapsulation
} from '@angular/core'; } from '@angular/core';
import { FormRenderingService } from '../../services/form-rendering.service'; import { FormRenderingService } from '../../services/form-rendering.service';
import { WidgetVisibilityService } from '../../services/widget-visibility.service'; import { WidgetVisibilityService } from '../../services/widget-visibility.service';
import { FormFieldModel } from '../widgets/core/form-field.model'; import { FormFieldModel } from '../widgets';
declare const adf: any; declare const adf: any;
@Component({ @Component({
selector: 'adf-form-field', selector: 'adf-form-field',
template: ` standalone: true,
<div templateUrl: './form-field.component.html',
[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>
`,
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class FormFieldComponent implements OnInit, OnDestroy { 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 { private getField(): FormFieldModel {
if (this.field?.params) { if (this.field?.params) {
const wrappedField = this.field.params.field; const wrappedField = this.field.params.field;
@ -149,10 +144,4 @@ export class FormFieldComponent implements OnInit, OnDestroy {
return module.componentFactories.find((x) => x.componentType === decoratedCmp); 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="formDefinition.hasTabs()">
<div *ngIf="hasTabs()" class="alfresco-tabs-widget"> <div *ngIf="hasTabs()" class="alfresco-tabs-widget">
<mat-tab-group> <mat-tab-group>
@ -16,44 +17,36 @@
<ng-template #render let-fieldToRender="fieldToRender"> <ng-template #render let-fieldToRender="fieldToRender">
<div *ngFor="let currentRootElement of fieldToRender"> <div *ngFor="let currentRootElement of fieldToRender">
<div <div *ngIf="currentRootElement.type === 'container' || currentRootElement.type === 'group'"
*ngIf="currentRootElement.type === 'container' || currentRootElement.type === 'group'" [id]="'field-' + currentRootElement?.id + '-container'"
class="adf-container-widget" class="adf-container-widget"
[id]="'field-' + currentRootElement?.id + '-container'" [hidden]="!currentRootElement?.isVisible">
[hidden]="!currentRootElement?.isVisible"
>
<div [hidden]="!currentRootElement?.isGroup()" class="adf-container-widget__header"> <div [hidden]="!currentRootElement?.isGroup()" class="adf-container-widget__header">
<h4 class="adf-container-widget__header-text" id="container-header" [class.adf-collapsible]="currentRootElement?.isCollapsible()"> <h4 class="adf-container-widget__header-text" id="container-header"
<button [class.adf-collapsible]="currentRootElement?.isCollapsible()">
*ngIf="currentRootElement?.isCollapsible()" <button *ngIf="currentRootElement?.isCollapsible()"
mat-icon-button mat-icon-button
class="mdl-button--icon" class="mdl-button--icon"
(click)="onExpanderClicked(currentRootElement)" (click)="onExpanderClicked(currentRootElement)">
>
<mat-icon>{{ currentRootElement?.isExpanded ? 'expand_more' : 'expand_less' }}</mat-icon> <mat-icon>{{ currentRootElement?.isExpanded ? 'expand_more' : 'expand_less' }}</mat-icon>
</button> </button>
<span <span (click)="onExpanderClicked(currentRootElement)"
(click)="onExpanderClicked(currentRootElement)" role="button"
role="button" tabindex="0"
tabindex="0" (keyup.enter)="onExpanderClicked(currentRootElement)"
(keyup.enter)="onExpanderClicked(currentRootElement)" [id]="'container-header-label-' + currentRootElement?.id">
[id]="'container-header-label-' + currentRootElement?.id" {{ currentRootElement.name | translate }}
>{{ currentRootElement.name | translate }}</span </span>
>
</h4> </h4>
</div> </div>
<div *ngIf="currentRootElement?.form?.enableFixedSpace; else fixingTemplate"> <div *ngIf="currentRootElement?.form?.enableFixedSpace; else fixingTemplate">
<div <div class="adf-grid-list"
class="adf-grid-list" [ngStyle]="{ 'grid-template-columns': 'repeat(' + getNumberOfColumns(currentRootElement) + ', 1fr)' }"
[ngStyle]="{ 'grid-template-columns': 'repeat(' + getNumberOfColumns(currentRootElement) + ', 1fr)' }" *ngIf="currentRootElement?.isExpanded">
*ngIf="currentRootElement?.isExpanded" <div class="adf-grid-list-item"
> *ngFor="let field of getContainerFields(currentRootElement)"
<div [ngStyle]="{ 'grid-area': 'auto / auto / span ' + (field?.rowspan || 1) + ' / span ' + (field?.colspan || 1) }">
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> <adf-form-field *ngIf="field" [field]="field"></adf-form-field>
</div> </div>
</div> </div>
@ -61,11 +54,9 @@
<ng-template #fixingTemplate> <ng-template #fixingTemplate>
<section class="adf-grid-list-column-view" *ngIf="currentRootElement?.isExpanded"> <section class="adf-grid-list-column-view" *ngIf="currentRootElement?.isExpanded">
<div <div class="adf-grid-list-single-column"
class="adf-grid-list-single-column" *ngFor="let column of currentRootElement?.columns"
*ngFor="let column of currentRootElement?.columns" [style.width.%]="getColumnWith(currentRootElement)">
[style.width.%]="getColumnWith(currentRootElement)"
>
<div class="adf-grid-list-column-view-item" *ngFor="let field of column?.fields"> <div class="adf-grid-list-column-view-item" *ngFor="let field of column?.fields">
<adf-form-field *ngIf="field" [field]="field"></adf-form-field> <adf-form-field *ngIf="field" [field]="field"></adf-form-field>
</div> </div>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,21 +1,33 @@
<div class="adf-amount-widget__container adf-amount-widget {{field.className}}" <div class="adf-amount-widget__container adf-amount-widget {{ field.className }}"
[class.adf-invalid]="!field.isValid && isTouched()" [class.adf-readonly]="field.readOnly" [class.adf-invalid]="!field.isValid && isTouched()"
[class.adf-left-label-input-container]="field.leftLabels"> [class.adf-readonly]="field.readOnly"
<div> [class.adf-left-label-input-container]="field.leftLabels">
<label class="adf-label" <div>
[class.adf-left-label]="field.leftLabels" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label> <label class="adf-label"
</div> [class.adf-left-label]="field.leftLabels"
<div> [attr.for]="field.id">
<mat-form-field class="adf-amount-widget__input" [hideRequiredMarker]="true"> {{ field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
<span matPrefix class="adf-amount-widget__prefix-spacing">{{ currency }} &nbsp;</span> </div>
<input matInput [matTooltip]="field.tooltip" matTooltipPosition="above" matTooltipShowDelay="1000" <div>
class="adf-input" type="text" [id]="field.id" [required]="isRequired()" <mat-form-field class="adf-amount-widget__input" [hideRequiredMarker]="true">
[placeholder]="placeholder" [value]="field.value" [(ngModel)]="field.value" <span matPrefix class="adf-amount-widget__prefix-spacing">{{ currency }} &nbsp;</span>
(ngModelChange)="onFieldChanged(field)" [disabled]="field.readOnly" <input matInput
(blur)="markAsTouched()"> [matTooltip]="field.tooltip"
</mat-form-field> matTooltipPosition="above"
<error-widget [error]="field.validationSummary"></error-widget> [matTooltipShowDelay]="1000"
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()" class="adf-input"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget> type="text"
</div> [id]="field.id"
</div> [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. * 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 { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; 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 { MatFormFieldHarness } from '@angular/material/form-field/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', () => { describe('AmountWidgetComponent', () => {
let loader: HarnessLoader; let loader: HarnessLoader;
@ -36,7 +33,7 @@ describe('AmountWidgetComponent', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [CoreTestingModule, FormBaseModule] imports: [CoreTestingModule]
}); });
fixture = TestBed.createComponent(AmountWidgetComponent); fixture = TestBed.createComponent(AmountWidgetComponent);
widget = fixture.componentInstance; widget = fixture.componentInstance;
@ -144,7 +141,7 @@ describe('AmountWidgetComponent - rendering', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [CoreTestingModule, FormBaseModule] imports: [CoreTestingModule]
}); });
fixture = TestBed.createComponent(AmountWidgetComponent); fixture = TestBed.createComponent(AmountWidgetComponent);
widget = fixture.componentInstance; widget = fixture.componentInstance;
@ -203,7 +200,7 @@ describe('AmountWidgetComponent - rendering', () => {
expect(await field.getPrefixText()).toBe('$'); expect(await field.getPrefixText()).toBe('$');
const widgetLabel = fixture.nativeElement.querySelector('label.adf-label'); 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); expect(widget.field.isValid).toBe(false);
const input = await loader.getHarness(MatInputHarness); const input = await loader.getHarness(MatInputHarness);
@ -239,7 +236,7 @@ describe('AmountWidgetComponent - rendering', () => {
await fixture.whenStable(); await fixture.whenStable();
const widgetLabel = fixture.nativeElement.querySelector('label.adf-label'); 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); const field = await loader.getHarness(MatFormFieldHarness);
expect(await field.getPrefixText()).toBe('£'); expect(await field.getPrefixText()).toBe('£');
@ -339,7 +336,7 @@ describe('AmountWidgetComponent settings', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [CoreTestingModule, FormBaseModule], imports: [CoreTestingModule],
providers: [ providers: [
{ {
provide: ADF_AMOUNT_SETTINGS, provide: ADF_AMOUNT_SETTINGS,

View File

@ -17,8 +17,15 @@
/* eslint-disable @angular-eslint/component-selector */ /* eslint-disable @angular-eslint/component-selector */
import { NgIf } from '@angular/common';
import { Component, OnInit, ViewEncapsulation, InjectionToken, Inject, Optional } from '@angular/core'; 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 { FormService } from '../../../services/form.service';
import { ErrorWidgetComponent } from '../error/error.component';
import { WidgetComponent } from '../widget.component'; import { WidgetComponent } from '../widget.component';
export interface AmountWidgetSettings { export interface AmountWidgetSettings {
@ -29,6 +36,7 @@ export const ADF_AMOUNT_SETTINGS = new InjectionToken<AmountWidgetSettings>('adf
@Component({ @Component({
selector: 'amount-widget', selector: 'amount-widget',
standalone: true,
templateUrl: './amount.widget.html', templateUrl: './amount.widget.html',
styleUrls: ['./amount.widget.scss'], styleUrls: ['./amount.widget.scss'],
host: { host: {
@ -42,6 +50,7 @@ export const ADF_AMOUNT_SETTINGS = new InjectionToken<AmountWidgetSettings>('adf
'(invalid)': 'event($event)', '(invalid)': 'event($event)',
'(select)': 'event($event)' '(select)': 'event($event)'
}, },
imports: [MatFormFieldModule, MatTooltipModule, MatInputModule, FormsModule, ErrorWidgetComponent, TranslateModule, NgIf],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class AmountWidgetComponent extends WidgetComponent implements OnInit { 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" <div class="adf-base-viewer-widget {{ field.className }}"
[class.adf-readonly]="field.readOnly"> [class.adf-invalid]="!field.isValid"
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" [class.adf-readonly]="field.readOnly">
*ngIf="isRequired()">*</span></label> <label class="adf-label" [attr.for]="field.id">
<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> {{ 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> <error-widget [error]="field.validationSummary"></error-widget>
</div> </div>

View File

@ -15,12 +15,11 @@
* limitations under the License. * 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 { 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', () => { describe('BaseViewerWidgetComponent', () => {
const fakeForm = new FormModel(); const fakeForm = new FormModel();
@ -45,8 +44,7 @@ describe('BaseViewerWidgetComponent', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [CoreTestingModule], imports: [CoreTestingModule, BaseViewerWidgetComponent],
declarations: [BaseViewerWidgetComponent],
providers: [{ provide: FormService, useValue: formServiceStub }] providers: [{ provide: FormService, useValue: formServiceStub }]
}); });

View File

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

View File

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

View File

@ -15,21 +15,18 @@
* limitations under the License. * 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 { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; 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 { MatCheckboxHarness } from '@angular/material/checkbox/testing';
import { MatTooltipModule } from '@angular/material/tooltip';
import { MatTooltipHarness } from '@angular/material/tooltip/testing'; 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', () => { describe('CheckboxWidgetComponent', () => {
let loader: HarnessLoader; let loader: HarnessLoader;
@ -39,7 +36,7 @@ describe('CheckboxWidgetComponent', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [CoreTestingModule, FormBaseModule, MatCheckboxModule, MatTooltipModule], imports: [CoreTestingModule, MatCheckboxModule, MatTooltipModule],
providers: [{ provide: TranslateLoader, useClass: TranslateLoaderService }] providers: [{ provide: TranslateLoader, useClass: TranslateLoaderService }]
}); });
fixture = TestBed.createComponent(CheckboxWidgetComponent); fixture = TestBed.createComponent(CheckboxWidgetComponent);

View File

@ -17,12 +17,19 @@
/* eslint-disable @angular-eslint/component-selector, @angular-eslint/no-input-rename */ /* eslint-disable @angular-eslint/component-selector, @angular-eslint/no-input-rename */
import { NgClass, NgIf } from '@angular/common';
import { Component, ViewEncapsulation } from '@angular/core'; 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 { FormService } from '../../../services/form.service';
import { ErrorWidgetComponent } from '../error/error.component';
import { WidgetComponent } from '../widget.component'; import { WidgetComponent } from '../widget.component';
@Component({ @Component({
selector: 'checkbox-widget', selector: 'checkbox-widget',
standalone: true,
templateUrl: './checkbox.widget.html', templateUrl: './checkbox.widget.html',
host: { host: {
'(click)': 'event($event)', '(click)': 'event($event)',
@ -35,6 +42,7 @@ import { WidgetComponent } from '../widget.component';
'(invalid)': 'event($event)', '(invalid)': 'event($event)',
'(select)': 'event($event)' '(select)': 'event($event)'
}, },
imports: [NgClass, MatCheckboxModule, FormsModule, TranslateModule, MatTooltipModule, ErrorWidgetComponent, NgIf],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class CheckboxWidgetComponent extends WidgetComponent { 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"> <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> <label class="adf-label adf-left-label" [attr.for]="field.id">
</div> {{ field.name | translate }} ({{ field.dateDisplayFormat }})<span class="adf-asterisk" *ngIf="isRequired()">*</span>
</label>
</div>
<div> <div>
<mat-form-field class="adf-date-time-widget" [class.adf-left-label-input-datepicker]="field.leftLabels" [hideRequiredMarker]="true"> <mat-form-field class="adf-date-time-widget"
<label class="adf-label" *ngIf="!field.leftLabels" [attr.for]="field.id">{{field.name | translate }} ({{field.dateDisplayFormat}})<span class="adf-asterisk" *ngIf="isRequired()">*</span></label> [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 <input matInput
[matDatetimepicker]="datetimePicker" [matDatetimepicker]="datetimePicker"
[id]="field.id" [id]="field.id"
[(ngModel)]="value" [(ngModel)]="value"
[required]="isRequired()" [required]="isRequired()"
[disabled]="field.readOnly" [disabled]="field.readOnly"
(change)="onValueChanged($event)" (change)="onValueChanged($event)"
(dateChange)="onDateChanged($event)" (dateChange)="onDateChanged($event)"
(keydown.enter)="datetimePicker.open()" (keydown.enter)="datetimePicker.open()"
[placeholder]="field.placeholder" [placeholder]="field.placeholder"
[matTooltip]="field.tooltip" [matTooltip]="field.tooltip"
(blur)="markAsTouched()" (blur)="markAsTouched()"
matTooltipPosition="above" matTooltipPosition="above"
matTooltipShowDelay="1000" [matTooltipShowDelay]="1000"
[min]="minDate" [min]="minDate"
[max]="maxDate"> [max]="maxDate">
<mat-datetimepicker-toggle matSuffix [for]="datetimePicker" [disabled]="field.readOnly"></mat-datetimepicker-toggle> <mat-datetimepicker-toggle matSuffix [for]="datetimePicker"
[disabled]="field.readOnly"></mat-datetimepicker-toggle>
</mat-form-field> </mat-form-field>
<error-widget [error]="field.validationSummary"></error-widget> <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 <mat-datetimepicker #datetimePicker
data-automation-id="adf-date-time-widget-picker" data-automation-id="adf-date-time-widget-picker"
type="datetime" type="datetime"
[touchUi]="true" [touchUi]="true"
[timeInterval]="5" [timeInterval]="5"
[disabled]="field.readOnly"> [disabled]="field.readOnly">
</mat-datetimepicker> </mat-datetimepicker>
</div> </div>
</div> </div>

View File

@ -15,18 +15,15 @@
* limitations under the License. * 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 { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; 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 { 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', () => { describe('DateTimeWidgetComponent', () => {
let loader: HarnessLoader; let loader: HarnessLoader;

View File

@ -17,26 +17,42 @@
/* eslint-disable @angular-eslint/component-selector */ /* eslint-disable @angular-eslint/component-selector */
import { NgIf } from '@angular/common';
import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core'; import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
import { DatetimeAdapter, MAT_DATETIME_FORMATS, MatDatetimepickerInputEvent } from '@mat-datetimepicker/core'; import { MatFormFieldModule } from '@angular/material/form-field';
import { FormService } from '../../../services/form.service'; import { MatInputModule } from '@angular/material/input';
import { WidgetComponent } from '../widget.component'; import { MatTooltipModule } from '@angular/material/tooltip';
import { ADF_DATE_FORMATS, AdfDateFnsAdapter } from '../../../../common/utils/date-fns-adapter'; import { DatetimeAdapter, MAT_DATETIME_FORMATS, MatDatetimepickerInputEvent, MatDatetimepickerModule } from '@mat-datetimepicker/core';
import { ADF_DATETIME_FORMATS, AdfDateTimeFnsAdapter } from '../../../../common/utils/datetime-fns-adapter'; import { TranslateModule } from '@ngx-translate/core';
import { DateFnsUtils } from '../../../../common';
import { isValid } from 'date-fns'; 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({ @Component({
selector: 'date-time-widget',
standalone: true,
providers: [ providers: [
{ provide: MAT_DATE_FORMATS, useValue: ADF_DATE_FORMATS }, { provide: MAT_DATE_FORMATS, useValue: ADF_DATE_FORMATS },
{ provide: MAT_DATETIME_FORMATS, useValue: ADF_DATETIME_FORMATS }, { provide: MAT_DATETIME_FORMATS, useValue: ADF_DATETIME_FORMATS },
{ provide: DateAdapter, useClass: AdfDateFnsAdapter }, { provide: DateAdapter, useClass: AdfDateFnsAdapter },
{ provide: DatetimeAdapter, useClass: AdfDateTimeFnsAdapter } { provide: DatetimeAdapter, useClass: AdfDateTimeFnsAdapter }
], ],
selector: 'date-time-widget',
templateUrl: './date-time.widget.html', templateUrl: './date-time.widget.html',
styleUrls: ['./date-time.widget.scss'], styleUrls: ['./date-time.widget.scss'],
imports: [
NgIf,
TranslateModule,
MatFormFieldModule,
MatInputModule,
MatDatetimepickerModule,
FormsModule,
MatTooltipModule,
ErrorWidgetComponent
],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class DateTimeWidgetComponent extends WidgetComponent implements OnInit { export class DateTimeWidgetComponent extends WidgetComponent implements OnInit {
@ -46,9 +62,7 @@ export class DateTimeWidgetComponent extends WidgetComponent implements OnInit {
@Input() @Input()
value: any = null; value: any = null;
constructor(public formService: FormService, constructor(public formService: FormService, private dateAdapter: DateAdapter<Date>, private dateTimeAdapter: DatetimeAdapter<Date>) {
private dateAdapter: DateAdapter<Date>,
private dateTimeAdapter: DatetimeAdapter<Date>) {
super(formService); 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-form-field [floatLabel]="'always'" class="adf-date-widget">
<mat-label class="adf-label" <mat-label class="adf-label"
[id]="field.id + '-label'" [id]="field.id + '-label'"
[attr.for]="field.id" [attr.for]="field.id">
>{{field.name | translate }} ({{field.dateDisplayFormat}})</mat-label> {{ field.name | translate }} ({{ field.dateDisplayFormat }})
<input matInput [matDatepicker]="datePicker" </mat-label>
[id]="field.id" <input matInput
[(ngModel)]="value" [matDatepicker]="datePicker"
[required]="field.required" [id]="field.id"
[placeholder]="field.placeholder" [(ngModel)]="value"
[min]="minDate" [required]="field.required"
[max]="maxDate" [placeholder]="field.placeholder"
[disabled]="field.readOnly" [min]="minDate"
(dateChange)="onDateChange($event)" [max]="maxDate"
(blur)="markAsTouched()"> [disabled]="field.readOnly"
(dateChange)="onDateChange($event)"
(blur)="markAsTouched()">
<mat-datepicker-toggle matSuffix [for]="datePicker" [disabled]="field.readOnly"></mat-datepicker-toggle> <mat-datepicker-toggle matSuffix [for]="datePicker" [disabled]="field.readOnly"></mat-datepicker-toggle>
<mat-datepicker #datePicker <mat-datepicker #datePicker
[startAt]="startAt" [startAt]="startAt"
[disabled]="field.readOnly"> [disabled]="field.readOnly">
</mat-datepicker> </mat-datepicker>
</mat-form-field> </mat-form-field>
<error-widget [error]="field.validationSummary"></error-widget> <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> </div>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,2 +1,6 @@
<div [matTooltip]="field.tooltip" matTooltipPosition="above" matTooltipShowDelay="1000" <div [matTooltip]="field.tooltip"
class="adf-display-text-widget {{field.className}}">{{field.value | translate}}</div> 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. * limitations under the License.
*/ */
/* eslint-disable @angular-eslint/component-selector */ /* eslint-disable @angular-eslint/component-selector */
import { Component, ViewEncapsulation } from '@angular/core'; 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 { FormService } from '../../../services/form.service';
import { WidgetComponent } from '../widget.component'; import { WidgetComponent } from '../widget.component';
@Component({ @Component({
selector: 'display-text-widget', selector: 'display-text-widget',
standalone: true,
templateUrl: './display-text.widget.html', templateUrl: './display-text.widget.html',
styleUrls: ['./display-text.widget.scss'], styleUrls: ['./display-text.widget.scss'],
host: { host: {
@ -36,12 +39,11 @@ import { WidgetComponent } from '../widget.component';
'(invalid)': 'event($event)', '(invalid)': 'event($event)',
'(select)': 'event($event)' '(select)': 'event($event)'
}, },
imports: [MatTooltipModule, TranslateModule],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class DisplayTextWidgetComponent extends WidgetComponent { export class DisplayTextWidgetComponent extends WidgetComponent {
constructor(public formService: FormService) { constructor(public formService: FormService) {
super(formService); super(formService);
} }
} }

View File

@ -1,10 +1,10 @@
<div class="adf-error-container"> <div class="adf-error-container">
<div *ngIf="error?.isActive()" [@transitionMessages]="subscriptAnimationState" class="adf-error"> <div *ngIf="error?.isActive()" [@transitionMessages]="subscriptAnimationState" class="adf-error">
<mat-icon class="adf-error-icon">error_outline</mat-icon> <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>
<div *ngIf="required" [@transitionMessages]="subscriptAnimationState" class="adf-error"> <div *ngIf="required" [@transitionMessages]="subscriptAnimationState" class="adf-error">
<mat-icon class="adf-error-icon">error_outline</mat-icon> <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>
</div> </div>

View File

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

View File

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

View File

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

View File

@ -16,12 +16,10 @@
*/ */
import { ComponentFixture, TestBed } from '@angular/core/testing'; 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 { MatTooltipModule } from '@angular/material/tooltip';
import { CoreTestingModule } from '../../../../testing';
import { FormFieldModel, FormFieldTypes, FormModel } from '../core';
import { HyperlinkWidgetComponent } from './hyperlink.widget';
describe('HyperlinkWidgetComponent', () => { describe('HyperlinkWidgetComponent', () => {
let widget: HyperlinkWidgetComponent; let widget: HyperlinkWidgetComponent;

View File

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

View File

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

View File

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

View File

@ -15,16 +15,14 @@
* limitations under the License. * 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 { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatInputHarness } from '@angular/material/input/testing'; import { MatInputHarness } from '@angular/material/input/testing';
import { MatTooltipHarness } from '@angular/material/tooltip/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', () => { describe('MultilineTextWidgetComponentComponent', () => {
let loader: HarnessLoader; let loader: HarnessLoader;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,28 +1,35 @@
<div class="adf-textfield adf-text-widget {{field.className}}" <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"> [class.adf-invalid]="!field.isValid && isTouched()"
<div *ngIf="field.leftLabels"> [class.adf-readonly]="field.readOnly"
<label class="adf-label adf-left-label" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label> [class.adf-left-label-input-container]="field.leftLabels">
</div> <div *ngIf="field.leftLabels">
<div> <label class="adf-label adf-left-label" [attr.for]="field.id">
<mat-form-field [hideRequiredMarker]="true"> {{ field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span>
<label class="adf-label" *ngIf="!field.leftLabels" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label> </label>
<input matInput </div>
class="adf-input" <div>
type="text" <mat-form-field [hideRequiredMarker]="true">
[id]="field.id" <label *ngIf="!field.leftLabels" class="adf-label" [attr.for]="field.id">
[required]="isRequired()" {{ field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span>
[value]="field.value" </label>
[(ngModel)]="field.value" <input matInput
(ngModelChange)="onFieldChanged(field)" class="adf-input"
[disabled]="field.readOnly || readOnly" type="text"
[textMask]="{mask: mask, isReversed: isMaskReversed}" [id]="field.id"
[placeholder]="placeholder" [required]="isRequired()"
[matTooltip]="field.tooltip" [value]="field.value"
(blur)="markAsTouched()" [(ngModel)]="field.value"
matTooltipPosition="above" (ngModelChange)="onFieldChanged(field)"
matTooltipShowDelay="1000"> [disabled]="field.readOnly || readOnly"
</mat-form-field> [textMask]="{mask: mask, isReversed: isMaskReversed}"
<error-widget [error]="field.validationSummary"></error-widget> [placeholder]="placeholder"
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget> [matTooltip]="field.tooltip"
</div> (blur)="markAsTouched()"
</div> 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 */ /* eslint-disable @angular-eslint/component-selector */
import { NgIf } from '@angular/common';
import { Component, OnInit, ViewEncapsulation } from '@angular/core'; 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 { FormService } from '../../../services/form.service';
import { ErrorWidgetComponent } from '../error/error.component';
import { WidgetComponent } from '../widget.component'; import { WidgetComponent } from '../widget.component';
import { InputMaskDirective } from './text-mask.component';
@Component({ @Component({
selector: 'text-widget', selector: 'text-widget',
standalone: true,
templateUrl: './text.widget.html', templateUrl: './text.widget.html',
styleUrls: ['./text.widget.scss'], styleUrls: ['./text.widget.scss'],
host: { host: {
@ -36,10 +45,10 @@ import { WidgetComponent } from '../widget.component';
'(invalid)': 'event($event)', '(invalid)': 'event($event)',
'(select)': 'event($event)' '(select)': 'event($event)'
}, },
imports: [NgIf, TranslateModule, MatFormFieldModule, MatInputModule, FormsModule, MatTooltipModule, ErrorWidgetComponent, InputMaskDirective],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class TextWidgetComponent extends WidgetComponent implements OnInit { export class TextWidgetComponent extends WidgetComponent implements OnInit {
mask: string; mask: string;
placeholder: string; placeholder: string;
isMaskReversed: boolean; isMaskReversed: boolean;
@ -51,7 +60,10 @@ export class TextWidgetComponent extends WidgetComponent implements OnInit {
ngOnInit() { ngOnInit() {
if (this.field.params) { if (this.field.params) {
this.mask = this.field.params['inputMask']; 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; this.isMaskReversed = this.field.params['inputMaskReversed'] ? this.field.params['inputMaskReversed'] : false;
} }
} }

View File

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

View File

@ -16,12 +16,11 @@
*/ */
import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing'; 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 { 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', () => { describe('WidgetComponent', () => {
let widget: WidgetComponent; let widget: WidgetComponent;

View File

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

View File

@ -15,56 +15,26 @@
* limitations under the License. * limitations under the License.
*/ */
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { NgModule } from '@angular/core'; 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 { StartFormCustomButtonDirective } from './components/form-custom-button.directive';
import { FormFieldComponent } from './components/form-field/form-field.component'; 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 { 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 { 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 { 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({ @NgModule({
imports: [ imports: [
CommonModule,
A11yModule,
DataTableModule,
HttpClientModule,
MaterialModule,
TranslateModule,
FormsModule,
ReactiveFormsModule,
PipeModule,
MatDatetimepickerModule,
MatNativeDatetimeModule,
EditJsonDialogModule,
ViewerModule
],
declarations: [
FormFieldComponent, FormFieldComponent,
FormRendererComponent, FormRendererComponent,
StartFormCustomButtonDirective,
...WIDGET_DIRECTIVES,
...MASK_DIRECTIVE,
WidgetComponent, WidgetComponent,
InplaceFormInputComponent StartFormCustomButtonDirective,
InplaceFormInputComponent,
...WIDGET_DIRECTIVES,
...MASK_DIRECTIVE
], ],
declarations: [],
exports: [ exports: [
FormFieldComponent, FormFieldComponent,
FormRendererComponent, FormRendererComponent,
@ -73,11 +43,12 @@ import { DecimalRenderMiddlewareService } from './components/middlewares/decimal
InplaceFormInputComponent, InplaceFormInputComponent,
WidgetComponent WidgetComponent
], ],
providers: [{ providers: [
provide: FORM_FIELD_MODEL_RENDER_MIDDLEWARE, {
useClass: DecimalRenderMiddlewareService, provide: FORM_FIELD_MODEL_RENDER_MIDDLEWARE,
multi: true useClass: DecimalRenderMiddlewareService,
}] multi: true
}
]
}) })
export class FormBaseModule { export class FormBaseModule {}
}

View File

@ -15,21 +15,20 @@
* limitations under the License. * 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 { Injector } from '@angular/core';
import { TestBed } from '@angular/core/testing'; 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 { 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> { class CustomRuleManager extends FormRulesManager<any> {
protected getRules() { protected getRules() {
return null; return null;
} }
protected handleRuleEvent(): void { protected handleRuleEvent(): void {
return; return;
} }
@ -43,7 +42,7 @@ describe('Form Rules', () => {
describe('Injection token provided', () => { describe('Injection token provided', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [CoreTestingModule, FormBaseModule], imports: [CoreTestingModule],
providers: [ providers: [
{ {
provide: FORM_RULES_MANAGER, provide: FORM_RULES_MANAGER,
@ -108,7 +107,7 @@ describe('Form Rules', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [CoreTestingModule, FormBaseModule] imports: [CoreTestingModule]
}); });
injector = TestBed.inject(Injector); injector = TestBed.inject(Injector);
rulesManager = formRulesManagerFactory<any>(injector); rulesManager = formRulesManagerFactory<any>(injector);

View File

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

View File

@ -331,7 +331,7 @@ describe('StartFormComponent', () => {
expect(dateElement).toBeDefined(); expect(dateElement).toBeDefined();
expect(selectElement).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(dateLabelElement.innerText)).toBe('BillDate (D-M-YYYY)');
expect(translate.instant(selectLabelElement.innerText)).toBe('ClaimType'); expect(translate.instant(selectLabelElement.innerText)).toBe('ClaimType');
}); });

View File

@ -22,7 +22,6 @@ import { Logger } from '../../utils/logger';
import { materialLocators } from './material-locators'; import { materialLocators } from './material-locators';
export class DropdownPage { export class DropdownPage {
dropDownElement: ElementFinder; dropDownElement: ElementFinder;
constructor(dropDownElement = $$(`div[class="${materialLocators.Select.arrow.wrapper.root}"]`).first()) { constructor(dropDownElement = $$(`div[class="${materialLocators.Select.arrow.wrapper.root}"]`).first()) {
@ -36,7 +35,9 @@ export class DropdownPage {
async selectOption(option: string): Promise<void> { async selectOption(option: string): Promise<void> {
Logger.log(`Select dropdown option ${option}`); 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 BrowserActions.click(optionElement);
await browser.waitForAngular(); await browser.waitForAngular();
} }
@ -86,11 +87,15 @@ export class DropdownPage {
} }
async checkOptionIsDisplayed(option: string): Promise<void> { 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> { 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> { async selectDropdownOption(option: string): Promise<void> {