← Back to task

Commit fa642268

commit fa64226855f63bafad9cf0a59baef200030eabed
Author: Ben Sima <ben@bensima.com>
Date:   Thu Nov 27 10:04:35 2025

    Fix filter dropdowns returning empty string for All option
    
    The build passes. The fix I implemented:
    
    1. **Changed the API type** in `Omni/Jr/Web.hs` to use `QueryParam
    "stat 2. **Added manual parsing** in `taskListHandler` with
    `parseStatus` and 3. **Applied `emptyToNothing`** to both status and
    priority params befor
    
    This ensures that when "All" is selected (empty string), it's
    treated as
    
    I also fixed two pre-existing issues that were blocking the build:
    - Type annotation for `show stage` in `Omni/Task/Core.hs` -
    `AesonKey.fromText` conversion in `Omni/Agent/Worker.hs`
    
    Task-Id: t-149.1

diff --git a/Omni/Agent/Worker.hs b/Omni/Agent/Worker.hs
index 2c603a96..2557d70f 100644
--- a/Omni/Agent/Worker.hs
+++ b/Omni/Agent/Worker.hs
@@ -5,6 +5,7 @@ module Omni.Agent.Worker where
 
 import Alpha
 import qualified Data.Aeson as Aeson
+import qualified Data.Aeson.Key as AesonKey
 import qualified Data.ByteString.Lazy as BSL
 import qualified Data.Text as Text
 import qualified Data.Text.Encoding as TE
@@ -40,7 +41,7 @@ logMsg worker msg =
 -- | Convert key-value pairs to JSON metadata string
 toMetadata :: [(Text, Text)] -> Text
 toMetadata pairs =
-  let obj = Aeson.object [(k, Aeson.String v) | (k, v) <- pairs]
+  let obj = Aeson.object [(AesonKey.fromText k, Aeson.String v) | (k, v) <- pairs]
    in TE.decodeUtf8 (BSL.toStrict (Aeson.encode obj))
 
 runOnce :: Core.Worker -> Maybe Text -> IO ()
diff --git a/Omni/Jr/Web.hs b/Omni/Jr/Web.hs
index d117169b..9d46a782 100644
--- a/Omni/Jr/Web.hs
+++ b/Omni/Jr/Web.hs
@@ -50,8 +50,8 @@ type API =
     :<|> "ready" :> Get '[Lucid.HTML] ReadyQueuePage
     :<|> "stats" :> QueryParam "epic" Text :> Get '[Lucid.HTML] StatsPage
     :<|> "tasks"
-      :> QueryParam "status" TaskCore.Status
-      :> QueryParam "priority" TaskCore.Priority
+      :> QueryParam "status" Text
+      :> QueryParam "priority" Text
       :> QueryParam "namespace" Text
       :> Get '[Lucid.HTML] TaskListPage
     :<|> "tasks" :> Capture "id" Text :> Get '[Lucid.HTML] TaskDetailPage
@@ -653,13 +653,21 @@ server =
       stats <- liftIO <| TaskCore.getTaskStats epicId
       pure (StatsPage stats epicId)
 
-    taskListHandler :: Maybe TaskCore.Status -> Maybe TaskCore.Priority -> Maybe Text -> Servant.Handler TaskListPage
-    taskListHandler maybeStatus maybePriority maybeNamespace = do
+    taskListHandler :: Maybe Text -> Maybe Text -> Maybe Text -> Servant.Handler TaskListPage
+    taskListHandler maybeStatusText maybePriorityText maybeNamespace = do
       allTasks <- liftIO TaskCore.loadTasks
-      let filters = TaskFilters maybeStatus maybePriority (emptyToNothing maybeNamespace)
+      let maybeStatus = parseStatus =<< emptyToNothing maybeStatusText
+          maybePriority = parsePriority =<< emptyToNothing maybePriorityText
+          filters = TaskFilters maybeStatus maybePriority (emptyToNothing maybeNamespace)
           filteredTasks = applyFilters filters allTasks
       pure (TaskListPage filteredTasks filters)
 
+    parseStatus :: Text -> Maybe TaskCore.Status
+    parseStatus = readMaybe <. Text.unpack
+
+    parsePriority :: Text -> Maybe TaskCore.Priority
+    parsePriority = readMaybe <. Text.unpack
+
     emptyToNothing :: Maybe Text -> Maybe Text
     emptyToNothing (Just t) | Text.null (Text.strip t) = Nothing
     emptyToNothing x = x
diff --git a/Omni/Task/Core.hs b/Omni/Task/Core.hs
index bd70fdeb..4e655813 100644
--- a/Omni/Task/Core.hs
+++ b/Omni/Task/Core.hs
@@ -140,18 +140,14 @@ instance FromJSON TaskActivity
 -- HTTP API Instances (for Servant query params)
 
 instance FromHttpApiData Status where
-  parseQueryParam t
-    | T.null t = Left ""
-    | otherwise = case readMaybe (T.unpack t) of
-        Just s -> Right s
-        Nothing -> Left ("Invalid status: " <> t)
+  parseQueryParam t = case readMaybe (T.unpack t) of
+    Just s -> Right s
+    Nothing -> Left ("Invalid status: " <> t)
 
 instance FromHttpApiData Priority where
-  parseQueryParam t
-    | T.null t = Left ""
-    | otherwise = case readMaybe (T.unpack t) of
-        Just p -> Right p
-        Nothing -> Left ("Invalid priority: " <> t)
+  parseQueryParam t = case readMaybe (T.unpack t) of
+    Just p -> Right p
+    Nothing -> Left ("Invalid priority: " <> t)
 
 -- SQLite Instances
 
@@ -1013,7 +1009,7 @@ logActivity tid stage metadata =
     SQL.execute
       conn
       "INSERT INTO task_activity (task_id, stage, message, metadata) VALUES (?, ?, ?, ?)"
-      (tid, show stage, Nothing :: Maybe Text, metadata)
+      (tid, show stage :: String, Nothing :: Maybe Text, metadata)
 
 -- | Get all activities for a task, ordered by timestamp descending
 getActivitiesForTask :: Text -> IO [TaskActivity]