Sidebar elements editor
This commit is contained in:
+141
-1
@@ -1,4 +1,4 @@
|
||||
import { Workspace, TodoEntity, DocEntity, Status } from "./types";
|
||||
import { Workspace, TodoEntity, DocEntity, Status, LayoutNode } from "./types";
|
||||
|
||||
export function createDefaultWorkspace(): Workspace {
|
||||
const now = Date.now();
|
||||
@@ -129,3 +129,143 @@ export function listWorkspaces(): Workspace[] {
|
||||
}
|
||||
return workspaces;
|
||||
}
|
||||
|
||||
// layout helpers -------------------------------------------------------------------
|
||||
|
||||
type RemoveResult = { layout: LayoutNode[]; removedEntityIds: string[] };
|
||||
|
||||
function collectEntityIds(node: LayoutNode): string[] {
|
||||
if (node.type === "item") return [node.entityId];
|
||||
const ids: string[] = [];
|
||||
for (const child of node.children) {
|
||||
ids.push(...collectEntityIds(child));
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
export function removeLayoutNode(
|
||||
layout: LayoutNode[],
|
||||
id: string,
|
||||
): RemoveResult {
|
||||
let removed: string[] = [];
|
||||
|
||||
function recurse(nodes: LayoutNode[]): LayoutNode[] {
|
||||
return nodes
|
||||
.map((node) => {
|
||||
if (node.type === "group") {
|
||||
if (node.id === id) {
|
||||
removed.push(...collectEntityIds(node));
|
||||
return null;
|
||||
}
|
||||
const children = recurse(node.children);
|
||||
if (children.length !== node.children.length) {
|
||||
// some children removed
|
||||
}
|
||||
return { ...node, children } as LayoutNode;
|
||||
} else {
|
||||
if (node.entityId === id) {
|
||||
removed.push(node.entityId);
|
||||
return null;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
})
|
||||
.filter(Boolean) as LayoutNode[];
|
||||
}
|
||||
|
||||
const newLayout = recurse(layout);
|
||||
return { layout: newLayout, removedEntityIds: removed };
|
||||
}
|
||||
|
||||
export function renameLayoutGroup(
|
||||
layout: LayoutNode[],
|
||||
id: string,
|
||||
newName: string,
|
||||
): LayoutNode[] {
|
||||
return layout.map((node) => {
|
||||
if (node.type === "group") {
|
||||
if (node.id === id) {
|
||||
return { ...node, name: newName };
|
||||
}
|
||||
return {
|
||||
...node,
|
||||
children: renameLayoutGroup(node.children, id, newName),
|
||||
};
|
||||
}
|
||||
return node;
|
||||
});
|
||||
}
|
||||
|
||||
export function addLayoutGroup(
|
||||
layout: LayoutNode[],
|
||||
parentId: string | null,
|
||||
group: LayoutNode,
|
||||
): LayoutNode[] {
|
||||
if (!parentId) {
|
||||
return [...layout, group];
|
||||
}
|
||||
return layout.map((node) => {
|
||||
if (node.type === "group") {
|
||||
if (node.id === parentId) {
|
||||
return { ...node, children: [...node.children, group] };
|
||||
}
|
||||
return {
|
||||
...node,
|
||||
children: addLayoutGroup(node.children, parentId, group),
|
||||
};
|
||||
}
|
||||
return node;
|
||||
});
|
||||
}
|
||||
|
||||
export function addLayoutItem(
|
||||
layout: LayoutNode[],
|
||||
parentId: string | null,
|
||||
item: LayoutNode,
|
||||
): LayoutNode[] {
|
||||
if (!parentId) {
|
||||
return [...layout, item];
|
||||
}
|
||||
return layout.map((node) => {
|
||||
if (node.type === "group") {
|
||||
if (node.id === parentId) {
|
||||
return { ...node, children: [...node.children, item] };
|
||||
}
|
||||
return {
|
||||
...node,
|
||||
children: addLayoutItem(node.children, parentId, item),
|
||||
};
|
||||
}
|
||||
return node;
|
||||
});
|
||||
}
|
||||
|
||||
// entity creation helpers ----------------------------------------------------------
|
||||
|
||||
export function createTodoEntity(name = "New list"): TodoEntity {
|
||||
const id = crypto.randomUUID();
|
||||
const now = Date.now();
|
||||
return {
|
||||
id,
|
||||
type: "todo",
|
||||
name,
|
||||
config: { statuses: [] },
|
||||
tags: {},
|
||||
tasks: {},
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
}
|
||||
|
||||
export function createDocEntity(name = "New doc"): DocEntity {
|
||||
const id = crypto.randomUUID();
|
||||
const now = Date.now();
|
||||
return {
|
||||
id,
|
||||
type: "doc",
|
||||
name,
|
||||
content: { version: "2.28.0", time: now, blocks: [] },
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user