feat: update kanban view, dashboard view, add backlog status
This commit is contained in:
@@ -9,25 +9,23 @@ import {
|
||||
|
||||
describe("parseDashboardInboundMessage", () => {
|
||||
it("parses ready", () => {
|
||||
expect(parseDashboardInboundMessage({ type: "ready" })).toEqual(
|
||||
ok({ type: "ready" } satisfies DashboardInboundMessage),
|
||||
expect(parseDashboardInboundMessage({ variant: "ready" })).toEqual(
|
||||
ok({ variant: "ready" } satisfies DashboardInboundMessage),
|
||||
);
|
||||
});
|
||||
|
||||
it("parses selectTask", () => {
|
||||
expect(
|
||||
parseDashboardInboundMessage({ type: "selectTask", id: "abc" }),
|
||||
).toEqual(ok({ type: "selectTask", id: "abc" }));
|
||||
parseDashboardInboundMessage({ variant: "selectTask", id: "abc" }),
|
||||
).toEqual(ok({ variant: "selectTask", id: "abc" }));
|
||||
});
|
||||
|
||||
it("parses setFilter", () => {
|
||||
const raw = {
|
||||
type: "setFilter",
|
||||
const raw = { variant: "setFilter",
|
||||
filter: { statuses: ["todo"], query: "login" },
|
||||
};
|
||||
expect(parseDashboardInboundMessage(raw)).toEqual(
|
||||
ok({
|
||||
type: "setFilter",
|
||||
ok({ variant: "setFilter",
|
||||
filter: { statuses: ["todo"], query: "login" },
|
||||
}),
|
||||
);
|
||||
@@ -35,23 +33,20 @@ describe("parseDashboardInboundMessage", () => {
|
||||
|
||||
it("parses setGroupBy", () => {
|
||||
expect(
|
||||
parseDashboardInboundMessage({
|
||||
type: "setGroupBy",
|
||||
parseDashboardInboundMessage({ variant: "setGroupBy",
|
||||
groupBy: GroupBy.STATUS,
|
||||
}),
|
||||
).toEqual(ok({ type: "setGroupBy", groupBy: GroupBy.STATUS }));
|
||||
).toEqual(ok({ variant: "setGroupBy", groupBy: GroupBy.STATUS }));
|
||||
});
|
||||
|
||||
it("parses saveDescription", () => {
|
||||
expect(
|
||||
parseDashboardInboundMessage({
|
||||
type: "saveDescription",
|
||||
parseDashboardInboundMessage({ variant: "saveDescription",
|
||||
id: "abc",
|
||||
description: "updated body",
|
||||
}),
|
||||
).toEqual(
|
||||
ok({
|
||||
type: "saveDescription",
|
||||
ok({ variant: "saveDescription",
|
||||
id: "abc",
|
||||
description: "updated body",
|
||||
}),
|
||||
@@ -59,14 +54,14 @@ describe("parseDashboardInboundMessage", () => {
|
||||
});
|
||||
|
||||
it("parses refresh", () => {
|
||||
expect(parseDashboardInboundMessage({ type: "refresh" })).toEqual(
|
||||
ok({ type: "refresh" }),
|
||||
expect(parseDashboardInboundMessage({ variant: "refresh" })).toEqual(
|
||||
ok({ variant: "refresh" }),
|
||||
);
|
||||
});
|
||||
|
||||
it("parses createTask", () => {
|
||||
expect(parseDashboardInboundMessage({ type: "createTask" })).toEqual(
|
||||
ok({ type: "createTask" } satisfies DashboardInboundMessage),
|
||||
expect(parseDashboardInboundMessage({ variant: "createTask" })).toEqual(
|
||||
ok({ variant: "createTask" } satisfies DashboardInboundMessage),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -78,22 +73,21 @@ describe("parseDashboardInboundMessage", () => {
|
||||
});
|
||||
|
||||
it("rejects unknown type", () => {
|
||||
const result = parseDashboardInboundMessage({ type: "explode" });
|
||||
const result = parseDashboardInboundMessage({ variant: "explode" });
|
||||
expect(result.isErr()).toBe(true);
|
||||
if (result.isOk()) return;
|
||||
expect(result.error.variant).toBe(AppErrorVariant.INVALID_MESSAGE);
|
||||
});
|
||||
|
||||
it("rejects selectTask without id", () => {
|
||||
const result = parseDashboardInboundMessage({ type: "selectTask" });
|
||||
const result = parseDashboardInboundMessage({ variant: "selectTask" });
|
||||
expect(result.isErr()).toBe(true);
|
||||
if (result.isOk()) return;
|
||||
expect(result.error.variant).toBe(AppErrorVariant.INVALID_MESSAGE);
|
||||
});
|
||||
|
||||
it("rejects setGroupBy with invalid groupBy", () => {
|
||||
const result = parseDashboardInboundMessage({
|
||||
type: "setGroupBy",
|
||||
const result = parseDashboardInboundMessage({ variant: "setGroupBy",
|
||||
groupBy: "__not_a_group_by__",
|
||||
});
|
||||
expect(result.isErr()).toBe(true);
|
||||
@@ -102,8 +96,7 @@ describe("parseDashboardInboundMessage", () => {
|
||||
});
|
||||
|
||||
it("rejects saveDescription with non-string description", () => {
|
||||
const result = parseDashboardInboundMessage({
|
||||
type: "saveDescription",
|
||||
const result = parseDashboardInboundMessage({ variant: "saveDescription",
|
||||
id: "abc",
|
||||
description: 42,
|
||||
});
|
||||
|
||||
+21
-23
@@ -4,13 +4,13 @@ import { TaskFilter } from "./filterTasks";
|
||||
import { GroupBy, isGroupBy } from "./groupBy";
|
||||
|
||||
export type DashboardInboundMessage =
|
||||
| { type: "ready" }
|
||||
| { type: "selectTask"; id: string }
|
||||
| { type: "setFilter"; filter: TaskFilter }
|
||||
| { type: "setGroupBy"; groupBy: GroupBy }
|
||||
| { type: "saveDescription"; id: string; description: string }
|
||||
| { type: "refresh" }
|
||||
| { type: "createTask" };
|
||||
| { variant: "ready" }
|
||||
| { variant: "selectTask"; id: string }
|
||||
| { variant: "setFilter"; filter: TaskFilter }
|
||||
| { variant: "setGroupBy"; groupBy: GroupBy }
|
||||
| { variant: "saveDescription"; id: string; description: string }
|
||||
| { variant: "refresh" }
|
||||
| { variant: "createTask" };
|
||||
|
||||
function invalid(detail?: string): Result<DashboardInboundMessage, AppError> {
|
||||
return err(
|
||||
@@ -31,56 +31,54 @@ export function parseDashboardInboundMessage(
|
||||
return invalid();
|
||||
}
|
||||
|
||||
const type = raw.type;
|
||||
if (typeof type !== "string") {
|
||||
const variant = raw.variant;
|
||||
if (typeof variant !== "string") {
|
||||
return invalid();
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
switch (variant) {
|
||||
case "ready":
|
||||
case "refresh":
|
||||
case "createTask":
|
||||
return ok({ type });
|
||||
return ok({ variant });
|
||||
|
||||
case "selectTask": {
|
||||
if (typeof raw.id !== "string" || raw.id.length === 0) {
|
||||
return invalid(type);
|
||||
return invalid(variant);
|
||||
}
|
||||
return ok({ type: "selectTask", id: raw.id });
|
||||
return ok({ variant: "selectTask", id: raw.id });
|
||||
}
|
||||
|
||||
case "setFilter": {
|
||||
if (!isRecord(raw.filter)) {
|
||||
return invalid(type);
|
||||
return invalid(variant);
|
||||
}
|
||||
return ok({
|
||||
type: "setFilter",
|
||||
return ok({ variant: "setFilter",
|
||||
filter: raw.filter as TaskFilter,
|
||||
});
|
||||
}
|
||||
|
||||
case "setGroupBy": {
|
||||
if (!isGroupBy(raw.groupBy)) {
|
||||
return invalid(type);
|
||||
return invalid(variant);
|
||||
}
|
||||
return ok({ type: "setGroupBy", groupBy: raw.groupBy });
|
||||
return ok({ variant: "setGroupBy", groupBy: raw.groupBy });
|
||||
}
|
||||
|
||||
case "saveDescription": {
|
||||
if (typeof raw.id !== "string" || raw.id.length === 0) {
|
||||
return invalid(type);
|
||||
return invalid(variant);
|
||||
}
|
||||
if (typeof raw.description !== "string") {
|
||||
return invalid(type);
|
||||
return invalid(variant);
|
||||
}
|
||||
return ok({
|
||||
type: "saveDescription",
|
||||
return ok({ variant: "saveDescription",
|
||||
id: raw.id,
|
||||
description: raw.description,
|
||||
});
|
||||
}
|
||||
|
||||
default:
|
||||
return invalid(type);
|
||||
return invalid(variant);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,12 @@ import { GroupBy, TaskGroup } from "./groupTasks";
|
||||
|
||||
/** Host → webview messages (presentation payload only). */
|
||||
export type DashboardOutboundMessage =
|
||||
| {
|
||||
type: "state";
|
||||
| { variant: "state";
|
||||
filter: TaskFilter;
|
||||
groupBy: GroupBy;
|
||||
selectedId: string | undefined;
|
||||
groups: TaskGroup[];
|
||||
selected: Task | null;
|
||||
}
|
||||
| { type: "error"; error: AppError }
|
||||
| { type: "saved"; task: Task };
|
||||
| { variant: "error"; error: AppError }
|
||||
| { variant: "saved"; task: Task };
|
||||
|
||||
Reference in New Issue
Block a user