feat(FN-3203): improve agent detail view with runs tab and ListView UX

Merges FN-3181, FN-3190, and FN-3203: adds an initial runs tab to the agent detail view with auto-expand for the selected run, fixes ListView split-pane UX issues, aligns agent run duration calculation with the `AgentHeartbeatRun.endedAt` field, and restores task detail PR spacing. Updates include n

Fusion-Task-Id: FN-3203
This commit is contained in:
Fusion
2026-05-02 04:49:47 -07:00
committed by gsxdsm
parent 3e747f2190
commit 5986924229
4 changed files with 51 additions and 18 deletions

View File

@@ -922,7 +922,7 @@ function DashboardTab({
<div key={run.id} className="run-item">
<StatusIcon size={14} style={{ color: statusSpec.color }} />
<span>{relativeTime(run.startedAt)}</span>
<span className="text-muted">{Math.max(0, Math.round((new Date(run.completedAt || run.startedAt).getTime() - new Date(run.startedAt).getTime()) / 1000))}s</span>
<span className="text-muted">{Math.max(0, Math.round((new Date(run.endedAt || run.startedAt).getTime() - new Date(run.startedAt).getTime()) / 1000))}s</span>
</div>
);
})}

View File

@@ -237,6 +237,10 @@
margin-top: var(--space-lg);
}
.detail-pr-section {
margin-top: var(--space-lg);
}
.detail-provider-icons {
display: inline-flex;
align-items: center;

View File

@@ -2294,23 +2294,25 @@ export function TaskDetailModal({
</div>
{/* PR Section - only for in-review tasks */}
{task.column === "in-review" && (
<PrSection
taskId={task.id}
projectId={projectId}
prInfo={task.prInfo}
automationStatus={task.status ?? null}
autoMerge={settings?.autoMerge ?? false}
prAuthAvailable={prAuthAvailable ?? false}
onPrCreated={(prInfo) => {
// Update task locally to show new PR
(task as TaskDetail).prInfo = prInfo;
addToast(`PR #${prInfo.number} created`, "success");
}}
onPrUpdated={(prInfo) => {
(task as TaskDetail).prInfo = prInfo;
}}
addToast={addToast}
/>
<div className="detail-section detail-pr-section">
<PrSection
taskId={task.id}
projectId={projectId}
prInfo={task.prInfo}
automationStatus={task.status ?? null}
autoMerge={settings?.autoMerge ?? false}
prAuthAvailable={prAuthAvailable ?? false}
onPrCreated={(prInfo) => {
// Update task locally to show new PR
(task as TaskDetail).prInfo = prInfo;
addToast(`PR #${prInfo.number} created`, "success");
}}
onPrUpdated={(prInfo) => {
(task as TaskDetail).prInfo = prInfo;
}}
addToast={addToast}
/>
</div>
)}
</>
)}

View File

@@ -1345,6 +1345,33 @@ describe("TaskDetailModal", () => {
});
});
it("wraps in-review PR content in a spaced detail section after dependencies", () => {
const { container } = render(
<TaskDetailModal
task={makeTask({ column: "in-review", status: "creating-pr", dependencies: ["FN-001"] })}
onClose={noop}
onMoveTask={noopMove}
onDeleteTask={noopDelete}
onMergeTask={noopMerge}
onOpenDetail={noopOpenDetail}
addToast={noop}
/>,
);
const depsSection = container.querySelector(".detail-deps");
const prSection = container.querySelector(".detail-pr-section");
expect(depsSection).toBeTruthy();
expect(prSection).toBeTruthy();
expect(depsSection?.nextElementSibling).toBe(prSection);
expect(prSection?.querySelector(".pr-section")).toBeTruthy();
});
it("defines tokenized margin on detail-pr-section spacing contract", () => {
const css = loadAllAppCss();
expectBaseRule(css, ".detail-pr-section", "margin-top: var(--space-lg);");
});
it("activity list does not have nested scroll constraints", () => {
const { container } = render(
<TaskDetailModal