diff options
| author | Daksh Pareek <dakshpareek7@gmail.com> | 2025-01-12 21:53:34 +0530 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-01-12 16:23:34 +0000 |
| commit | b6293d118e7545b81e216073e66cd54c5b1a0b00 (patch) | |
| tree | 19c2308ea7ea26593d890770945a2c5c71440048 /packages | |
| parent | b8bd7d7eb27aaaadae728599f64a0874f66196ea (diff) | |
| download | karakeep-b6293d118e7545b81e216073e66cd54c5b1a0b00.tar.zst | |
feat: Add Bookmark Sorting Feature (#812)
* feat: add bookmark sorting by creation date
- Add sort order toggle in GlobalActions component
- Implement ascending/descending sort functionality
- Update translations for sorting feature in all languages
- Add sort order icons and dropdown menu
- Maintain sort preference in URL params
* feat: add bookmark sorting by creation date
- Add sort order toggle in GlobalActions component
- Implement ascending/descending sort functionality
- Update translations for sorting feature in all languages
- Add sort order icons and dropdown menu
- Maintain sort preference in URL params during session
Note: Sort order resets to default on page refresh, server-side persistence can be implemented in future enhancement
* feat: Add global sort by date feature with shared sort order state
- Implement global sort order functionality using a shared Zustand store (`useSortOrder` hook).
- Update `getBookmarks` and `searchBookmarks` endpoints to accept a `sortOrder` parameter.
- Refactor code to import `ZSortOrder` from shared types (`bookmarks.ts`), ensuring consistency across the codebase.
- Update components (`UpdatableBookmarksGrid`, `bookmark-search`) to use the shared `useSortOrder` hook.
- Remove unused `zSortBy` definition from `packages/shared/types/bookmarks.ts` to avoid confusion.
- Ensure consistent naming conventions by prefixing Zod inferred types with `Z`.
- Clean up code and address previous PR feedback comments.
* tiny fixes and fixing TS errors
---------
Co-authored-by: Mohamed Bassem <me@mbassem.com>
Diffstat (limited to 'packages')
| -rw-r--r-- | packages/shared/types/bookmarks.ts | 5 | ||||
| -rw-r--r-- | packages/trpc/routers/bookmarks.ts | 50 |
2 files changed, 44 insertions, 11 deletions
diff --git a/packages/shared/types/bookmarks.ts b/packages/shared/types/bookmarks.ts index 0a414ff9..650f151c 100644 --- a/packages/shared/types/bookmarks.ts +++ b/packages/shared/types/bookmarks.ts @@ -12,6 +12,9 @@ export const enum BookmarkTypes { UNKNOWN = "unknown", } +export const zSortOrder = z.enum(["asc", "desc"]); +export type ZSortOrder = z.infer<typeof zSortOrder>; + export const zAssetTypesSchema = z.enum([ "screenshot", "bannerImage", @@ -166,6 +169,7 @@ export const zGetBookmarksRequestSchema = z.object({ // The value is currently not being used, but keeping it so that client can still set it to true for older // servers. useCursorV2: z.boolean().optional(), + sortOrder: zSortOrder.optional().default("desc"), }); export type ZGetBookmarksRequest = z.infer<typeof zGetBookmarksRequestSchema>; @@ -211,4 +215,5 @@ export const zSearchBookmarksRequestSchema = z.object({ text: z.string(), limit: z.number().max(MAX_NUM_BOOKMARKS_PER_PAGE).optional(), cursor: zSearchBookmarksCursor.nullish(), + sortOrder: zSortOrder.optional().default("desc"), }); diff --git a/packages/trpc/routers/bookmarks.ts b/packages/trpc/routers/bookmarks.ts index f7f8e6b7..349ff688 100644 --- a/packages/trpc/routers/bookmarks.ts +++ b/packages/trpc/routers/bookmarks.ts @@ -1,5 +1,17 @@ import { experimental_trpcMiddleware, TRPCError } from "@trpc/server"; -import { and, desc, eq, exists, gt, inArray, lt, lte, or } from "drizzle-orm"; +import { + and, + asc, + desc, + eq, + exists, + gt, + gte, + inArray, + lt, + lte, + or, +} from "drizzle-orm"; import invariant from "tiny-invariant"; import { z } from "zod"; @@ -566,6 +578,7 @@ export const bookmarksAppRouter = router({ if (!input.limit) { input.limit = DEFAULT_NUM_BOOKMARKS_PER_PAGE; } + const sortOrder = input.sortOrder || "desc"; const client = await getSearchIdxClient(); if (!client) { throw new TRPCError({ @@ -592,7 +605,7 @@ export const bookmarksAppRouter = router({ filter, showRankingScore: true, attributesToRetrieve: ["id"], - sort: ["createdAt:desc"], + sort: [`createdAt:${sortOrder}`], limit: input.limit, ...(input.cursor ? { @@ -734,18 +747,31 @@ export const bookmarksAppRouter = router({ ) : undefined, input.cursor - ? or( - lt(bookmarks.createdAt, input.cursor.createdAt), - and( - eq(bookmarks.createdAt, input.cursor.createdAt), - lte(bookmarks.id, input.cursor.id), - ), - ) + ? input.sortOrder === "asc" + ? or( + gt(bookmarks.createdAt, input.cursor.createdAt), + and( + eq(bookmarks.createdAt, input.cursor.createdAt), + gte(bookmarks.id, input.cursor.id), + ), + ) + : or( + lt(bookmarks.createdAt, input.cursor.createdAt), + and( + eq(bookmarks.createdAt, input.cursor.createdAt), + lte(bookmarks.id, input.cursor.id), + ), + ) : undefined, ), ) .limit(input.limit + 1) - .orderBy(desc(bookmarks.createdAt), desc(bookmarks.id)), + .orderBy( + input.sortOrder === "asc" + ? asc(bookmarks.createdAt) + : desc(bookmarks.createdAt), + desc(bookmarks.id), + ), ); // TODO: Consider not inlining the tags in the response of getBookmarks as this query is getting kinda expensive const results = await ctx.db @@ -849,7 +875,9 @@ export const bookmarksAppRouter = router({ bookmarksArr.sort((a, b) => { if (a.createdAt != b.createdAt) { - return b.createdAt.getTime() - a.createdAt.getTime(); + return input.sortOrder === "asc" + ? a.createdAt.getTime() - b.createdAt.getTime() + : b.createdAt.getTime() - a.createdAt.getTime(); } else { return b.id.localeCompare(a.id); } |
