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,
});