feat: add sidebar panel
This commit is contained in:
@@ -1,10 +1,28 @@
|
||||
import * as path from "path";
|
||||
import * as vscode from "vscode";
|
||||
import { ConfigStore } from "./storage/configStore";
|
||||
import { TaskStore } from "./storage/taskStore";
|
||||
import { TaskTreeProvider } from "./views/taskTreeProvider";
|
||||
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
const taskStore = new TaskStore();
|
||||
const configStore = new ConfigStore();
|
||||
const taskTreeProvider = new TaskTreeProvider();
|
||||
|
||||
vscode.window.registerTreeDataProvider(
|
||||
"projectTasks.tasks",
|
||||
taskTreeProvider,
|
||||
);
|
||||
|
||||
const projectPath = configStore.getProjectTaskPath();
|
||||
if (projectPath) {
|
||||
const taskPattern = path.join(projectPath, "*.task.md").replace(/\\/g, "/");
|
||||
const watcher = vscode.workspace.createFileSystemWatcher(taskPattern);
|
||||
watcher.onDidCreate(() => taskTreeProvider.refresh());
|
||||
watcher.onDidChange(() => taskTreeProvider.refresh());
|
||||
watcher.onDidDelete(() => taskTreeProvider.refresh());
|
||||
context.subscriptions.push(watcher);
|
||||
}
|
||||
|
||||
const statusBarItem = vscode.window.createStatusBarItem(
|
||||
vscode.StatusBarAlignment.Left,
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
import * as vscode from "vscode";
|
||||
import { Task, TaskStatus } from "../model/task";
|
||||
import { TaskStore } from "../storage/taskStore";
|
||||
import { ConfigStore } from "../storage/configStore";
|
||||
|
||||
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 {
|
||||
constructor(
|
||||
label: string,
|
||||
public readonly tasks: Task[],
|
||||
icon: vscode.ThemeIcon,
|
||||
) {
|
||||
super(label, vscode.TreeItemCollapsibleState.Collapsed);
|
||||
this.iconPath = icon;
|
||||
this.description = `(${tasks.length})`;
|
||||
}
|
||||
}
|
||||
|
||||
export class TaskTreeProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
||||
private _onDidChangeTreeData = new vscode.EventEmitter<
|
||||
vscode.TreeItem | undefined | null | void
|
||||
>();
|
||||
readonly onDidChangeTreeData = this._onDidChangeTreeData.event;
|
||||
|
||||
private taskStore = new TaskStore();
|
||||
private configStore = new 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.listTasks(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;
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user