aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
authorDaksh Pareek <dakshpareek7@gmail.com>2025-01-12 21:53:34 +0530
committerGitHub <noreply@github.com>2025-01-12 16:23:34 +0000
commitb6293d118e7545b81e216073e66cd54c5b1a0b00 (patch)
tree19c2308ea7ea26593d890770945a2c5c71440048 /packages
parentb8bd7d7eb27aaaadae728599f64a0874f66196ea (diff)
downloadkarakeep-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.ts5
-rw-r--r--packages/trpc/routers/bookmarks.ts50
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);
}