Workspace editing
This commit is contained in:
@@ -34,7 +34,11 @@ import {
|
|||||||
|
|
||||||
import { ChevronDown } from "lucide-react";
|
import { ChevronDown } from "lucide-react";
|
||||||
import { Route, SetState, Workspace } from "@/lib/types";
|
import { Route, SetState, Workspace } from "@/lib/types";
|
||||||
import { listWorkspaces, saveWorkspaceToLocalStorage } from "@/lib/workspace";
|
import {
|
||||||
|
listWorkspaces,
|
||||||
|
saveWorkspaceToLocalStorage,
|
||||||
|
createDefaultWorkspace,
|
||||||
|
} from "@/lib/workspace";
|
||||||
import { openFileDialog } from "@/lib/import";
|
import { openFileDialog } from "@/lib/import";
|
||||||
|
|
||||||
// Simple ID generator
|
// Simple ID generator
|
||||||
@@ -79,6 +83,9 @@ export default function AppSidebar({
|
|||||||
|
|
||||||
const [isRenameOpen, setIsRenameOpen] = React.useState(false);
|
const [isRenameOpen, setIsRenameOpen] = React.useState(false);
|
||||||
const [proposedName, setProposedName] = React.useState(workspace.name);
|
const [proposedName, setProposedName] = React.useState(workspace.name);
|
||||||
|
const [isWorkspaceCreateOpen, setIsWorkspaceCreateOpen] =
|
||||||
|
React.useState(false);
|
||||||
|
const [newWorkspaceName, setNewWorkspaceName] = React.useState("");
|
||||||
const [isCreateOpen, setIsCreateOpen] = React.useState(false);
|
const [isCreateOpen, setIsCreateOpen] = React.useState(false);
|
||||||
const [createMode, setCreateMode] = React.useState<"list" | "doc" | "group">(
|
const [createMode, setCreateMode] = React.useState<"list" | "doc" | "group">(
|
||||||
"list",
|
"list",
|
||||||
@@ -168,16 +175,19 @@ export default function AppSidebar({
|
|||||||
className="w-[--radix-popper-anchor-width]"
|
className="w-[--radix-popper-anchor-width]"
|
||||||
>
|
>
|
||||||
{/* list all known workspaces */}
|
{/* list all known workspaces */}
|
||||||
{availableWorkspaces.map((w) => (
|
{[
|
||||||
|
availableWorkspaces.find((w) => w.id === workspace.id),
|
||||||
|
...availableWorkspaces.filter((w) => w.id !== workspace.id),
|
||||||
|
].map((w) => (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
key={w.id}
|
key={w?.id}
|
||||||
className={
|
className={
|
||||||
w.id === workspace.id ? "font-semibold" : undefined
|
w?.id === workspace.id ? "font-semibold" : undefined
|
||||||
}
|
}
|
||||||
onSelect={() => switchWorkspace(w.id)}
|
onSelect={() => w && switchWorkspace(w?.id)}
|
||||||
>
|
>
|
||||||
{w.name}
|
{w?.name}
|
||||||
{w.id === workspace.id ? " (current)" : ""}
|
{w?.id === workspace.id ? " (current)" : ""}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
))}
|
))}
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
@@ -209,16 +219,23 @@ export default function AppSidebar({
|
|||||||
New group (root)
|
New group (root)
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItem onSelect={importWorkspace}>
|
|
||||||
Import Workspace
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuSeparator />
|
|
||||||
<DropdownMenuItem onSelect={() => setIsRenameOpen(true)}>
|
<DropdownMenuItem onSelect={() => setIsRenameOpen(true)}>
|
||||||
Rename Workspace
|
Rename Workspace
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem onSelect={importWorkspace}>
|
||||||
|
Import Workspace
|
||||||
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem onSelect={exportWorkspace}>
|
<DropdownMenuItem onSelect={exportWorkspace}>
|
||||||
Export Workspace
|
Export Workspace
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem
|
||||||
|
onSelect={() => {
|
||||||
|
setNewWorkspaceName("New workspace");
|
||||||
|
setIsWorkspaceCreateOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Create workspace
|
||||||
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</SidebarMenuItem>
|
</SidebarMenuItem>
|
||||||
@@ -279,6 +296,48 @@ export default function AppSidebar({
|
|||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
{/* create workspace dialog */}
|
||||||
|
<Dialog
|
||||||
|
open={isWorkspaceCreateOpen}
|
||||||
|
onOpenChange={setIsWorkspaceCreateOpen}
|
||||||
|
>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Create workspace</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Provide a name for the workspace.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<Input
|
||||||
|
value={newWorkspaceName}
|
||||||
|
onChange={(e) => setNewWorkspaceName(e.target.value)}
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => setIsWorkspaceCreateOpen(false)}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
const ws = createDefaultWorkspace();
|
||||||
|
ws.name = newWorkspaceName || ws.name;
|
||||||
|
ws.updatedAt = Date.now();
|
||||||
|
ws.createdAt = ws.createdAt || Date.now();
|
||||||
|
saveWorkspaceToLocalStorage(ws);
|
||||||
|
setAvailableWorkspaces(listWorkspaces());
|
||||||
|
switchWorkspace(ws.id);
|
||||||
|
if (setWorkspace) setWorkspace(ws);
|
||||||
|
setIsWorkspaceCreateOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Create
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
{/* create dialog */}
|
{/* create dialog */}
|
||||||
<Dialog open={isCreateOpen} onOpenChange={setIsCreateOpen}>
|
<Dialog open={isCreateOpen} onOpenChange={setIsCreateOpen}>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
|
|||||||
Reference in New Issue
Block a user