From 4aea2197977bc42274e972052f045d7eb0887717 Mon Sep 17 00:00:00 2001
From: crisnicandrei <62384997+crisnicandrei@users.noreply.github.com>
Date: Tue, 20 Feb 2024 18:42:48 +0200
Subject: [PATCH 1/8] PER-9446-form input
Implementation of the form input component from the new component library.
I have kept the old implementation and added a way to also use it without a form control, also using a debounce + style changes
---
.../component-library/components.module.ts | 21 +-
.../form-input/form-input.component.html | 32 +++
.../form-input/form-input.component.scss | 93 ++++++++
.../form-input/form-input.component.spec.ts | 161 ++++++++++++++
.../form-input/form-input.component.ts | 204 ++++++++++++++++++
src/app/shared/utilities/forms.ts | 3 +-
src/assets/fonts/Usual/Usual-Bold.ttf | Bin 0 -> 73464 bytes
src/assets/fonts/Usual/Usual-Bold.woff | Bin 0 -> 35116 bytes
src/assets/fonts/Usual/Usual-Bold.woff2 | Bin 0 -> 20648 bytes
src/assets/fonts/Usual/Usual-BoldItalic.ttf | Bin 0 -> 76576 bytes
src/assets/fonts/Usual/Usual-BoldItalic.woff | Bin 0 -> 35344 bytes
src/assets/fonts/Usual/Usual-Bolditalic.woff2 | Bin 0 -> 22204 bytes
src/assets/fonts/Usual/Usual-ExtraBold.ttf | Bin 0 -> 73540 bytes
src/assets/fonts/Usual/Usual-ExtraBold.woff | Bin 0 -> 34612 bytes
src/assets/fonts/Usual/Usual-ExtraBold.woff2 | Bin 0 -> 20500 bytes
.../fonts/Usual/Usual-ExtraBoldItalic.ttf | Bin 0 -> 76540 bytes
.../fonts/Usual/Usual-ExtraBoldItalic.woff | Bin 0 -> 35072 bytes
.../fonts/Usual/Usual-ExtraBoldItalic.woff2 | Bin 0 -> 21804 bytes
src/assets/fonts/Usual/Usual-Italic.ttf | Bin 0 -> 77300 bytes
src/assets/fonts/Usual/Usual-Italic.woff | Bin 0 -> 34396 bytes
src/assets/fonts/Usual/Usual-Italic.woff2 | Bin 0 -> 22352 bytes
src/assets/fonts/Usual/Usual-Light.ttf | Bin 0 -> 74116 bytes
src/assets/fonts/Usual/Usual-Light.woff | Bin 0 -> 33884 bytes
src/assets/fonts/Usual/Usual-Light.woff2 | Bin 0 -> 20084 bytes
src/assets/fonts/Usual/Usual-LightItalic.ttf | Bin 0 -> 77940 bytes
src/assets/fonts/Usual/Usual-LightItalic.woff | Bin 0 -> 34540 bytes
.../fonts/Usual/Usual-LightItalic.woff2 | Bin 0 -> 22400 bytes
src/assets/fonts/Usual/Usual-Medium.ttf | Bin 0 -> 73640 bytes
src/assets/fonts/Usual/Usual-Medium.woff | Bin 0 -> 34924 bytes
src/assets/fonts/Usual/Usual-Medium.woff2 | Bin 0 -> 20856 bytes
src/assets/fonts/Usual/Usual-MediumItalic.ttf | Bin 0 -> 77004 bytes
.../fonts/Usual/Usual-MediumItalic.woff | Bin 0 -> 35296 bytes
.../fonts/Usual/Usual-MediumItalic.woff2 | Bin 0 -> 22548 bytes
src/assets/fonts/Usual/Usual-Regular.ttf | Bin 0 -> 74016 bytes
src/assets/fonts/Usual/Usual-Regular.woff | Bin 0 -> 34164 bytes
src/assets/fonts/Usual/Usual-Regular.woff2 | Bin 0 -> 20568 bytes
src/styles/_fonts.scss | 84 ++++++++
src/styles/_variables.scss | 48 +++--
38 files changed, 624 insertions(+), 22 deletions(-)
create mode 100644 src/app/component-library/components/form-input/form-input.component.html
create mode 100644 src/app/component-library/components/form-input/form-input.component.scss
create mode 100644 src/app/component-library/components/form-input/form-input.component.spec.ts
create mode 100644 src/app/component-library/components/form-input/form-input.component.ts
create mode 100644 src/assets/fonts/Usual/Usual-Bold.ttf
create mode 100644 src/assets/fonts/Usual/Usual-Bold.woff
create mode 100644 src/assets/fonts/Usual/Usual-Bold.woff2
create mode 100644 src/assets/fonts/Usual/Usual-BoldItalic.ttf
create mode 100644 src/assets/fonts/Usual/Usual-BoldItalic.woff
create mode 100644 src/assets/fonts/Usual/Usual-Bolditalic.woff2
create mode 100644 src/assets/fonts/Usual/Usual-ExtraBold.ttf
create mode 100644 src/assets/fonts/Usual/Usual-ExtraBold.woff
create mode 100644 src/assets/fonts/Usual/Usual-ExtraBold.woff2
create mode 100644 src/assets/fonts/Usual/Usual-ExtraBoldItalic.ttf
create mode 100644 src/assets/fonts/Usual/Usual-ExtraBoldItalic.woff
create mode 100644 src/assets/fonts/Usual/Usual-ExtraBoldItalic.woff2
create mode 100644 src/assets/fonts/Usual/Usual-Italic.ttf
create mode 100644 src/assets/fonts/Usual/Usual-Italic.woff
create mode 100644 src/assets/fonts/Usual/Usual-Italic.woff2
create mode 100644 src/assets/fonts/Usual/Usual-Light.ttf
create mode 100644 src/assets/fonts/Usual/Usual-Light.woff
create mode 100644 src/assets/fonts/Usual/Usual-Light.woff2
create mode 100644 src/assets/fonts/Usual/Usual-LightItalic.ttf
create mode 100644 src/assets/fonts/Usual/Usual-LightItalic.woff
create mode 100644 src/assets/fonts/Usual/Usual-LightItalic.woff2
create mode 100644 src/assets/fonts/Usual/Usual-Medium.ttf
create mode 100644 src/assets/fonts/Usual/Usual-Medium.woff
create mode 100644 src/assets/fonts/Usual/Usual-Medium.woff2
create mode 100644 src/assets/fonts/Usual/Usual-MediumItalic.ttf
create mode 100644 src/assets/fonts/Usual/Usual-MediumItalic.woff
create mode 100644 src/assets/fonts/Usual/Usual-MediumItalic.woff2
create mode 100644 src/assets/fonts/Usual/Usual-Regular.ttf
create mode 100644 src/assets/fonts/Usual/Usual-Regular.woff
create mode 100644 src/assets/fonts/Usual/Usual-Regular.woff2
create mode 100644 src/styles/_fonts.scss
diff --git a/src/app/component-library/components.module.ts b/src/app/component-library/components.module.ts
index aee0b7feb..8c45764ff 100644
--- a/src/app/component-library/components.module.ts
+++ b/src/app/component-library/components.module.ts
@@ -1,12 +1,23 @@
/* @format */
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
-import { ToggleComponent } from './components/toggle/toggle.component';
+import {
+ FaIconLibrary,
+ FontAwesomeModule,
+} from '@fortawesome/angular-fontawesome';
+import { faExclamationCircle } from '@fortawesome/free-solid-svg-icons';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { FormInputComponent } from './components/form-input/form-input.component';
import { ButtonComponent } from './components/button/button.component';
+import { ToggleComponent } from './components/toggle/toggle.component';
@NgModule({
- declarations: [ToggleComponent, ButtonComponent],
- imports: [CommonModule],
- exports: [ToggleComponent, ButtonComponent],
+ declarations: [FormInputComponent, ToggleComponent, ButtonComponent],
+ imports: [CommonModule, FontAwesomeModule, FormsModule, ReactiveFormsModule],
+ exports: [FormInputComponent],
})
-export class ComponentsModule {}
+export class ComponentsModule {
+ constructor(private library: FaIconLibrary) {
+ library.addIcons(faExclamationCircle);
+ }
+}
diff --git a/src/app/component-library/components/form-input/form-input.component.html b/src/app/component-library/components/form-input/form-input.component.html
new file mode 100644
index 000000000..cd1391a26
--- /dev/null
+++ b/src/app/component-library/components/form-input/form-input.component.html
@@ -0,0 +1,32 @@
+
+
+ {{ placeholder }}
+
+
+
+
+ {{ errors }}
+
diff --git a/src/app/component-library/components/form-input/form-input.component.scss b/src/app/component-library/components/form-input/form-input.component.scss
new file mode 100644
index 000000000..50065b22d
--- /dev/null
+++ b/src/app/component-library/components/form-input/form-input.component.scss
@@ -0,0 +1,93 @@
+/* @format */
+@import 'fonts';
+@import 'variables';
+
+:host {
+ position: relative;
+}
+
+.form-input {
+ border-radius: 12px;
+ font-family: 'UsualRegular', sans-serif;
+ font-size: 14px;
+ line-height: 24px;
+ font-weight: 600;
+ border: 1px solid $form-border;
+ padding: 12px;
+ height: 48px;
+
+ &-errors {
+ background-color: $form-background-error;
+ border: 1px solid $form-border-error;
+ }
+
+ &:focus {
+ box-shadow: none;
+ background-color: $form-background-focus;
+ border: 1px solid $form-border-focus;
+ }
+
+ &::placeholder {
+ text-transform: uppercase;
+ font-family: 'UsualRegular', sans-serif;
+ line-height: 16px;
+ letter-spacing: 16%;
+ font-weight: 400;
+ font-size: 10px;
+ }
+
+ &-default {
+ color: $form-default-text-color;
+ }
+
+ &-dark {
+ background-color: $form-background-dark;
+ opacity: 0.8;
+ color: white;
+ border: 1px solid transparent;
+ &:focus {
+ background-color: $form-background-dark !important;
+ opacity: 1;
+ border: 1px solid $form-border;
+ }
+ &::placeholder {
+ color: white;
+ }
+ }
+}
+
+.input-vertical-label {
+ position: absolute;
+ font-family: 'UsualRegular', sans-serif;
+ font-size: 10px;
+ font-weight: 400;
+ text-transform: uppercase;
+ left: 12px;
+ top: 4px;
+ &-dark {
+ color: $form-label-dark;
+ }
+}
+
+.hidden {
+ display: none;
+}
+
+.input-vertical-error {
+ font-family: 'UsualRegular', sans-serif;
+ font-size: 12px;
+ font-weight: 400;
+ line-height: 16px;
+ letter-spacing: 0em;
+ text-align: left;
+ color: $form-error-red;
+ margin-left: 15px;
+ margin-top: 5px;
+}
+
+.error-icon {
+ position: absolute;
+ right: 20px;
+ top: 12px;
+ color: $form-error-red;
+}
diff --git a/src/app/component-library/components/form-input/form-input.component.spec.ts b/src/app/component-library/components/form-input/form-input.component.spec.ts
new file mode 100644
index 000000000..e5688e35c
--- /dev/null
+++ b/src/app/component-library/components/form-input/form-input.component.spec.ts
@@ -0,0 +1,161 @@
+/* @format */
+import { Shallow } from 'shallow-render';
+import { ComponentsModule } from '../../components.module';
+import { FormInputComponent, FormInputConfig } from './form-input.component';
+import { ReactiveFormsModule, UntypedFormControl } from '@angular/forms';
+
+type AttrOnOff = 'on' | 'off';
+
+describe('FormInputComponent', () => {
+ let shallow: Shallow;
+
+ beforeEach(async () => {
+ shallow = new Shallow(FormInputComponent, ComponentsModule).import(
+ ReactiveFormsModule
+ );
+ });
+
+ it('should create with an empty control', async () => {
+ const mockControl = new UntypedFormControl('');
+ const { instance } = await shallow.render({
+ bind: { control: mockControl },
+ });
+
+ expect(instance).toBeTruthy();
+ });
+
+ it('should create with a control', async () => {
+ const mockControl = new UntypedFormControl('input');
+ const { instance } = await shallow.render({
+ bind: { control: mockControl },
+ });
+
+ expect(instance).toBeTruthy();
+ });
+
+ it('should bind the input type with empty form control', async () => {
+ const mockControl = new UntypedFormControl('');
+ const { find } = await shallow.render({
+ bind: { type: 'password', control: mockControl },
+ });
+
+ const inputElement = find('input').nativeElement;
+
+ expect(inputElement.type).toBe('password');
+ });
+
+ it('should bind the input type with form control', async () => {
+ const control = new UntypedFormControl('input');
+ const { find } = await shallow.render({
+ bind: { control: control, type: 'password' },
+ });
+
+ const inputElement = find('input').nativeElement;
+
+ expect(inputElement.type).toBe('password');
+ });
+
+ it('should hide label for empty number inputs', async () => {
+ const mockControl = new UntypedFormControl('');
+
+ const { instance } = await shallow.render({
+ bind: { type: 'number', control: mockControl },
+ });
+
+ expect(instance.isLabelHidden()).toBeTrue();
+ });
+
+ it('should show label for non-empty text inputs', async () => {
+ const mockControl = new UntypedFormControl('Some text');
+
+ const { instance } = await shallow.render({
+ bind: { type: 'text', control: mockControl },
+ });
+
+ expect(instance.isLabelHidden()).toBeFalse();
+ });
+
+ it('should set input attributes based on config', async () => {
+ const mockControl = new UntypedFormControl('Some text');
+
+ const config: FormInputConfig = {
+ autocorrect: 'off',
+ autocapitalize: 'off',
+ spellcheck: 'off',
+ };
+ const { find } = await shallow.render({
+ bind: { config, control: mockControl },
+ });
+
+ const inputElement = find('input').nativeElement;
+
+ expect(inputElement.getAttribute('autocorrect')).toBe(config.autocorrect);
+
+ expect(inputElement.getAttribute('autocapitalize')).toBe(
+ config.autocapitalize
+ );
+
+ expect(inputElement.getAttribute('spellcheck')).toBe(config.spellcheck);
+ });
+
+ it('should emit valueChange event on input value change', async () => {
+ const mockControl = new UntypedFormControl('');
+
+ const mockValue = 'test value';
+ const { instance, find } = await shallow.render({
+ bind: { control: mockControl },
+ });
+
+ const spy = spyOn(instance.valueChangeSubject, 'next');
+
+ instance.onInputChange(mockValue);
+
+ expect(spy).toHaveBeenCalledWith(mockValue);
+ });
+
+ it('should apply right-align class based on config', async () => {
+ const mockControl = new UntypedFormControl('');
+ const { instance, fixture } = await shallow.render({
+ bind: { config: { textAlign: 'right' }, control: mockControl },
+ });
+ fixture.detectChanges();
+
+ expect(instance.rightAlign).toBeTrue();
+ });
+ it('should bind the placeholder attribute to the input element', async () => {
+ const mockControl = new UntypedFormControl('');
+ const placeholderValue = 'Enter text here';
+ const { find } = await shallow.render({
+ bind: { placeholder: placeholderValue, control: mockControl },
+ });
+
+ const inputElement = find('input').nativeElement;
+
+ expect(inputElement.placeholder).toBe(placeholderValue);
+ });
+
+ it('should return the correct error from the validation array', async () => {
+ const mockControl = new UntypedFormControl('');
+ const { instance } = await shallow.render({
+ bind: {
+ validators: [
+ {
+ validation: 'minLength',
+ message: 'Must be at least 3 characters',
+ value: 3,
+ },
+ {
+ validation: 'maxLength',
+ message: 'Must be at most 10 characters',
+ value: 10,
+ },
+ ],
+ control: mockControl,
+ },
+ });
+
+ const errorMessage = instance.getInputErrorFromValue('aa')
+
+ expect(errorMessage).toBe('Must be at least 3 characters');
+ });
+});
diff --git a/src/app/component-library/components/form-input/form-input.component.ts b/src/app/component-library/components/form-input/form-input.component.ts
new file mode 100644
index 000000000..78276969b
--- /dev/null
+++ b/src/app/component-library/components/form-input/form-input.component.ts
@@ -0,0 +1,204 @@
+/* @format */
+import {
+ Component,
+ OnInit,
+ Input,
+ ElementRef,
+ AfterViewInit,
+ HostBinding,
+ Output,
+ EventEmitter,
+ SimpleChanges,
+} from '@angular/core';
+import { UntypedFormControl, Validators, FormControl } from '@angular/forms';
+import { getFormInputError } from '@shared/utilities/forms';
+import { find } from 'lodash';
+import { Subject, Subscription } from 'rxjs';
+import { debounceTime } from 'rxjs/operators';
+
+export interface FormInputSelectOption {
+ text: string | number;
+ value: string | number;
+}
+
+type AttrOnOff = 'on' | 'off';
+
+type Variant = 'light' | 'dark';
+
+export interface FormInputConfig {
+ autocorrect?: AttrOnOff;
+ autocomplete?: string;
+ autocapitalize?: AttrOnOff;
+ spellcheck?: AttrOnOff;
+ autoselect?: boolean;
+ validateDirty?: boolean;
+ textAlign?: string;
+ format?: string;
+ readOnly?: boolean;
+}
+
+@Component({
+ selector: 'pr-form-input-comp',
+ templateUrl: './form-input.component.html',
+ styleUrls: ['./form-input.component.scss'],
+})
+export class FormInputComponent implements OnInit, AfterViewInit {
+ @Input() type = 'text';
+ @Input() fieldName: string;
+ @Input() placeholder: string;
+ @Input() control: UntypedFormControl;
+ @Input() errors: string;
+ @Input() selectOptions: FormInputSelectOption[];
+ @Input() variant: Variant = 'light';
+ @Input() validators: {
+ validation: string;
+ message: string;
+ value?: number | string;
+ }[] = [];
+
+ @HostBinding('class.right-align') rightAlign = false;
+ @HostBinding('class.input-vertical') inputVertical = true;
+
+ @Input() config: FormInputConfig;
+
+ @Input() debounceTime: number = 0; // Time in milliseconds
+ @Output() valueChange = new EventEmitter();
+
+ public value = '';
+ private validatorsThatRequireAValue = [
+ 'min',
+ 'minLength',
+ 'maxLength',
+ 'max',
+ ];
+
+ public valueChangeSubject = new Subject();
+ private valueChangeSubscription: Subscription;
+
+ constructor(private element: ElementRef) {
+ this.subscribeToValueChanges();
+ }
+
+ ngOnChanges(changes: SimpleChanges): void {
+ // If debounceTime changes, resubscribe to apply the new debounce time
+ if (changes['debounceTime']) {
+ this.subscribeToValueChanges();
+ }
+ }
+
+ private subscribeToValueChanges() {
+ if (!this.control) {
+ if (this.valueChangeSubscription) {
+ this.valueChangeSubscription.unsubscribe(); // Prevent memory leaks
+ }
+
+ this.valueChangeSubscription = this.valueChangeSubject
+ .pipe(debounceTime(this.debounceTime))
+ .subscribe((value) => {
+ this.value = value;
+ this.valueChange.emit(value);
+ this.errors = this.getInputErrorFromValue(value);
+ });
+ }
+ }
+
+ onInputChange(value: string) {
+ this.value = value;
+ this.valueChangeSubject.next(value);
+ }
+
+ ngOnInit() {
+ if (this.control) {
+ this.control.statusChanges.subscribe(() => {
+ this.errors = getFormInputError(this);
+ });
+ }
+ if (this.config) {
+ this.rightAlign = this.config.textAlign === 'right';
+ }
+ }
+
+ isLabelHidden() {
+ switch (this.type) {
+ case 'number':
+ if (this.control) {
+ return this.control.value === '';
+ }
+ return this.value === '';
+ case 'date':
+ return false;
+ default:
+ if (this.control) {
+ return !this.control.value || !this.control.value.length;
+ }
+ return !this.value;
+ }
+ }
+
+ ngAfterViewInit() {
+ const inputField =
+ this.element.nativeElement.querySelector('.form-control');
+
+ inputField.addEventListener('blur', (event) => {
+ if (this.control) {
+ this.errors = getFormInputError(this);
+ } else {
+ this.errors = this.getInputErrorFromValue(this.value);
+ }
+ });
+
+ if (this.config) {
+ if (this.config.autocorrect) {
+ inputField.setAttribute('autocorrect', this.config.autocorrect);
+ }
+
+ if (this.config.autocomplete) {
+ inputField.setAttribute('autocomplete', this.config.autocomplete);
+ }
+
+ if (this.config.autocapitalize) {
+ inputField.setAttribute('autocapitalize', this.config.autocapitalize);
+ }
+
+ if (this.config.spellcheck) {
+ inputField.setAttribute('spellcheck', this.config.spellcheck);
+ }
+
+ if ((this.config.autoselect && this.control.value) || this.value) {
+ inputField.addEventListener('focus', (event) => {
+ inputField.setSelectionRange(0, inputField.value.length);
+ });
+ }
+
+ if (this.config.readOnly) {
+ inputField.setAttribute('readonly', true);
+ inputField.setSelectionRange(0, inputField.value.length);
+ }
+ }
+ }
+
+ getElement() {
+ return this.element;
+ }
+
+ public getInputErrorFromValue(value: string) {
+ const errorMessages = [];
+ for (let i = 0; i < this.validators.length; i++) {
+ const validator = this.validators[i];
+ let control = null;
+ if (!this.validatorsThatRequireAValue.includes(validator.validation)) {
+ control = new FormControl(value, Validators[validator.validation]);
+ } else {
+ control = new FormControl(
+ value,
+ Validators[validator.validation](validator.value)
+ );
+ }
+ if (control.invalid) {
+ errorMessages.push(validator.message);
+ }
+ }
+
+ return errorMessages.pop();
+ }
+}
diff --git a/src/app/shared/utilities/forms.ts b/src/app/shared/utilities/forms.ts
index 5a52ce52b..ba6c05dc6 100644
--- a/src/app/shared/utilities/forms.ts
+++ b/src/app/shared/utilities/forms.ts
@@ -8,6 +8,7 @@ import {
} from '@angular/forms';
import { APP_CONFIG } from '@root/app/app.config';
import { FormInputComponent } from '@shared/components/form-input/form-input.component';
+import { FormInputComponent as FormInput } from '@root/app/component-library/components/form-input/form-input.component';
import { DeviceService } from '@shared/services/device/device.service';
export function matchControlValidator(
@@ -97,7 +98,7 @@ export function setFormErrors(form: UntypedFormGroup, errors: any) {
}
}
-export function getFormInputError(formInput: FormInputComponent) {
+export function getFormInputError(formInput: FormInputComponent | FormInput) {
const control = formInput.control;
if (
diff --git a/src/assets/fonts/Usual/Usual-Bold.ttf b/src/assets/fonts/Usual/Usual-Bold.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..029e32424a55eb87c20be76eb5866e312ee583de
GIT binary patch
literal 73464
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