-
- setRoute({
- workspace: workspace.id,
- entity: node.entityId,
- })
- }
- >
- {workspaceEntity.name}
-
+
+
+ setRoute({
+ workspace: workspace.id,
+ entity: node.entityId,
+ })
+ }
+ >
+ {workspaceEntity.name}
+
+
+
+
+
+
+ openDialog("rename-item", workspaceEntity.name)}
+ >
+ Rename
+
+ {
+ if (window.confirm("Delete this list?")) {
+ deleteEntity(node.entityId);
+ }
+ }}
+ >
+ Delete
+
+
+
+
);
}
diff --git a/src/hooks/workspace.ts b/src/hooks/workspace.ts
index c90f08c..72a182f 100644
--- a/src/hooks/workspace.ts
+++ b/src/hooks/workspace.ts
@@ -1,7 +1,11 @@
-import { Entity, EntityId, Workspace } from "@/lib/types";
+import { Entity, EntityId, LayoutNode, Workspace } from "@/lib/types";
import {
loadWorkspaceFromLocalStorage,
saveWorkspaceToLocalStorage,
+ addLayoutItem,
+ addLayoutGroup,
+ removeLayoutNode,
+ renameLayoutGroup,
} from "@/lib/workspace";
import { useEffect, useState } from "react";
@@ -23,6 +27,105 @@ export function useWorkspace() {
);
};
+ const renameEntity = (entityId: EntityId, newName: string) => {
+ updateEntity(entityId, (e) => ({ ...e, name: newName }));
+ };
+
+ const deleteEntity = (entityId: EntityId) => {
+ setWorkspace((prev) => {
+ if (!prev) return prev;
+ const { [entityId]: _, ...rest } = prev.entities;
+ // also remove from layout
+ const { layout: newLayout } = removeLayoutNode(prev.layout, entityId);
+ return {
+ ...prev,
+ entities: rest,
+ layout: newLayout,
+ updatedAt: Date.now(),
+ };
+ });
+ };
+
+ const addEntity = (type: "todo" | "doc", parentGroupId: string | null) => {
+ if (!workspace) return;
+ const now = Date.now();
+ const id = crypto.randomUUID();
+ let entity: Entity;
+ if (type === "todo") {
+ entity = {
+ id,
+ type: "todo",
+ name: "New list",
+ config: { statuses: [] },
+ tags: {},
+ tasks: {},
+ createdAt: now,
+ updatedAt: now,
+ } as any;
+ } else {
+ entity = {
+ id,
+ type: "doc",
+ name: "New doc",
+ content: { version: "2.28.0", time: now, blocks: [] },
+ createdAt: now,
+ updatedAt: now,
+ } as any;
+ }
+ setWorkspace((prev) => {
+ if (!prev) return prev;
+ const newEntities = { ...prev.entities, [id]: entity };
+ const newLayout = addLayoutItem(prev.layout, parentGroupId, {
+ type: "item",
+ entityId: id,
+ });
+ return {
+ ...prev,
+ entities: newEntities,
+ layout: newLayout,
+ updatedAt: Date.now(),
+ };
+ });
+ return id;
+ };
+
+ const addGroup = (name = "New group", parentGroupId: string | null) => {
+ const id = crypto.randomUUID();
+ const group: LayoutNode = { type: "group", id, name, children: [] };
+ setWorkspace((prev) => {
+ if (!prev) return prev;
+ const newLayout = addLayoutGroup(prev.layout, parentGroupId, group);
+ return { ...prev, layout: newLayout, updatedAt: Date.now() };
+ });
+ return id;
+ };
+
+ const removeNode = (id: string) => {
+ setWorkspace((prev) => {
+ if (!prev) return prev;
+ const { layout: newLayout, removedEntityIds } = removeLayoutNode(
+ prev.layout,
+ id,
+ );
+ const newEntities = { ...prev.entities } as Record