diff options
| author | MohamedBassem <me@mbassem.com> | 2024-04-09 15:49:24 +0100 |
|---|---|---|
| committer | MohamedBassem <me@mbassem.com> | 2024-04-09 15:49:24 +0100 |
| commit | fe13408831dce4bdae4911098d6079a097cae9e8 (patch) | |
| tree | 228bbb192b3a0f3417a4526c382b0a3ddf7e04ff /apps/web | |
| parent | 994691b02515dfb579a5c3618631065bd76b9e4b (diff) | |
| download | karakeep-fe13408831dce4bdae4911098d6079a097cae9e8.tar.zst | |
feature(web): Allow uploading directly into lists/tags. Fixes #69
Diffstat (limited to 'apps/web')
| -rw-r--r-- | apps/web/app/dashboard/archive/page.tsx | 1 | ||||
| -rw-r--r-- | apps/web/app/dashboard/bookmarks/page.tsx | 21 | ||||
| -rw-r--r-- | apps/web/app/dashboard/favourites/page.tsx | 1 | ||||
| -rw-r--r-- | apps/web/app/dashboard/layout.tsx | 2 | ||||
| -rw-r--r-- | apps/web/app/dashboard/lists/[listId]/page.tsx | 28 | ||||
| -rw-r--r-- | apps/web/app/dashboard/tags/[tagName]/page.tsx | 1 | ||||
| -rw-r--r-- | apps/web/components/dashboard/UploadDropzone.tsx | 25 | ||||
| -rw-r--r-- | apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx | 6 | ||||
| -rw-r--r-- | apps/web/components/dashboard/bookmarks/BookmarkedTextEditor.tsx | 38 | ||||
| -rw-r--r-- | apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx | 21 | ||||
| -rw-r--r-- | apps/web/components/dashboard/bookmarks/EditorCard.tsx | 7 | ||||
| -rw-r--r-- | apps/web/components/dashboard/bookmarks/TagsEditor.tsx | 14 | ||||
| -rw-r--r-- | apps/web/components/dashboard/bookmarks/UpdatableBookmarksGrid.tsx | 10 | ||||
| -rw-r--r-- | apps/web/lib/hooks/list-context.tsx | 21 |
14 files changed, 75 insertions, 121 deletions
diff --git a/apps/web/app/dashboard/archive/page.tsx b/apps/web/app/dashboard/archive/page.tsx index b2b4df4f..26ec45e9 100644 --- a/apps/web/app/dashboard/archive/page.tsx +++ b/apps/web/app/dashboard/archive/page.tsx @@ -14,6 +14,7 @@ export default async function ArchivedBookmarkPage() { } query={{ archived: true }} showDivider={true} + showEditorCard={true} /> ); } diff --git a/apps/web/app/dashboard/bookmarks/page.tsx b/apps/web/app/dashboard/bookmarks/page.tsx index 9907df4d..90f4f2cb 100644 --- a/apps/web/app/dashboard/bookmarks/page.tsx +++ b/apps/web/app/dashboard/bookmarks/page.tsx @@ -1,23 +1,20 @@ import React from "react"; import Bookmarks from "@/components/dashboard/bookmarks/Bookmarks"; import TopNav from "@/components/dashboard/bookmarks/TopNav"; -import UploadDropzone from "@/components/dashboard/UploadDropzone"; import { Separator } from "@/components/ui/separator"; export default async function BookmarksPage() { return ( <div> - <UploadDropzone> - <TopNav /> - <Separator /> - <div className="my-4 flex-1"> - <Bookmarks - header={<p className="text-2xl">Bookmarks</p>} - query={{ archived: false }} - showEditorCard={true} - /> - </div> - </UploadDropzone> + <TopNav /> + <Separator /> + <div className="my-4 flex-1"> + <Bookmarks + header={<p className="text-2xl">Bookmarks</p>} + query={{ archived: false }} + showEditorCard={true} + /> + </div> </div> ); } diff --git a/apps/web/app/dashboard/favourites/page.tsx b/apps/web/app/dashboard/favourites/page.tsx index 13d793c6..423a8e69 100644 --- a/apps/web/app/dashboard/favourites/page.tsx +++ b/apps/web/app/dashboard/favourites/page.tsx @@ -6,6 +6,7 @@ export default async function FavouritesBookmarkPage() { header={<p className="text-2xl">⭐️ Favourites</p>} query={{ favourited: true }} showDivider={true} + showEditorCard={true} /> ); } diff --git a/apps/web/app/dashboard/layout.tsx b/apps/web/app/dashboard/layout.tsx index 628c3a34..3b6908f8 100644 --- a/apps/web/app/dashboard/layout.tsx +++ b/apps/web/app/dashboard/layout.tsx @@ -21,7 +21,7 @@ export default async function Dashboard({ <MobileSidebar /> <Separator /> </div> - <div className="container p-4">{children}</div> + <div className="container min-h-screen p-4">{children}</div> </main> </div> ); diff --git a/apps/web/app/dashboard/lists/[listId]/page.tsx b/apps/web/app/dashboard/lists/[listId]/page.tsx index 2b8025e5..49bf77f7 100644 --- a/apps/web/app/dashboard/lists/[listId]/page.tsx +++ b/apps/web/app/dashboard/lists/[listId]/page.tsx @@ -1,7 +1,6 @@ import { notFound } from "next/navigation"; import Bookmarks from "@/components/dashboard/bookmarks/Bookmarks"; import DeleteListButton from "@/components/dashboard/lists/DeleteListButton"; -import { BookmarkListContextProvider } from "@/lib/hooks/list-context"; import { api } from "@/server/api/client"; import { TRPCError } from "@trpc/server"; @@ -23,19 +22,18 @@ export default async function ListPage({ } return ( - <BookmarkListContextProvider listId={list.id}> - <Bookmarks - query={{ listId: list.id }} - showDivider={true} - header={ - <div className="flex justify-between"> - <span className="text-2xl"> - {list.icon} {list.name} - </span> - <DeleteListButton list={list} /> - </div> - } - /> - </BookmarkListContextProvider> + <Bookmarks + query={{ listId: list.id }} + showDivider={true} + showEditorCard={true} + header={ + <div className="flex justify-between"> + <span className="text-2xl"> + {list.icon} {list.name} + </span> + <DeleteListButton list={list} /> + </div> + } + /> ); } diff --git a/apps/web/app/dashboard/tags/[tagName]/page.tsx b/apps/web/app/dashboard/tags/[tagName]/page.tsx index 6bbb5234..b8bf351d 100644 --- a/apps/web/app/dashboard/tags/[tagName]/page.tsx +++ b/apps/web/app/dashboard/tags/[tagName]/page.tsx @@ -32,6 +32,7 @@ export default async function TagPage({ </div> } query={{ tagId: tag.id }} + showEditorCard={true} /> ); } diff --git a/apps/web/components/dashboard/UploadDropzone.tsx b/apps/web/components/dashboard/UploadDropzone.tsx index 70e6483a..bd08d2cf 100644 --- a/apps/web/components/dashboard/UploadDropzone.tsx +++ b/apps/web/components/dashboard/UploadDropzone.tsx @@ -1,12 +1,12 @@ "use client"; import React, { useState } from "react"; -import { api } from "@/lib/trpc"; import { cn } from "@/lib/utils"; import { useMutation } from "@tanstack/react-query"; import { TRPCClientError } from "@trpc/client"; import DropZone from "react-dropzone"; +import { useCreateBookmarkWithPostHook } from "@hoarder/shared-react/hooks/bookmarks"; import { zUploadErrorSchema, zUploadResponseSchema, @@ -16,20 +16,15 @@ import LoadingSpinner from "../ui/spinner"; import { toast } from "../ui/use-toast"; function useUploadAsset({ onComplete }: { onComplete: () => void }) { - const invalidateAllBookmarks = - api.useUtils().bookmarks.getBookmarks.invalidate; - - const { mutateAsync: createBookmark } = - api.bookmarks.createBookmark.useMutation({ - onSuccess: () => { - toast({ description: "Bookmark uploaded" }); - invalidateAllBookmarks(); - onComplete(); - }, - onError: () => { - toast({ description: "Something went wrong", variant: "destructive" }); - }, - }); + const { mutateAsync: createBookmark } = useCreateBookmarkWithPostHook({ + onSuccess: () => { + toast({ description: "Bookmark uploaded" }); + onComplete(); + }, + onError: () => { + toast({ description: "Something went wrong", variant: "destructive" }); + }, + }); const { mutateAsync: runUpload } = useMutation({ mutationFn: async (file: File) => { diff --git a/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx b/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx index e3cfc796..a8ec1ab5 100644 --- a/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx +++ b/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx @@ -1,6 +1,6 @@ "use client"; -import { useContext, useState } from "react"; +import { useState } from "react"; import { Button } from "@/components/ui/button"; import { DropdownMenu, @@ -10,7 +10,6 @@ import { } from "@/components/ui/dropdown-menu"; import { useToast } from "@/components/ui/use-toast"; import { useClientConfig } from "@/lib/clientConfig"; -import { BookmarkListContext } from "@/lib/hooks/list-context"; import { Link, List, @@ -29,6 +28,7 @@ import { useUpdateBookmark, } from "@hoarder/shared-react/hooks//bookmarks"; import { useRemoveBookmarkFromList } from "@hoarder/shared-react/hooks//lists"; +import { useBookmarkGridContext } from "@hoarder/shared-react/hooks/bookmark-grid-context"; import { useAddToListModal } from "./AddToListModal"; import { BookmarkedTextEditor } from "./BookmarkedTextEditor"; @@ -48,7 +48,7 @@ export default function BookmarkOptions({ bookmark }: { bookmark: ZBookmark }) { const [isTextEditorOpen, setTextEditorOpen] = useState(false); - const { listId } = useContext(BookmarkListContext); + const { listId } = useBookmarkGridContext() ?? {}; const onError = () => { toast({ diff --git a/apps/web/components/dashboard/bookmarks/BookmarkedTextEditor.tsx b/apps/web/components/dashboard/bookmarks/BookmarkedTextEditor.tsx index eb618474..294f2b5a 100644 --- a/apps/web/components/dashboard/bookmarks/BookmarkedTextEditor.tsx +++ b/apps/web/components/dashboard/bookmarks/BookmarkedTextEditor.tsx @@ -21,7 +21,7 @@ export function BookmarkedTextEditor({ open, setOpen, }: { - bookmark?: ZBookmark; + bookmark: ZBookmark; open: boolean; setOpen: (open: boolean) => void; }) { @@ -30,30 +30,14 @@ export function BookmarkedTextEditor({ bookmark && bookmark.content.type == "text" ? bookmark.content.text : "", ); - const invalidateAllBookmarksCache = - api.useUtils().bookmarks.getBookmarks.invalidate; const invalidateOneBookmarksCache = api.useUtils().bookmarks.getBookmark.invalidate; - const { mutate: createBookmarkMutator, isPending: isCreationPending } = - api.bookmarks.createBookmark.useMutation({ - onSuccess: () => { - invalidateAllBookmarksCache(); - toast({ - description: "Note created!", - }); - setOpen(false); - setNoteText(""); - }, - onError: () => { - toast({ description: "Something went wrong", variant: "destructive" }); - }, - }); - const { mutate: updateBookmarkMutator, isPending: isUpdatePending } = + const { mutate: updateBookmarkMutator, isPending } = api.bookmarks.updateBookmarkText.useMutation({ onSuccess: () => { invalidateOneBookmarksCache({ - bookmarkId: bookmark!.id, + bookmarkId: bookmark.id, }); toast({ description: "Note updated!", @@ -64,20 +48,12 @@ export function BookmarkedTextEditor({ toast({ description: "Something went wrong", variant: "destructive" }); }, }); - const isPending = isCreationPending || isUpdatePending; const onSave = () => { - if (isNewBookmark) { - createBookmarkMutator({ - type: "text", - text: noteText, - }); - } else { - updateBookmarkMutator({ - bookmarkId: bookmark.id, - text: noteText, - }); - } + updateBookmarkMutator({ + bookmarkId: bookmark.id, + text: noteText, + }); }; return ( diff --git a/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx b/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx index 048dab85..bace3435 100644 --- a/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx +++ b/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useMemo } from "react"; import { ActionButton } from "@/components/ui/action-button"; import tailwindConfig from "@/tailwind.config"; @@ -78,15 +76,16 @@ export default function BookmarksGrid({ {bookmarks.map((b) => renderBookmark(b))} </Masonry> {hasNextPage && ( - <ActionButton - ignoreDemoMode={true} - loading={isFetchingNextPage} - onClick={() => fetchNextPage()} - className="mx-auto w-min" - variant="ghost" - > - Load More - </ActionButton> + <div className="flex justify-center"> + <ActionButton + ignoreDemoMode={true} + loading={isFetchingNextPage} + onClick={() => fetchNextPage()} + variant="ghost" + > + Load More + </ActionButton> + </div> )} </> ); diff --git a/apps/web/components/dashboard/bookmarks/EditorCard.tsx b/apps/web/components/dashboard/bookmarks/EditorCard.tsx index b9e46a30..10ad1f13 100644 --- a/apps/web/components/dashboard/bookmarks/EditorCard.tsx +++ b/apps/web/components/dashboard/bookmarks/EditorCard.tsx @@ -7,12 +7,13 @@ import { Separator } from "@/components/ui/separator"; import { Textarea } from "@/components/ui/textarea"; import { toast } from "@/components/ui/use-toast"; import { useClientConfig } from "@/lib/clientConfig"; -import { api } from "@/lib/trpc"; import { cn } from "@/lib/utils"; import { zodResolver } from "@hookform/resolvers/zod"; import { useForm } from "react-hook-form"; import { z } from "zod"; +import { useCreateBookmarkWithPostHook } from "@hoarder/shared-react/hooks/bookmarks"; + function useFocusOnKeyPress(inputRef: React.RefObject<HTMLTextAreaElement>) { useEffect(() => { function handleKeyPress(e: KeyboardEvent) { @@ -47,10 +48,8 @@ export default function EditorCard({ className }: { className?: string }) { useImperativeHandle(ref, () => inputRef.current); useFocusOnKeyPress(inputRef); - const invalidateBookmarksCache = api.useUtils().bookmarks.invalidate; - const { mutate, isPending } = api.bookmarks.createBookmark.useMutation({ + const { mutate, isPending } = useCreateBookmarkWithPostHook({ onSuccess: () => { - invalidateBookmarksCache(); form.reset(); }, onError: () => { diff --git a/apps/web/components/dashboard/bookmarks/TagsEditor.tsx b/apps/web/components/dashboard/bookmarks/TagsEditor.tsx index 91294b2e..c1a4cc70 100644 --- a/apps/web/components/dashboard/bookmarks/TagsEditor.tsx +++ b/apps/web/components/dashboard/bookmarks/TagsEditor.tsx @@ -8,6 +8,7 @@ import CreateableSelect from "react-select/creatable"; import type { ZBookmark } from "@hoarder/trpc/types/bookmarks"; import type { ZAttachedByEnum } from "@hoarder/trpc/types/tags"; +import { useUpdateBookmarkTags } from "@hoarder/shared-react/hooks/bookmarks"; interface EditableTag { attachedBy: ZAttachedByEnum; @@ -17,16 +18,12 @@ interface EditableTag { export function TagsEditor({ bookmark }: { bookmark: ZBookmark }) { const demoMode = !!useClientConfig().demoMode; - const apiUtils = api.useUtils(); - const { mutate } = api.bookmarks.updateTags.useMutation({ + const { mutate } = useUpdateBookmarkTags({ onSuccess: () => { toast({ description: "Tags has been updated!", }); - apiUtils.bookmarks.getBookmark.invalidate({ bookmarkId: bookmark.id }); - apiUtils.tags.list.invalidate(); - apiUtils.tags.get.invalidate(); }, onError: () => { toast({ @@ -58,7 +55,7 @@ export function TagsEditor({ bookmark }: { bookmark: ZBookmark }) { case "create-option": { mutate({ bookmarkId: bookmark.id, - attach: [{ tag: actionMeta.option.label }], + attach: [{ tagName: actionMeta.option.label }], detach: [], }); break; @@ -68,7 +65,10 @@ export function TagsEditor({ bookmark }: { bookmark: ZBookmark }) { mutate({ bookmarkId: bookmark.id, attach: [ - { tag: actionMeta.option.label, tagId: actionMeta.option?.value }, + { + tagName: actionMeta.option.label, + tagId: actionMeta.option?.value, + }, ], detach: [], }); diff --git a/apps/web/components/dashboard/bookmarks/UpdatableBookmarksGrid.tsx b/apps/web/components/dashboard/bookmarks/UpdatableBookmarksGrid.tsx index a344320e..fe69201c 100644 --- a/apps/web/components/dashboard/bookmarks/UpdatableBookmarksGrid.tsx +++ b/apps/web/components/dashboard/bookmarks/UpdatableBookmarksGrid.tsx @@ -1,11 +1,13 @@ "use client"; +import UploadDropzone from "@/components/dashboard/UploadDropzone"; import { api } from "@/lib/trpc"; import type { ZGetBookmarksRequest, ZGetBookmarksResponse, } from "@hoarder/trpc/types/bookmarks"; +import { BookmarkGridContextProvider } from "@hoarder/shared-react/hooks/bookmark-grid-context"; import BookmarksGrid from "./BookmarksGrid"; @@ -29,7 +31,7 @@ export default function UpdatableBookmarksGrid({ getNextPageParam: (lastPage) => lastPage.nextCursor, }); - return ( + const grid = ( <BookmarksGrid bookmarks={data!.pages.flatMap((b) => b.bookmarks)} hasNextPage={hasNextPage} @@ -38,4 +40,10 @@ export default function UpdatableBookmarksGrid({ showEditorCard={showEditorCard} /> ); + + return ( + <BookmarkGridContextProvider query={query}> + {showEditorCard ? <UploadDropzone>{grid}</UploadDropzone> : grid} + </BookmarkGridContextProvider> + ); } diff --git a/apps/web/lib/hooks/list-context.tsx b/apps/web/lib/hooks/list-context.tsx deleted file mode 100644 index cb8a20b2..00000000 --- a/apps/web/lib/hooks/list-context.tsx +++ /dev/null @@ -1,21 +0,0 @@ -"use client"; - -import { createContext } from "react"; - -export const BookmarkListContext = createContext<{ - listId: string | undefined; -}>({ listId: undefined }); - -export function BookmarkListContextProvider({ - listId, - children, -}: { - listId: string; - children: React.ReactNode; -}) { - return ( - <BookmarkListContext.Provider value={{ listId }}> - {children} - </BookmarkListContext.Provider> - ); -} |
