feat: add survey webhook

This commit is contained in:
moonrailgun 2024-10-09 00:21:15 +08:00
parent 5d54ca1cbc
commit de572426eb
3 changed files with 50 additions and 12 deletions

View File

@ -1,12 +1,7 @@
import { createFileRoute, useNavigate } from '@tanstack/react-router';
import { useTranslation } from '@i18next-toolkit/react'; import { useTranslation } from '@i18next-toolkit/react';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { useEvent, useEventWithLoading } from '@/hooks/useEvent'; import { useEventWithLoading } from '@/hooks/useEvent';
import { useCurrentWorkspaceId } from '@/store/user';
import { defaultErrorHandler, trpc } from '@/api/trpc';
import { Card, CardContent, CardFooter } from '@/components/ui/card'; import { Card, CardContent, CardFooter } from '@/components/ui/card';
import { CommonWrapper } from '@/components/CommonWrapper';
import { routeAuthBeforeLoad } from '@/utils/route';
import { z } from 'zod'; import { z } from 'zod';
import { import {
Form, Form,
@ -18,7 +13,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, useWatch } from 'react-hook-form'; import { useForm, useFieldArray } 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';
@ -49,6 +44,7 @@ const addFormSchema = z.object({
}), }),
feedChannelIds: z.array(z.string()), feedChannelIds: z.array(z.string()),
feedTemplate: z.string(), feedTemplate: z.string(),
webhookUrl: z.string().url(),
}); });
export type SurveyEditFormValues = z.infer<typeof addFormSchema>; export type SurveyEditFormValues = z.infer<typeof addFormSchema>;
@ -80,6 +76,7 @@ export const SurveyEditForm: React.FC<SurveyEditFormProps> = React.memo(
}, },
feedChannelIds: [], feedChannelIds: [],
feedTemplate: '', feedTemplate: '',
webhookUrl: '',
}, },
}); });
@ -87,7 +84,7 @@ export const SurveyEditForm: React.FC<SurveyEditFormProps> = React.memo(
const [handleSubmit, isLoading] = useEventWithLoading( const [handleSubmit, isLoading] = useEventWithLoading(
async (values: SurveyEditFormValues) => { async (values: SurveyEditFormValues) => {
await props.onSubmit(values); await props.onSubmit({ ...values });
form.reset(); form.reset();
} }
); );
@ -297,6 +294,23 @@ export const SurveyEditForm: React.FC<SurveyEditFormProps> = React.memo(
)} )}
/> />
)} )}
<FormField
control={form.control}
name="webhookUrl"
render={({ field }) => (
<FormItem>
<FormLabel>{t('Webhook Url')}</FormLabel>
<FormControl className="w-full">
<Input {...field} />
</FormControl>
<FormDescription>
{t('Optional, webhook url to send survey payload')}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</CardContent> </CardContent>
<CardFooter> <CardFooter>

View File

@ -495,6 +495,7 @@ model Survey {
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 feedTemplate String @default("") // send survey result to feed channel
webhookUrl String @default("")
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)

View File

@ -22,6 +22,7 @@ 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 { formatString } from '../../utils/template.js';
import { logger } from '../../utils/logger.js'; import { logger } from '../../utils/logger.js';
import axios from 'axios';
export const surveyRouter = router({ export const surveyRouter = router({
all: workspaceProcedure all: workspaceProcedure
@ -154,7 +155,7 @@ export const surveyRouter = router({
const sessionId = hashUuid(workspaceId, surveyId, ip, userAgent!); const sessionId = hashUuid(workspaceId, surveyId, ip, userAgent!);
await prisma.surveyResult.create({ const result = await prisma.surveyResult.create({
data: { data: {
surveyId, surveyId,
sessionId, sessionId,
@ -195,7 +196,7 @@ export const surveyRouter = router({
try { try {
const surveyPayload = SurveyPayloadSchema.parse(survey.payload); const surveyPayload = SurveyPayloadSchema.parse(survey.payload);
createFeedEvent(workspaceId, { await createFeedEvent(workspaceId, {
channelId: channelId, channelId: channelId,
eventName: 'receive', eventName: 'receive',
eventContent: formatString(templateStr, { eventContent: formatString(templateStr, {
@ -216,6 +217,17 @@ export const surveyRouter = router({
} }
}); });
} }
if (survey && survey.webhookUrl) {
axios
.post(survey.webhookUrl)
.then(() => {
return axios.post(survey.webhookUrl, {
...result,
});
})
.catch((err) => logger.error('[surveySubmitWebhook]', err));
}
}); });
return 'success'; return 'success';
@ -233,12 +245,19 @@ export const surveyRouter = router({
payload: SurveyPayloadSchema, payload: SurveyPayloadSchema,
feedChannelIds: z.array(z.string()), feedChannelIds: z.array(z.string()),
feedTemplate: z.string(), feedTemplate: z.string(),
webhookUrl: z.string(),
}) })
) )
.output(SurveyModelSchema) .output(SurveyModelSchema)
.mutation(async ({ input }) => { .mutation(async ({ input }) => {
const { workspaceId, name, payload, feedChannelIds, feedTemplate } = const {
input; workspaceId,
name,
payload,
feedChannelIds,
feedTemplate,
webhookUrl,
} = input;
const res = await prisma.survey.create({ const res = await prisma.survey.create({
data: { data: {
@ -247,6 +266,7 @@ export const surveyRouter = router({
payload, payload,
feedChannelIds, feedChannelIds,
feedTemplate, feedTemplate,
webhookUrl,
}, },
}); });
@ -266,6 +286,7 @@ export const surveyRouter = router({
payload: SurveyPayloadSchema.optional(), payload: SurveyPayloadSchema.optional(),
feedChannelIds: z.array(z.string()).optional(), feedChannelIds: z.array(z.string()).optional(),
feedTemplate: z.string().optional(), feedTemplate: z.string().optional(),
webhookUrl: z.string().optional(),
}) })
) )
.output(SurveyModelSchema) .output(SurveyModelSchema)
@ -277,6 +298,7 @@ export const surveyRouter = router({
payload, payload,
feedChannelIds, feedChannelIds,
feedTemplate, feedTemplate,
webhookUrl,
} = input; } = input;
const res = await prisma.survey.update({ const res = await prisma.survey.update({
@ -289,6 +311,7 @@ export const surveyRouter = router({
payload, payload,
feedChannelIds, feedChannelIds,
feedTemplate, feedTemplate,
webhookUrl,
}, },
}); });