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
- notifications / hooks / pages and buttons encode and decode their ids
### Fixed
- 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')
export class ButtonModel {
readonly _id: number
@Field(() => ID)
readonly id: string
@ -24,8 +26,9 @@ export class ButtonModel {
@Field({ nullable: true })
readonly color?: string
constructor(button: Partial<PageButtonEntity>) {
this.id = button.id.toString()
constructor(id: string, button: Partial<PageButtonEntity>) {
this._id = button.id
this.id = id
this.url = button.url
this.action = button.action
this.text = button.text

View File

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

View File

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

View File

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

View File

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

View File

@ -1,9 +1,10 @@
import { Field, ID, ObjectType } from '@nestjs/graphql'
import { PageEntity } from '../../entity/page.entity'
import { ButtonModel } from './button.model'
@ObjectType('Page')
export class PageModel {
readonly _id: number
@Field(() => ID)
readonly id: string
@ -19,22 +20,18 @@ export class PageModel {
@Field({ nullable: true })
readonly buttonText?: string
@Field(() => [ButtonModel])
readonly buttons: ButtonModel[]
constructor(page: Partial<PageEntity>) {
constructor(id: string, page?: Partial<PageEntity>) {
if (!page) {
this.id = Math.random().toString()
this.id = id
this.show = false
this.buttons = []
return
}
this.id = page.id.toString()
this._id = page.id
this.id = id
this.show = page.show
this.title = page.title
this.paragraph = page.paragraph
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 { UserModel } from '../../dto/user/user.model'
import { FormEntity } from '../../entity/form.entity'
import { PageEntity } from '../../entity/page.entity'
import { UserEntity } from '../../entity/user.entity'
import { FormService } from '../../service/form/form.service'
import { IdService } from '../../service/id.service'
@ -55,7 +56,14 @@ export class FormResolver {
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)
@ -87,7 +95,14 @@ export class FormResolver {
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)
@ -106,9 +121,21 @@ export class FormResolver {
@Parent() parent: FormModel,
@Context('cache') cache: ContextCache,
): 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)
@ -116,9 +143,18 @@ export class FormResolver {
@Parent() parent: FormModel,
@Context('cache') cache: ContextCache,
): 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 })

View File

@ -6,6 +6,7 @@ import { FormResolver } from './form.resolver'
import { FormStatisticQuery } from './form.statistic.query'
import { FormStatisticResolver } from './form.statistic.resolver'
import { FormUpdateMutation } from './form.update.mutation'
import { PageResolver } from './page.resolver'
export const formResolvers = [
FormCreateMutation,
@ -16,4 +17,5 @@ export const formResolvers = [
FormStatisticQuery,
FormStatisticResolver,
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 { PageButtonEntity } from '../../entity/page.button.entity'
import { PageEntity } from '../../entity/page.entity'
import { IdService } from '../id.service'
@Injectable()
export class FormUpdateService {
@ -20,6 +21,7 @@ export class FormUpdateService {
private readonly formFieldRepository: Repository<FormFieldEntity>,
@InjectRepository(FormHookEntity)
private readonly formHookRepository: Repository<FormHookEntity>,
private readonly idService: IdService,
) {
}
@ -347,12 +349,12 @@ export class FormUpdateService {
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) {
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) {
return found