deleting folder logic
This commit is contained in:
parent
aa97a6771e
commit
9a5a0e13d3
@ -13,6 +13,7 @@ import {
|
|||||||
createFile,
|
createFile,
|
||||||
deleteFile,
|
deleteFile,
|
||||||
generateCode,
|
generateCode,
|
||||||
|
getFolder,
|
||||||
getProjectSize,
|
getProjectSize,
|
||||||
getSandboxFiles,
|
getSandboxFiles,
|
||||||
renameFile,
|
renameFile,
|
||||||
@ -130,6 +131,11 @@ io.on("connection", async (socket) => {
|
|||||||
callback(file.data)
|
callback(file.data)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
socket.on("getFolder", async (folderId: string, callback) => {
|
||||||
|
const files = await getFolder(folderId)
|
||||||
|
callback(files)
|
||||||
|
})
|
||||||
|
|
||||||
// todo: send diffs + debounce for efficiency
|
// todo: send diffs + debounce for efficiency
|
||||||
socket.on("saveFile", async (fileId: string, body: string) => {
|
socket.on("saveFile", async (fileId: string, body: string) => {
|
||||||
try {
|
try {
|
||||||
@ -264,6 +270,33 @@ io.on("connection", async (socket) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
socket.on("renameFolder", async (folderId: string, newName: string) => {
|
||||||
|
// todo
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("deleteFolder", async (folderId: string, callback) => {
|
||||||
|
const files = await getFolder(folderId)
|
||||||
|
|
||||||
|
console.log("deleting folder", folderId, files)
|
||||||
|
|
||||||
|
await Promise.all(files.map(async (file) => {
|
||||||
|
fs.unlink(path.join(dirName, file), function (err) {
|
||||||
|
if (err) throw err
|
||||||
|
})
|
||||||
|
|
||||||
|
sandboxFiles.fileData = sandboxFiles.fileData.filter(
|
||||||
|
(f) => f.id !== file
|
||||||
|
)
|
||||||
|
|
||||||
|
await deleteFile(file)
|
||||||
|
}))
|
||||||
|
|
||||||
|
const newFiles = await getSandboxFiles(data.sandboxId)
|
||||||
|
|
||||||
|
callback(newFiles.files)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
socket.on("createTerminal", (id: string, callback) => {
|
socket.on("createTerminal", (id: string, callback) => {
|
||||||
console.log("creating terminal", id)
|
console.log("creating terminal", id)
|
||||||
if (terminals[id] || Object.keys(terminals).length >= 4) {
|
if (terminals[id] || Object.keys(terminals).length >= 4) {
|
||||||
@ -339,6 +372,7 @@ io.on("connection", async (socket) => {
|
|||||||
instructions: string,
|
instructions: string,
|
||||||
callback
|
callback
|
||||||
) => {
|
) => {
|
||||||
|
// Log code generation credit in DB
|
||||||
const fetchPromise = fetch(`https://database.ishaan1013.workers.dev/api/sandbox/generate`, {
|
const fetchPromise = fetch(`https://database.ishaan1013.workers.dev/api/sandbox/generate`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
@ -349,6 +383,7 @@ io.on("connection", async (socket) => {
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Generate code from cloudflare workers AI
|
||||||
const generateCodePromise = generateCode({
|
const generateCodePromise = generateCode({
|
||||||
fileName,
|
fileName,
|
||||||
code,
|
code,
|
||||||
|
@ -1,23 +1,28 @@
|
|||||||
import { RateLimiterMemory } from "rate-limiter-flexible"
|
import { RateLimiterMemory } from "rate-limiter-flexible"
|
||||||
|
|
||||||
export const saveFileRL = new RateLimiterMemory({
|
export const saveFileRL = new RateLimiterMemory({
|
||||||
points: 3,
|
points: 2,
|
||||||
duration: 1,
|
duration: 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const MAX_BODY_SIZE = 5 * 1024 * 1024
|
export const MAX_BODY_SIZE = 5 * 1024 * 1024
|
||||||
|
|
||||||
export const createFileRL = new RateLimiterMemory({
|
export const createFileRL = new RateLimiterMemory({
|
||||||
points: 3,
|
points: 1,
|
||||||
duration: 1,
|
duration: 2,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const renameFileRL = new RateLimiterMemory({
|
export const renameFileRL = new RateLimiterMemory({
|
||||||
points: 3,
|
points: 1,
|
||||||
duration: 1,
|
duration: 2,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const deleteFileRL = new RateLimiterMemory({
|
export const deleteFileRL = new RateLimiterMemory({
|
||||||
points: 3,
|
points: 1,
|
||||||
duration: 1,
|
duration: 2,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const deleteFolderRL = new RateLimiterMemory({
|
||||||
|
points: 1,
|
||||||
|
duration: 2,
|
||||||
})
|
})
|
@ -10,16 +10,25 @@ import {
|
|||||||
} from "./types"
|
} from "./types"
|
||||||
|
|
||||||
export const getSandboxFiles = async (id: string) => {
|
export const getSandboxFiles = async (id: string) => {
|
||||||
const sandboxRes = await fetch(
|
const res = await fetch(
|
||||||
`https://storage.ishaan1013.workers.dev/api?sandboxId=${id}`
|
`https://storage.ishaan1013.workers.dev/api?sandboxId=${id}`
|
||||||
)
|
)
|
||||||
const sandboxData: R2Files = await sandboxRes.json()
|
const data: R2Files = await res.json()
|
||||||
|
|
||||||
const paths = sandboxData.objects.map((obj) => obj.key)
|
const paths = data.objects.map((obj) => obj.key)
|
||||||
const processedFiles = await processFiles(paths, id)
|
const processedFiles = await processFiles(paths, id)
|
||||||
return processedFiles
|
return processedFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getFolder = async (folderId: string) => {
|
||||||
|
const res = await fetch(
|
||||||
|
`https://storage.ishaan1013.workers.dev/api?folderId=${folderId}`
|
||||||
|
)
|
||||||
|
const data: R2Files = await res.json()
|
||||||
|
|
||||||
|
return data.objects.map((obj) => obj.key)
|
||||||
|
}
|
||||||
|
|
||||||
const processFiles = async (paths: string[], id: string) => {
|
const processFiles = async (paths: string[], id: string) => {
|
||||||
const root: TFolder = { id: "/", type: "folder", name: "/", children: [] }
|
const root: TFolder = { id: "/", type: "folder", name: "/", children: [] }
|
||||||
const fileData: TFileData[] = []
|
const fileData: TFileData[] = []
|
||||||
|
@ -36,11 +36,15 @@ export default {
|
|||||||
if (method === 'GET') {
|
if (method === 'GET') {
|
||||||
const params = url.searchParams;
|
const params = url.searchParams;
|
||||||
const sandboxId = params.get('sandboxId');
|
const sandboxId = params.get('sandboxId');
|
||||||
|
const folderId = params.get('folderId');
|
||||||
const fileId = params.get('fileId');
|
const fileId = params.get('fileId');
|
||||||
|
|
||||||
if (sandboxId) {
|
if (sandboxId) {
|
||||||
const res = await env.R2.list({ prefix: `projects/${sandboxId}` });
|
const res = await env.R2.list({ prefix: `projects/${sandboxId}` });
|
||||||
return new Response(JSON.stringify(res), { status: 200 });
|
return new Response(JSON.stringify(res), { status: 200 });
|
||||||
|
} else if (folderId) {
|
||||||
|
const res = await env.R2.list({ prefix: folderId });
|
||||||
|
return new Response(JSON.stringify(res), { status: 200 });
|
||||||
} else if (fileId) {
|
} else if (fileId) {
|
||||||
const obj = await env.R2.get(fileId);
|
const obj = await env.R2.get(fileId);
|
||||||
if (obj === null) {
|
if (obj === null) {
|
||||||
|
@ -58,6 +58,7 @@ export default function CodeEditor({
|
|||||||
const [tabs, setTabs] = useState<TTab[]>([]);
|
const [tabs, setTabs] = useState<TTab[]>([]);
|
||||||
const [activeFileId, setActiveFileId] = useState<string>("");
|
const [activeFileId, setActiveFileId] = useState<string>("");
|
||||||
const [activeFileContent, setActiveFileContent] = useState("");
|
const [activeFileContent, setActiveFileContent] = useState("");
|
||||||
|
const [deletingFolderId, setDeletingFolderId] = useState("");
|
||||||
|
|
||||||
// Editor state
|
// Editor state
|
||||||
const [editorLanguage, setEditorLanguage] = useState("plaintext");
|
const [editorLanguage, setEditorLanguage] = useState("plaintext");
|
||||||
@ -435,14 +436,16 @@ export default function CodeEditor({
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Close tab and remove from tabs
|
// Close tab and remove from tabs
|
||||||
const closeTab = (tab: TFile) => {
|
const closeTab = (id: string) => {
|
||||||
const numTabs = tabs.length;
|
const numTabs = tabs.length;
|
||||||
const index = tabs.findIndex((t) => t.id === tab.id);
|
const index = tabs.findIndex((t) => t.id === id);
|
||||||
|
|
||||||
|
console.log("closing tab", id, index);
|
||||||
|
|
||||||
if (index === -1) return;
|
if (index === -1) return;
|
||||||
|
|
||||||
const nextId =
|
const nextId =
|
||||||
activeFileId === tab.id
|
activeFileId === id
|
||||||
? numTabs === 1
|
? numTabs === 1
|
||||||
? null
|
? null
|
||||||
: index < numTabs - 1
|
: index < numTabs - 1
|
||||||
@ -450,7 +453,7 @@ export default function CodeEditor({
|
|||||||
: tabs[index - 1].id
|
: tabs[index - 1].id
|
||||||
: activeFileId;
|
: activeFileId;
|
||||||
|
|
||||||
setTabs((prev) => prev.filter((t) => t.id !== tab.id));
|
setTabs((prev) => prev.filter((t) => t.id !== id));
|
||||||
|
|
||||||
if (!nextId) {
|
if (!nextId) {
|
||||||
setActiveFileId("");
|
setActiveFileId("");
|
||||||
@ -462,6 +465,36 @@ export default function CodeEditor({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const closeTabs = (ids: string[]) => {
|
||||||
|
const numTabs = tabs.length;
|
||||||
|
|
||||||
|
if (numTabs === 0) return;
|
||||||
|
|
||||||
|
const allIndexes = ids.map((id) => tabs.findIndex((t) => t.id === id));
|
||||||
|
|
||||||
|
const indexes = allIndexes.filter((index) => index !== -1);
|
||||||
|
if (indexes.length === 0) return;
|
||||||
|
|
||||||
|
console.log("closing tabs", ids, indexes);
|
||||||
|
|
||||||
|
const activeIndex = tabs.findIndex((t) => t.id === activeFileId);
|
||||||
|
|
||||||
|
const newTabs = tabs.filter((t) => !ids.includes(t.id));
|
||||||
|
setTabs(newTabs);
|
||||||
|
|
||||||
|
if (indexes.length === numTabs) {
|
||||||
|
setActiveFileId("");
|
||||||
|
} else {
|
||||||
|
const nextTab =
|
||||||
|
newTabs.length > activeIndex
|
||||||
|
? newTabs[activeIndex]
|
||||||
|
: newTabs[newTabs.length - 1];
|
||||||
|
if (nextTab) {
|
||||||
|
selectFile(nextTab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleRename = (
|
const handleRename = (
|
||||||
id: string,
|
id: string,
|
||||||
newName: string,
|
newName: string,
|
||||||
@ -486,13 +519,25 @@ export default function CodeEditor({
|
|||||||
socket.emit("deleteFile", file.id, (response: (TFolder | TFile)[]) => {
|
socket.emit("deleteFile", file.id, (response: (TFolder | TFile)[]) => {
|
||||||
setFiles(response);
|
setFiles(response);
|
||||||
});
|
});
|
||||||
closeTab(file);
|
closeTab(file.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteFolder = (folder: TFolder) => {
|
const handleDeleteFolder = (folder: TFolder) => {
|
||||||
// socket.emit("deleteFolder", folder.id, (response: (TFolder | TFile)[]) => {
|
setDeletingFolderId(folder.id);
|
||||||
// setFiles(response)
|
console.log("deleting folder", folder.id);
|
||||||
// })
|
|
||||||
|
socket.emit("getFolder", folder.id, (response: string[]) =>
|
||||||
|
closeTabs(response)
|
||||||
|
);
|
||||||
|
|
||||||
|
socket.emit("deleteFolder", folder.id, (response: (TFolder | TFile)[]) => {
|
||||||
|
setFiles(response);
|
||||||
|
setDeletingFolderId("");
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
setDeletingFolderId("");
|
||||||
|
}, 3000);
|
||||||
};
|
};
|
||||||
|
|
||||||
// On disabled access for shared users, show un-interactable loading placeholder + info modal
|
// On disabled access for shared users, show un-interactable loading placeholder + info modal
|
||||||
@ -581,6 +626,7 @@ export default function CodeEditor({
|
|||||||
// setFiles(prev => [...prev, { id, name, type: "folder", children: [] }])
|
// setFiles(prev => [...prev, { id, name, type: "folder", children: [] }])
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
deletingFolderId={deletingFolderId}
|
||||||
// AI Copilot Toggle
|
// AI Copilot Toggle
|
||||||
ai={ai}
|
ai={ai}
|
||||||
setAi={setAi}
|
setAi={setAi}
|
||||||
@ -604,7 +650,7 @@ export default function CodeEditor({
|
|||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
selectFile(tab);
|
selectFile(tab);
|
||||||
}}
|
}}
|
||||||
onClose={() => closeTab(tab)}
|
onClose={() => closeTab(tab.id)}
|
||||||
>
|
>
|
||||||
{tab.name}
|
{tab.name}
|
||||||
</Tab>
|
</Tab>
|
||||||
|
@ -20,6 +20,7 @@ export default function SidebarFile({
|
|||||||
handleRename,
|
handleRename,
|
||||||
handleDeleteFile,
|
handleDeleteFile,
|
||||||
movingId,
|
movingId,
|
||||||
|
deletingFolderId,
|
||||||
}: {
|
}: {
|
||||||
data: TFile;
|
data: TFile;
|
||||||
selectFile: (file: TTab) => void;
|
selectFile: (file: TTab) => void;
|
||||||
@ -31,8 +32,11 @@ export default function SidebarFile({
|
|||||||
) => boolean;
|
) => boolean;
|
||||||
handleDeleteFile: (file: TFile) => void;
|
handleDeleteFile: (file: TFile) => void;
|
||||||
movingId: string;
|
movingId: string;
|
||||||
|
deletingFolderId: string;
|
||||||
}) {
|
}) {
|
||||||
const isMoving = movingId === data.id;
|
const isMoving = movingId === data.id;
|
||||||
|
const isDeleting =
|
||||||
|
deletingFolderId.length > 0 && data.id.startsWith(deletingFolderId);
|
||||||
|
|
||||||
const ref = useRef(null); // for draggable
|
const ref = useRef(null); // for draggable
|
||||||
const [dragging, setDragging] = useState(false);
|
const [dragging, setDragging] = useState(false);
|
||||||
@ -40,7 +44,11 @@ export default function SidebarFile({
|
|||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
const [imgSrc, setImgSrc] = useState(`/icons/${getIconForFile(data.name)}`);
|
const [imgSrc, setImgSrc] = useState(`/icons/${getIconForFile(data.name)}`);
|
||||||
const [editing, setEditing] = useState(false);
|
const [editing, setEditing] = useState(false);
|
||||||
const [pendingDelete, setPendingDelete] = useState(false);
|
const [pendingDelete, setPendingDelete] = useState(isDeleting);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setPendingDelete(isDeleting);
|
||||||
|
}, [isDeleting]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const el = ref.current;
|
const el = ref.current;
|
||||||
@ -104,8 +112,9 @@ export default function SidebarFile({
|
|||||||
</>
|
</>
|
||||||
) : pendingDelete ? (
|
) : pendingDelete ? (
|
||||||
<>
|
<>
|
||||||
<Loader2 className="text-muted-foreground w-4 h-4 animate-spin mr-2" />
|
<div className="text-muted-foreground animate-pulse">
|
||||||
<div className="text-muted-foreground">Deleting...</div>
|
Deleting...
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<form
|
<form
|
||||||
|
@ -11,9 +11,11 @@ import {
|
|||||||
ContextMenuItem,
|
ContextMenuItem,
|
||||||
ContextMenuTrigger,
|
ContextMenuTrigger,
|
||||||
} from "@/components/ui/context-menu";
|
} from "@/components/ui/context-menu";
|
||||||
import { Pencil, Trash2 } from "lucide-react";
|
import { Loader2, Pencil, Trash2 } from "lucide-react";
|
||||||
import { dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
|
import { dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
|
||||||
|
|
||||||
|
// Note: Renaming has not been implemented in the backend yet, so UI relating to renaming is commented out
|
||||||
|
|
||||||
export default function SidebarFolder({
|
export default function SidebarFolder({
|
||||||
data,
|
data,
|
||||||
selectFile,
|
selectFile,
|
||||||
@ -21,6 +23,7 @@ export default function SidebarFolder({
|
|||||||
handleDeleteFile,
|
handleDeleteFile,
|
||||||
handleDeleteFolder,
|
handleDeleteFolder,
|
||||||
movingId,
|
movingId,
|
||||||
|
deletingFolderId,
|
||||||
}: {
|
}: {
|
||||||
data: TFolder;
|
data: TFolder;
|
||||||
selectFile: (file: TTab) => void;
|
selectFile: (file: TTab) => void;
|
||||||
@ -33,10 +36,14 @@ export default function SidebarFolder({
|
|||||||
handleDeleteFile: (file: TFile) => void;
|
handleDeleteFile: (file: TFile) => void;
|
||||||
handleDeleteFolder: (folder: TFolder) => void;
|
handleDeleteFolder: (folder: TFolder) => void;
|
||||||
movingId: string;
|
movingId: string;
|
||||||
|
deletingFolderId: string;
|
||||||
}) {
|
}) {
|
||||||
const ref = useRef(null); // drop target
|
const ref = useRef(null); // drop target
|
||||||
const [isDraggedOver, setIsDraggedOver] = useState(false);
|
const [isDraggedOver, setIsDraggedOver] = useState(false);
|
||||||
|
|
||||||
|
const isDeleting =
|
||||||
|
deletingFolderId.length > 0 && data.id.startsWith(deletingFolderId);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const el = ref.current;
|
const el = ref.current;
|
||||||
|
|
||||||
@ -58,9 +65,10 @@ export default function SidebarFolder({
|
|||||||
// return !file;
|
// return !file;
|
||||||
// },
|
// },
|
||||||
|
|
||||||
|
// no dropping while awaiting move
|
||||||
canDrop: () => {
|
canDrop: () => {
|
||||||
return !movingId;
|
return !movingId;
|
||||||
}, // no dropping while awaiting move
|
},
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -69,28 +77,20 @@ export default function SidebarFolder({
|
|||||||
? getIconForOpenFolder(data.name)
|
? getIconForOpenFolder(data.name)
|
||||||
: getIconForFolder(data.name);
|
: getIconForFolder(data.name);
|
||||||
|
|
||||||
const [editing, setEditing] = useState(false);
|
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
// const [editing, setEditing] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
if (editing) {
|
// if (editing) {
|
||||||
inputRef.current?.focus();
|
// inputRef.current?.focus();
|
||||||
}
|
// }
|
||||||
}, [editing]);
|
// }, [editing]);
|
||||||
|
|
||||||
// return (
|
|
||||||
// <div
|
|
||||||
// ref={ref}
|
|
||||||
// className="w-full h-7 rounded-full"
|
|
||||||
// style={{backgroundColor: isDraggedOver ? "red" : "blue"}}
|
|
||||||
// >
|
|
||||||
// </div>
|
|
||||||
// )
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenu>
|
<ContextMenu>
|
||||||
<ContextMenuTrigger
|
<ContextMenuTrigger
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
disabled={isDeleting}
|
||||||
onClick={() => setIsOpen((prev) => !prev)}
|
onClick={() => setIsOpen((prev) => !prev)}
|
||||||
className={`${
|
className={`${
|
||||||
isDraggedOver ? "bg-secondary/50 rounded-t-sm" : "rounded-sm"
|
isDraggedOver ? "bg-secondary/50 rounded-t-sm" : "rounded-sm"
|
||||||
@ -103,13 +103,26 @@ export default function SidebarFolder({
|
|||||||
height={18}
|
height={18}
|
||||||
className="mr-2"
|
className="mr-2"
|
||||||
/>
|
/>
|
||||||
|
{isDeleting ? (
|
||||||
|
<>
|
||||||
|
<div className="text-muted-foreground animate-pulse">
|
||||||
|
Deleting...
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
<form
|
<form
|
||||||
onSubmit={(e) => {
|
// onSubmit={(e) => {
|
||||||
e.preventDefault();
|
// e.preventDefault();
|
||||||
setEditing(false);
|
// setEditing(false);
|
||||||
}}
|
// }}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
ref={inputRef}
|
||||||
|
disabled
|
||||||
|
className={`pointer-events-none bg-transparent transition-all focus-visible:outline-none focus-visible:ring-offset-2 focus-visible:ring-offset-background focus-visible:ring-2 focus-visible:ring-ring rounded-sm w-full`}
|
||||||
|
defaultValue={data.name}
|
||||||
|
/>
|
||||||
|
{/* <input
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
className={`bg-transparent transition-all focus-visible:outline-none focus-visible:ring-offset-2 focus-visible:ring-offset-background focus-visible:ring-2 focus-visible:ring-ring rounded-sm w-full ${
|
className={`bg-transparent transition-all focus-visible:outline-none focus-visible:ring-offset-2 focus-visible:ring-offset-background focus-visible:ring-2 focus-visible:ring-ring rounded-sm w-full ${
|
||||||
editing ? "" : "pointer-events-none"
|
editing ? "" : "pointer-events-none"
|
||||||
@ -119,24 +132,24 @@ export default function SidebarFolder({
|
|||||||
onBlur={() => {
|
onBlur={() => {
|
||||||
setEditing(false);
|
setEditing(false);
|
||||||
}}
|
}}
|
||||||
/>
|
/> */}
|
||||||
</form>
|
</form>
|
||||||
|
)}
|
||||||
</ContextMenuTrigger>
|
</ContextMenuTrigger>
|
||||||
<ContextMenuContent>
|
<ContextMenuContent>
|
||||||
<ContextMenuItem
|
<ContextMenuItem
|
||||||
onClick={() => {
|
disabled
|
||||||
setEditing(true);
|
// onClick={() => {
|
||||||
}}
|
// setEditing(true);
|
||||||
|
// }}
|
||||||
>
|
>
|
||||||
<Pencil className="w-4 h-4 mr-2" />
|
<Pencil className="w-4 h-4 mr-2" />
|
||||||
Rename
|
Rename
|
||||||
</ContextMenuItem>
|
</ContextMenuItem>
|
||||||
<ContextMenuItem
|
<ContextMenuItem
|
||||||
// disabled={pendingDelete}
|
disabled={isDeleting}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
console.log("delete");
|
handleDeleteFolder(data);
|
||||||
// setPendingDelete(true)
|
|
||||||
// handleDeleteFile(data)
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Trash2 className="w-4 h-4 mr-2" />
|
<Trash2 className="w-4 h-4 mr-2" />
|
||||||
@ -160,6 +173,7 @@ export default function SidebarFolder({
|
|||||||
handleRename={handleRename}
|
handleRename={handleRename}
|
||||||
handleDeleteFile={handleDeleteFile}
|
handleDeleteFile={handleDeleteFile}
|
||||||
movingId={movingId}
|
movingId={movingId}
|
||||||
|
deletingFolderId={deletingFolderId}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<SidebarFolder
|
<SidebarFolder
|
||||||
@ -170,6 +184,7 @@ export default function SidebarFolder({
|
|||||||
handleDeleteFile={handleDeleteFile}
|
handleDeleteFile={handleDeleteFile}
|
||||||
handleDeleteFolder={handleDeleteFolder}
|
handleDeleteFolder={handleDeleteFolder}
|
||||||
movingId={movingId}
|
movingId={movingId}
|
||||||
|
deletingFolderId={deletingFolderId}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
|
@ -26,6 +26,7 @@ export default function Sidebar({
|
|||||||
addNew,
|
addNew,
|
||||||
ai,
|
ai,
|
||||||
setAi,
|
setAi,
|
||||||
|
deletingFolderId,
|
||||||
}: {
|
}: {
|
||||||
sandboxData: Sandbox;
|
sandboxData: Sandbox;
|
||||||
files: (TFile | TFolder)[];
|
files: (TFile | TFolder)[];
|
||||||
@ -43,6 +44,7 @@ export default function Sidebar({
|
|||||||
addNew: (name: string, type: "file" | "folder") => void;
|
addNew: (name: string, type: "file" | "folder") => void;
|
||||||
ai: boolean;
|
ai: boolean;
|
||||||
setAi: React.Dispatch<React.SetStateAction<boolean>>;
|
setAi: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
deletingFolderId: string;
|
||||||
}) {
|
}) {
|
||||||
const ref = useRef(null); // drop target
|
const ref = useRef(null); // drop target
|
||||||
|
|
||||||
@ -147,6 +149,7 @@ export default function Sidebar({
|
|||||||
handleRename={handleRename}
|
handleRename={handleRename}
|
||||||
handleDeleteFile={handleDeleteFile}
|
handleDeleteFile={handleDeleteFile}
|
||||||
movingId={movingId}
|
movingId={movingId}
|
||||||
|
deletingFolderId={deletingFolderId}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<SidebarFolder
|
<SidebarFolder
|
||||||
@ -157,6 +160,7 @@ export default function Sidebar({
|
|||||||
handleDeleteFile={handleDeleteFile}
|
handleDeleteFile={handleDeleteFile}
|
||||||
handleDeleteFolder={handleDeleteFolder}
|
handleDeleteFolder={handleDeleteFolder}
|
||||||
movingId={movingId}
|
movingId={movingId}
|
||||||
|
deletingFolderId={deletingFolderId}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user