Merge pull request #890 from Hexastack/fix/define-content-type-fields-type

fix: define a type for fields in ContentType schema
This commit is contained in:
Yassine
2025-04-12 00:04:53 +01:00
committed by GitHub
6 changed files with 59 additions and 42 deletions

View File

@@ -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,
},
],
};

View File

@@ -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) {}

View File

@@ -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({

View File

@@ -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) => {

View File

@@ -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

View File

@@ -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,
},
],
},