From fa39265142a7aa452a273e4290d58757af2786bb Mon Sep 17 00:00:00 2001 From: yxshv Date: Sun, 14 Apr 2024 14:29:23 +0530 Subject: new modals --- apps/web/src/components/ChatMessage.tsx | 22 ++- apps/web/src/components/Main.tsx | 25 +++- .../web/src/components/Sidebar/AddMemoryDialog.tsx | 3 +- .../src/components/Sidebar/DeleteConfirmation.tsx | 35 +++++ apps/web/src/components/Sidebar/EditNoteDialog.tsx | 152 +++++++++++++++++++++ apps/web/src/components/Sidebar/FilterCombobox.tsx | 5 +- apps/web/src/components/Sidebar/MemoriesBar.tsx | 98 ++++++------- 7 files changed, 277 insertions(+), 63 deletions(-) create mode 100644 apps/web/src/components/Sidebar/DeleteConfirmation.tsx create mode 100644 apps/web/src/components/Sidebar/EditNoteDialog.tsx (limited to 'apps/web/src/components') diff --git a/apps/web/src/components/ChatMessage.tsx b/apps/web/src/components/ChatMessage.tsx index db0778c4..1567a9ac 100644 --- a/apps/web/src/components/ChatMessage.tsx +++ b/apps/web/src/components/ChatMessage.tsx @@ -1,9 +1,10 @@ import React, { useEffect } from "react"; import { motion } from "framer-motion"; -import { ArrowUpRight, Globe } from "lucide-react"; +import { ArrowUpRight, Globe, Text } from "lucide-react"; import { convertRemToPixels } from "@/lib/utils"; import { SpaceIcon } from "@/assets/Memories"; import Markdown from "react-markdown"; +import { ChatHistory } from "../../types/memory"; export function ChatAnswer({ children: message, @@ -11,7 +12,7 @@ export function ChatAnswer({ loading = false, }: { children: string; - sources?: string[]; + sources?: ChatHistory['answer']['sources']; loading?: boolean; }) { return ( @@ -29,15 +30,22 @@ export function ChatAnswer({ Related Memories -
- {sources?.map((source) => ( +
+ {sources?.map((source) => source.isNote ? ( + + ) : ( - {cleanUrl(source)} + {cleanUrl(source.source)} ))}
diff --git a/apps/web/src/components/Main.tsx b/apps/web/src/components/Main.tsx index bbdb630d..df6a08bf 100644 --- a/apps/web/src/components/Main.tsx +++ b/apps/web/src/components/Main.tsx @@ -13,6 +13,7 @@ import { useRouter, useSearchParams } from "next/navigation"; import { useMemory } from "@/contexts/MemoryContext"; import Image from "next/image"; +import { getMemoriesFromUrl } from "@/actions/db"; function supportsDVH() { try { @@ -185,11 +186,25 @@ export default function Main({ sidebarOpen }: { sidebarOpen: boolean }) { }, ); - const sourcesInJson = (await sourcesResponse.json()) as { - ids: string[]; - }; - console.log(sourcesInJson); + const sourcesInJson = getIdsFromSource(((await sourcesResponse.json()) as { + ids: string[] + }).ids) ?? []; + + + const notesInSources = sourcesInJson.filter( + (urls) => urls.startsWith("https://notes.supermemory.dhr.wtf/") + ) + const nonNotes = sourcesInJson.filter( + i => !notesInSources.includes(i) + ) + + const fetchedTitles = await getMemoriesFromUrl(notesInSources); + + const sources = [ + ...nonNotes.map(n => ({ isNote: false, source: n ?? "" })), + ...fetchedTitles.map(n => ({ isNote: true, source: n.title ?? "" })) + ] setIsAiLoading(false); setChatHistory((prev) => { @@ -200,7 +215,7 @@ export default function Main({ sidebarOpen }: { sidebarOpen: boolean }) { ...lastMessage, answer: { parts: lastMessage.answer.parts, - sources: getIdsFromSource(sourcesInJson.ids) ?? [], + sources }, }, ]; diff --git a/apps/web/src/components/Sidebar/AddMemoryDialog.tsx b/apps/web/src/components/Sidebar/AddMemoryDialog.tsx index 95bb3d22..f6a7224f 100644 --- a/apps/web/src/components/Sidebar/AddMemoryDialog.tsx +++ b/apps/web/src/components/Sidebar/AddMemoryDialog.tsx @@ -165,13 +165,12 @@ export function NoteAddPage({ closeDialog }: { closeDialog: () => void }) { onClick={() => { if (check()) { setLoading(true); - const randomId = Math.floor(Math.random() * 1000000); addMemory( { content, title: name, type: "note", - url: `https://notes.supermemory.dhr.wtf/${randomId}`, + url: `https://notes.supermemory.dhr.wtf/`, image: "", savedAt: new Date(), }, diff --git a/apps/web/src/components/Sidebar/DeleteConfirmation.tsx b/apps/web/src/components/Sidebar/DeleteConfirmation.tsx new file mode 100644 index 00000000..9324b147 --- /dev/null +++ b/apps/web/src/components/Sidebar/DeleteConfirmation.tsx @@ -0,0 +1,35 @@ +import { Dialog, DialogContent, DialogTrigger, DialogTitle, DialogDescription, DialogClose, DialogFooter } from "../ui/dialog"; + +export default function DeleteConfirmation({ onDelete, trigger = true, children }: { trigger?: boolean, onDelete?: () => void; children: React.ReactNode }) { + return ( + + {trigger ? ( + + {children} + + ) : ( + <> + {children} + + )} + + Are you sure? + + You will not be able to recover this it. + + + + Delete + + + Cancel + + + + + ) +} diff --git a/apps/web/src/components/Sidebar/EditNoteDialog.tsx b/apps/web/src/components/Sidebar/EditNoteDialog.tsx new file mode 100644 index 00000000..b7760656 --- /dev/null +++ b/apps/web/src/components/Sidebar/EditNoteDialog.tsx @@ -0,0 +1,152 @@ + +import { Editor } from "novel"; +import { + DialogClose, + DialogFooter, +} from "../ui/dialog"; +import { Input } from "../ui/input"; +import { Markdown } from "tiptap-markdown"; +import { useEffect, useRef, useState } from "react"; +import { FilterSpaces } from "./FilterCombobox"; +import { useMemory } from "@/contexts/MemoryContext"; +import { Loader, Plus, Trash, X } from "lucide-react"; +import { motion } from "framer-motion"; +import { StoredContent } from "@/server/db/schema"; +import { fetchContent } from "@/actions/db"; +import { isArraysEqual } from "@/lib/utils"; +import DeleteConfirmation from "./DeleteConfirmation"; + + +export function NoteEdit({ memory, closeDialog }: { memory: StoredContent, closeDialog: () => any }) { + const { updateMemory, deleteMemory } = useMemory(); + + const [initialSpaces, setInitialSpaces] = useState([]) + const [selectedSpacesId, setSelectedSpacesId] = useState([]); + + const inputRef = useRef(null); + const [name, setName] = useState(memory.title ?? ""); + const [content, setContent] = useState(memory.content); + const [loading, setLoading] = useState(false); + + function check(): boolean { + const data = { + name: name.trim(), + content, + }; + if (!data.name || data.name.length < 1) { + if (!inputRef.current) { + alert("Please enter a name for the note"); + return false; + } + inputRef.current.value = ""; + inputRef.current.placeholder = "Please enter a title for the note"; + inputRef.current.dataset["error"] = "true"; + setTimeout(() => { + inputRef.current!.placeholder = "Title of the note"; + inputRef.current!.dataset["error"] = "false"; + }, 500); + inputRef.current.focus(); + return false; + } + return true; + } + + useEffect(() => { + fetchContent(memory.id).then((data) => { + if (data?.spaces) { + setInitialSpaces(data.spaces) + setSelectedSpacesId(data.spaces) + } + }) + }, []) + + return ( +
+ setName(e.target.value)} + /> + { + if (!editor) return; + setContent(editor.storage.markdown.getMarkdown()); + }} + extensions={[Markdown]} + className="novel-editor bg-rgray-4 border-rgray-7 dark mt-5 max-h-[60vh] min-h-[40vh] w-[50vw] overflow-y-auto rounded-lg border [&>div>div]:p-5" + /> + + + { + deleteMemory(memory.id) + }}> + + + + + Cancel + + +
+ ); +} + diff --git a/apps/web/src/components/Sidebar/FilterCombobox.tsx b/apps/web/src/components/Sidebar/FilterCombobox.tsx index f93ae710..7625e2b6 100644 --- a/apps/web/src/components/Sidebar/FilterCombobox.tsx +++ b/apps/web/src/components/Sidebar/FilterCombobox.tsx @@ -90,6 +90,7 @@ export function FilterSpaces({ align={align} side={side} className="w-[200px] p-0" + onCloseAutoFocus={e => e.preventDefault()} > @@ -128,7 +129,7 @@ export function FilterSpaces({ className="text-rgray-11" > - {space.name} + {space.name.length > 10 ? space.name.slice(0, 10) + "..." : space.name} {selectedSpaces.includes(space.id)} - {m.title} + {(m.title && m.title?.length > 14) ? m.title?.slice(0, 14) + "..." : m.title} i.id === m.id) !== undefined diff --git a/apps/web/src/components/Sidebar/MemoriesBar.tsx b/apps/web/src/components/Sidebar/MemoriesBar.tsx index 6c640e26..1218407b 100644 --- a/apps/web/src/components/Sidebar/MemoriesBar.tsx +++ b/apps/web/src/components/Sidebar/MemoriesBar.tsx @@ -37,15 +37,15 @@ import { DialogFooter, DialogClose, } from "../ui/dialog"; -import { Label } from "../ui/label"; import useViewport from "@/hooks/useViewport"; import useTouchHold from "@/hooks/useTouchHold"; import { DialogTrigger } from "@radix-ui/react-dialog"; import { AddMemoryPage, NoteAddPage, SpaceAddPage } from "./AddMemoryDialog"; import { ExpandedSpace } from "./ExpandedSpace"; import { StoredContent, StoredSpace } from "@/server/db/schema"; -import Image from "next/image"; import { useDebounce } from "@/hooks/useDebounce"; +import { NoteEdit } from "./EditNoteDialog"; +import DeleteConfirmation from "./DeleteConfirmation"; export function MemoriesBar() { const [parent, enableAnimations] = useAutoAnimate(); @@ -194,39 +194,58 @@ const SpaceExitVariant: Variant = { }, }; -export function MemoryItem({ id, title, image, type }: StoredContent) { +export function MemoryItem(props: StoredContent) { + + const { id, title, image, type } = props + const name = title ? title.length > 10 ? title.slice(0, 10) + "..." : title : ""; + const [isDialogOpen, setIsDialogOpen] = useState(false); + return ( -
- + +
setIsDialogOpen(true)} className="cursor-pointer hover:bg-rgray-2 has-[[data-state='true']]:bg-rgray-2 has-[[data-space-text]:focus-visible]:bg-rgray-2 has-[[data-space-text]:focus-visible]:ring-rgray-7 [&:has-[[data-space-text]:focus-visible]>[data-more-button]]:opacity-100 relative flex select-none flex-col-reverse items-center justify-center rounded-md p-2 pb-4 text-center font-normal ring-transparent transition has-[[data-space-text]:focus-visible]:outline-none has-[[data-space-text]:focus-visible]:ring-2 md:has-[[data-state='true']]:bg-transparent [&:hover>[data-more-button]]:opacity-100"> + { + type === "note" ? + ( + + + + ) : ( + + ) + } -
- {type === "page" ? ( - { - (e.target as HTMLImageElement).src = - "/icons/white_without_bg.png"; - }} - /> - ) : type === "note" ? ( -
- -
- ) : ( - <> - )} -
-
+
+ {type === "page" ? ( + { + (e.target as HTMLImageElement).src = + "/icons/white_without_bg.png"; + }} + /> + ) : type === "note" ? ( + + ) : ( + <> + )} +
+
+ + setIsDialogOpen(false)} memory={props} /> + + ); } @@ -254,6 +273,9 @@ export function SpaceItem({ }, [cachedMemories]); const _name = name.length > 10 ? name.slice(0, 10) + "..." : name; + + console.log(spaceMemories) + return ( void; }) { return ( - + + ); } -- cgit v1.2.3