diff options
Diffstat (limited to 'apps/web/components')
| -rw-r--r-- | apps/web/components/dashboard/UploadDropzone.tsx | 55 | ||||
| -rw-r--r-- | apps/web/components/dashboard/bookmarks/EditorCard.tsx | 15 | ||||
| -rw-r--r-- | apps/web/components/utils/BookmarkAlreadyExistsToast.tsx | 20 |
3 files changed, 68 insertions, 22 deletions
diff --git a/apps/web/components/dashboard/UploadDropzone.tsx b/apps/web/components/dashboard/UploadDropzone.tsx index be30a77f..60398ede 100644 --- a/apps/web/components/dashboard/UploadDropzone.tsx +++ b/apps/web/components/dashboard/UploadDropzone.tsx @@ -1,6 +1,7 @@ "use client"; -import React, { useState } from "react"; +import React, { useCallback, useState } from "react"; +import { parseNetscapeBookmarkFile } from "@/lib/netscapeBookmarkParser"; import { cn } from "@/lib/utils"; import { useMutation } from "@tanstack/react-query"; import { TRPCClientError } from "@trpc/client"; @@ -14,19 +15,26 @@ import { import LoadingSpinner from "../ui/spinner"; import { toast } from "../ui/use-toast"; +import BookmarkAlreadyExistsToast from "../utils/BookmarkAlreadyExistsToast"; -function useUploadAsset({ onComplete }: { onComplete: () => void }) { +function useUploadAsset() { const { mutateAsync: createBookmark } = useCreateBookmarkWithPostHook({ - onSuccess: () => { - toast({ description: "Bookmark uploaded" }); - onComplete(); + onSuccess: (resp) => { + if (resp.alreadyExists) { + toast({ + description: <BookmarkAlreadyExistsToast bookmarkId={resp.id} />, + variant: "default", + }); + } else { + toast({ description: "Bookmark uploaded" }); + } }, onError: () => { toast({ description: "Something went wrong", variant: "destructive" }); }, }); - const { mutateAsync: runUpload } = useMutation({ + const { mutateAsync: runUploadAsset } = useMutation({ mutationFn: async (file: File) => { const formData = new FormData(); formData.append("file", file); @@ -53,7 +61,35 @@ function useUploadAsset({ onComplete }: { onComplete: () => void }) { }, }); - return runUpload; + const { mutateAsync: runUploadBookmarkFile } = useMutation({ + mutationFn: async (file: File) => { + return await parseNetscapeBookmarkFile(file); + }, + onSuccess: async (resp) => { + return Promise.all( + resp.map((url) => + createBookmark({ type: "link", url: url.toString() }), + ), + ); + }, + onError: (error) => { + toast({ + description: error.message, + variant: "destructive", + }); + }, + }); + + return useCallback( + (file: File) => { + if (file.type === "text/html") { + return runUploadBookmarkFile(file); + } else { + return runUploadAsset(file); + } + }, + [runUploadAsset, runUploadBookmarkFile], + ); } function useUploadAssets({ @@ -65,7 +101,7 @@ function useUploadAssets({ onFileError: (name: string, e: Error) => void; onAllUploaded: () => void; }) { - const runUpload = useUploadAsset({ onComplete: onFileUpload }); + const runUpload = useUploadAsset(); return async (files: File[]) => { if (files.length == 0) { @@ -74,6 +110,7 @@ function useUploadAssets({ for (const file of files) { try { await runUpload(file); + onFileUpload(); } catch (e) { if (e instanceof TRPCClientError || e instanceof Error) { onFileError(file.name, e); @@ -137,7 +174,7 @@ export default function UploadDropzone({ </div> ) : ( <p className="text-2xl font-bold text-gray-700"> - Drop Your Image + Drop Your Image / Bookmark file </p> )} </div> diff --git a/apps/web/components/dashboard/bookmarks/EditorCard.tsx b/apps/web/components/dashboard/bookmarks/EditorCard.tsx index 8425f669..44d68378 100644 --- a/apps/web/components/dashboard/bookmarks/EditorCard.tsx +++ b/apps/web/components/dashboard/bookmarks/EditorCard.tsx @@ -1,6 +1,5 @@ import type { SubmitErrorHandler, SubmitHandler } from "react-hook-form"; import React, { useEffect, useImperativeHandle, useRef } from "react"; -import Link from "next/link"; import { ActionButton } from "@/components/ui/action-button"; import { Form, FormControl, FormItem } from "@/components/ui/form"; import InfoTooltip from "@/components/ui/info-tooltip"; @@ -8,11 +7,11 @@ import MultipleChoiceDialog from "@/components/ui/multiple-choice-dialog"; import { Separator } from "@/components/ui/separator"; import { Textarea } from "@/components/ui/textarea"; import { toast } from "@/components/ui/use-toast"; +import BookmarkAlreadyExistsToast from "@/components/utils/BookmarkAlreadyExistsToast"; import { useClientConfig } from "@/lib/clientConfig"; import { useBookmarkLayoutSwitch } from "@/lib/userLocalSettings/bookmarksLayout"; import { cn } from "@/lib/utils"; import { zodResolver } from "@hookform/resolvers/zod"; -import { ExternalLink } from "lucide-react"; import { useForm } from "react-hook-form"; import { z } from "zod"; @@ -64,17 +63,7 @@ export default function EditorCard({ className }: { className?: string }) { onSuccess: (resp) => { if (resp.alreadyExists) { toast({ - description: ( - <div className="flex items-center gap-1"> - Bookmark already exists. - <Link - className="flex underline-offset-4 hover:underline" - href={`/dashboard/preview/${resp.id}`} - > - Open <ExternalLink className="ml-1 size-4" /> - </Link> - </div> - ), + description: <BookmarkAlreadyExistsToast bookmarkId={resp.id} />, variant: "default", }); } diff --git a/apps/web/components/utils/BookmarkAlreadyExistsToast.tsx b/apps/web/components/utils/BookmarkAlreadyExistsToast.tsx new file mode 100644 index 00000000..66bdb17a --- /dev/null +++ b/apps/web/components/utils/BookmarkAlreadyExistsToast.tsx @@ -0,0 +1,20 @@ +import Link from "next/link"; +import { ExternalLink } from "lucide-react"; + +export default function BookmarkAlreadyExistsToast({ + bookmarkId, +}: { + bookmarkId: string; +}) { + return ( + <div className="flex items-center gap-1"> + Bookmark already exists. + <Link + className="flex underline-offset-4 hover:underline" + href={`/dashboard/preview/${bookmarkId}`} + > + Open <ExternalLink className="ml-1 size-4" /> + </Link> + </div> + ); +} |
