diff --git a/api/src/cms/controllers/content-type.controller.spec.ts b/api/src/cms/controllers/content-type.controller.spec.ts index 14dc871c..da6044a3 100644 --- a/api/src/cms/controllers/content-type.controller.spec.ts +++ b/api/src/cms/controllers/content-type.controller.spec.ts @@ -13,6 +13,7 @@ import { AttachmentRepository } from '@/attachment/repositories/attachment.repos import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; import { AttachmentService } from '@/attachment/services/attachment.service'; import { BlockService } from '@/chat/services/block.service'; +import { FieldType } from '@/setting/schemas/types'; import { NOT_FOUND_ID } from '@/utils/constants/mock'; import { getUpdateOneError } from '@/utils/test/errors/messages'; import { installContentFixtures } from '@/utils/test/fixtures/content'; @@ -100,27 +101,27 @@ describe('ContentTypeController', () => { { name: 'address', label: 'Address', - type: 'text', + type: FieldType.text, }, { name: 'image', label: 'Image', - type: 'file', + type: FieldType.file, }, { name: 'description', label: 'Description', - type: 'html', + type: FieldType.html, }, { name: 'rooms', label: 'Rooms', - type: 'file', + type: FieldType.file, }, { name: 'price', label: 'Price', - type: 'file', + type: FieldType.file, }, ], }; diff --git a/api/src/cms/dto/contentType.dto.ts b/api/src/cms/dto/contentType.dto.ts index f4f2ae25..bd6e5f0f 100644 --- a/api/src/cms/dto/contentType.dto.ts +++ b/api/src/cms/dto/contentType.dto.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -19,11 +19,12 @@ import { ValidateNested, } from 'class-validator'; +import { FieldType } from '@/setting/schemas/types'; import { DtoConfig } from '@/utils/types/dto.types'; import { ValidateRequiredFields } from '../validators/validate-required-fields.validator'; -export class FieldType { +export class ContentField { @IsString() @IsNotEmpty() @Matches(/^[a-z][a-z_0-9]*$/) @@ -34,11 +35,12 @@ export class FieldType { label: string; @IsString() - @IsEnum(['text', 'url', 'textarea', 'checkbox', 'file', 'html'], { + @IsNotEmpty() + @IsEnum(FieldType, { message: "type must be one of the following values: 'text', 'url', 'textarea', 'checkbox', 'file', 'html'", }) - type: string; + type: FieldType; } export class ContentTypeCreateDto { @@ -47,13 +49,16 @@ export class ContentTypeCreateDto { @IsNotEmpty() name: string; - @ApiPropertyOptional({ description: 'Content type fields', type: FieldType }) + @ApiPropertyOptional({ + description: 'Content type fields', + type: ContentField, + }) @IsOptional() @IsArray() @ValidateNested({ each: true }) @Validate(ValidateRequiredFields) - @Type(() => FieldType) - fields?: FieldType[]; + @Type(() => ContentField) + fields?: ContentField[]; } export class ContentTypeUpdateDto extends PartialType(ContentTypeCreateDto) {} diff --git a/api/src/cms/schemas/content-type.schema.ts b/api/src/cms/schemas/content-type.schema.ts index e1d95921..6b6b3e43 100644 --- a/api/src/cms/schemas/content-type.schema.ts +++ b/api/src/cms/schemas/content-type.schema.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -9,9 +9,12 @@ import { ModelDefinition, Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; import mongoose from 'mongoose'; +import { FieldType } from '@/setting/schemas/types'; import { BaseSchema } from '@/utils/generics/base-schema'; import { LifecycleHookManager } from '@/utils/generics/lifecycle-hook-manager'; +import { ContentField } from '../dto/contentType.dto'; + @Schema({ timestamps: true }) export class ContentType extends BaseSchema { /** @@ -30,20 +33,16 @@ export class ContentType extends BaseSchema { { name: 'title', label: 'Title', - type: 'text', + type: FieldType.text, }, { name: 'status', label: 'Status', - type: 'checkbox', + type: FieldType.checkbox, }, ], }) - fields: { - name: string; - label: string; - type: string; - }[]; + fields: ContentField[]; } export const ContentTypeModel: ModelDefinition = LifecycleHookManager.attach({ diff --git a/api/src/cms/validators/validate-required-fields.validator.ts b/api/src/cms/validators/validate-required-fields.validator.ts index 4d7cae5b..64fe33ae 100644 --- a/api/src/cms/validators/validate-required-fields.validator.ts +++ b/api/src/cms/validators/validate-required-fields.validator.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -12,24 +12,26 @@ import { ValidatorConstraintInterface, } from 'class-validator'; -import { FieldType } from '../dto/contentType.dto'; +import { FieldType } from '@/setting/schemas/types'; + +import { ContentField } from '../dto/contentType.dto'; @ValidatorConstraint({ name: 'validateRequiredFields', async: false }) export class ValidateRequiredFields implements ValidatorConstraintInterface { - private readonly REQUIRED_FIELDS: FieldType[] = [ + private readonly REQUIRED_FIELDS: ContentField[] = [ { name: 'title', label: 'Title', - type: 'text', + type: FieldType.text, }, { name: 'status', label: 'Status', - type: 'checkbox', + type: FieldType.checkbox, }, ]; - validate(fields: FieldType[]): boolean { + validate(fields: ContentField[]): boolean { const errors: string[] = []; this.REQUIRED_FIELDS.forEach((requiredField, index) => { diff --git a/api/src/setting/schemas/types.ts b/api/src/setting/schemas/types.ts index fbf30493..f53aa8d8 100644 --- a/api/src/setting/schemas/types.ts +++ b/api/src/setting/schemas/types.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -20,6 +20,15 @@ export enum SettingType { multiple_attachment = 'multiple_attachment', } +export enum FieldType { + text = 'text', + url = 'url', + textarea = 'textarea', + checkbox = 'checkbox', + file = 'file', + html = 'html', +} + /** * The following interfaces are declared, and currently not used * TextSetting diff --git a/api/src/utils/test/fixtures/contenttype.ts b/api/src/utils/test/fixtures/contenttype.ts index 8c295b05..016bc323 100644 --- a/api/src/utils/test/fixtures/contenttype.ts +++ b/api/src/utils/test/fixtures/contenttype.ts @@ -13,6 +13,7 @@ import { ContentType, ContentTypeModel, } from '@/cms/schemas/content-type.schema'; +import { FieldType } from '@/setting/schemas/types'; import { getFixturesWithDefaultValues } from '../defaultValues'; import { FixturesTypeBuilder } from '../types'; @@ -27,12 +28,12 @@ export const contentTypeDefaultValues: TContentTypeFixtures['defaultValues'] = { { name: 'title', label: 'Title', - type: 'text', + type: FieldType.text, }, { name: 'status', label: 'Status', - type: 'checkbox', + type: FieldType.checkbox, }, ], }; @@ -44,27 +45,27 @@ const contentTypes: TContentTypeFixtures['values'][] = [ { name: 'title', label: 'Title', - type: 'text', + type: FieldType.text, }, { name: 'status', label: 'Status', - type: 'checkbox', + type: FieldType.checkbox, }, { name: 'description', label: 'Description', - type: 'text', + type: FieldType.text, }, { name: 'image', label: 'Image', - type: 'file', + type: FieldType.file, }, { name: 'subtitle', label: 'Image', - type: 'file', + type: FieldType.file, }, ], }, @@ -74,22 +75,22 @@ const contentTypes: TContentTypeFixtures['values'][] = [ { name: 'title', label: 'Title', - type: 'text', + type: FieldType.text, }, { name: 'status', label: 'Status', - type: 'checkbox', + type: FieldType.checkbox, }, { name: 'address', label: 'Address', - type: 'text', + type: FieldType.text, }, { name: 'image', label: 'Image', - type: 'file', + type: FieldType.file, }, ], }, @@ -99,22 +100,22 @@ const contentTypes: TContentTypeFixtures['values'][] = [ { name: 'title', label: 'Title', - type: 'text', + type: FieldType.text, }, { name: 'status', label: 'Status', - type: 'checkbox', + type: FieldType.checkbox, }, { name: 'address', label: 'Address', - type: 'text', + type: FieldType.text, }, { name: 'image', label: 'Image', - type: 'file', + type: FieldType.file, }, ], },