Agents for developpement added + frontend add + backend added. Git viewer created + agent and template creator + layout and project creator
70 lines
1.8 KiB
TypeScript
70 lines
1.8 KiB
TypeScript
/**
|
|
* Pure helper that folds a flat list of changed file paths into a directory
|
|
* tree, so the Git panel can show changes as a file tree (L8 visual). Kept free
|
|
* of React for straightforward unit testing.
|
|
*/
|
|
|
|
import type { GitFileStatus } from "@/domain";
|
|
|
|
/** A node in the changed-files tree: a directory or a file leaf. */
|
|
export interface GitTreeNode {
|
|
/** Last path segment (folder or file name). */
|
|
name: string;
|
|
/** Full repo-relative path of this node. */
|
|
path: string;
|
|
/** Whether this node is a directory (has children) or a file leaf. */
|
|
isDir: boolean;
|
|
/** For file leaves: whether the change is staged. */
|
|
staged: boolean;
|
|
/** Child nodes (empty for files). */
|
|
children: GitTreeNode[];
|
|
}
|
|
|
|
/**
|
|
* Builds the directory tree for a set of changed files. Directories come before
|
|
* files at each level, both alphabetically sorted.
|
|
*/
|
|
export function buildFileTree(files: GitFileStatus[]): GitTreeNode[] {
|
|
const root: GitTreeNode = {
|
|
name: "",
|
|
path: "",
|
|
isDir: true,
|
|
staged: false,
|
|
children: [],
|
|
};
|
|
|
|
for (const file of files) {
|
|
const parts = file.path.split("/").filter(Boolean);
|
|
let node = root;
|
|
parts.forEach((part, i) => {
|
|
const isLeaf = i === parts.length - 1;
|
|
const path = parts.slice(0, i + 1).join("/");
|
|
let child = node.children.find(
|
|
(c) => c.name === part && c.isDir === !isLeaf,
|
|
);
|
|
if (!child) {
|
|
child = {
|
|
name: part,
|
|
path,
|
|
isDir: !isLeaf,
|
|
staged: file.staged,
|
|
children: [],
|
|
};
|
|
node.children.push(child);
|
|
}
|
|
node = child;
|
|
});
|
|
}
|
|
|
|
sort(root);
|
|
return root.children;
|
|
}
|
|
|
|
function sort(node: GitTreeNode): void {
|
|
node.children.sort((a, b) => {
|
|
if (a.isDir !== b.isDir) return a.isDir ? -1 : 1;
|
|
return a.name.localeCompare(b.name);
|
|
});
|
|
node.children.forEach(sort);
|
|
}
|