feat: add feed template string of survey
This commit is contained in:
parent
d9862105ed
commit
22fc5f98f8
@ -504,6 +504,9 @@ importers:
|
|||||||
lodash:
|
lodash:
|
||||||
specifier: ^4.17.21
|
specifier: ^4.17.21
|
||||||
version: 4.17.21
|
version: 4.17.21
|
||||||
|
lodash-es:
|
||||||
|
specifier: ^4.17.21
|
||||||
|
version: 4.17.21
|
||||||
maxmind:
|
maxmind:
|
||||||
specifier: ^4.3.18
|
specifier: ^4.3.18
|
||||||
version: 4.3.18
|
version: 4.3.18
|
||||||
@ -592,6 +595,9 @@ importers:
|
|||||||
'@types/lodash':
|
'@types/lodash':
|
||||||
specifier: ^4.14.198
|
specifier: ^4.14.198
|
||||||
version: 4.14.198
|
version: 4.14.198
|
||||||
|
'@types/lodash-es':
|
||||||
|
specifier: ^4.17.12
|
||||||
|
version: 4.17.12
|
||||||
'@types/md5':
|
'@types/md5':
|
||||||
specifier: ^2.3.5
|
specifier: ^2.3.5
|
||||||
version: 2.3.5
|
version: 2.3.5
|
||||||
|
@ -18,7 +18,7 @@ import {
|
|||||||
FormMessage,
|
FormMessage,
|
||||||
} from '@/components/ui/form';
|
} from '@/components/ui/form';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { useForm, useFieldArray } from 'react-hook-form';
|
import { useForm, useFieldArray, useWatch } from 'react-hook-form';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { generateRandomString } from '@/utils/common';
|
import { generateRandomString } from '@/utils/common';
|
||||||
import { LuArrowDown, LuArrowUp, LuMinus, LuPlus } from 'react-icons/lu';
|
import { LuArrowDown, LuArrowUp, LuMinus, LuPlus } from 'react-icons/lu';
|
||||||
@ -48,6 +48,7 @@ const addFormSchema = z.object({
|
|||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
feedChannelIds: z.array(z.string()),
|
feedChannelIds: z.array(z.string()),
|
||||||
|
feedTemplate: z.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type SurveyEditFormValues = z.infer<typeof addFormSchema>;
|
export type SurveyEditFormValues = z.infer<typeof addFormSchema>;
|
||||||
@ -78,9 +79,12 @@ export const SurveyEditForm: React.FC<SurveyEditFormProps> = React.memo(
|
|||||||
items: [generateDefaultItem()],
|
items: [generateDefaultItem()],
|
||||||
},
|
},
|
||||||
feedChannelIds: [],
|
feedChannelIds: [],
|
||||||
|
feedTemplate: '',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const feedChannelIds = form.watch('feedChannelIds');
|
||||||
|
|
||||||
const [handleSubmit, isLoading] = useEventWithLoading(
|
const [handleSubmit, isLoading] = useEventWithLoading(
|
||||||
async (values: SurveyEditFormValues) => {
|
async (values: SurveyEditFormValues) => {
|
||||||
await props.onSubmit(values);
|
await props.onSubmit(values);
|
||||||
@ -263,6 +267,36 @@ export const SurveyEditForm: React.FC<SurveyEditFormProps> = React.memo(
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{feedChannelIds.length > 0 && (
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="feedTemplate"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t('Feed Template')}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
placeholder="survey {{_surveyName}} receive a new record."
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
<p>
|
||||||
|
{t(
|
||||||
|
'Survey Template String, here are available variables:'
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{'{{_surveyName}} '}
|
||||||
|
{fields.map((f) => `{{${f.name}}}`).join(' ')}
|
||||||
|
</p>
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|
||||||
<CardFooter>
|
<CardFooter>
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
"isolated-vm": "^4.7.2",
|
"isolated-vm": "^4.7.2",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
"lodash-es": "^4.17.21",
|
||||||
"maxmind": "^4.3.18",
|
"maxmind": "^4.3.18",
|
||||||
"md5": "^2.3.0",
|
"md5": "^2.3.0",
|
||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
@ -82,6 +83,7 @@
|
|||||||
"@types/fs-extra": "^11.0.3",
|
"@types/fs-extra": "^11.0.3",
|
||||||
"@types/jsonwebtoken": "^9.0.5",
|
"@types/jsonwebtoken": "^9.0.5",
|
||||||
"@types/lodash": "^4.14.198",
|
"@types/lodash": "^4.14.198",
|
||||||
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/md5": "^2.3.5",
|
"@types/md5": "^2.3.5",
|
||||||
"@types/morgan": "^1.9.5",
|
"@types/morgan": "^1.9.5",
|
||||||
"@types/node": "^18.17.12",
|
"@types/node": "^18.17.12",
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Survey" ADD COLUMN "feedTemplate" TEXT NOT NULL DEFAULT '';
|
@ -459,6 +459,7 @@ model Survey {
|
|||||||
/// @zod.custom(imports.SurveyPayloadSchema)
|
/// @zod.custom(imports.SurveyPayloadSchema)
|
||||||
payload Json @db.Json
|
payload Json @db.Json
|
||||||
feedChannelIds String[] @default([]) // send survey result to feed channel
|
feedChannelIds String[] @default([]) // send survey result to feed channel
|
||||||
|
feedTemplate String @default("") // send survey result to feed channel
|
||||||
createdAt DateTime @default(now()) @db.Timestamptz(6)
|
createdAt DateTime @default(now()) @db.Timestamptz(6)
|
||||||
updatedAt DateTime @updatedAt @db.Timestamptz(6)
|
updatedAt DateTime @updatedAt @db.Timestamptz(6)
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ export const SurveyModelSchema = z.object({
|
|||||||
*/
|
*/
|
||||||
payload: imports.SurveyPayloadSchema,
|
payload: imports.SurveyPayloadSchema,
|
||||||
feedChannelIds: z.string().array(),
|
feedChannelIds: z.string().array(),
|
||||||
|
feedTemplate: z.string(),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date(),
|
updatedAt: z.date(),
|
||||||
})
|
})
|
||||||
|
@ -20,6 +20,8 @@ import { buildCursorResponseSchema } from '../../utils/schema.js';
|
|||||||
import { fetchDataByCursor } from '../../utils/prisma.js';
|
import { fetchDataByCursor } from '../../utils/prisma.js';
|
||||||
import { Prisma } from '@prisma/client';
|
import { Prisma } from '@prisma/client';
|
||||||
import { createFeedEvent } from '../../model/feed/event.js';
|
import { createFeedEvent } from '../../model/feed/event.js';
|
||||||
|
import { formatString } from '../../utils/template.js';
|
||||||
|
import { logger } from '../../utils/logger.js';
|
||||||
|
|
||||||
export const surveyRouter = router({
|
export const surveyRouter = router({
|
||||||
all: workspaceProcedure
|
all: workspaceProcedure
|
||||||
@ -185,15 +187,33 @@ export const surveyRouter = router({
|
|||||||
Array.isArray(survey.feedChannelIds) &&
|
Array.isArray(survey.feedChannelIds) &&
|
||||||
survey.feedChannelIds.length > 0
|
survey.feedChannelIds.length > 0
|
||||||
) {
|
) {
|
||||||
|
const templateStr =
|
||||||
|
survey.feedTemplate ||
|
||||||
|
'survey {{_surveyName}} receive a new record.';
|
||||||
|
|
||||||
survey.feedChannelIds.forEach((channelId) => {
|
survey.feedChannelIds.forEach((channelId) => {
|
||||||
|
try {
|
||||||
|
const surveyPayload = SurveyPayloadSchema.parse(survey.payload);
|
||||||
|
|
||||||
createFeedEvent(workspaceId, {
|
createFeedEvent(workspaceId, {
|
||||||
channelId: channelId,
|
channelId: channelId,
|
||||||
eventName: 'receive',
|
eventName: 'receive',
|
||||||
eventContent: `survey [${survey.name}] receive a new record.`,
|
eventContent: formatString(templateStr, {
|
||||||
|
_surveyName: survey.name,
|
||||||
|
...Object.fromEntries(
|
||||||
|
surveyPayload.items.map((item) => [
|
||||||
|
item.name,
|
||||||
|
payload[item.name] ?? '',
|
||||||
|
])
|
||||||
|
),
|
||||||
|
}),
|
||||||
tags: [],
|
tags: [],
|
||||||
source: 'survey',
|
source: 'survey',
|
||||||
important: false,
|
important: false,
|
||||||
});
|
});
|
||||||
|
} catch (err) {
|
||||||
|
logger.error('[surveySubmitSendFeed]', err);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -212,11 +232,13 @@ export const surveyRouter = router({
|
|||||||
name: z.string(),
|
name: z.string(),
|
||||||
payload: SurveyPayloadSchema,
|
payload: SurveyPayloadSchema,
|
||||||
feedChannelIds: z.array(z.string()),
|
feedChannelIds: z.array(z.string()),
|
||||||
|
feedTemplate: z.string(),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.output(SurveyModelSchema)
|
.output(SurveyModelSchema)
|
||||||
.mutation(async ({ input }) => {
|
.mutation(async ({ input }) => {
|
||||||
const { workspaceId, name, payload, feedChannelIds } = input;
|
const { workspaceId, name, payload, feedChannelIds, feedTemplate } =
|
||||||
|
input;
|
||||||
|
|
||||||
const res = await prisma.survey.create({
|
const res = await prisma.survey.create({
|
||||||
data: {
|
data: {
|
||||||
@ -224,6 +246,7 @@ export const surveyRouter = router({
|
|||||||
name,
|
name,
|
||||||
payload,
|
payload,
|
||||||
feedChannelIds,
|
feedChannelIds,
|
||||||
|
feedTemplate,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -242,11 +265,19 @@ export const surveyRouter = router({
|
|||||||
name: z.string().optional(),
|
name: z.string().optional(),
|
||||||
payload: SurveyPayloadSchema.optional(),
|
payload: SurveyPayloadSchema.optional(),
|
||||||
feedChannelIds: z.array(z.string()).optional(),
|
feedChannelIds: z.array(z.string()).optional(),
|
||||||
|
feedTemplate: z.string().optional(),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.output(SurveyModelSchema)
|
.output(SurveyModelSchema)
|
||||||
.mutation(async ({ input }) => {
|
.mutation(async ({ input }) => {
|
||||||
const { workspaceId, surveyId, name, payload, feedChannelIds } = input;
|
const {
|
||||||
|
workspaceId,
|
||||||
|
surveyId,
|
||||||
|
name,
|
||||||
|
payload,
|
||||||
|
feedChannelIds,
|
||||||
|
feedTemplate,
|
||||||
|
} = input;
|
||||||
|
|
||||||
const res = await prisma.survey.update({
|
const res = await prisma.survey.update({
|
||||||
where: {
|
where: {
|
||||||
@ -257,6 +288,7 @@ export const surveyRouter = router({
|
|||||||
name,
|
name,
|
||||||
payload,
|
payload,
|
||||||
feedChannelIds,
|
feedChannelIds,
|
||||||
|
feedTemplate,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
4
src/server/types/global.d.ts
vendored
4
src/server/types/global.d.ts
vendored
@ -1,8 +1,8 @@
|
|||||||
import type { JWTPayload } from '../middleware/auth';
|
import type { JWTPayload } from '../middleware/auth.ts';
|
||||||
import type {
|
import type {
|
||||||
MonitorStatusPageListSchema,
|
MonitorStatusPageListSchema,
|
||||||
SurveyPayloadSchema,
|
SurveyPayloadSchema,
|
||||||
} from '../prisma/zod/schemas';
|
} from '../prisma/zod/schemas/index.ts';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
namespace Express {
|
namespace Express {
|
||||||
|
13
src/server/utils/template.ts
Normal file
13
src/server/utils/template.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { template, templateSettings } from 'lodash-es';
|
||||||
|
|
||||||
|
templateSettings.interpolate = /{{([\s\S]+?)}}/g;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* buildTemplate('hello {{ user }}!', { user: 'mustache' })
|
||||||
|
* => 'hello mustache!'
|
||||||
|
*/
|
||||||
|
export function formatString(raw: string, variable: Record<string, string>) {
|
||||||
|
return template(raw)(variable);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user