From dbe2b82d2f53761d9504fb4e5cf37f64a2000b7a Mon Sep 17 00:00:00 2001 From: Ben Sima Date: Thu, 27 Nov 2025 09:59:42 -0500 Subject: Show activity timeline on task detail page in web UI All builds pass. Here's a summary of the changes I made: **Omni/Task/Core.hs:** - Added `getActivitiesForTask` function to query task_activity table for **Omni/Jr/Web.hs:** - Added `Data.Time` import for timestamp formatting - Updated `TaskDetailPage` type to include `[TaskCore.TaskActivity]` - Updated `taskDetailHandler` to fetch activities for the task - Added activity timeline rendering in `toHtml` instance for InProgress - Added helper functions: `renderActivity`, `stageClass`, `stageIcon`, ` **Omni/Jr/Web/Style.hs:** - Added `activityTimelineStyles` function with vertical timeline CSS - Added stage-specific colors (claiming=blue, running=yellow, reviewing= - Added dark mode styles for the activity timeline Task-Id: t-148.3 --- Omni/Jr/Web/Style.hs | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) (limited to 'Omni/Jr/Web/Style.hs') diff --git a/Omni/Jr/Web/Style.hs b/Omni/Jr/Web/Style.hs index c1ad47e..8b6a8a7 100644 --- a/Omni/Jr/Web/Style.hs +++ b/Omni/Jr/Web/Style.hs @@ -29,6 +29,7 @@ stylesheet = do statusBadges buttonStyles formStyles + activityTimelineStyles responsiveStyles darkModeStyles @@ -434,6 +435,96 @@ formStyles = do fontSize (px 14) Stylesheet.key "resize" ("vertical" :: Text) +activityTimelineStyles :: Css +activityTimelineStyles = do + ".activity-section" ? do + marginTop (em 1.5) + backgroundColor white + borderRadius (px 8) (px 8) (px 8) (px 8) + padding (px 16) (px 16) (px 16) (px 16) + boxShadow (NE.singleton (bsColor (rgba 0 0 0 0.1) (shadow (px 0) (px 1)))) + ".activity-timeline" ? do + position relative + paddingLeft (px 24) + marginTop (px 12) + ".activity-timeline" # before ? do + Stylesheet.key "content" ("''" :: Text) + position absolute + left (px 8) + top (px 0) + bottom (px 0) + width (px 2) + backgroundColor "#e5e7eb" + ".activity-item" ? do + position relative + display flex + Stylesheet.key "gap" ("12px" :: Text) + paddingBottom (px 16) + marginBottom (px 0) + ".activity-item" # lastChild ? paddingBottom (px 0) + ".activity-icon" ? do + position absolute + left (px (-20)) + width (px 18) + height (px 18) + borderRadius (pct 50) (pct 50) (pct 50) (pct 50) + display flex + alignItems center + justifyContent center + fontSize (px 10) + fontWeight bold + backgroundColor white + border (px 2) solid "#e5e7eb" + ".activity-content" ? do + Stylesheet.key "flex" ("1" :: Text) + ".activity-header" ? do + display flex + alignItems center + Stylesheet.key "gap" ("8px" :: Text) + marginBottom (px 4) + ".activity-stage" ? do + fontWeight (weight 600) + fontSize (px 14) + ".activity-time" ? do + fontSize (px 12) + color "#6b7280" + ".activity-message" ? do + margin (px 4) (px 0) (px 0) (px 0) + fontSize (px 14) + color "#374151" + ".activity-metadata" ? do + marginTop (px 8) + (".activity-metadata" |> "summary") ? do + fontSize (px 12) + color "#6b7280" + cursor pointer + ".metadata-json" ? do + fontSize (px 11) + backgroundColor "#f3f4f6" + padding (px 8) (px 8) (px 8) (px 8) + borderRadius (px 4) (px 4) (px 4) (px 4) + marginTop (px 4) + maxHeight (px 200) + overflow auto + ".stage-claiming" |> ".activity-icon" ? do + borderColor "#3b82f6" + color "#3b82f6" + ".stage-running" |> ".activity-icon" ? do + borderColor "#f59e0b" + color "#f59e0b" + ".stage-reviewing" |> ".activity-icon" ? do + borderColor "#8b5cf6" + color "#8b5cf6" + ".stage-retrying" |> ".activity-icon" ? do + borderColor "#f97316" + color "#f97316" + ".stage-completed" |> ".activity-icon" ? do + borderColor "#10b981" + color "#10b981" + ".stage-failed" |> ".activity-icon" ? do + borderColor "#ef4444" + color "#ef4444" + responsiveStyles :: Css responsiveStyles = do query Media.screen [Media.maxWidth (px 600)] <| do @@ -529,6 +620,17 @@ darkModeStyles = ".stats-row" ? borderBottomColor "#374151" ".progress-bar" ? backgroundColor "#374151" ".progress-fill" ? backgroundColor "#60a5fa" + ".activity-section" ? do + backgroundColor "#1f2937" + boxShadow (NE.singleton (bsColor (rgba 0 0 0 0.3) (shadow (px 0) (px 2)))) + ".activity-timeline" # before ? backgroundColor "#374151" + ".activity-icon" ? do + backgroundColor "#1f2937" + borderColor "#374151" + ".activity-time" ? color "#9ca3af" + ".activity-message" ? color "#d1d5db" + (".activity-metadata" |> "summary") ? color "#9ca3af" + ".metadata-json" ? backgroundColor "#374151" prefersDark :: Stylesheet.Feature prefersDark = -- cgit v1.2.3