aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMohamedBassem <me@mbassem.com>2024-04-26 11:59:20 +0100
committerMohamedBassem <me@mbassem.com>2024-04-26 11:59:20 +0100
commit5aabbec42afcabce826fff14a667a2ca3b0b701f (patch)
treed4191e153c977a244f0223baa15d5640e1df06a6
parent4efcac7e32b1471078142ece8c7d8db3ebffa443 (diff)
downloadkarakeep-5aabbec42afcabce826fff14a667a2ca3b0b701f.tar.zst
fix: Change tag listing API to return unused tags
-rw-r--r--apps/web/components/dashboard/tags/AllTagsView.tsx25
-rw-r--r--packages/trpc/routers/tags.ts59
2 files changed, 52 insertions, 32 deletions
diff --git a/apps/web/components/dashboard/tags/AllTagsView.tsx b/apps/web/components/dashboard/tags/AllTagsView.tsx
index 1f9f2dba..ce780a2f 100644
--- a/apps/web/components/dashboard/tags/AllTagsView.tsx
+++ b/apps/web/components/dashboard/tags/AllTagsView.tsx
@@ -2,6 +2,11 @@
import Link from "next/link";
import { Button } from "@/components/ui/button";
+import {
+ Collapsible,
+ CollapsibleContent,
+ CollapsibleTrigger,
+} from "@/components/ui/collapsible";
import InfoTooltip from "@/components/ui/info-tooltip";
import { Separator } from "@/components/ui/separator";
import { api } from "@/lib/trpc";
@@ -54,7 +59,8 @@ export default function AllTagsView({
const allTags = data.tags.sort((a, b) => b.count - a.count);
const humanTags = allTags.filter((t) => (t.countAttachedBy.human ?? 0) > 0);
- const aiTags = allTags.filter((t) => (t.countAttachedBy.human ?? 0) == 0);
+ const aiTags = allTags.filter((t) => (t.countAttachedBy.ai ?? 0) > 0);
+ const emptyTags = allTags.filter((t) => t.count === 0);
const tagsToPill = (tags: typeof allTags) => {
let tagPill;
@@ -86,6 +92,23 @@ export default function AllTagsView({
</InfoTooltip>
</span>
<div className="flex flex-wrap gap-3">{tagsToPill(aiTags)}</div>
+
+ <Separator />
+
+ <span className="flex items-center gap-2">
+ <p className="text-lg">Unused Tags</p>
+ <InfoTooltip size={15} className="my-auto" variant="explain">
+ <p>Tags that are not attached to any bookmarks</p>
+ </InfoTooltip>
+ </span>
+ <Collapsible>
+ <CollapsibleTrigger className="pb-2">
+ <Button variant="link">Show {emptyTags.length} unused tags</Button>
+ </CollapsibleTrigger>
+ <CollapsibleContent>
+ <div className="flex flex-wrap gap-3">{tagsToPill(emptyTags)}</div>
+ </CollapsibleContent>
+ </Collapsible>
</>
);
}
diff --git a/packages/trpc/routers/tags.ts b/packages/trpc/routers/tags.ts
index 2e6efa8e..4806079a 100644
--- a/packages/trpc/routers/tags.ts
+++ b/packages/trpc/routers/tags.ts
@@ -1,5 +1,5 @@
import { experimental_trpcMiddleware, TRPCError } from "@trpc/server";
-import { and, count, eq, inArray } from "drizzle-orm";
+import { and, eq, inArray } from "drizzle-orm";
import { z } from "zod";
import type { ZAttachedByEnum } from "@hoarder/shared/types/tags";
@@ -306,36 +306,33 @@ export const tagsAppRouter = router({
}),
)
.query(async ({ ctx }) => {
- const res = await ctx.db
- .select({
- id: tagsOnBookmarks.tagId,
- name: bookmarkTags.name,
- attachedBy: tagsOnBookmarks.attachedBy,
- count: count(),
- })
- .from(tagsOnBookmarks)
- .groupBy(tagsOnBookmarks.tagId, tagsOnBookmarks.attachedBy)
- .innerJoin(bookmarkTags, eq(bookmarkTags.id, tagsOnBookmarks.tagId))
- .where(eq(bookmarkTags.userId, ctx.user.id));
-
- const tags = res.reduce<
- Record<string, z.infer<typeof zGetTagResponseSchema>>
- >((acc, row) => {
- if (!(row.id in acc)) {
- acc[row.id] = {
- id: row.id,
- name: row.name,
- count: 0,
- countAttachedBy: {
- ai: 0,
- human: 0,
+ const tags = await ctx.db.query.bookmarkTags.findMany({
+ where: eq(bookmarkTags.userId, ctx.user.id),
+ with: {
+ tagsOnBookmarks: {
+ columns: {
+ attachedBy: true,
},
- };
- }
- acc[row.id].count += row.count;
- acc[row.id].countAttachedBy[row.attachedBy]! += row.count;
- return acc;
- }, {});
- return { tags: Object.values(tags) };
+ },
+ },
+ });
+
+ const resp = tags.map(({ tagsOnBookmarks, ...rest }) => ({
+ ...rest,
+ count: tagsOnBookmarks.length,
+ countAttachedBy: tagsOnBookmarks.reduce<
+ Record<ZAttachedByEnum, number>
+ >(
+ (acc, curr) => {
+ if (curr.attachedBy) {
+ acc[curr.attachedBy]++;
+ }
+ return acc;
+ },
+ { ai: 0, human: 0 },
+ ),
+ }));
+
+ return { tags: resp };
}),
});