Merge remote-tracking branch 'origin/v0.3' into feat/2891-linux-hwpod-qemu
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { loadTaskTreeRoute } from "./tasktree-route-loader";
|
||||
|
||||
describe("loadTaskTreeRoute", () => {
|
||||
it("loads only the global overview for the TaskTree root route", async () => {
|
||||
const overview = vi.fn().mockResolvedValue({ ok: true });
|
||||
const timeline = vi.fn();
|
||||
|
||||
const result = await loadTaskTreeRoute({ overview, timeline }, "");
|
||||
|
||||
expect(result.view).toBe("global");
|
||||
expect(overview).toHaveBeenCalledOnce();
|
||||
expect(timeline).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("loads a group timeline without depending on the global overview", async () => {
|
||||
const overview = vi.fn();
|
||||
const timeline = vi.fn().mockResolvedValue({ ok: true });
|
||||
|
||||
const result = await loadTaskTreeRoute({ overview, timeline }, "tg_example");
|
||||
|
||||
expect(result.view).toBe("group");
|
||||
expect(timeline).toHaveBeenCalledOnce();
|
||||
expect(timeline).toHaveBeenCalledWith("tg_example");
|
||||
expect(overview).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
import type { tasktreeAPI } from "@/api/tasktree";
|
||||
|
||||
type TaskTreeReadApi = Pick<typeof tasktreeAPI, "overview" | "timeline">;
|
||||
|
||||
export async function loadTaskTreeRoute(api: TaskTreeReadApi, groupId: string) {
|
||||
if (groupId) {
|
||||
return { view: "group" as const, response: await api.timeline(groupId) };
|
||||
}
|
||||
return { view: "global" as const, response: await api.overview() };
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import TaskTreeDetailPanel from "@/components/tasktree/TaskTreeDetailPanel.vue";
|
||||
import MessageMarkdown from "@/components/workbench/MessageMarkdown.vue";
|
||||
import { displayTimeConfig } from "@/config/runtime";
|
||||
import { decideNestedWheelBoundary, type NestedWheelBoundaryState } from "@/utils/nested-wheel-boundary";
|
||||
import { loadTaskTreeRoute } from "@/utils/tasktree-route-loader";
|
||||
import { deriveEffectiveTaskTimeRanges } from "@/utils/tasktree-time-range";
|
||||
|
||||
const route = useRoute();
|
||||
@@ -108,32 +109,37 @@ watch(requestedDetailMode, (mode) => { detailMode.value = mode; });
|
||||
|
||||
async function loadActiveView() {
|
||||
loading.value = true; error.value = null;
|
||||
const overviewResponse = await tasktreeAPI.overview();
|
||||
if (!overviewResponse.ok || overviewResponse.data?.ok === false) {
|
||||
loading.value = false;
|
||||
error.value = overviewResponse.data?.error?.message || overviewResponse.error || "TaskTree 全局视图加载失败";
|
||||
return;
|
||||
}
|
||||
overview.value = overviewResponse.data?.data?.groups ?? [];
|
||||
groups.value = overview.value.map((item) => item.group);
|
||||
if (!groupId.value) {
|
||||
const activeGroupId = groupId.value;
|
||||
const result = await loadTaskTreeRoute(tasktreeAPI, activeGroupId);
|
||||
if (result.view === "global") {
|
||||
const overviewResponse = result.response;
|
||||
if (!overviewResponse.ok || overviewResponse.data?.ok === false) {
|
||||
loading.value = false;
|
||||
error.value = overviewResponse.data?.error?.message || overviewResponse.error || "TaskTree 全局视图加载失败";
|
||||
return;
|
||||
}
|
||||
overview.value = overviewResponse.data?.data?.groups ?? [];
|
||||
groups.value = overview.value.map((item) => item.group);
|
||||
timeline.value = null;
|
||||
loading.value = false;
|
||||
await nextTick();
|
||||
positionTimelineAtNow("global");
|
||||
return;
|
||||
}
|
||||
const timelineResponse = await tasktreeAPI.timeline(groupId.value);
|
||||
const timelineResponse = result.response;
|
||||
loading.value = false;
|
||||
if (!timelineResponse.ok || timelineResponse.data?.ok === false || !timelineResponse.data?.data) {
|
||||
error.value = timelineResponse.data?.error?.message || timelineResponse.error || "TaskTree timeline 加载失败";
|
||||
return;
|
||||
}
|
||||
timeline.value = timelineResponse.data.data;
|
||||
if (!groups.value.some((group) => group.id === timeline.value?.group.id)) {
|
||||
groups.value = [...groups.value, timeline.value.group];
|
||||
}
|
||||
initializedChildGroups.clear();
|
||||
syncSelectedTaskFromRoute();
|
||||
await nextTick();
|
||||
positionTimelineAtNow(groupId.value);
|
||||
positionTimelineAtNow(activeGroupId);
|
||||
}
|
||||
function selectGroup(event: Event) {
|
||||
const value = (event.target as HTMLSelectElement).value;
|
||||
|
||||
Reference in New Issue
Block a user