From 3270164710179a534692eabca77285dd28d887a7 Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Sat, 31 Aug 2024 00:58:44 +0800 Subject: [PATCH] feat: add archive feature --- src/client/components/feed/FeedEventItem.tsx | 39 +++++++++++-- .../migration.sql | 2 + src/server/prisma/schema.prisma | 1 + src/server/prisma/zod/feedevent.ts | 1 + src/server/trpc/routers/feed/index.ts | 55 +++++++++++++++++++ 5 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 src/server/prisma/migrations/20240830162007_add_feed_event_archived_field/migration.sql diff --git a/src/client/components/feed/FeedEventItem.tsx b/src/client/components/feed/FeedEventItem.tsx index 1f30b23..41c83f1 100644 --- a/src/client/components/feed/FeedEventItem.tsx +++ b/src/client/components/feed/FeedEventItem.tsx @@ -1,4 +1,4 @@ -import { AppRouterOutput } from '@/api/trpc'; +import { AppRouterOutput, trpc } from '@/api/trpc'; import React from 'react'; import { Badge } from '../ui/badge'; import dayjs from 'dayjs'; @@ -6,6 +6,12 @@ import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip'; import { MarkdownViewer } from '../MarkdownEditor'; import { FeedIcon } from './FeedIcon'; import { cn } from '@/utils/style'; +import { Button } from '../ui/button'; +import { LuArchive } from 'react-icons/lu'; +import { useCurrentWorkspaceId } from '@/store/user'; +import { useEvent } from '@/hooks/useEvent'; +import { toast } from 'sonner'; +import { useTranslation } from '@i18next-toolkit/react'; type FeedEventItemType = AppRouterOutput['feed']['fetchEventsByCursor']['items'][number]; @@ -14,6 +20,21 @@ export const FeedEventItem: React.FC<{ className?: string; event: FeedEventItemType; }> = React.memo(({ className, event }) => { + const workspaceId = useCurrentWorkspaceId(); + const archiveEventMutation = trpc.feed.archiveEvent.useMutation(); + const trpcUtils = trpc.useUtils(); + const { t } = useTranslation(); + + const handleArchive = useEvent(async () => { + await archiveEventMutation.mutateAsync({ + workspaceId, + channelId: event.channelId, + eventId: event.id, + }); + trpcUtils.feed.fetchEventsByCursor.refetch(); + toast.success(t('Event archived')); + }); + return (
-
+
-
+ +
+ +
{event.source} @@ -46,7 +77,7 @@ export const FeedEventItem: React.FC<{
{dayjs(event.createdAt).fromNow()}
- +

{dayjs(event.createdAt).format('YYYY-MM-DD HH:mm:ss')}

diff --git a/src/server/prisma/migrations/20240830162007_add_feed_event_archived_field/migration.sql b/src/server/prisma/migrations/20240830162007_add_feed_event_archived_field/migration.sql new file mode 100644 index 0000000..e1db275 --- /dev/null +++ b/src/server/prisma/migrations/20240830162007_add_feed_event_archived_field/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "FeedEvent" ADD COLUMN "archived" BOOLEAN NOT NULL DEFAULT false; diff --git a/src/server/prisma/schema.prisma b/src/server/prisma/schema.prisma index 860d385..9dd1b7f 100644 --- a/src/server/prisma/schema.prisma +++ b/src/server/prisma/schema.prisma @@ -531,6 +531,7 @@ model FeedEvent { senderName String? // use for display who url String? // url link important Boolean + archived Boolean @default(false) @db.Boolean channel FeedChannel @relation(fields: [channelId], references: [id], onUpdate: Cascade, onDelete: Cascade) diff --git a/src/server/prisma/zod/feedevent.ts b/src/server/prisma/zod/feedevent.ts index 01d5960..6cb6fe7 100644 --- a/src/server/prisma/zod/feedevent.ts +++ b/src/server/prisma/zod/feedevent.ts @@ -15,6 +15,7 @@ export const FeedEventModelSchema = z.object({ senderName: z.string().nullish(), url: z.string().nullish(), important: z.boolean(), + archived: z.boolean(), }) export interface CompleteFeedEvent extends z.infer { diff --git a/src/server/trpc/routers/feed/index.ts b/src/server/trpc/routers/feed/index.ts index 6a9060d..263b50d 100644 --- a/src/server/trpc/routers/feed/index.ts +++ b/src/server/trpc/routers/feed/index.ts @@ -187,6 +187,7 @@ export const feedRouter = router({ const { items, nextCursor } = await fetchDataByCursor(prisma.feedEvent, { where: { channelId, + archived: false, }, limit, cursor, @@ -307,6 +308,60 @@ export const feedRouter = router({ return event; }), + archiveEvent: workspaceOwnerProcedure + .meta( + buildFeedPublicOpenapi({ + method: 'PATCH', + path: '/{channelId}/{eventId}/archive', + }) + ) + .input( + z.object({ + channelId: z.string(), + eventId: z.string(), + }) + ) + .output(z.void()) + .mutation(async ({ input }) => { + const { channelId, eventId } = input; + + await prisma.feedEvent.update({ + data: { + archived: true, + }, + where: { + id: eventId, + channelId, + }, + }); + }), + unarchiveEvent: workspaceOwnerProcedure + .meta( + buildFeedPublicOpenapi({ + method: 'PATCH', + path: '/{channelId}/{eventId}/unarchive', + }) + ) + .input( + z.object({ + channelId: z.string(), + eventId: z.string(), + }) + ) + .output(z.void()) + .mutation(async ({ input }) => { + const { channelId, eventId } = input; + + await prisma.feedEvent.update({ + data: { + archived: false, + }, + where: { + id: eventId, + channelId, + }, + }); + }), integration: feedIntegrationRouter, });