Tweaks to parameters, allows for listing providers

This commit is contained in:
Chris Anderson 2023-01-26 22:58:30 -06:00
parent eefbe15747
commit c366722efb
8 changed files with 112 additions and 55 deletions

View file

@ -99,7 +99,7 @@ const campaignUpdateParams: JSONSchemaType<Partial<CampaignParams>> = {
router.patch('/:campaignId', async ctx => { router.patch('/:campaignId', async ctx => {
const payload = validate(campaignUpdateParams, ctx.request.body) const payload = validate(campaignUpdateParams, ctx.request.body)
ctx.body = await updateCampaign(ctx.state.campaign!.id, payload) ctx.body = await updateCampaign(ctx.state.campaign!.id, ctx.state.project.id, payload)
}) })
router.post('/:campaignId/send', async ctx => { router.post('/:campaignId/send', async ctx => {

View file

@ -57,8 +57,9 @@ export const createCampaign = async (projectId: number, params: CampaignParams):
}) })
} }
export const updateCampaign = async (id: number, params: Partial<CampaignParams>): Promise<Campaign | undefined> => { export const updateCampaign = async (id: number, projectId: number, params: Partial<CampaignParams>): Promise<Campaign | undefined> => {
return await Campaign.updateAndFetch(id, params) await Campaign.update(qb => qb.where('id', id), params)
return getCampaign(id, projectId)
} }
export const getCampaignUsers = async (id: number, params: SearchParams, projectId: number) => { export const getCampaignUsers = async (id: number, params: SearchParams, projectId: number) => {

View file

@ -1,10 +1,12 @@
import Router from '@koa/router' import Router from '@koa/router'
import { ProjectState } from '../auth/AuthMiddleware'
import { loadEmailControllers } from './email' import { loadEmailControllers } from './email'
import { allProviders } from './ProviderService'
import { loadPushControllers } from './push' import { loadPushControllers } from './push'
import { loadTextControllers } from './text' import { loadTextControllers } from './text'
import { loadWebhookControllers } from './webhook' import { loadWebhookControllers } from './webhook'
const router = new Router({ const router = new Router<ProjectState>({
prefix: '/providers', prefix: '/providers',
}) })
@ -13,4 +15,8 @@ loadEmailControllers(router)
loadWebhookControllers(router) loadWebhookControllers(router)
loadPushControllers(router) loadPushControllers(router)
router.get('/', async ctx => {
ctx.body = await allProviders(ctx.state.project.id)
})
export default router export default router

View file

@ -4,6 +4,10 @@ import { JSONSchemaType, validate } from '../core/validate'
import Provider, { ExternalProviderParams, ProviderGroup } from './Provider' import Provider, { ExternalProviderParams, ProviderGroup } from './Provider'
import { createProvider, getProvider, updateProvider } from './ProviderRepository' import { createProvider, getProvider, updateProvider } from './ProviderRepository'
export const allProviders = async (projectId: number) => {
return await Provider.all(qb => qb.where('project_id', projectId))
}
export const createController = <T extends ExternalProviderParams>(group: ProviderGroup, name: string, schema: JSONSchemaType<T>): Router => { export const createController = <T extends ExternalProviderParams>(group: ProviderGroup, name: string, schema: JSONSchemaType<T>): Router => {
const router = new Router< const router = new Router<
ProjectState & { provider?: Provider } ProjectState & { provider?: Provider }

View file

@ -6,7 +6,6 @@ import Model, { ModelParams } from '../core/Model'
export default class Template extends Model { export default class Template extends Model {
project_id!: number project_id!: number
campaign_id!: number campaign_id!: number
name!: string
type!: ChannelType type!: ChannelType
data!: Record<string, any> data!: Record<string, any>
locale!: string locale!: string
@ -29,6 +28,7 @@ export default class Template extends Model {
} }
export type TemplateParams = Omit<Template, ModelParams | 'map' | 'screenshotUrl'> export type TemplateParams = Omit<Template, ModelParams | 'map' | 'screenshotUrl'>
export type TemplateUpdateParams = Pick<Template, 'type' | 'data'>
export type TemplateType = EmailTemplate | TextTemplate | PushTemplate | WebhookTemplate export type TemplateType = EmailTemplate | TextTemplate | PushTemplate | WebhookTemplate
export interface CompiledEmail { export interface CompiledEmail {

View file

@ -3,7 +3,7 @@ import { ProjectState } from '../auth/AuthMiddleware'
import { JSONSchemaType, validate } from '../core/validate' import { JSONSchemaType, validate } from '../core/validate'
import { searchParamsSchema } from '../core/searchParams' import { searchParamsSchema } from '../core/searchParams'
import { extractQueryParams } from '../utilities' import { extractQueryParams } from '../utilities'
import Template, { TemplateParams } from './Template' import Template, { TemplateParams, TemplateUpdateParams } from './Template'
import { createTemplate, getTemplate, pagedTemplates, updateTemplate } from './TemplateService' import { createTemplate, getTemplate, pagedTemplates, updateTemplate } from './TemplateService'
import { Variables } from '.' import { Variables } from '.'
import { User } from '../users/User' import { User } from '../users/User'
@ -20,8 +20,54 @@ router.get('/', async ctx => {
ctx.body = await pagedTemplates(params, ctx.state.project.id) ctx.body = await pagedTemplates(params, ctx.state.project.id)
}) })
const templateParams: JSONSchemaType<TemplateParams> = { const templateDataEmailParams = {
$id: 'templateParams', type: 'object',
required: ['from', 'subject', 'text', 'html'],
properties: {
from: { type: 'string' },
cc: {
type: 'string',
nullable: true,
},
bcc: {
type: 'string',
nullable: true,
},
reply_to: {
type: 'string',
nullable: true,
},
subject: { type: 'string' },
text: { type: 'string' },
html: { type: 'string' },
},
}
const templateDataTextParams = {
type: 'object',
required: ['text'],
properties: {
text: { type: 'string' },
},
}
const templateDataPushParams = {
type: 'object',
required: ['title', 'topic', 'body'],
properties: {
title: { type: 'string' },
topic: { type: 'string' },
body: { type: 'string' },
custom: {
type: 'object',
nullable: true,
additionalProperties: true,
},
},
}
const templateCreateParams: JSONSchemaType<TemplateParams> = {
$id: 'templateCreateParams',
oneOf: [{ oneOf: [{
type: 'object', type: 'object',
required: ['type', 'campaign_id', 'locale', 'data'], required: ['type', 'campaign_id', 'locale', 'data'],
@ -36,28 +82,7 @@ const templateParams: JSONSchemaType<TemplateParams> = {
locale: { locale: {
type: 'string', type: 'string',
}, },
data: { data: templateDataEmailParams as any,
type: 'object',
required: ['from', 'subject', 'text', 'html'],
properties: {
from: { type: 'string' },
cc: {
type: 'string',
nullable: true,
},
bcc: {
type: 'string',
nullable: true,
},
reply_to: {
type: 'string',
nullable: true,
},
subject: { type: 'string' },
text: { type: 'string' },
html: { type: 'string' },
},
} as any,
}, },
additionalProperties: false, additionalProperties: false,
}, },
@ -75,13 +100,7 @@ const templateParams: JSONSchemaType<TemplateParams> = {
locale: { locale: {
type: 'string', type: 'string',
}, },
data: { data: templateDataTextParams as any,
type: 'object',
required: ['text'],
properties: {
text: { type: 'string' },
},
} as any,
}, },
additionalProperties: false, additionalProperties: false,
}, },
@ -99,26 +118,13 @@ const templateParams: JSONSchemaType<TemplateParams> = {
locale: { locale: {
type: 'string', type: 'string',
}, },
data: { data: templateDataPushParams as any,
type: 'object',
required: ['title', 'topic', 'body'],
properties: {
title: { type: 'string' },
topic: { type: 'string' },
body: { type: 'string' },
custom: {
type: 'object',
nullable: true,
additionalProperties: true,
},
},
} as any,
}, },
additionalProperties: false, additionalProperties: false,
}], }],
} }
router.post('/', async ctx => { router.post('/', async ctx => {
const payload = validate(templateParams, ctx.request.body) const payload = validate(templateCreateParams, ctx.request.body)
ctx.body = await createTemplate(ctx.state.project.id, payload) ctx.body = await createTemplate(ctx.state.project.id, payload)
}) })
@ -135,8 +141,47 @@ router.get('/:templateId', async ctx => {
ctx.body = ctx.state.template ctx.body = ctx.state.template
}) })
const templateUpdateParams: JSONSchemaType<TemplateUpdateParams> = {
$id: 'templateUpdateParams',
oneOf: [{
type: 'object',
required: ['type', 'data'],
properties: {
type: {
type: 'string',
enum: ['email'],
},
data: templateDataEmailParams as any,
},
additionalProperties: false,
},
{
type: 'object',
required: ['type', 'data'],
properties: {
type: {
type: 'string',
enum: ['text'],
},
data: templateDataTextParams as any,
},
additionalProperties: false,
},
{
type: 'object',
required: ['type', 'data'],
properties: {
type: {
type: 'string',
enum: ['push'],
},
data: templateDataPushParams as any,
},
additionalProperties: false,
}],
}
router.patch('/:templateId', async ctx => { router.patch('/:templateId', async ctx => {
const payload = validate(templateParams, ctx.request.body) const payload = validate(templateUpdateParams, ctx.request.body)
ctx.body = await updateTemplate(ctx.state.template!.id, payload) ctx.body = await updateTemplate(ctx.state.template!.id, payload)
}) })

