Files
xboct-flow/src/views/taskTreeProvider.ts
T

96 lines
2.7 KiB
TypeScript

import { Task, TaskStatus } from "@/model/task";
import { IConfigProvider, ITaskRepository } from "@/ports";
import * as vscode from "vscode";
const STATUS_ORDER: TaskStatus[] = ["todo", "in-progress", "done", "cancelled"];
const STATUS_ICONS: Record<TaskStatus, vscode.ThemeIcon> = {
todo: new vscode.ThemeIcon("circle-outline"),
"in-progress": new vscode.ThemeIcon("sync"),
done: new vscode.ThemeIcon("check"),
cancelled: new vscode.ThemeIcon("close"),
};
class TaskGroupTreeItem extends vscode.TreeItem {
readonly tasks: Task[];
constructor(label: string, tasks: Task[], icon: vscode.ThemeIcon) {
super(label, vscode.TreeItemCollapsibleState.Collapsed);
this.iconPath = icon;
this.tasks = tasks;
this.description = `(${tasks.length})`;
}
}
export class TaskTreeProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
#onDidChangeTreeData = new vscode.EventEmitter<
vscode.TreeItem | undefined | null | void
>();
readonly onDidChangeTreeData = this.#onDidChangeTreeData.event;
#taskStore: ITaskRepository;
#configStore: IConfigProvider;
constructor(taskStore: ITaskRepository, configStore: IConfigProvider) {
this.#taskStore = taskStore;
this.#configStore = configStore;
}
refresh(): void {
this.#onDidChangeTreeData.fire();
}
getTreeItem(element: vscode.TreeItem): vscode.TreeItem {
return element;
}
async getChildren(element?: vscode.TreeItem): Promise<vscode.TreeItem[]> {
if (!element) {
return this.getRootChildren();
}
return this.getTaskChildren(element as TaskGroupTreeItem);
}
private async getRootChildren(): Promise<vscode.TreeItem[]> {
const projectPath = this.#configStore.getProjectTaskPath();
if (!projectPath) {
return [new vscode.TreeItem("Open a workspace folder to start")];
}
const tasks = await this.#taskStore.list(projectPath);
return STATUS_ORDER.map((status) => {
const groupTasks = tasks.filter((t) => t.status === status);
const label =
status === "todo"
? "To Do"
: status === "in-progress"
? "In Progress"
: status === "done"
? "Done"
: "Cancelled";
const item = new TaskGroupTreeItem(
label,
groupTasks,
STATUS_ICONS[status],
);
item.id = `group-${status}`;
item.contextValue = "taskGroup";
return item;
});
}
private getTaskChildren(group: TaskGroupTreeItem): vscode.TreeItem[] {
return group.tasks.map((task) => {
const item = new vscode.TreeItem(task.title);
item.id = task.id;
item.description = task.priority;
item.tooltip = new vscode.MarkdownString(
`**${task.title}**\n\nPriority: ${task.priority}\nStatus: ${task.status}${task.assignee ? `\nAssignee: ${task.assignee}` : ""}`,
);
item.contextValue = "task";
return item;
});
}
}