64 lines
1.8 KiB
TypeScript
64 lines
1.8 KiB
TypeScript
export interface DocumentRecord {
|
|
access_scope: "private" | "shared" | "public";
|
|
id: string;
|
|
workspace_id: string;
|
|
title: string | null;
|
|
parent_id: string | null;
|
|
sort_order: number | null;
|
|
is_starred: boolean | null;
|
|
is_template: boolean;
|
|
created_at: string;
|
|
updated_at: string | null;
|
|
}
|
|
|
|
export interface DocumentNode extends DocumentRecord {
|
|
children: DocumentNode[];
|
|
}
|
|
|
|
export function buildDocumentTree(records: DocumentRecord[]): DocumentNode[] {
|
|
const nodeMap = new Map<string, DocumentNode>();
|
|
records.forEach((record) => {
|
|
nodeMap.set(record.id, { ...record, children: [] });
|
|
});
|
|
|
|
const roots: DocumentNode[] = [];
|
|
records.forEach((record) => {
|
|
const node = nodeMap.get(record.id);
|
|
if (!node) return;
|
|
if (record.parent_id && nodeMap.has(record.parent_id)) {
|
|
nodeMap.get(record.parent_id)!.children.push(node);
|
|
} else {
|
|
roots.push(node);
|
|
}
|
|
});
|
|
|
|
const sortTree = (nodes: DocumentNode[]) => {
|
|
nodes.sort((a, b) => {
|
|
const orderA = a.sort_order ?? Number.MAX_SAFE_INTEGER;
|
|
const orderB = b.sort_order ?? Number.MAX_SAFE_INTEGER;
|
|
if (orderA !== orderB) {
|
|
return orderA - orderB;
|
|
}
|
|
return new Date(a.created_at).getTime() - new Date(b.created_at).getTime();
|
|
});
|
|
nodes.forEach((child) => sortTree(child.children));
|
|
};
|
|
|
|
sortTree(roots);
|
|
return roots;
|
|
}
|
|
|
|
export function findBreadcrumb(records: DocumentRecord[], targetId: string): DocumentRecord[] {
|
|
const map = new Map<string, DocumentRecord>();
|
|
records.forEach((item) => map.set(item.id, item));
|
|
const path: DocumentRecord[] = [];
|
|
let current: DocumentRecord | undefined = map.get(targetId);
|
|
|
|
while (current) {
|
|
path.unshift(current);
|
|
current = current.parent_id ? map.get(current.parent_id) : undefined;
|
|
}
|
|
|
|
return path;
|
|
}
|