View file

@ -1,6 +1,6 @@
import { Readable } from 'stream' import { Readable } from 'stream'
import { SearchParams } from '../core/searchParams' import { SearchParams } from '../core/searchParams'
import Template, { TemplateParams, TemplateType } from './Template' import Template, { TemplateParams, TemplateType, TemplateUpdateParams } from './Template'
import nodeHtmlToImage from 'node-html-to-image' import nodeHtmlToImage from 'node-html-to-image'
import App from '../app' import App from '../app'
import TemplateSnapshotJob from './TemplateSnapshotJob' import TemplateSnapshotJob from './TemplateSnapshotJob'
@ -40,7 +40,7 @@ export const createTemplate = async (projectId: number, params: TemplateParams)
return template return template
} }
export const updateTemplate = async (templateId: number, params: TemplateParams) => { export const updateTemplate = async (templateId: number, params: TemplateUpdateParams) => {
const template = await Template.updateAndFetch(templateId, prune(params)) const template = await Template.updateAndFetch(templateId, prune(params))
App.main.queue.enqueue( App.main.queue.enqueue(

View file

@ -44,6 +44,7 @@ export class User extends Model {
data!: Record<string, any> // first_name, last_name live in data data!: Record<string, any> // first_name, last_name live in data
attributes!: UserAttribute[] // ??? attributes!: UserAttribute[] // ???
timezone!: string timezone!: string
locale!: string
static jsonAttributes = ['data', 'devices'] static jsonAttributes = ['data', 'devices']
static virtualAttributes = ['firstName', 'lastName', 'fullName'] static virtualAttributes = ['firstName', 'lastName', 'fullName']