Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -121,23 +121,14 @@ describe('AccountSettingsComponent', () => {
});

describe('Main form tests', () => {
it('initializes the form with default values', async () => {
component.ngOnInit();
fixture.detectChanges();

// Wait for async observable subscription and form patching to complete
await fixture.whenStable();

// Trigger change detection after async updates
fixture.detectChanges();

it('initializes the form with default values', () => {
const formValue = component.form.getRawValue();
expect(formValue.name).toBe(userResponse.attributes.name);
expect(formValue.email).toBe(userResponse.attributes.email);
expect(formValue.registeredSince).toBe('08/04/2025 6:25:56');
});

it('validates email as required', async () => {
it('validates email as required', () => {
const emailControl = component.form.get('email');
emailControl?.patchValue(null);
component.form.updateValueAndValidity();
Expand Down
26 changes: 13 additions & 13 deletions src/app/core/_components/forms/simple-forms/form.component.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { Subscription } from 'rxjs';
import { GlobalService } from 'src/app/core/_services/main.service';
import { MetadataService } from 'src/app/core/_services/metadata.service';
import { AlertService } from 'src/app/core/_services/shared/alert.service';
import { AutoTitleService } from 'src/app/core/_services/shared/autotitle.service';
import { UnsubscribeService } from 'src/app/core/_services/unsubscribe.service';

import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { ActivatedRoute, Params, Router } from '@angular/router';

import { BaseModel } from '@models/base.model';
import { ResponseWrapper } from '@models/response.model';

import { JsonAPISerializer } from '@services/api/serializer-service';
import { ConfirmDialogService } from '@services/confirm/confirm-dialog.service';
import { ServiceConfig } from '@services/main.config';
import { GlobalService } from '@services/main.service';
import { MetadataService } from '@services/metadata.service';
import { AlertService } from '@services/shared/alert.service';
import { AutoTitleService } from '@services/shared/autotitle.service';
import { UnsubscribeService } from '@services/unsubscribe.service';

@Component({
selector: 'app-form',
Expand All @@ -25,7 +26,8 @@ import { ServiceConfig } from '@services/main.config';
*/
export class FormComponent implements OnInit, OnDestroy {
// Metadata Text, titles, subtitles, forms, and API path
globalMetadata: any[] = [];
globalMetadata: ReturnType<MetadataService['getInfoMetadata']>[0];

serviceConfig: ServiceConfig;

/**
Expand Down Expand Up @@ -78,16 +80,14 @@ export class FormComponent implements OnInit, OnDestroy {
/**
* An array of form field metadata that describes the form structure.
* Each item in the array represents a form field, including its type, label, and other properties.
* @type {any[]}
*/
formMetadata: any[] = [];
formMetadata: ReturnType<MetadataService['getFormMetadata']> = [];

/**
* Initial values for form fields (optional).
* If provided, these values are used to initialize form controls in the dynamic form.
* @type {any[]}
*/
formValues: any[] = [];
formValues: (BaseModel & Record<string, unknown>)[] = [];

// Subscription for managing asynchronous data retrieval
private subscriptionService: Subscription;
Expand Down Expand Up @@ -128,7 +128,7 @@ export class FormComponent implements OnInit, OnDestroy {
this.formMetadata = this.metadataService.getFormMetadata(formKind);
this.title = this.globalMetadata['title'];
this.customform = this.globalMetadata['customform'];
titleService.set([this.title]);
this.titleService.set([this.title]);
// Load metadata and form information
if (this.type === 'edit') {
this.getIndex();
Expand Down Expand Up @@ -199,7 +199,7 @@ export class FormComponent implements OnInit, OnDestroy {
* Handles the submission of the form.
* @param formValues - The values submitted from the form.
*/
onFormSubmit(formValues: any) {
onFormSubmit(formValues: (BaseModel & Record<string, unknown>)[]) {
if (this.customform) {
this.modifyFormValues(formValues);
}
Expand All @@ -226,7 +226,7 @@ export class FormComponent implements OnInit, OnDestroy {
* @param formValues - The form values to be modified.
* @returns The modified form values.
*/
modifyFormValues(formValues: any) {
modifyFormValues(formValues: (BaseModel | Record<string, unknown>)[]) {
// Check the formMetadata for fields with 'replacevalue' property
this.getIndex();
for (const field of this.formMetadata) {
Expand Down
37 changes: 21 additions & 16 deletions src/app/core/_components/forms/simple-forms/formconfig.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,22 @@ import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';

import { JConfig } from '@models/configs.model';
import { HorizontalNav } from '@models/horizontalnav.model';
import { ResponseWrapper } from '@models/response.model';

import { JsonAPISerializer } from '@services/api/serializer-service';
import { SERV, ServiceConfig } from '@services/main.config';
import { GlobalService } from '@services/main.service';
import { MetadataService } from '@services/metadata.service';
import { InfoMetadataForm, MetadataFormField, MetadataService } from '@services/metadata.service';
import { AlertService } from '@services/shared/alert.service';
import { AutoTitleService } from '@services/shared/autotitle.service';
import { UIConfigService } from '@services/shared/storage.service';
import { UnsubscribeService } from '@services/unsubscribe.service';

type ConfigValues = Record<string, string | boolean>;
type ConfigIds = Record<string, number>;

@Component({
selector: 'app-form',
templateUrl: 'formconfig.component.html',
Expand All @@ -26,7 +30,7 @@ import { UnsubscribeService } from '@services/unsubscribe.service';
*/
export class FormConfigComponent implements OnInit, OnDestroy {
// Metadata Text, titles, subtitles, forms, and API path
globalMetadata: any[] = [];
globalMetadata: InfoMetadataForm;
serviceConfig: ServiceConfig;

/**
Expand All @@ -51,23 +55,21 @@ export class FormConfigComponent implements OnInit, OnDestroy {
/**
* An array of form field metadata that describes the form structure.
* Each item in the array represents a form field, including its type, label, and other properties.
* @type {any[]}
*/
formMetadata: any[] = [];
formMetadata: MetadataFormField[] = [];

/**
* Initial values for form fields (optional).
* If provided, these values are used to initialize form controls in the dynamic form.
* @type {any[]}

*/
formValues: any[] = [];
formValues: object;

/**
* An array of objects containing IDs and corresponding item names.
* This information is used to map form field names to their associated IDs.
* @type {any[]}
*/
formIds: any[] = [];
formIds: ConfigIds = {};

// Subscription for managing asynchronous data retrieval
private mySubscription: Subscription;
Expand Down Expand Up @@ -135,19 +137,22 @@ export class FormConfigComponent implements OnInit, OnDestroy {
.getAll(this.serviceConfig, { page: { size: 500 } })
.subscribe((response: ResponseWrapper) => {
const responseBody = { data: response.data, included: response.included };
const configValues = this.serializer.deserialize(responseBody) as any[];
const config = this.serializer.deserialize<JConfig[]>(responseBody);

this.formValues = config.reduce<ConfigValues>((configValues, item) => {
let value: string | boolean = item.value;

this.formValues = configValues.reduce((configValues, item) => {
if (item.value === '1') {
item.value = true;
value = true;
} else if (item.value === '0') {
item.value = false;
value = false;
}
configValues[item.item] = item.value;

configValues[item.item] = value;
return configValues;
}, {});
// Maps the item with the id, so can be used for update
this.formIds = configValues.reduce((result, item) => {
this.formIds = config.reduce<ConfigIds>((result, item) => {
result[item.item] = item.id;
return result;
}, {});
Expand All @@ -168,10 +173,10 @@ export class FormConfigComponent implements OnInit, OnDestroy {
* Handles the submission of the form.
* @param form - The form object containing the updated values.
*/
onFormSubmit(form: any) {
onFormSubmit(form: FormGroup) {
const currentFormValues = form;
const initialFormValues = this.formValues;
const changedFields: Record<string, any> = {};
const changedFields: Record<string, unknown> = {};

for (const key in currentFormValues) {
if (Object.prototype.hasOwnProperty.call(currentFormValues, key)) {
Expand Down
8 changes: 8 additions & 0 deletions src/app/core/_constants/settings.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ export interface Setting {
description: string;
}

/**
* Options for select inputs, used in various settings
*/
export interface Option {
label: string;
value: number | string | boolean;
}

export const dateFormats: Setting[] = [
{ value: 'd/M/yy', description: 'd/M/yy (ie. 6/7/23 )' },
{
Expand Down
Loading