mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-08-28 05:25:33 +00:00
fix: space deletion state cleanup and single-select for add document (#748)
fix: space deletion + new space not reflecting in selector Deleting a space wasn't switching back to Nova Spaces because we were reading stale cache data New spaces created from the add-document modal weren't showing up in the dropdown Added single-select mode to the space selector in the add-document flow since you're picking one space, not multiple.
This commit is contained in:
parent
cc2dcaa306
commit
7339822997
4 changed files with 100 additions and 59 deletions
|
|
@ -380,40 +380,42 @@ export function AddDocument({
|
|||
|
||||
<div
|
||||
className={cn(
|
||||
"overflow-auto flex flex-col justify-between px-1 scrollbar-thin flex-1",
|
||||
"flex flex-col flex-1 min-h-0 px-1",
|
||||
isMobile ? "w-full" : "w-2/3",
|
||||
)}
|
||||
>
|
||||
{activeTab === "note" && (
|
||||
<NoteContent
|
||||
onSubmit={handleNoteSubmit}
|
||||
onContentChange={handleNoteContentChange}
|
||||
isSubmitting={noteMutation.isPending}
|
||||
isOpen={isOpen}
|
||||
/>
|
||||
)}
|
||||
{activeTab === "link" && (
|
||||
<LinkContent
|
||||
onSubmit={handleLinkSubmit}
|
||||
onDataChange={handleLinkDataChange}
|
||||
isSubmitting={linkMutation.isPending}
|
||||
isOpen={isOpen}
|
||||
/>
|
||||
)}
|
||||
{activeTab === "file" && (
|
||||
<FileContent
|
||||
onSubmit={handleFileSubmit}
|
||||
onDataChange={handleFileDataChange}
|
||||
isSubmitting={fileMutation.isPending}
|
||||
isOpen={isOpen}
|
||||
/>
|
||||
)}
|
||||
{activeTab === "connect" && (
|
||||
<ConnectContent selectedProject={localSelectedProject} />
|
||||
)}
|
||||
<div className="overflow-auto flex-1 min-h-0 scrollbar-thin">
|
||||
{activeTab === "note" && (
|
||||
<NoteContent
|
||||
onSubmit={handleNoteSubmit}
|
||||
onContentChange={handleNoteContentChange}
|
||||
isSubmitting={noteMutation.isPending}
|
||||
isOpen={isOpen}
|
||||
/>
|
||||
)}
|
||||
{activeTab === "link" && (
|
||||
<LinkContent
|
||||
onSubmit={handleLinkSubmit}
|
||||
onDataChange={handleLinkDataChange}
|
||||
isSubmitting={linkMutation.isPending}
|
||||
isOpen={isOpen}
|
||||
/>
|
||||
)}
|
||||
{activeTab === "file" && (
|
||||
<FileContent
|
||||
onSubmit={handleFileSubmit}
|
||||
onDataChange={handleFileDataChange}
|
||||
isSubmitting={fileMutation.isPending}
|
||||
isOpen={isOpen}
|
||||
/>
|
||||
)}
|
||||
{activeTab === "connect" && (
|
||||
<ConnectContent selectedProject={localSelectedProject} />
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
"flex gap-2 pt-3",
|
||||
"flex gap-2 pt-3 shrink-0",
|
||||
isMobile ? "flex-col" : "justify-between",
|
||||
)}
|
||||
>
|
||||
|
|
@ -424,6 +426,7 @@ export function AddDocument({
|
|||
setLocalSelectedProject(projects[0] ?? localSelectedProject)
|
||||
}
|
||||
variant="insideOut"
|
||||
singleSelect
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -65,9 +65,11 @@ const EMOJI_LIST = [
|
|||
export function AddSpaceModal({
|
||||
isOpen,
|
||||
onClose,
|
||||
onCreated,
|
||||
}: {
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
onCreated?: (containerTag: string) => void
|
||||
}) {
|
||||
const [spaceName, setSpaceName] = useState("")
|
||||
const [emoji, setEmoji] = useState("📁")
|
||||
|
|
@ -87,8 +89,11 @@ export function AddSpaceModal({
|
|||
createProjectMutation.mutate(
|
||||
{ name: trimmedName, emoji: emoji || undefined },
|
||||
{
|
||||
onSuccess: () => {
|
||||
onSuccess: (data) => {
|
||||
analytics.spaceCreated()
|
||||
if (data?.containerTag) {
|
||||
onCreated?.(data.containerTag)
|
||||
}
|
||||
handleClose()
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ interface SelectSpacesModalProps {
|
|||
selectedProjects: string[]
|
||||
onApply: (selected: string[]) => void
|
||||
projects: ContainerTagListType[]
|
||||
singleSelect?: boolean
|
||||
}
|
||||
|
||||
export function SelectSpacesModal({
|
||||
|
|
@ -24,6 +25,7 @@ export function SelectSpacesModal({
|
|||
selectedProjects,
|
||||
onApply,
|
||||
projects,
|
||||
singleSelect = false,
|
||||
}: SelectSpacesModalProps) {
|
||||
const [searchQuery, setSearchQuery] = useState("")
|
||||
const [localSelection, setLocalSelection] =
|
||||
|
|
@ -44,6 +46,10 @@ export function SelectSpacesModal({
|
|||
}
|
||||
|
||||
const handleToggle = (containerTag: string) => {
|
||||
if (singleSelect) {
|
||||
setLocalSelection([containerTag])
|
||||
return
|
||||
}
|
||||
setLocalSelection((prev) => {
|
||||
if (prev.includes(containerTag)) {
|
||||
return prev.filter((tag) => tag !== containerTag)
|
||||
|
|
@ -117,10 +123,12 @@ export function SelectSpacesModal({
|
|||
dmSans125ClassName(),
|
||||
)}
|
||||
>
|
||||
Select Spaces
|
||||
Select Space{!singleSelect && "s"}
|
||||
</p>
|
||||
<p className="text-[#737373] font-medium text-[16px] leading-[1.35]">
|
||||
Choose one or more spaces to filter your memories
|
||||
{singleSelect
|
||||
? "Choose a space for your memory"
|
||||
: "Choose one or more spaces to filter your memories"}
|
||||
</p>
|
||||
</div>
|
||||
<DialogPrimitive.Close
|
||||
|
|
@ -173,16 +181,29 @@ export function SelectSpacesModal({
|
|||
: "bg-transparent border border-transparent hover:bg-[#14161A]/50",
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
"w-5 h-5 rounded-md border-2 flex items-center justify-center shrink-0 transition-colors",
|
||||
isSelected
|
||||
? "bg-blue-500 border-blue-500"
|
||||
: "border-[#737373]",
|
||||
)}
|
||||
>
|
||||
{isSelected && <Check className="size-3 text-white" />}
|
||||
</div>
|
||||
{singleSelect ? (
|
||||
<div
|
||||
className={cn(
|
||||
"w-5 h-5 rounded-full border-2 flex items-center justify-center shrink-0 transition-colors",
|
||||
isSelected ? "border-blue-500" : "border-[#737373]",
|
||||
)}
|
||||
>
|
||||
{isSelected && (
|
||||
<div className="w-2.5 h-2.5 rounded-full bg-blue-500" />
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className={cn(
|
||||
"w-5 h-5 rounded-md border-2 flex items-center justify-center shrink-0 transition-colors",
|
||||
isSelected
|
||||
? "bg-blue-500 border-blue-500"
|
||||
: "border-[#737373]",
|
||||
)}
|
||||
>
|
||||
{isSelected && <Check className="size-3 text-white" />}
|
||||
</div>
|
||||
)}
|
||||
<span className="text-lg">{project.emoji || "📁"}</span>
|
||||
<span className="text-[#fafafa] text-sm font-medium truncate flex-1">
|
||||
{project.name ?? project.containerTag}
|
||||
|
|
@ -195,9 +216,13 @@ export function SelectSpacesModal({
|
|||
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-[#737373] text-sm">
|
||||
{localSelection.length === 0
|
||||
? "No spaces selected (showing all)"
|
||||
: `${localSelection.length} space${localSelection.length > 1 ? "s" : ""} selected`}
|
||||
{singleSelect
|
||||
? localSelection.length === 0
|
||||
? "No space selected"
|
||||
: "1 space selected"
|
||||
: localSelection.length === 0
|
||||
? "No spaces selected (showing all)"
|
||||
: `${localSelection.length} space${localSelection.length > 1 ? "s" : ""} selected`}
|
||||
</p>
|
||||
<div className="flex items-center gap-[22px]">
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ export interface SpaceSelectorProps {
|
|||
showNewSpace?: boolean
|
||||
enableDelete?: boolean
|
||||
compact?: boolean
|
||||
singleSelect?: boolean
|
||||
}
|
||||
|
||||
const triggerVariants = {
|
||||
|
|
@ -70,6 +71,7 @@ export function SpaceSelector({
|
|||
showNewSpace = true,
|
||||
enableDelete = false,
|
||||
compact = false,
|
||||
singleSelect = false,
|
||||
}: SpaceSelectorProps) {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [showCreateDialog, setShowCreateDialog] = useState(false)
|
||||
|
|
@ -272,20 +274,24 @@ export function SpaceSelector({
|
|||
>
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex flex-col">
|
||||
<DropdownMenuItem
|
||||
onClick={handleSelectNovaSpaces}
|
||||
className={cn(
|
||||
"flex items-center gap-2 px-3 py-2.5 rounded-md cursor-pointer text-white text-sm font-medium",
|
||||
isNovaSpaces
|
||||
? "bg-[#293952]/40"
|
||||
: "opacity-60 hover:opacity-100 hover:bg-[#293952]/40",
|
||||
)}
|
||||
>
|
||||
<Globe className="size-4" />
|
||||
<span className="flex-1">Nova Spaces</span>
|
||||
</DropdownMenuItem>
|
||||
{!singleSelect && (
|
||||
<>
|
||||
<DropdownMenuItem
|
||||
onClick={handleSelectNovaSpaces}
|
||||
className={cn(
|
||||
"flex items-center gap-2 px-3 py-2.5 rounded-md cursor-pointer text-white text-sm font-medium",
|
||||
isNovaSpaces
|
||||
? "bg-[#293952]/40"
|
||||
: "opacity-60 hover:opacity-100 hover:bg-[#293952]/40",
|
||||
)}
|
||||
>
|
||||
<Globe className="size-4" />
|
||||
<span className="flex-1">Nova Spaces</span>
|
||||
</DropdownMenuItem>
|
||||
|
||||
<DropdownMenuSeparator className="bg-[#2E3033] my-1" />
|
||||
<DropdownMenuSeparator className="bg-[#2E3033] my-1" />
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="px-3 py-1">
|
||||
<span className="text-[10px] uppercase tracking-wider text-[#737373] font-medium">
|
||||
|
|
@ -362,7 +368,7 @@ export function SpaceSelector({
|
|||
}}
|
||||
>
|
||||
<Layers className="size-4" />
|
||||
<span>Select Spaces</span>
|
||||
<span>Select Space{!singleSelect && "s"}</span>
|
||||
</button>
|
||||
|
||||
{showNewSpace && (
|
||||
|
|
@ -386,6 +392,7 @@ export function SpaceSelector({
|
|||
<AddSpaceModal
|
||||
isOpen={showCreateDialog}
|
||||
onClose={() => setShowCreateDialog(false)}
|
||||
onCreated={(containerTag) => onValueChange([containerTag])}
|
||||
/>
|
||||
|
||||
<SelectSpacesModal
|
||||
|
|
@ -394,6 +401,7 @@ export function SpaceSelector({
|
|||
selectedProjects={selectedProjects}
|
||||
onApply={handleSelectSpacesApply}
|
||||
projects={allProjects}
|
||||
singleSelect={singleSelect}
|
||||
/>
|
||||
|
||||
<Dialog
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue