feat: delete webhook functionality
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Zap } from 'lucide-react';
|
import { Zap } from 'lucide-react';
|
||||||
|
import { ToggleLeft, ToggleRight } from 'lucide-react';
|
||||||
|
|
||||||
|
import { trpc } from '@documenso/trpc/react';
|
||||||
import { Button } from '@documenso/ui/primitives/button';
|
import { Button } from '@documenso/ui/primitives/button';
|
||||||
|
|
||||||
import { SettingsHeader } from '~/components/(dashboard)/settings/layout/header';
|
import { SettingsHeader } from '~/components/(dashboard)/settings/layout/header';
|
||||||
@@ -9,17 +11,7 @@ import { CreateWebhookDialog } from '~/components/(dashboard)/settings/webhooks/
|
|||||||
import { DeleteWebhookDialog } from '~/components/(dashboard)/settings/webhooks/delete-webhook-dialog';
|
import { DeleteWebhookDialog } from '~/components/(dashboard)/settings/webhooks/delete-webhook-dialog';
|
||||||
|
|
||||||
export default function WebhookPage() {
|
export default function WebhookPage() {
|
||||||
// TODO: Fetch webhooks from the DB after implementing the backend
|
const { data: webhooks } = trpc.webhook.getWebhooks.useQuery();
|
||||||
const webhooks = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
secret: 'my-secret',
|
|
||||||
webhookUrl: 'https://example.com/webhook',
|
|
||||||
eventTriggers: ['document.created', 'document.signed'],
|
|
||||||
enabled: true,
|
|
||||||
userID: 1,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@@ -30,7 +22,7 @@ export default function WebhookPage() {
|
|||||||
<CreateWebhookDialog />
|
<CreateWebhookDialog />
|
||||||
</SettingsHeader>
|
</SettingsHeader>
|
||||||
|
|
||||||
{webhooks.length === 0 && (
|
{webhooks?.length === 0 && (
|
||||||
// TODO: Perhaps add some illustrations here to make the page more engaging
|
// TODO: Perhaps add some illustrations here to make the page more engaging
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<p className="text-muted-foreground mt-2 text-sm italic">
|
<p className="text-muted-foreground mt-2 text-sm italic">
|
||||||
@@ -39,9 +31,9 @@ export default function WebhookPage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{webhooks.length > 0 && (
|
{webhooks?.length > 0 && (
|
||||||
<div className="mt-4 flex max-w-xl flex-col gap-y-4">
|
<div className="mt-4 flex max-w-xl flex-col gap-y-4">
|
||||||
{webhooks.map((webhook) => (
|
{webhooks?.map((webhook) => (
|
||||||
<div key={webhook.id} className="border-border rounded-lg border p-4">
|
<div key={webhook.id} className="border-border rounded-lg border p-4">
|
||||||
<div className="flex items-center justify-between gap-x-4">
|
<div className="flex items-center justify-between gap-x-4">
|
||||||
<div>
|
<div>
|
||||||
@@ -53,6 +45,15 @@ export default function WebhookPage() {
|
|||||||
<Zap className="mr-1 h-4 w-4 fill-yellow-400 stroke-yellow-600" /> {trigger}
|
<Zap className="mr-1 h-4 w-4 fill-yellow-400 stroke-yellow-600" /> {trigger}
|
||||||
</p>
|
</p>
|
||||||
))}
|
))}
|
||||||
|
{webhook.enabled ? (
|
||||||
|
<h4 className="mt-4 flex items-center gap-2 text-lg">
|
||||||
|
Active <ToggleRight className="h-6 w-6 fill-green-200 stroke-green-400" />
|
||||||
|
</h4>
|
||||||
|
) : (
|
||||||
|
<h4 className="mt-4 flex items-center gap-2 text-lg">
|
||||||
|
Inactive <ToggleLeft className="h-6 w-6 fill-slate-200 stroke-slate-400" />
|
||||||
|
</h4>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col-reverse space-y-2 space-y-reverse sm:flex-row sm:justify-end sm:space-x-2 sm:space-y-0">
|
<div className="flex flex-col-reverse space-y-2 space-y-reverse sm:flex-row sm:justify-end sm:space-x-2 sm:space-y-0">
|
||||||
|
|||||||
@@ -127,7 +127,6 @@ export const CreateWebhookDialog = ({ trigger, ...props }: CreateWebhookDialogPr
|
|||||||
<MultiSelectCombobox
|
<MultiSelectCombobox
|
||||||
listValues={value}
|
listValues={value}
|
||||||
onChange={(values: string[]) => {
|
onChange={(values: string[]) => {
|
||||||
console.log(values);
|
|
||||||
onChange(values);
|
onChange(values);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export const DeleteWebhookDialog = ({ webhook, children }: DeleteWebhookDialogPr
|
|||||||
|
|
||||||
type TDeleteWebhookFormSchema = z.infer<typeof ZDeleteWebhookFormSchema>;
|
type TDeleteWebhookFormSchema = z.infer<typeof ZDeleteWebhookFormSchema>;
|
||||||
|
|
||||||
const { mutateAsync: deleteWebhook } = trpc.webhook.deleteWebhookById.useMutation();
|
const { mutateAsync: deleteWebhook } = trpc.webhook.deleteWebhook.useMutation();
|
||||||
|
|
||||||
const form = useForm<TDeleteWebhookFormSchema>({
|
const form = useForm<TDeleteWebhookFormSchema>({
|
||||||
resolver: zodResolver(ZDeleteWebhookFormSchema),
|
resolver: zodResolver(ZDeleteWebhookFormSchema),
|
||||||
|
|||||||
15
packages/lib/server-only/webhooks/delete-webhook-by-id.ts
Normal file
15
packages/lib/server-only/webhooks/delete-webhook-by-id.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { prisma } from '@documenso/prisma';
|
||||||
|
|
||||||
|
export type DeleteWebhookByIdOptions = {
|
||||||
|
id: number;
|
||||||
|
userId: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteWebhookById = async ({ id, userId }: DeleteWebhookByIdOptions) => {
|
||||||
|
return await prisma.webhook.delete({
|
||||||
|
where: {
|
||||||
|
id,
|
||||||
|
userId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
import { TRPCError } from '@trpc/server';
|
import { TRPCError } from '@trpc/server';
|
||||||
|
|
||||||
import { createWebhook } from '@documenso/lib/server-only/webhooks/create-webhook';
|
import { createWebhook } from '@documenso/lib/server-only/webhooks/create-webhook';
|
||||||
|
import { deleteWebhookById } from '@documenso/lib/server-only/webhooks/delete-webhook-by-id';
|
||||||
import { getWebhooksByUserId } from '@documenso/lib/server-only/webhooks/get-webhooks-by-user-id';
|
import { getWebhooksByUserId } from '@documenso/lib/server-only/webhooks/get-webhooks-by-user-id';
|
||||||
|
|
||||||
import { authenticatedProcedure, router } from '../trpc';
|
import { authenticatedProcedure, router } from '../trpc';
|
||||||
import { ZCreateWebhookFormSchema } from './schema';
|
import { ZCreateWebhookFormSchema } from './schema';
|
||||||
|
import { ZDeleteWebhookSchema } from './schema';
|
||||||
|
|
||||||
export const webhookRouter = router({
|
export const webhookRouter = router({
|
||||||
getWebhooks: authenticatedProcedure.query(async ({ ctx }) => {
|
getWebhooks: authenticatedProcedure.query(async ({ ctx }) => {
|
||||||
@@ -32,4 +34,21 @@ export const webhookRouter = router({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
deleteWebhook: authenticatedProcedure
|
||||||
|
.input(ZDeleteWebhookSchema)
|
||||||
|
.mutation(async ({ input, ctx }) => {
|
||||||
|
try {
|
||||||
|
const { id } = input;
|
||||||
|
|
||||||
|
return await deleteWebhookById({
|
||||||
|
id,
|
||||||
|
userId: ctx.user.id,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: 'BAD_REQUEST',
|
||||||
|
message: 'We were unable to create this webhook. Please try again later.',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,4 +11,10 @@ export const ZCreateWebhookFormSchema = z.object({
|
|||||||
enabled: z.boolean(),
|
enabled: z.boolean(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const ZDeleteWebhookSchema = z.object({
|
||||||
|
id: z.number(),
|
||||||
|
});
|
||||||
|
|
||||||
export type TCreateWebhookFormSchema = z.infer<typeof ZCreateWebhookFormSchema>;
|
export type TCreateWebhookFormSchema = z.infer<typeof ZCreateWebhookFormSchema>;
|
||||||
|
|
||||||
|
export type TDeleteWebhookSchema = z.infer<typeof ZDeleteWebhookSchema>;
|
||||||
|
|||||||
Reference in New Issue
Block a user