feat(charts): manage investigation charts in a scrolling workspace
Generic Container CI/CD / test-build-publish (push) Successful in 2m7s
Frontend CI/CD / build-test-publish-and-deploy (push) Successful in 2m8s

This commit is contained in:
2026-11-10 17:56:23 +08:00
parent 865491cb23
commit 0ae0a41e61
80 changed files with 4672 additions and 470 deletions
@@ -114,6 +114,9 @@ async function waitForChart(
}
export function useInvestigationPresentation(options: Options) {
const windowScope = JSON.stringify([options.scope, options.scopeId, options.projectId, options.task?.task_id, options.task?.execution_generation]);
const [chartWindow, setChartWindow] = useState({ scope: windowScope, requested: false });
if (chartWindow.scope !== windowScope) setChartWindow({ scope: windowScope, requested: false });
const valuesRef = useRef(options);
valuesRef.current = options;
const storeRef = useRef(new PresentationViewHistory());
@@ -155,6 +158,14 @@ export function useInvestigationPresentation(options: Options) {
: "live",
[]
);
const requestChartWindow = useCallback((origin: InvestigationPresentationActivity["source"]) => {
const current = valuesRef.current;
if (storeRef.current.selectedId !== null || current.scope === "chat" || current.scope === "preview") return;
if (origin !== "live" || !current.enabled || current.task?.status !== "running") return;
const panel = document.querySelector<HTMLElement>(`[data-presentation-scope="${current.scope ?? "investigation"}"]`);
if (panel?.dataset.investigationCollapsed === "true") return;
setChartWindow({ scope: JSON.stringify([current.scope, current.scopeId, current.projectId, current.task?.task_id, current.task?.execution_generation]), requested: true });
}, []);
const update = useCallback(
(updater: (view: PresentationView) => PresentationView) => {
storeRef.current.update(updater(storeRef.current.current));
@@ -289,6 +300,7 @@ export function useInvestigationPresentation(options: Options) {
})
);
signal.throwIfAborted();
if (command.action === "open_chart") requestChartWindow(origin);
if (historyId !== null) store.finish(historyId, "completed", undefined, actionSnapshot, pendingEntry);
publish();
setActivity((current) =>
@@ -327,7 +339,7 @@ export function useInvestigationPresentation(options: Options) {
throw cause;
}
},
[scene, publish, update]
[scene, publish, update, requestChartWindow]
);
useEffect(() => {
@@ -555,6 +567,8 @@ export function useInvestigationPresentation(options: Options) {
const visible = storeRef.current.visible;
const reviewing = storeRef.current.selectedId !== null;
return {
chartWindowAutoOpen: chartWindow.scope === windowScope && chartWindow.requested,
chartWindowScope: windowScope,
charts: visible.charts,
blocks: visible.blocks,
records: visible.records,