update for sql based backend
This commit is contained in:
parent
93b6596b1b
commit
356ebb80c1
@ -6,6 +6,9 @@
|
|||||||
| SECRET_KEY | `changeMe` | JWT Secret for authentication |
|
| SECRET_KEY | `changeMe` | JWT Secret for authentication |
|
||||||
| CLI | *automatically* | activates pretty print for log output |
|
| CLI | *automatically* | activates pretty print for log output |
|
||||||
| NODE_ENV | `production` | |
|
| NODE_ENV | `production` | |
|
||||||
|
| HIDE_CONTRIB | `false` | decide if backlings to ohmyform should be added |
|
||||||
|
| SIGNUP_DISABLED | `false` | if users can sign up |
|
||||||
|
| LOGIN_NOTE | *not set* | Info box on top of login screen |
|
||||||
|
|
||||||
## Mailing
|
## Mailing
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
import { Field, InputType } from '@nestjs/graphql'
|
import { Field, ID, InputType } from '@nestjs/graphql'
|
||||||
|
|
||||||
@InputType()
|
@InputType()
|
||||||
export class ButtonInput {
|
export class ButtonInput {
|
||||||
|
@Field(() => ID, { nullable: true })
|
||||||
|
readonly id?: string
|
||||||
|
|
||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
readonly url?: string
|
readonly url?: string
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
import { Field, ObjectType } from '@nestjs/graphql'
|
import { Field, ID, ObjectType } from '@nestjs/graphql'
|
||||||
import { PageButtonEntity } from '../../entity/page.button.entity'
|
import { PageButtonEntity } from '../../entity/page.button.entity'
|
||||||
|
|
||||||
@ObjectType('Button')
|
@ObjectType('Button')
|
||||||
export class ButtonModel {
|
export class ButtonModel {
|
||||||
|
@Field(() => ID)
|
||||||
|
readonly id: string
|
||||||
|
|
||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
readonly url?: string
|
readonly url?: string
|
||||||
|
|
||||||
@ -22,6 +25,7 @@ export class ButtonModel {
|
|||||||
readonly color?: string
|
readonly color?: string
|
||||||
|
|
||||||
constructor(button: Partial<PageButtonEntity>) {
|
constructor(button: Partial<PageButtonEntity>) {
|
||||||
|
this.id = button.id.toString()
|
||||||
this.url = button.url
|
this.url = button.url
|
||||||
this.action = button.action
|
this.action = button.action
|
||||||
this.text = button.text
|
this.text = button.text
|
||||||
|
|||||||
@ -22,11 +22,11 @@ export class ColorsModel {
|
|||||||
readonly buttonText: string
|
readonly buttonText: string
|
||||||
|
|
||||||
constructor(partial: Partial<ColorsEmbedded>) {
|
constructor(partial: Partial<ColorsEmbedded>) {
|
||||||
this.background = partial.background
|
this.background = partial.background ?? '#fff'
|
||||||
this.question = partial.question
|
this.question = partial.question ?? '#333'
|
||||||
this.answer = partial.answer
|
this.answer = partial.answer ?? '#333'
|
||||||
this.button = partial.button
|
this.button = partial.button ?? '#fff'
|
||||||
this.buttonActive = partial.buttonActive
|
this.buttonActive = partial.buttonActive ?? '#40a9ff'
|
||||||
this.buttonText = partial.buttonText
|
this.buttonText = partial.buttonText ?? '#666'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,9 @@ export class FormFieldInput {
|
|||||||
@Field()
|
@Field()
|
||||||
readonly value: string
|
readonly value: string
|
||||||
|
|
||||||
|
@Field({ nullable: true })
|
||||||
|
readonly disabled?: boolean
|
||||||
|
|
||||||
@Field(() => [FormFieldOptionInput], { nullable: true })
|
@Field(() => [FormFieldOptionInput], { nullable: true })
|
||||||
readonly options: FormFieldOptionInput[]
|
readonly options: FormFieldOptionInput[]
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,9 @@ import { Field, ID, InputType } from '@nestjs/graphql'
|
|||||||
|
|
||||||
@InputType()
|
@InputType()
|
||||||
export class FormFieldLogicInput {
|
export class FormFieldLogicInput {
|
||||||
|
@Field(() => ID, { nullable: true })
|
||||||
|
readonly id?: string
|
||||||
|
|
||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
readonly formula: string
|
readonly formula: string
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
import { Field, InputType } from '@nestjs/graphql'
|
import { Field, ID, InputType } from '@nestjs/graphql'
|
||||||
|
|
||||||
@InputType()
|
@InputType()
|
||||||
export class FormFieldOptionInput {
|
export class FormFieldOptionInput {
|
||||||
|
@Field(() => ID, { nullable: true })
|
||||||
|
readonly id?: string
|
||||||
|
|
||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
readonly key: string
|
readonly key: string
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
import { Field, ObjectType } from '@nestjs/graphql'
|
import { Field, ID, ObjectType } from '@nestjs/graphql'
|
||||||
import { FormFieldOptionEntity } from '../../entity/form.field.option.entity'
|
import { FormFieldOptionEntity } from '../../entity/form.field.option.entity'
|
||||||
|
|
||||||
@ObjectType('FormFieldOption')
|
@ObjectType('FormFieldOption')
|
||||||
export class FormFieldOptionModel {
|
export class FormFieldOptionModel {
|
||||||
|
@Field(() => ID)
|
||||||
|
readonly id: string
|
||||||
|
|
||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
readonly key: string
|
readonly key: string
|
||||||
|
|
||||||
@ -13,6 +16,7 @@ export class FormFieldOptionModel {
|
|||||||
readonly value: string
|
readonly value: string
|
||||||
|
|
||||||
constructor(option: FormFieldOptionEntity) {
|
constructor(option: FormFieldOptionEntity) {
|
||||||
|
this.id = option.id.toString()
|
||||||
this.key = option.key
|
this.key = option.key
|
||||||
this.title = option.title
|
this.title = option.title
|
||||||
this.value = option.value
|
this.value = option.value
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
import { Field, InputType } from '@nestjs/graphql'
|
import { Field, ID, InputType } from '@nestjs/graphql'
|
||||||
|
|
||||||
@InputType('FormNotificationInput')
|
@InputType('FormNotificationInput')
|
||||||
export class FormNotificationInput {
|
export class FormNotificationInput {
|
||||||
|
@Field(() => ID, { nullable: true })
|
||||||
|
readonly id?: string
|
||||||
|
|
||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
readonly subject?: string
|
readonly subject?: string
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
import { Field, InterfaceType } from '@nestjs/graphql'
|
import { Field, ID, InterfaceType, ObjectType } from '@nestjs/graphql'
|
||||||
import { FormNotificationEntity } from '../../entity/form.notification.entity'
|
import { FormNotificationEntity } from '../../entity/form.notification.entity'
|
||||||
|
|
||||||
@InterfaceType('FormNotification')
|
@ObjectType('FormNotification')
|
||||||
export class FormNotificationModel {
|
export class FormNotificationModel {
|
||||||
|
@Field(() => ID)
|
||||||
|
readonly id: string
|
||||||
|
|
||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
readonly subject?: string
|
readonly subject?: string
|
||||||
|
|
||||||
@ -25,6 +28,7 @@ export class FormNotificationModel {
|
|||||||
readonly enabled: boolean
|
readonly enabled: boolean
|
||||||
|
|
||||||
constructor(partial: Partial<FormNotificationEntity>) {
|
constructor(partial: Partial<FormNotificationEntity>) {
|
||||||
|
this.id = partial.id.toString()
|
||||||
this.subject = partial.subject
|
this.subject = partial.subject
|
||||||
this.htmlTemplate = partial.htmlTemplate
|
this.htmlTemplate = partial.htmlTemplate
|
||||||
this.enabled = partial.enabled
|
this.enabled = partial.enabled
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
import { Field, InputType } from '@nestjs/graphql'
|
import { Field, ID, InputType } from '@nestjs/graphql'
|
||||||
import { ButtonInput } from './button.input'
|
import { ButtonInput } from './button.input'
|
||||||
|
|
||||||
@InputType()
|
@InputType()
|
||||||
export class PageInput {
|
export class PageInput {
|
||||||
|
@Field(() => ID, { nullable: true })
|
||||||
|
readonly id?: string
|
||||||
|
|
||||||
@Field()
|
@Field()
|
||||||
readonly show: boolean
|
readonly show: boolean
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,13 @@
|
|||||||
import { Field, ObjectType } from '@nestjs/graphql'
|
import { Field, ID, ObjectType } from '@nestjs/graphql'
|
||||||
|
import { randomBytes } from 'crypto'
|
||||||
import { PageEntity } from '../../entity/page.entity'
|
import { PageEntity } from '../../entity/page.entity'
|
||||||
import { ButtonModel } from './button.model'
|
import { ButtonModel } from './button.model'
|
||||||
|
|
||||||
@ObjectType('Page')
|
@ObjectType('Page')
|
||||||
export class PageModel {
|
export class PageModel {
|
||||||
|
@Field(() => ID)
|
||||||
|
readonly id: string
|
||||||
|
|
||||||
@Field()
|
@Field()
|
||||||
readonly show: boolean
|
readonly show: boolean
|
||||||
|
|
||||||
@ -20,10 +24,18 @@ export class PageModel {
|
|||||||
readonly buttons: ButtonModel[]
|
readonly buttons: ButtonModel[]
|
||||||
|
|
||||||
constructor(page: Partial<PageEntity>) {
|
constructor(page: Partial<PageEntity>) {
|
||||||
|
if (!page) {
|
||||||
|
this.id = Math.random().toString()
|
||||||
|
this.show = false
|
||||||
|
this.buttons = []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.id = page.id.toString()
|
||||||
this.show = page.show
|
this.show = page.show
|
||||||
this.title = page.title
|
this.title = page.title
|
||||||
this.paragraph = page.paragraph
|
this.paragraph = page.paragraph
|
||||||
this.buttonText = page.buttonText
|
this.buttonText = page.buttonText
|
||||||
this.buttons = page.buttons.map(button => new ButtonModel(button))
|
this.buttons = (page.buttons || []).map(button => new ButtonModel(button))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,22 +37,22 @@ export class FormEntity {
|
|||||||
@OneToMany(() => SubmissionEntity, submission => submission.form)
|
@OneToMany(() => SubmissionEntity, submission => submission.form)
|
||||||
public submissions: SubmissionEntity[]
|
public submissions: SubmissionEntity[]
|
||||||
|
|
||||||
@OneToMany(() => FormFieldEntity, field => field.form, { eager: true, orphanedRowAction: 'delete' })
|
@OneToMany(() => FormFieldEntity, field => field.form, { eager: true, orphanedRowAction: 'delete', cascade: true })
|
||||||
public fields: FormFieldEntity[]
|
public fields: FormFieldEntity[]
|
||||||
|
|
||||||
@OneToMany(() => FormHookEntity, field => field.form, { eager: true, orphanedRowAction: 'delete' })
|
@OneToMany(() => FormHookEntity, field => field.form, { eager: true, orphanedRowAction: 'delete', cascade: true })
|
||||||
public hooks: FormHookEntity[]
|
public hooks: FormHookEntity[]
|
||||||
|
|
||||||
@ManyToOne(() => UserEntity, { eager: true })
|
@ManyToOne(() => UserEntity, { eager: true })
|
||||||
public admin: UserEntity
|
public admin: UserEntity
|
||||||
|
|
||||||
@ManyToOne(() => PageEntity, { eager: true })
|
@ManyToOne(() => PageEntity, { eager: true, cascade: true })
|
||||||
public startPage: PageEntity;
|
public startPage: PageEntity;
|
||||||
|
|
||||||
@ManyToOne(() => PageEntity, { eager: true })
|
@ManyToOne(() => PageEntity, { eager: true, cascade: true })
|
||||||
public endPage: PageEntity;
|
public endPage: PageEntity;
|
||||||
|
|
||||||
@OneToMany(() => FormNotificationEntity, notification => notification.form, { eager: true, orphanedRowAction: 'delete' })
|
@OneToMany(() => FormNotificationEntity, notification => notification.form, { eager: true, orphanedRowAction: 'delete', cascade: true })
|
||||||
public notifications: FormNotificationEntity[]
|
public notifications: FormNotificationEntity[]
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
|
|||||||
@ -33,8 +33,8 @@ export class FormFieldEntity {
|
|||||||
@Column()
|
@Column()
|
||||||
public required: boolean
|
public required: boolean
|
||||||
|
|
||||||
@Column()
|
@Column({ type: 'boolean' })
|
||||||
public disabled: boolean
|
public disabled = false
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
public type: string
|
public type: string
|
||||||
|
|||||||
@ -11,23 +11,23 @@ export class FormNotificationEntity {
|
|||||||
public form: FormEntity
|
public form: FormEntity
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
readonly subject?: string
|
public subject?: string
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
readonly htmlTemplate?: string
|
public htmlTemplate?: string
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
readonly enabled: boolean
|
public enabled: boolean
|
||||||
|
|
||||||
@ManyToOne(() => FormFieldEntity)
|
@ManyToOne(() => FormFieldEntity)
|
||||||
readonly fromField?: FormFieldEntity
|
public fromField?: FormFieldEntity
|
||||||
|
|
||||||
@ManyToOne(() => FormFieldEntity)
|
@ManyToOne(() => FormFieldEntity)
|
||||||
readonly toField?: FormFieldEntity
|
public toField?: FormFieldEntity
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
readonly toEmail?: string
|
public toEmail?: string
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
readonly fromEmail?: string
|
public fromEmail?: string
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,20 +10,20 @@ export class PageButtonEntity {
|
|||||||
public page: PageEntity
|
public page: PageEntity
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
readonly url?: string
|
public url?: string
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
readonly action?: string
|
public action?: string
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
readonly text: string
|
public text: string
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
readonly bgColor?: string
|
public bgColor?: string
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
readonly activeColor?: string
|
public activeColor?: string
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
readonly color?: string
|
public color?: string
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,17 +7,17 @@ export class PageEntity {
|
|||||||
public id: number
|
public id: number
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
readonly show: boolean
|
public show: boolean
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
readonly title?: string
|
public title?: string
|
||||||
|
|
||||||
@Column({ type: 'text', nullable: true })
|
@Column({ type: 'text', nullable: true })
|
||||||
readonly paragraph?: string
|
public paragraph?: string
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
readonly buttonText?: string
|
public buttonText?: string
|
||||||
|
|
||||||
@OneToMany(() => PageButtonEntity, button => button.page)
|
@OneToMany(() => PageButtonEntity, button => button.page, { eager: true, orphanedRowAction: 'delete', cascade: true })
|
||||||
readonly buttons: PageButtonEntity[]
|
public buttons: PageButtonEntity[]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import { FormService } from '../../service/form/form.service'
|
|||||||
import { ContextCache } from '../context.cache'
|
import { ContextCache } from '../context.cache'
|
||||||
|
|
||||||
@Resolver(() => FormModel)
|
@Resolver(() => FormModel)
|
||||||
export class FormResolver {
|
export class FormQuery {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly formService: FormService,
|
private readonly formService: FormService,
|
||||||
) {
|
) {
|
||||||
|
|||||||
@ -113,11 +113,6 @@ export class FormResolver {
|
|||||||
): Promise<UserModel> {
|
): Promise<UserModel> {
|
||||||
const form = await cache.get(cache.getCacheKey(FormEntity.name, parent.id))
|
const form = await cache.get(cache.getCacheKey(FormEntity.name, parent.id))
|
||||||
|
|
||||||
if (!form.populated('admin')) {
|
|
||||||
form.populate('admin')
|
|
||||||
await form.execPopulate()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!form.admin) {
|
if (!form.admin) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Args, Context, Query, Resolver } from '@nestjs/graphql'
|
import { Args, Context, Query, Resolver } from '@nestjs/graphql'
|
||||||
import { GraphQLInt } from 'graphql'
|
import { GraphQLInt } from 'graphql'
|
||||||
|
import { Roles } from '../../decorator/roles.decorator'
|
||||||
import { User } from '../../decorator/user.decorator'
|
import { User } from '../../decorator/user.decorator'
|
||||||
import { FormModel } from '../../dto/form/form.model'
|
import { FormModel } from '../../dto/form/form.model'
|
||||||
import { FormPagerModel } from '../../dto/form/form.pager.model'
|
import { FormPagerModel } from '../../dto/form/form.pager.model'
|
||||||
@ -16,12 +17,13 @@ export class FormSearchResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Query(() => FormPagerModel)
|
@Query(() => FormPagerModel)
|
||||||
|
@Roles('user')
|
||||||
async listForms(
|
async listForms(
|
||||||
@User() user: UserEntity,
|
@User() user: UserEntity,
|
||||||
@Args('start', {type: () => GraphQLInt, defaultValue: 0, nullable: true}) start: number,
|
@Args('start', {type: () => GraphQLInt, defaultValue: 0, nullable: true}) start: number,
|
||||||
@Args('limit', {type: () => GraphQLInt, defaultValue: 50, nullable: true}) limit: number,
|
@Args('limit', {type: () => GraphQLInt, defaultValue: 50, nullable: true}) limit: number,
|
||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
) {
|
): Promise<FormPagerModel> {
|
||||||
const [forms, total] = await this.formService.find(
|
const [forms, total] = await this.formService.find(
|
||||||
start,
|
start,
|
||||||
limit,
|
limit,
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { FormCreateMutation } from './form.create.mutation'
|
import { FormCreateMutation } from './form.create.mutation'
|
||||||
import { FormDeleteMutation } from './form.delete.mutation'
|
import { FormDeleteMutation } from './form.delete.mutation'
|
||||||
|
import { FormQuery } from './form.query'
|
||||||
import { FormResolver } from './form.resolver'
|
import { FormResolver } from './form.resolver'
|
||||||
import { FormSearchResolver } from './form.search.resolver'
|
import { FormSearchResolver } from './form.search.resolver'
|
||||||
import { FormStatisticResolver } from './form.statistic.resolver'
|
import { FormStatisticResolver } from './form.statistic.resolver'
|
||||||
@ -8,6 +9,7 @@ import { FormUpdateMutation } from './form.update.mutation'
|
|||||||
export const formResolvers = [
|
export const formResolvers = [
|
||||||
FormCreateMutation,
|
FormCreateMutation,
|
||||||
FormDeleteMutation,
|
FormDeleteMutation,
|
||||||
|
FormQuery,
|
||||||
FormResolver,
|
FormResolver,
|
||||||
FormSearchResolver,
|
FormSearchResolver,
|
||||||
FormStatisticResolver,
|
FormStatisticResolver,
|
||||||
|
|||||||
@ -36,6 +36,8 @@ export class AuthService {
|
|||||||
username: user.username,
|
username: user.username,
|
||||||
roles: user.roles,
|
roles: user.roles,
|
||||||
sub: user.id,
|
sub: user.id,
|
||||||
|
}, {
|
||||||
|
expiresIn: '4h',
|
||||||
}),
|
}),
|
||||||
refreshToken: this.jwtService.sign({
|
refreshToken: this.jwtService.sign({
|
||||||
sub: user.id,
|
sub: user.id,
|
||||||
|
|||||||
@ -17,9 +17,9 @@ export class FormCreateService {
|
|||||||
const form = new FormEntity()
|
const form = new FormEntity()
|
||||||
|
|
||||||
form.title = input.title
|
form.title = input.title
|
||||||
form.isLive = input.isLive
|
form.isLive = Boolean(input.isLive)
|
||||||
form.showFooter = input.showFooter
|
form.showFooter = Boolean(input.showFooter)
|
||||||
form.language = input.language
|
form.language = input.language || 'en'
|
||||||
|
|
||||||
form.admin = admin
|
form.admin = admin
|
||||||
|
|
||||||
|
|||||||
@ -13,6 +13,10 @@ export class FormService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async isAdmin(form: FormEntity, user: UserEntity): Promise<boolean> {
|
async isAdmin(form: FormEntity, user: UserEntity): Promise<boolean> {
|
||||||
|
if (!user) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
if (user.roles.includes('superuser')) {
|
if (user.roles.includes('superuser')) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -23,6 +27,8 @@ export class FormService {
|
|||||||
async find(start: number, limit: number, sort: any = {}, user?: UserEntity): Promise<[FormEntity[], number]> {
|
async find(start: number, limit: number, sort: any = {}, user?: UserEntity): Promise<[FormEntity[], number]> {
|
||||||
const qb = this.formRepository.createQueryBuilder('f')
|
const qb = this.formRepository.createQueryBuilder('f')
|
||||||
|
|
||||||
|
qb.leftJoinAndSelect('f.admin', 'a')
|
||||||
|
|
||||||
if (user) {
|
if (user) {
|
||||||
qb.where('f.admin = :user', { user: user.id })
|
qb.where('f.admin = :user', { user: user.id })
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,12 @@ import { Repository } from 'typeorm'
|
|||||||
import { FormUpdateInput } from '../../dto/form/form.update.input'
|
import { FormUpdateInput } from '../../dto/form/form.update.input'
|
||||||
import { FormEntity } from '../../entity/form.entity'
|
import { FormEntity } from '../../entity/form.entity'
|
||||||
import { FormFieldEntity } from '../../entity/form.field.entity'
|
import { FormFieldEntity } from '../../entity/form.field.entity'
|
||||||
|
import { FormFieldLogicEntity } from '../../entity/form.field.logic.entity'
|
||||||
|
import { FormFieldOptionEntity } from '../../entity/form.field.option.entity'
|
||||||
import { FormHookEntity } from '../../entity/form.hook.entity'
|
import { FormHookEntity } from '../../entity/form.hook.entity'
|
||||||
|
import { FormNotificationEntity } from '../../entity/form.notification.entity'
|
||||||
|
import { PageButtonEntity } from '../../entity/page.button.entity'
|
||||||
|
import { PageEntity } from '../../entity/page.entity'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FormUpdateService {
|
export class FormUpdateService {
|
||||||
@ -35,36 +40,83 @@ export class FormUpdateService {
|
|||||||
form.isLive = input.isLive
|
form.isLive = input.isLive
|
||||||
}
|
}
|
||||||
|
|
||||||
const fieldMapping = {}
|
|
||||||
|
|
||||||
if (input.fields !== undefined) {
|
if (input.fields !== undefined) {
|
||||||
form.fields = await Promise.all(input.fields.map(async (nextField) => {
|
form.fields = await Promise.all(input.fields.map(async (nextField) => {
|
||||||
let field = form.fields.find(field => field.id.toString() === nextField.id)
|
let field = form.fields.find(field => field.id?.toString() === nextField.id)
|
||||||
|
|
||||||
if (!field) {
|
if (!field) {
|
||||||
field = new FormFieldEntity()
|
field = new FormFieldEntity()
|
||||||
field.type = nextField.type
|
field.type = nextField.type
|
||||||
}
|
}
|
||||||
|
|
||||||
// ability for other fields to apply mapping
|
if (nextField.title !== undefined) {
|
||||||
fieldMapping[nextField.id] = field.id.toString()
|
|
||||||
field.title = nextField.title
|
field.title = nextField.title
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextField.description !== undefined) {
|
||||||
field.description = nextField.description
|
field.description = nextField.description
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextField.disabled !== undefined) {
|
||||||
|
field.disabled = nextField.disabled
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextField.required !== undefined) {
|
||||||
field.required = nextField.required
|
field.required = nextField.required
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextField.value !== undefined) {
|
||||||
field.value = nextField.value
|
field.value = nextField.value
|
||||||
|
}
|
||||||
|
|
||||||
if (nextField.slug !== undefined) {
|
if (nextField.slug !== undefined) {
|
||||||
field.slug = nextField.slug
|
field.slug = nextField.slug
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextField.logic !== undefined) {
|
if (nextField.logic !== undefined) {
|
||||||
// TODO prepare logic entries
|
field.logic = nextField.logic.map(nextLogic => {
|
||||||
// field.logicJump = nextField.logicJump
|
const logic = field.logic?.find(logic => logic.id?.toString() === nextLogic.id) || new FormFieldLogicEntity()
|
||||||
|
|
||||||
|
logic.field = field
|
||||||
|
|
||||||
|
if (nextLogic.formula !== undefined) {
|
||||||
|
logic.formula = nextLogic.formula
|
||||||
|
}
|
||||||
|
if (nextLogic.action !== undefined) {
|
||||||
|
logic.action = nextLogic.action as any
|
||||||
|
}
|
||||||
|
if (nextLogic.visible !== undefined) {
|
||||||
|
logic.visible = nextLogic.visible
|
||||||
|
}
|
||||||
|
if (nextLogic.require !== undefined) {
|
||||||
|
logic.require = nextLogic.require
|
||||||
|
}
|
||||||
|
if (nextLogic.disable !== undefined) {
|
||||||
|
logic.disable = nextLogic.disable
|
||||||
|
}
|
||||||
|
if (nextLogic.jumpTo !== undefined) {
|
||||||
|
logic.jumpTo = form.fields.find(value => value.id?.toString() === nextLogic.jumpTo)
|
||||||
|
}
|
||||||
|
if (nextLogic.enabled !== undefined) {
|
||||||
|
logic.enabled = nextLogic.enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
return logic
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextField.options !== undefined) {
|
if (nextField.options !== undefined) {
|
||||||
// TODO prepare options
|
field.options = nextField.options.map(nextOption => {
|
||||||
// field.options = nextField.options
|
const option = field.options?.find(option => option.id?.toString() === nextOption.id) || new FormFieldOptionEntity()
|
||||||
|
|
||||||
|
option.field = field
|
||||||
|
|
||||||
|
option.title = nextOption.title
|
||||||
|
option.value = nextOption.value
|
||||||
|
option.key = nextOption.key
|
||||||
|
|
||||||
|
return option
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextField.rating !== undefined) {
|
if (nextField.rating !== undefined) {
|
||||||
@ -78,11 +130,7 @@ export class FormUpdateService {
|
|||||||
|
|
||||||
if (input.hooks !== undefined) {
|
if (input.hooks !== undefined) {
|
||||||
form.hooks = input.hooks.map((nextHook) => {
|
form.hooks = input.hooks.map((nextHook) => {
|
||||||
let hook = form.hooks && form.hooks.find(hook => hook.id.toString() === nextHook.id)
|
const hook = form.hooks?.find(hook => hook.id?.toString() === nextHook.id) || new FormHookEntity()
|
||||||
|
|
||||||
if (!hook) {
|
|
||||||
hook = new FormHookEntity()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ability for other fields to apply mapping
|
// ability for other fields to apply mapping
|
||||||
hook.url = nextHook.url
|
hook.url = nextHook.url
|
||||||
@ -97,14 +145,6 @@ export class FormUpdateService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const extractField = (id) => {
|
|
||||||
if (id && fieldMapping[id]) {
|
|
||||||
return fieldMapping[id]
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input.design !== undefined) {
|
if (input.design !== undefined) {
|
||||||
if (input.design.font !== undefined) {
|
if (input.design.font !== undefined) {
|
||||||
form.design.font = input.design.font
|
form.design.font = input.design.font
|
||||||
@ -132,14 +172,38 @@ export class FormUpdateService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
if (input.selfNotifications !== undefined) {
|
if (input.notifications !== undefined) {
|
||||||
form.set('selfNotifications', {
|
form.notifications = input.notifications.map(notificationInput => {
|
||||||
...input.selfNotifications,
|
const notification = form.notifications?.find(value => value.id?.toString() === notificationInput.id) || new FormNotificationEntity()
|
||||||
fromField: extractField(input.selfNotifications.fromField)
|
|
||||||
|
notification.form = form
|
||||||
|
notification.enabled = notificationInput.enabled
|
||||||
|
|
||||||
|
if (notificationInput.fromEmail !== undefined) {
|
||||||
|
notification.fromEmail = notificationInput.fromEmail
|
||||||
|
}
|
||||||
|
if (notificationInput.fromField !== undefined) {
|
||||||
|
notification.fromField = form.fields.find(value => value.id?.toString() === notificationInput.fromField)
|
||||||
|
}
|
||||||
|
if (notificationInput.subject !== undefined) {
|
||||||
|
notification.subject = notificationInput.subject
|
||||||
|
}
|
||||||
|
if (notificationInput.htmlTemplate !== undefined) {
|
||||||
|
notification.htmlTemplate = notificationInput.htmlTemplate
|
||||||
|
}
|
||||||
|
if (notificationInput.toEmail !== undefined) {
|
||||||
|
notification.toEmail = notificationInput.toEmail
|
||||||
|
}
|
||||||
|
if (notificationInput.toField !== undefined) {
|
||||||
|
notification.toField = form.fields.find(value => value.id?.toString() === notificationInput.toField)
|
||||||
|
}
|
||||||
|
|
||||||
|
return notification
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if (input.respondentNotifications !== undefined) {
|
if (input.respondentNotifications !== undefined) {
|
||||||
form.set('respondentNotifications', {
|
form.set('respondentNotifications', {
|
||||||
...input.respondentNotifications,
|
...input.respondentNotifications,
|
||||||
@ -149,13 +213,79 @@ export class FormUpdateService {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (input.startPage !== undefined) {
|
if (input.startPage !== undefined) {
|
||||||
// TODO fix start page
|
if (!form.startPage) {
|
||||||
// form.set('startPage', input.startPage)
|
form.startPage = new PageEntity()
|
||||||
|
form.startPage.show = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.startPage.show !== undefined) {
|
||||||
|
form.startPage.show = input.startPage.show
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.startPage.title !== undefined) {
|
||||||
|
form.startPage.title = input.startPage.title
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.startPage.paragraph !== undefined) {
|
||||||
|
form.startPage.paragraph = input.startPage.paragraph
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.startPage.buttonText !== undefined) {
|
||||||
|
form.startPage.buttonText = input.startPage.buttonText
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.startPage.buttons !== undefined) {
|
||||||
|
form.startPage.buttons = input.startPage.buttons.map(buttonInput => {
|
||||||
|
const entity = form.startPage?.buttons?.find(value => value.id?.toString() === buttonInput.id) || new PageButtonEntity()
|
||||||
|
entity.page = form.startPage
|
||||||
|
entity.url = buttonInput.url
|
||||||
|
entity.action = buttonInput.action
|
||||||
|
entity.text = buttonInput.text
|
||||||
|
entity.color = buttonInput.color
|
||||||
|
entity.bgColor = buttonInput.bgColor
|
||||||
|
entity.activeColor = buttonInput.activeColor
|
||||||
|
|
||||||
|
return entity
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.endPage !== undefined) {
|
if (input.endPage !== undefined) {
|
||||||
// TODO fix end page
|
if (!form.endPage) {
|
||||||
// form.set('endPage', input.endPage)
|
form.endPage = new PageEntity()
|
||||||
|
form.endPage.show = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.endPage.show !== undefined) {
|
||||||
|
form.endPage.show = input.endPage.show
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.endPage.title !== undefined) {
|
||||||
|
form.endPage.title = input.endPage.title
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.endPage.paragraph !== undefined) {
|
||||||
|
form.endPage.paragraph = input.endPage.paragraph
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.endPage.buttonText !== undefined) {
|
||||||
|
form.endPage.buttonText = input.endPage.buttonText
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.endPage.buttons !== undefined) {
|
||||||
|
form.endPage.buttons = input.endPage.buttons.map(buttonInput => {
|
||||||
|
const entity = form.endPage?.buttons?.find(value => value.id?.toString() === buttonInput.id) || new PageButtonEntity()
|
||||||
|
entity.page = form.endPage
|
||||||
|
entity.url = buttonInput.url
|
||||||
|
entity.action = buttonInput.action
|
||||||
|
entity.text = buttonInput.text
|
||||||
|
entity.color = buttonInput.color
|
||||||
|
entity.bgColor = buttonInput.bgColor
|
||||||
|
entity.activeColor = buttonInput.activeColor
|
||||||
|
|
||||||
|
return entity
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.formRepository.save(form)
|
await this.formRepository.save(form)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user