Compare commits
3 Commits
master
...
feat/surve
Author | SHA1 | Date | |
---|---|---|---|
|
cbd6821def | ||
|
8a6a75f3f5 | ||
|
fd63f2a22e |
@ -1,12 +1,7 @@
|
||||
import { createFileRoute, useNavigate } from '@tanstack/react-router';
|
||||
import { useTranslation } from '@i18next-toolkit/react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useEvent, useEventWithLoading } from '@/hooks/useEvent';
|
||||
import { useCurrentWorkspaceId } from '@/store/user';
|
||||
import { defaultErrorHandler, trpc } from '@/api/trpc';
|
||||
import { useEventWithLoading } from '@/hooks/useEvent';
|
||||
import { Card, CardContent, CardFooter } from '@/components/ui/card';
|
||||
import { CommonWrapper } from '@/components/CommonWrapper';
|
||||
import { routeAuthBeforeLoad } from '@/utils/route';
|
||||
import { z } from 'zod';
|
||||
import {
|
||||
Form,
|
||||
@ -18,7 +13,7 @@ import {
|
||||
FormMessage,
|
||||
} from '@/components/ui/form';
|
||||
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 { generateRandomString } from '@/utils/common';
|
||||
import { LuArrowDown, LuArrowUp, LuMinus, LuPlus } from 'react-icons/lu';
|
||||
@ -49,6 +44,7 @@ const addFormSchema = z.object({
|
||||
}),
|
||||
feedChannelIds: z.array(z.string()),
|
||||
feedTemplate: z.string(),
|
||||
webhookUrl: z.string().url().or(z.literal('')),
|
||||
});
|
||||
|
||||
export type SurveyEditFormValues = z.infer<typeof addFormSchema>;
|
||||
@ -80,6 +76,7 @@ export const SurveyEditForm: React.FC<SurveyEditFormProps> = React.memo(
|
||||
},
|
||||
feedChannelIds: [],
|
||||
feedTemplate: '',
|
||||
webhookUrl: '',
|
||||
},
|
||||
});
|
||||
|
||||
@ -87,7 +84,7 @@ export const SurveyEditForm: React.FC<SurveyEditFormProps> = React.memo(
|
||||
|
||||
const [handleSubmit, isLoading] = useEventWithLoading(
|
||||
async (values: SurveyEditFormValues) => {
|
||||
await props.onSubmit(values);
|
||||
await props.onSubmit({ ...values });
|
||||
form.reset();
|
||||
}
|
||||
);
|
||||
@ -297,6 +294,23 @@ export const SurveyEditForm: React.FC<SurveyEditFormProps> = React.memo(
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="webhookUrl"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel optional={true}>{t('Webhook Url')}</FormLabel>
|
||||
<FormControl className="w-full">
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t('Optional, webhook url to send survey payload')}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</CardContent>
|
||||
|
||||
<CardFooter>
|
||||
|
@ -2,7 +2,7 @@ import { createFileRoute, useNavigate } from '@tanstack/react-router';
|
||||
import { useTranslation } from '@i18next-toolkit/react';
|
||||
import { useEvent } from '@/hooks/useEvent';
|
||||
import { useCurrentWorkspaceId } from '@/store/user';
|
||||
import { trpc } from '@/api/trpc';
|
||||
import { defaultErrorHandler, trpc } from '@/api/trpc';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { CommonWrapper } from '@/components/CommonWrapper';
|
||||
import { routeAuthBeforeLoad } from '@/utils/route';
|
||||
@ -25,7 +25,9 @@ function PageComponent() {
|
||||
const { surveyId } = Route.useParams<{ surveyId: string }>();
|
||||
const workspaceId = useCurrentWorkspaceId();
|
||||
const navigate = useNavigate();
|
||||
const mutation = trpc.survey.update.useMutation();
|
||||
const mutation = trpc.survey.update.useMutation({
|
||||
onError: defaultErrorHandler,
|
||||
});
|
||||
const { data: survey, isLoading } = trpc.survey.get.useQuery({
|
||||
workspaceId,
|
||||
surveyId,
|
||||
|
@ -1,3 +1,8 @@
|
||||
import { version } from '@tianji/shared';
|
||||
import axios from 'axios';
|
||||
|
||||
axios.defaults.headers.common['User-Agent'] = `tianji/${version}`;
|
||||
|
||||
(BigInt.prototype as any).toJSON = function () {
|
||||
const int = Number.parseInt(this.toString());
|
||||
return int ?? this.toString();
|
||||
|
@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "Survey" ADD COLUMN "webhookUrl" TEXT NOT NULL DEFAULT '';
|
@ -495,6 +495,7 @@ model Survey {
|
||||
payload Json @db.Json
|
||||
feedChannelIds 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)
|
||||
updatedAt DateTime @updatedAt @db.Timestamptz(6)
|
||||
|
||||
|
@ -18,6 +18,7 @@ export const SurveyModelSchema = z.object({
|
||||
payload: imports.SurveyPayloadSchema,
|
||||
feedChannelIds: z.string().array(),
|
||||
feedTemplate: z.string(),
|
||||
webhookUrl: z.string(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
})
|
||||
|
@ -22,6 +22,7 @@ import { Prisma } from '@prisma/client';
|
||||
import { createFeedEvent } from '../../model/feed/event.js';
|
||||
import { formatString } from '../../utils/template.js';
|
||||
import { logger } from '../../utils/logger.js';
|
||||
import axios from 'axios';
|
||||
|
||||
export const surveyRouter = router({
|
||||
all: workspaceProcedure
|
||||
@ -154,7 +155,7 @@ export const surveyRouter = router({
|
||||
|
||||
const sessionId = hashUuid(workspaceId, surveyId, ip, userAgent!);
|
||||
|
||||
await prisma.surveyResult.create({
|
||||
const result = await prisma.surveyResult.create({
|
||||
data: {
|
||||
surveyId,
|
||||
sessionId,
|
||||
@ -191,11 +192,11 @@ export const surveyRouter = router({
|
||||
survey.feedTemplate ||
|
||||
'survey {{_surveyName}} receive a new record.';
|
||||
|
||||
survey.feedChannelIds.forEach((channelId) => {
|
||||
survey.feedChannelIds.forEach(async (channelId) => {
|
||||
try {
|
||||
const surveyPayload = SurveyPayloadSchema.parse(survey.payload);
|
||||
|
||||
createFeedEvent(workspaceId, {
|
||||
await createFeedEvent(workspaceId, {
|
||||
channelId: channelId,
|
||||
eventName: 'receive',
|
||||
eventContent: formatString(templateStr, {
|
||||
@ -216,6 +217,19 @@ export const surveyRouter = router({
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (survey && survey.webhookUrl) {
|
||||
axios
|
||||
.post(survey.webhookUrl, {
|
||||
...result,
|
||||
})
|
||||
.then(() => {
|
||||
logger.info(
|
||||
`[surveySubmitWebhook] send webhooks to ${survey.webhookUrl} success!`
|
||||
);
|
||||
})
|
||||
.catch((err) => logger.error('[surveySubmitWebhook]', err));
|
||||
}
|
||||
});
|
||||
|
||||
return 'success';
|
||||
@ -233,12 +247,19 @@ export const surveyRouter = router({
|
||||
payload: SurveyPayloadSchema,
|
||||
feedChannelIds: z.array(z.string()),
|
||||
feedTemplate: z.string(),
|
||||
webhookUrl: z.string(),
|
||||
})
|
||||
)
|
||||
.output(SurveyModelSchema)
|
||||
.mutation(async ({ input }) => {
|
||||
const { workspaceId, name, payload, feedChannelIds, feedTemplate } =
|
||||
input;
|
||||
const {
|
||||
workspaceId,
|
||||
name,
|
||||
payload,
|
||||
feedChannelIds,
|
||||
feedTemplate,
|
||||
webhookUrl,
|
||||
} = input;
|
||||
|
||||
const res = await prisma.survey.create({
|
||||
data: {
|
||||
@ -247,6 +268,7 @@ export const surveyRouter = router({
|
||||
payload,
|
||||
feedChannelIds,
|
||||
feedTemplate,
|
||||
webhookUrl,
|
||||
},
|
||||
});
|
||||
|
||||
@ -266,6 +288,7 @@ export const surveyRouter = router({
|
||||
payload: SurveyPayloadSchema.optional(),
|
||||
feedChannelIds: z.array(z.string()).optional(),
|
||||
feedTemplate: z.string().optional(),
|
||||
webhookUrl: z.string().optional(),
|
||||
})
|
||||
)
|
||||
.output(SurveyModelSchema)
|
||||
@ -277,6 +300,7 @@ export const surveyRouter = router({
|
||||
payload,
|
||||
feedChannelIds,
|
||||
feedTemplate,
|
||||
webhookUrl,
|
||||
} = input;
|
||||
|
||||
const res = await prisma.survey.update({
|
||||
@ -289,6 +313,7 @@ export const surveyRouter = router({
|
||||
payload,
|
||||
feedChannelIds,
|
||||
feedTemplate,
|
||||
webhookUrl,
|
||||
},
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user