form builder module
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
import { Controller, Get, Post, Body, Patch, Param, Delete, UseGuards } from '@nestjs/common';
|
||||
import { ApiBearerAuth, ApiOperation } from '@nestjs/swagger';
|
||||
import { AdminAuthGuard } from '../../auth/guards/adminAuth.guard';
|
||||
import { FieldService } from '../provider/field.service';
|
||||
import { CreateFieldDto } from '../dto/create-field.dto';
|
||||
import { CreateFieldOptionDto } from '../dto/create-field-option.dto';
|
||||
import { FieldOptionService } from '../provider/field-option.service';
|
||||
import { UpdateFieldDto } from '../dto/update-field.dto';
|
||||
import { UpdateFieldOptionDto } from '../dto/update-field-option.dto';
|
||||
|
||||
@Controller('admin')
|
||||
@ApiBearerAuth()
|
||||
export class FormBuilderController {
|
||||
constructor(
|
||||
private readonly fieldService: FieldService,
|
||||
private readonly fieldOptionService: FieldOptionService,
|
||||
) { }
|
||||
|
||||
|
||||
/*================================ Field ========================== */
|
||||
|
||||
@Post('section/:id/field')
|
||||
@ApiOperation({ summary: 'Create field for section' })
|
||||
@UseGuards(AdminAuthGuard)
|
||||
createField(@Body() dto: CreateFieldDto, @Param('id') sectionId: string) {
|
||||
return this.fieldService.create(sectionId,dto);
|
||||
}
|
||||
|
||||
@Get('section/:id/field')
|
||||
@ApiOperation({ summary: 'find all secion fields' })
|
||||
@UseGuards(AdminAuthGuard)
|
||||
findAllSectionFields(@Param('id') sectionId: string) {
|
||||
return this.fieldService.findAll(+sectionId);
|
||||
}
|
||||
|
||||
@Get('section/field/:id')
|
||||
@ApiOperation({ summary: 'Find one field' })
|
||||
@UseGuards(AdminAuthGuard)
|
||||
findOneFiled(@Param('id') id: string) {
|
||||
return this.fieldService.findById(+id);
|
||||
}
|
||||
|
||||
@Patch('section/field/:id')
|
||||
@ApiOperation({ summary: 'Update field' })
|
||||
@UseGuards(AdminAuthGuard)
|
||||
updateField(@Param('id') id: string, @Body() dto: UpdateFieldDto) {
|
||||
return this.fieldService.update(+id, dto);
|
||||
}
|
||||
|
||||
@Delete('section/field/:id')
|
||||
@ApiOperation({ summary: 'Renopve field' })
|
||||
@UseGuards(AdminAuthGuard)
|
||||
removeField(@Param('id') id: string) {
|
||||
return this.fieldService.remove(+id);
|
||||
}
|
||||
|
||||
/*================================ Field Option ========================== */
|
||||
|
||||
@Post('field/:id/option')
|
||||
@ApiOperation({ summary: 'Create field Options ' })
|
||||
@UseGuards(AdminAuthGuard)
|
||||
createFieldOption(@Body() dto: CreateFieldOptionDto, @Param('id') id: string) {
|
||||
return this.fieldOptionService.create(+id, dto);
|
||||
}
|
||||
|
||||
@Get('field/:id/option')
|
||||
@ApiOperation({ summary: 'find all field Option' })
|
||||
@UseGuards(AdminAuthGuard)
|
||||
findAllFiledOptions(@Param('id') fieldId: string) {
|
||||
return this.fieldOptionService.findAll(+fieldId);
|
||||
}
|
||||
|
||||
@Get('field/option/:id')
|
||||
@ApiOperation({ summary: 'Find one field Option' })
|
||||
@UseGuards(AdminAuthGuard)
|
||||
findOneFiledOption(@Param('id') id: string) {
|
||||
return this.fieldOptionService.findById(+id);
|
||||
}
|
||||
|
||||
@Patch('field/option/:id')
|
||||
@ApiOperation({ summary: 'Update field Option' })
|
||||
@UseGuards(AdminAuthGuard)
|
||||
updateFieldOption(@Param('id') id: string, @Body() dto: UpdateFieldOptionDto) {
|
||||
return this.fieldOptionService.update(+id, dto);
|
||||
}
|
||||
|
||||
@Delete('field/option/:id')
|
||||
@ApiOperation({ summary: 'Renopve field Option' })
|
||||
@UseGuards(AdminAuthGuard)
|
||||
removeFieldOption(@Param('id') id: string) {
|
||||
return this.fieldOptionService.remove(+id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { IsString, IsOptional, IsInt, Min, IsNotEmpty } from 'class-validator';
|
||||
import { ApiPropertyOptional, ApiProperty } from '@nestjs/swagger';
|
||||
import { Type } from 'class-transformer';
|
||||
|
||||
export class CreateFieldOptionDto {
|
||||
@IsString()
|
||||
@ApiProperty()
|
||||
value: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(0)
|
||||
@Type(() => Number)
|
||||
@ApiPropertyOptional({ example: 1 })
|
||||
order?: number;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { IsString, IsOptional, IsBoolean, IsInt, Min, IsEnum, IsNotEmpty } from 'class-validator';
|
||||
import { ApiPropertyOptional, ApiProperty } from '@nestjs/swagger';
|
||||
import { Type } from 'class-transformer';
|
||||
import { FieldType } from '../interface/print';
|
||||
|
||||
export class CreateFieldDto {
|
||||
@IsString()
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
|
||||
@IsBoolean()
|
||||
@Type(() => Boolean)
|
||||
@ApiPropertyOptional({ example: true })
|
||||
isRequired: boolean;
|
||||
|
||||
@IsBoolean()
|
||||
@Type(() => Boolean)
|
||||
@ApiPropertyOptional({ example: true })
|
||||
multiple: boolean;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsEnum(FieldType)
|
||||
@ApiProperty({ enum: FieldType, example: FieldType.select })
|
||||
type: FieldType;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(0)
|
||||
@Type(() => Number)
|
||||
@ApiPropertyOptional({ example: 1 })
|
||||
order?: number;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { PartialType } from '@nestjs/swagger';
|
||||
import { CreateFieldOptionDto } from './create-field-option.dto';
|
||||
|
||||
export class UpdateFieldOptionDto extends PartialType(CreateFieldOptionDto) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
import { PartialType } from '@nestjs/swagger';
|
||||
import { CreateFieldDto } from './create-field.dto';
|
||||
|
||||
export class UpdateFieldDto extends PartialType(CreateFieldDto) { }
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Entity, Property, ManyToOne, PrimaryKey, Unique } from '@mikro-orm/core';
|
||||
import { BaseEntity } from '../../../common/entities/base.entity';
|
||||
import { Field } from './field.entity';
|
||||
|
||||
@Entity({ tableName: 'field_option' })
|
||||
export class FieldOption extends BaseEntity {
|
||||
@PrimaryKey({ autoincrement: true, type: 'bigint' })
|
||||
id: bigint;
|
||||
|
||||
@Property()
|
||||
value: string;
|
||||
|
||||
@ManyToOne(() => Field)
|
||||
field: Field;
|
||||
|
||||
@Property({ type: 'int', nullable: true })
|
||||
order?: number;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { Collection, Entity, Enum, ManyToOne, OneToMany, PrimaryKey, Property } from '@mikro-orm/core';
|
||||
import { FieldOption } from './field-option.entity';
|
||||
import { FieldType } from '../interface/print';
|
||||
import { Section } from 'src/modules/print/entities/section.entity';
|
||||
import { BaseEntity } from 'src/common/entities/base.entity';
|
||||
import { Product } from 'src/modules/product/entities/product.entity';
|
||||
|
||||
|
||||
@Entity({ tableName: 'field' })
|
||||
export class Field extends BaseEntity {
|
||||
@PrimaryKey({ type: 'bigint', autoincrement: true })
|
||||
id: bigint
|
||||
|
||||
@OneToMany(() => FieldOption, (attrValue) => attrValue.field)
|
||||
options = new Collection<FieldOption>(this)
|
||||
|
||||
@ManyToOne(() => Section, { nullable: true })
|
||||
section?: Section
|
||||
|
||||
@ManyToOne(() => Product, { nullable: true })
|
||||
product?: Product
|
||||
|
||||
@Property()
|
||||
name: string;
|
||||
|
||||
@Enum(() => FieldType)
|
||||
type: FieldType;
|
||||
|
||||
@Property({ type: 'boolean', default: false })
|
||||
isRequired: boolean = false;
|
||||
|
||||
@Property({ type: 'boolean', default: false })
|
||||
multiple: boolean = false;
|
||||
|
||||
@Property({ type: 'int', nullable: true })
|
||||
order?: number;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { FormBuilderController } from './controller/form-builder.controller';
|
||||
import { FieldService } from './provider/field.service';
|
||||
import { FieldOptionService } from './provider/field-option.service';
|
||||
import { PrintModule } from '../print/print.module';
|
||||
import { FieldRepository } from './repository/field.repository';
|
||||
import { FieldOptionRepository } from './repository/field-option.repository';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
|
||||
@Module({
|
||||
imports: [PrintModule, JwtModule.register({})],
|
||||
controllers: [FormBuilderController],
|
||||
providers: [FieldService, FieldOptionService, FieldRepository, FieldOptionRepository],
|
||||
exports: [FieldService, FieldOptionService, FieldRepository, FieldOptionRepository],
|
||||
})
|
||||
export class FormBuilderModule { }
|
||||
@@ -0,0 +1,9 @@
|
||||
export enum FieldType {
|
||||
text = 'text',
|
||||
textarea = 'textarea',
|
||||
number = 'number',
|
||||
select = 'select',
|
||||
radio = 'radio',
|
||||
checkbox = 'checkbox',
|
||||
date = 'date',
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { EntityManager } from '@mikro-orm/postgresql';
|
||||
import { RequiredEntityData } from '@mikro-orm/core';
|
||||
import { FieldRepository } from '../repository/field.repository';
|
||||
import { FieldOption } from '../entities/field-option.entity';
|
||||
import { CreateFieldOptionDto } from '../dto/create-field-option.dto';
|
||||
import { FieldOptionRepository } from '../repository/field-option.repository';
|
||||
import { UpdateFieldOptionDto } from '../dto/update-field-option.dto';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class FieldOptionService {
|
||||
|
||||
constructor(
|
||||
private readonly fieldOptionRepository: FieldOptionRepository,
|
||||
private readonly fieldRepository: FieldRepository,
|
||||
private readonly em: EntityManager,
|
||||
) { }
|
||||
|
||||
async create(fieldId: number, dto: CreateFieldOptionDto) {
|
||||
const field = await this.fieldRepository.findOne({ id: fieldId })
|
||||
|
||||
if (!field) {
|
||||
throw new BadRequestException("filed not found !")
|
||||
}
|
||||
|
||||
const data: RequiredEntityData<FieldOption> = {
|
||||
order: dto.order,
|
||||
value: dto.value,
|
||||
field
|
||||
};
|
||||
|
||||
const fieldOption = this.fieldOptionRepository.create(data)
|
||||
|
||||
await this.em.persistAndFlush(fieldOption)
|
||||
|
||||
return fieldOption
|
||||
|
||||
}
|
||||
|
||||
async update(fieldOptionId: number, dto: UpdateFieldOptionDto) {
|
||||
|
||||
const fieldOption = await this.fieldOptionRepository.findOne({ id: fieldOptionId })
|
||||
|
||||
if (!fieldOption) {
|
||||
throw new NotFoundException('fieldOption not found');
|
||||
}
|
||||
|
||||
this.fieldOptionRepository.assign(fieldOption, dto)
|
||||
|
||||
this.em.persistAndFlush(fieldOption)
|
||||
|
||||
return fieldOption
|
||||
|
||||
}
|
||||
|
||||
findAll(fieldId: number) {
|
||||
return this.fieldOptionRepository.find({ field: { id: fieldId } });
|
||||
}
|
||||
|
||||
async findById(fieldOptionId: number): Promise<FieldOption> {
|
||||
const fieldOption = await this.fieldOptionRepository.findOne({ id: fieldOptionId },
|
||||
{ populate: ['field'] });
|
||||
|
||||
if (!fieldOption) throw new NotFoundException('Field option not found');
|
||||
|
||||
return fieldOption;
|
||||
}
|
||||
|
||||
async remove(id: number): Promise<void> {
|
||||
const fieldOption = await this.findById(id);
|
||||
|
||||
fieldOption.deletedAt = new Date();
|
||||
return await this.em.persistAndFlush(fieldOption);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { EntityManager } from '@mikro-orm/postgresql';
|
||||
import { RequiredEntityData } from '@mikro-orm/core';
|
||||
import { FieldRepository } from '../repository/field.repository';
|
||||
import { SectionRepository } from 'src/modules/print/repository/section.repository';
|
||||
import { Field } from '../entities/field.entity';
|
||||
import { CreateFieldDto } from '../dto/create-field.dto';
|
||||
import { UpdateFieldDto } from '../dto/update-field.dto';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class FieldService {
|
||||
|
||||
constructor(
|
||||
private readonly sectionRepository: SectionRepository,
|
||||
private readonly fieldRepository: FieldRepository,
|
||||
private readonly em: EntityManager,
|
||||
) { }
|
||||
|
||||
async create(sectionId: string, dto: CreateFieldDto) {
|
||||
const section = await this.sectionRepository.findOne({ id: sectionId })
|
||||
|
||||
if (!section) {
|
||||
throw new BadRequestException("Section not found !")
|
||||
}
|
||||
|
||||
const data: RequiredEntityData<Field> = {
|
||||
name: dto.name,
|
||||
order: dto.order,
|
||||
type: dto.type,
|
||||
section,
|
||||
isRequired: dto.isRequired,
|
||||
multiple: dto.multiple
|
||||
};
|
||||
|
||||
const field = this.fieldRepository.create(data)
|
||||
|
||||
await this.em.persistAndFlush(field)
|
||||
|
||||
return field
|
||||
|
||||
}
|
||||
|
||||
async update(fieldId: number, dto: UpdateFieldDto) {
|
||||
|
||||
const field = await this.fieldRepository.findOne({ id: fieldId })
|
||||
|
||||
if (!field) {
|
||||
throw new NotFoundException('Field not found');
|
||||
}
|
||||
|
||||
this.sectionRepository.assign(field, dto)
|
||||
|
||||
this.em.persistAndFlush(field)
|
||||
|
||||
return field
|
||||
|
||||
}
|
||||
|
||||
findAll(sectionId: number) {
|
||||
return this.fieldRepository.find({
|
||||
section: { id: sectionId }
|
||||
},
|
||||
{ populate: ['options', 'options.value'] });
|
||||
}
|
||||
|
||||
async findById(fieldId: number): Promise<Field> {
|
||||
const field = await this.fieldRepository.findOne({ id: fieldId },
|
||||
{ populate: [] });
|
||||
|
||||
if (!field) throw new NotFoundException('Field not found');
|
||||
return field;
|
||||
}
|
||||
|
||||
async remove(id: number): Promise<void> {
|
||||
const field = await this.findById(id);
|
||||
|
||||
field.deletedAt = new Date();
|
||||
return await this.em.persistAndFlush(field);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { EntityManager, EntityRepository } from '@mikro-orm/postgresql';
|
||||
import { FieldOption } from '../entities/field-option.entity';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class FieldOptionRepository extends EntityRepository<FieldOption> {
|
||||
constructor(readonly em: EntityManager) {
|
||||
super(em, FieldOption);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { EntityManager, EntityRepository } from '@mikro-orm/postgresql';
|
||||
import { Field } from '../entities/field.entity';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class FieldRepository extends EntityRepository<Field> {
|
||||
constructor(readonly em: EntityManager) {
|
||||
super(em, Field);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user