feat: dashboard - add sorting and scope
This commit is contained in:
@@ -3,15 +3,21 @@ import { listLocatedTasks } from "@/commands/listLocatedTasks";
|
||||
import { resolveTaskLocations } from "@/commands/resolveTaskLocations";
|
||||
import { saveTaskDescription } from "@/commands/saveTaskDescription";
|
||||
import { buildDashboardView } from "@/dashboard/buildDashboardView";
|
||||
import { filterLocatedByScope } from "@/dashboard/filterLocatedByScope";
|
||||
import { TaskFilter } from "@/dashboard/filterTasks";
|
||||
import { GroupBy } from "@/dashboard/groupBy";
|
||||
import {
|
||||
parseDashboardInboundMessage,
|
||||
type DashboardInboundMessage,
|
||||
type DashboardScopeFilter,
|
||||
} from "@/dashboard/messages";
|
||||
import { DashboardOutboundMessage } from "@/dashboard/outboundMessages";
|
||||
import {
|
||||
DashboardListTask,
|
||||
DashboardOutboundMessage,
|
||||
} from "@/dashboard/outboundMessages";
|
||||
import { sortTasks, TaskSortDirection } from "@/dashboard/sortTasks";
|
||||
import { appError, AppErrorVariant } from "@/error";
|
||||
import { LocatedTask } from "@/model/taskLocation";
|
||||
import { LocatedTask, TaskScope } from "@/model/taskLocation";
|
||||
import { IConfigProvider, ITaskRepository } from "@/ports";
|
||||
import { presentError } from "@/ui/presentError";
|
||||
import { createNonce, getTaskDashboardHtml } from "./taskDashboardHtml";
|
||||
@@ -76,6 +82,8 @@ export class TaskDashboardPanel {
|
||||
#tasks: LocatedTask[] = [];
|
||||
#filter: TaskFilter = {};
|
||||
#groupBy: GroupBy = GroupBy.NONE;
|
||||
#scopeFilter: DashboardScopeFilter = "all";
|
||||
#sortDirection: TaskSortDirection = TaskSortDirection.ASC;
|
||||
#selectedId: string | undefined;
|
||||
#disposed = false;
|
||||
|
||||
@@ -158,6 +166,16 @@ export class TaskDashboardPanel {
|
||||
this.#postState();
|
||||
return;
|
||||
|
||||
case "setScopeFilter":
|
||||
this.#scopeFilter = message.scope;
|
||||
this.#postState();
|
||||
return;
|
||||
|
||||
case "setSortDirection":
|
||||
this.#sortDirection = message.direction;
|
||||
this.#postState();
|
||||
return;
|
||||
|
||||
case "saveDescription":
|
||||
await this.#saveDescription(message.id, message.description);
|
||||
return;
|
||||
@@ -172,7 +190,8 @@ export class TaskDashboardPanel {
|
||||
async #saveDescription(id: string, description: string): Promise<void> {
|
||||
const located = this.#tasks.find((item) => item.task.id === id);
|
||||
if (!located) {
|
||||
this.#post({ variant: "error",
|
||||
this.#post({
|
||||
variant: "error",
|
||||
error: appError(AppErrorVariant.NOT_FOUND, { id }),
|
||||
});
|
||||
return;
|
||||
@@ -201,20 +220,61 @@ export class TaskDashboardPanel {
|
||||
this.#deps.onTasksMutated?.();
|
||||
}
|
||||
|
||||
#scopeById(): Map<string, TaskScope> {
|
||||
return new Map(
|
||||
this.#tasks.map((item) => [item.task.id, item.location.scope]),
|
||||
);
|
||||
}
|
||||
|
||||
#withScope(task: import("@/model/task").Task): DashboardListTask | null {
|
||||
const scope = this.#scopeById().get(task.id);
|
||||
if (scope === undefined) {
|
||||
return null;
|
||||
}
|
||||
return { ...task, scope };
|
||||
}
|
||||
|
||||
#availableScopes(): TaskScope[] {
|
||||
const scopes = new Set(this.#tasks.map((item) => item.location.scope));
|
||||
for (const loc of resolveTaskLocations(this.#deps.config)) {
|
||||
scopes.add(loc.scope);
|
||||
}
|
||||
return [...scopes];
|
||||
}
|
||||
|
||||
#postState(): void {
|
||||
const plainTasks = this.#tasks.map((item) => item.task);
|
||||
const view = buildDashboardView(plainTasks, {
|
||||
const scoped = filterLocatedByScope(this.#tasks, this.#scopeFilter);
|
||||
const plainSorted = sortTasks(
|
||||
scoped.map((item) => item.task),
|
||||
this.#sortDirection,
|
||||
);
|
||||
const view = buildDashboardView(plainSorted, {
|
||||
filter: this.#filter,
|
||||
groupBy: this.#groupBy,
|
||||
selectedId: this.#selectedId,
|
||||
});
|
||||
|
||||
this.#post({ variant: "state",
|
||||
const groups = view.groups.map((group) => ({
|
||||
key: group.key,
|
||||
label: group.label,
|
||||
tasks: group.tasks
|
||||
.map((task) => this.#withScope(task))
|
||||
.filter((task): task is DashboardListTask => task !== null),
|
||||
}));
|
||||
|
||||
const selected =
|
||||
view.selected !== undefined ? this.#withScope(view.selected) : null;
|
||||
|
||||
this.#post({
|
||||
variant: "state",
|
||||
filter: this.#filter,
|
||||
groupBy: this.#groupBy,
|
||||
selectedId: this.#selectedId,
|
||||
groups: view.groups,
|
||||
selected: view.selected ?? null,
|
||||
groups,
|
||||
selected,
|
||||
scopeFilter: this.#scopeFilter,
|
||||
sortDirection: this.#sortDirection,
|
||||
availableScopes: this.#availableScopes(),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user