notifications / hooks / pages and buttons encode and decode their ids

This commit is contained in:
Michael Schramm 2022-03-14 15:47:20 +01:00
parent 7ea4f51f4b
commit 27aa5ebfb0
11 changed files with 113 additions and 27 deletions

View File

@ -24,6 +24,8 @@ Template for next version
### Changed ### Changed
- notifications / hooks / pages and buttons encode and decode their ids
### Fixed ### Fixed
- missing encode / decode for form fields within submissions (https://github.com/ohmyform/ui/commit/30ff2c96bca20c1641d9cbb96c34cce934e1afea#r68602651) - missing encode / decode for form fields within submissions (https://github.com/ohmyform/ui/commit/30ff2c96bca20c1641d9cbb96c34cce934e1afea#r68602651)

View File

@ -3,6 +3,8 @@ import { PageButtonEntity } from '../../entity/page.button.entity'
@ObjectType('Button') @ObjectType('Button')
export class ButtonModel { export class ButtonModel {
readonly _id: number
@Field(() => ID) @Field(() => ID)
readonly id: string readonly id: string
@ -24,8 +26,9 @@ export class ButtonModel {
@Field({ nullable: true }) @Field({ nullable: true })
readonly color?: string readonly color?: string
constructor(button: Partial<PageButtonEntity>) { constructor(id: string, button: Partial<PageButtonEntity>) {
this.id = button.id.toString() this._id = button.id
this.id = id
this.url = button.url this.url = button.url
this.action = button.action this.action = button.action
this.text = button.text this.text = button.text

View File

@ -3,6 +3,8 @@ import { FormFieldLogicEntity } from '../../entity/form.field.logic.entity'
@ObjectType('FormFieldLogic') @ObjectType('FormFieldLogic')
export class FormFieldLogicModel { export class FormFieldLogicModel {
readonly _id: number
@Field(() => ID) @Field(() => ID)
readonly id: string readonly id: string
@ -30,8 +32,9 @@ export class FormFieldLogicModel {
@Field() @Field()
readonly enabled: boolean readonly enabled: boolean
constructor(document: FormFieldLogicEntity) { constructor(id: string, document: FormFieldLogicEntity) {
this.id = document.id.toString() this._id = document.id
this.id = id
this.enabled = document.enabled this.enabled = document.enabled
this.formula = document.formula this.formula = document.formula

View File

@ -3,6 +3,8 @@ import { FormFieldOptionEntity } from '../../entity/form.field.option.entity'
@ObjectType('FormFieldOption') @ObjectType('FormFieldOption')
export class FormFieldOptionModel { export class FormFieldOptionModel {
readonly _id: number
@Field(() => ID) @Field(() => ID)
readonly id: string readonly id: string
@ -15,8 +17,9 @@ export class FormFieldOptionModel {
@Field() @Field()
readonly value: string readonly value: string
constructor(option: FormFieldOptionEntity) { constructor(id: string, option: FormFieldOptionEntity) {
this.id = option.id.toString() this._id = option.id
this.id = id
this.key = option.key this.key = option.key
this.title = option.title this.title = option.title
this.value = option.value this.value = option.value

View File

@ -3,6 +3,8 @@ import { FormHookEntity } from '../../entity/form.hook.entity'
@ObjectType('FormHook') @ObjectType('FormHook')
export class FormHookModel { export class FormHookModel {
readonly _id: number
@Field(() => ID) @Field(() => ID)
readonly id: string readonly id: string
@ -15,8 +17,9 @@ export class FormHookModel {
@Field({ nullable: true }) @Field({ nullable: true })
readonly format?: string readonly format?: string
constructor(hook: FormHookEntity) { constructor(id, hook: FormHookEntity) {
this.id = hook.id.toString() this._id = hook.id
this.id = id
this.enabled = hook.enabled this.enabled = hook.enabled
this.url = hook.url this.url = hook.url
this.format = hook.format this.format = hook.format

View File

@ -3,6 +3,8 @@ import { FormNotificationEntity } from '../../entity/form.notification.entity'
@ObjectType('FormNotification') @ObjectType('FormNotification')
export class FormNotificationModel { export class FormNotificationModel {
readonly _id: number
@Field(() => ID) @Field(() => ID)
readonly id: string readonly id: string
@ -27,8 +29,9 @@ export class FormNotificationModel {
@Field() @Field()
readonly enabled: boolean readonly enabled: boolean
constructor(partial: Partial<FormNotificationEntity>) { constructor(id: string, partial: Partial<FormNotificationEntity>) {
this.id = partial.id.toString() this._id = partial.id
this.id = id
this.subject = partial.subject this.subject = partial.subject
this.htmlTemplate = partial.htmlTemplate this.htmlTemplate = partial.htmlTemplate
this.enabled = partial.enabled this.enabled = partial.enabled

View File

@ -1,9 +1,10 @@
import { Field, ID, ObjectType } from '@nestjs/graphql' import { Field, ID, ObjectType } from '@nestjs/graphql'
import { PageEntity } from '../../entity/page.entity' import { PageEntity } from '../../entity/page.entity'
import { ButtonModel } from './button.model'
@ObjectType('Page') @ObjectType('Page')
export class PageModel { export class PageModel {
readonly _id: number
@Field(() => ID) @Field(() => ID)
readonly id: string readonly id: string
@ -19,22 +20,18 @@ export class PageModel {
@Field({ nullable: true }) @Field({ nullable: true })
readonly buttonText?: string readonly buttonText?: string
@Field(() => [ButtonModel]) constructor(id: string, page?: Partial<PageEntity>) {
readonly buttons: ButtonModel[]
constructor(page: Partial<PageEntity>) {
if (!page) { if (!page) {
this.id = Math.random().toString() this.id = id
this.show = false this.show = false
this.buttons = []
return return
} }
this.id = page.id.toString() this._id = page.id
this.id = id
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))
} }
} }

View File

@ -9,6 +9,7 @@ import { FormNotificationModel } from '../../dto/form/form.notification.model'
import { PageModel } from '../../dto/form/page.model' import { PageModel } from '../../dto/form/page.model'
import { UserModel } from '../../dto/user/user.model' import { UserModel } from '../../dto/user/user.model'
import { FormEntity } from '../../entity/form.entity' import { FormEntity } from '../../entity/form.entity'
import { PageEntity } from '../../entity/page.entity'
import { UserEntity } from '../../entity/user.entity' import { UserEntity } from '../../entity/user.entity'
import { FormService } from '../../service/form/form.service' import { FormService } from '../../service/form/form.service'
import { IdService } from '../../service/id.service' import { IdService } from '../../service/id.service'
@ -55,7 +56,14 @@ export class FormResolver {
throw new Error('no access to field') throw new Error('no access to field')
} }
return form.hooks?.map(hook => new FormHookModel(hook)) || [] if (!form.hooks) {
return []
}
return form.hooks.map(hook => new FormHookModel(
this.idService.encode(hook.id),
hook
))
} }
@ResolveField(() => Boolean) @ResolveField(() => Boolean)
@ -87,7 +95,14 @@ export class FormResolver {
throw new Error('no access to field') throw new Error('no access to field')
} }
return form.notifications?.map(notification => new FormNotificationModel(notification)) || [] if (!form.notifications) {
return []
}
return form.notifications.map(notification => new FormNotificationModel(
this.idService.encode(notification.id),
notification
))
} }
@ResolveField(() => DesignModel) @ResolveField(() => DesignModel)
@ -106,9 +121,21 @@ export class FormResolver {
@Parent() parent: FormModel, @Parent() parent: FormModel,
@Context('cache') cache: ContextCache, @Context('cache') cache: ContextCache,
): Promise<PageModel> { ): Promise<PageModel> {
const form = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent._id)) const { startPage } = await cache.get<FormEntity>(cache.getCacheKey(
FormEntity.name,
parent._id
))
return new PageModel(form.startPage) if (startPage) {
cache.add(cache.getCacheKey(PageEntity.name, startPage.id), startPage)
return new PageModel(
this.idService.encode(startPage.id),
startPage
)
}
return new PageModel(Math.random().toString())
} }
@ResolveField(() => PageModel) @ResolveField(() => PageModel)
@ -116,9 +143,18 @@ export class FormResolver {
@Parent() parent: FormModel, @Parent() parent: FormModel,
@Context('cache') cache: ContextCache, @Context('cache') cache: ContextCache,
): Promise<PageModel> { ): Promise<PageModel> {
const form = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent._id)) const { endPage } = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent._id))
return new PageModel(form.endPage) if (endPage) {
cache.add(cache.getCacheKey(PageEntity.name, endPage.id), endPage)
return new PageModel(
this.idService.encode(endPage.id),
endPage
)
}
return new PageModel(Math.random().toString())
} }
@ResolveField(() => UserModel, { nullable: true }) @ResolveField(() => UserModel, { nullable: true })

View File

@ -6,6 +6,7 @@ import { FormResolver } from './form.resolver'
import { FormStatisticQuery } from './form.statistic.query' import { FormStatisticQuery } from './form.statistic.query'
import { FormStatisticResolver } from './form.statistic.resolver' import { FormStatisticResolver } from './form.statistic.resolver'
import { FormUpdateMutation } from './form.update.mutation' import { FormUpdateMutation } from './form.update.mutation'
import { PageResolver } from './page.resolver'
export const formResolvers = [ export const formResolvers = [
FormCreateMutation, FormCreateMutation,
@ -16,4 +17,5 @@ export const formResolvers = [
FormStatisticQuery, FormStatisticQuery,
FormStatisticResolver, FormStatisticResolver,
FormUpdateMutation, FormUpdateMutation,
PageResolver,
] ]

View File

@ -0,0 +1,32 @@
import { Context, Parent, ResolveField, Resolver } from '@nestjs/graphql'
import { ButtonModel } from '../../dto/form/button.model'
import { FormModel } from '../../dto/form/form.model'
import { PageModel } from '../../dto/form/page.model'
import { PageEntity } from '../../entity/page.entity'
import { IdService } from '../../service/id.service'
import { ContextCache } from '../context.cache'
@Resolver(() => PageModel)
export class PageResolver {
constructor(
private readonly idService: IdService,
) {
}
@ResolveField(() => [ButtonModel])
async buttons(
@Parent() parent: FormModel,
@Context('cache') cache: ContextCache,
): Promise<ButtonModel[]> {
if (!parent._id) {
return []
}
const page = await cache.get<PageEntity>(cache.getCacheKey(PageEntity.name, parent._id))
return page.buttons.map(button => new ButtonModel(
this.idService.encode(button.id),
button
))
}
}

View File

@ -10,6 +10,7 @@ import { FormHookEntity } from '../../entity/form.hook.entity'
import { FormNotificationEntity } from '../../entity/form.notification.entity' import { FormNotificationEntity } from '../../entity/form.notification.entity'
import { PageButtonEntity } from '../../entity/page.button.entity' import { PageButtonEntity } from '../../entity/page.button.entity'
import { PageEntity } from '../../entity/page.entity' import { PageEntity } from '../../entity/page.entity'
import { IdService } from '../id.service'
@Injectable() @Injectable()
export class FormUpdateService { export class FormUpdateService {
@ -20,6 +21,7 @@ export class FormUpdateService {
private readonly formFieldRepository: Repository<FormFieldEntity>, private readonly formFieldRepository: Repository<FormFieldEntity>,
@InjectRepository(FormHookEntity) @InjectRepository(FormHookEntity)
private readonly formHookRepository: Repository<FormHookEntity>, private readonly formHookRepository: Repository<FormHookEntity>,
private readonly idService: IdService,
) { ) {
} }
@ -347,12 +349,12 @@ export class FormUpdateService {
return form return form
} }
private findByIdInList<T>(list: T[], id: string, fallback: T): T { private findByIdInList<T extends { id: number }>(list: T[], id: string, fallback: T): T {
if (!list) { if (!list) {
return fallback return fallback
} }
const found = list.find((value: any) => String(value.id) === String(id)) const found = list.find((value) => value.id === this.idService.decode(id))
if (found) { if (found) {
return found return found