fix(dashboard): card timer matches stats panel + resizable Changes diff modal

Two related dashboard fixes.

1. Card timer mismatch: the board card timer chip showed only workflow
   runtime (e.g. <1m on FN-2716) while the task detail Stats panel
   reported "Total execution time" of 7m+ for the same task. Cause —
   the slim board listing strips `task.log` to keep payloads small, so
   the card's client-side `[timing]` log scan returned 0. Now the slim
   path aggregates `[timing] … in <N>ms` durations server-side into a
   new `task.timedExecutionMs` field before stripping the log; the
   card prefers this aggregate, falling back to the client scan when
   the full log is loaded (TaskDetailModal). Wire payload stays slim.

2. View Changes diff modal: defaulted to `90vw × 80vh` and was not
   user-resizable. Switched to `min(95vw, 2200px) × min(90vh, ...)`
   default with `resize: both`, persisted via useModalResizePersist
   (`fusion:changes-diff-modal-size`). Mobile keeps fullscreen layout.
   Overlay dismiss switched to the shared `useOverlayDismiss` hook so
   resize-drags that release on the overlay don't close the modal.

Updated the diff modal's regression tests to match the new constraint
shape (still asserts max-height clamps to viewport via calc()).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-27 19:55:46 -07:00
parent 91d82b3dea
commit 156caf8a3c
6 changed files with 134 additions and 31 deletions

View File

@@ -1,10 +1,22 @@
.changes-diff-modal {
width: 90vw;
max-width: 1600px;
height: 80vh;
max-height: calc(100vh - 2 * var(--overlay-padding-top, 10vh));
/* Diff comparisons read better wide — default to a generous portion of
the viewport. The grip-resize remembers the user's chosen dimensions
across sessions via useModalResizePersist. */
min-width: 720px;
min-height: 420px;
max-width: calc(100vw - 40px);
max-height: calc(100dvh - 40px);
display: flex;
flex-direction: column;
overflow: hidden;
resize: both;
}
.changes-diff-modal:not([style*="width"]) {
width: min(95vw, 2200px);
}
.changes-diff-modal:not([style*="height"]) {
height: min(90vh, calc(100dvh - 40px));
}
.changes-diff-modal-header {
@@ -164,11 +176,15 @@
@media (max-width: 768px) {
.changes-diff-modal {
width: 100vw;
height: 100vh;
width: 100vw !important;
height: 100vh !important;
height: 100dvh !important;
max-width: 100%;
max-height: 100%;
max-height: 100vh;
max-height: 100dvh;
border-radius: 0;
/* Disable user resize on mobile — fullscreen layout. */
resize: none;
}
.changes-diff-header-title {