Skip to content

Commit 848483e

Browse files
committed
Fix handling of the custom datetime field for selecting jobs
1 parent 2acd43a commit 848483e

4 files changed

Lines changed: 124 additions & 46 deletions

File tree

dashboard/src/Dashboard/Component/JobsList.purs

Lines changed: 109 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,10 @@ data Action
148148
| FetchJobsSilent
149149
| HandleFetchResult (Either ApiError (Array Job))
150150
| SetTimeRange TimeRange
151-
| SetCustomSince String
152-
| SetCustomUntil String
151+
| SetCustomSinceDate String
152+
| SetCustomSinceTime String
153+
| SetCustomUntilDate String
154+
| SetCustomUntilTime String
153155
| ToggleAutoRefresh Boolean
154156
| SetFilterJobType String
155157
| SetFilterPackageName String
@@ -367,23 +369,41 @@ renderToolbar state =
367369

368370
customRangeRow
369371
| state.timeRange == Custom =
370-
[ HH.div [ HP.class_ (HH.ClassName "jobs-toolbar__custom-range") ]
371-
[ HH.label [ HP.class_ (HH.ClassName "toolbar-field__label") ] [ HH.text "FROM" ]
372-
, HH.input
373-
[ HP.type_ HP.InputDatetimeLocal
374-
, HP.class_ (HH.ClassName "toolbar-input")
375-
, HP.value state.sinceStr
376-
, HE.onValueInput SetCustomSince
377-
]
378-
, HH.label [ HP.class_ (HH.ClassName "toolbar-field__label") ] [ HH.text "TO" ]
379-
, HH.input
380-
[ HP.type_ HP.InputDatetimeLocal
381-
, HP.class_ (HH.ClassName "toolbar-input")
382-
, HP.value state.untilStr
383-
, HE.onValueInput SetCustomUntil
384-
]
385-
]
386-
]
372+
let
373+
sinceDatePart = String.take 10 state.sinceStr
374+
sinceTimePart = String.drop 11 state.sinceStr
375+
untilDatePart = String.take 10 state.untilStr
376+
untilTimePart = String.drop 11 state.untilStr
377+
in
378+
[ HH.div [ HP.class_ (HH.ClassName "jobs-toolbar__custom-range") ]
379+
[ HH.label [ HP.class_ (HH.ClassName "toolbar-field__label") ] [ HH.text "FROM" ]
380+
, HH.input
381+
[ HP.type_ HP.InputDate
382+
, HP.class_ (HH.ClassName "toolbar-input")
383+
, HP.value sinceDatePart
384+
, HE.onValueChange SetCustomSinceDate
385+
]
386+
, HH.input
387+
[ HP.type_ HP.InputTime
388+
, HP.class_ (HH.ClassName "toolbar-input")
389+
, HP.value sinceTimePart
390+
, HE.onValueChange SetCustomSinceTime
391+
]
392+
, HH.label [ HP.class_ (HH.ClassName "toolbar-field__label") ] [ HH.text "TO" ]
393+
, HH.input
394+
[ HP.type_ HP.InputDate
395+
, HP.class_ (HH.ClassName "toolbar-input")
396+
, HP.value untilDatePart
397+
, HE.onValueChange SetCustomUntilDate
398+
]
399+
, HH.input
400+
[ HP.type_ HP.InputTime
401+
, HP.class_ (HH.ClassName "toolbar-input")
402+
, HP.value untilTimePart
403+
, HE.onValueChange SetCustomUntilTime
404+
]
405+
]
406+
]
387407
| otherwise = []
388408

389409
-- | A labeled field: small uppercase label above the control.
@@ -585,11 +605,35 @@ handleAction = case _ of
585605
Initialize ->
586606
handleAction FetchJobs
587607

588-
-- The component owns its filter/sort state after initialization; URL params
589-
-- are only used once in initialState. Re-renders from the parent only
590-
-- update the apiConfig.
591-
Receive input ->
608+
-- When the parent passes new params (e.g. the user clicked the title to
609+
-- go home), re-apply them if they differ from the current component state.
610+
Receive input -> do
611+
state <- H.get
612+
let currentParams = stateToParams state
592613
H.modify_ _ { apiConfig = input.apiConfig }
614+
when (input.params /= currentParams) do
615+
let p = input.params
616+
H.modify_ _
617+
{ timeRange = parseTimeRange (fromMaybe "" p.range)
618+
, filters =
619+
{ jobType: p.jobType >>= parseJobType
620+
, packageName: fromMaybe "" p.package
621+
, packageVersion: fromMaybe "" p.version
622+
, compilerVersion: fromMaybe "" p.compiler
623+
, statusFilter: parseStatusFilter (fromMaybe "" p.status)
624+
}
625+
, sortOrder = case p.order of
626+
Just "asc" -> ASC
627+
_ -> defaultSortOrder
628+
, sinceStr = fromMaybe "" p.since
629+
, untilStr = fromMaybe "" p.until
630+
, currentPage = fromMaybe 1 p.page
631+
, since = Nothing
632+
, until = Nothing
633+
, pageCursors = []
634+
, hasNextPage = true
635+
}
636+
handleAction FetchJobs
593637

594638
FetchJobs -> do
595639
H.modify_ _ { loading = true, error = Nothing }
@@ -631,22 +675,29 @@ handleAction = case _ of
631675
handleAction FetchJobs
632676
notifyFiltersChanged
633677

634-
SetCustomSince val -> do
635-
H.modify_ _ { sinceStr = val, since = Nothing, until = Nothing, currentPage = 1, pageCursors = [], hasNextPage = true }
678+
SetCustomSinceDate dateVal -> do
636679
state <- H.get
637-
-- Fetch when both inputs have been provided.
638-
case Job.parseDateTimeLocal val, Job.parseDateTimeLocal state.untilStr of
639-
Just _, Just _ -> handleAction FetchJobs
640-
_, _ -> pure unit
641-
notifyFiltersChanged
680+
let timePart = String.drop 11 state.sinceStr
681+
let newSince = dateVal <> "T" <> (if timePart == "" then "00:00" else timePart)
682+
updateCustomSince newSince
642683

643-
SetCustomUntil val -> do
644-
H.modify_ _ { untilStr = val, since = Nothing, until = Nothing, currentPage = 1, pageCursors = [], hasNextPage = true }
684+
SetCustomSinceTime timeVal -> do
645685
state <- H.get
646-
case Job.parseDateTimeLocal state.sinceStr, Job.parseDateTimeLocal val of
647-
Just _, Just _ -> handleAction FetchJobs
648-
_, _ -> pure unit
649-
notifyFiltersChanged
686+
let datePart = String.take 10 state.sinceStr
687+
let newSince = (if datePart == "" then "1970-01-01" else datePart) <> "T" <> timeVal
688+
updateCustomSince newSince
689+
690+
SetCustomUntilDate dateVal -> do
691+
state <- H.get
692+
let timePart = String.drop 11 state.untilStr
693+
let newUntil = dateVal <> "T" <> (if timePart == "" then "00:00" else timePart)
694+
updateCustomUntil newUntil
695+
696+
SetCustomUntilTime timeVal -> do
697+
state <- H.get
698+
let datePart = String.take 10 state.untilStr
699+
let newUntil = (if datePart == "" then "1970-01-01" else datePart) <> "T" <> timeVal
700+
updateCustomUntil newUntil
650701

651702
ToggleAutoRefresh enabled -> do
652703
state <- H.get
@@ -762,6 +813,28 @@ doFetchJobs = do
762813
includeCompleted = Just (state.filters.statusFilter /= ActiveOnly)
763814
H.liftAff $ API.fetchJobs state.apiConfig { since, until, order: Just state.sortOrder, includeCompleted }
764815

816+
-- | Update the combined sinceStr from a date or time part change, fetch if
817+
-- | both endpoints parse, and sync the URL.
818+
updateCustomSince :: forall m. MonadAff m => String -> H.HalogenM State Action () Output m Unit
819+
updateCustomSince newSince = do
820+
H.modify_ _ { sinceStr = newSince, since = Nothing, until = Nothing, currentPage = 1, pageCursors = [], hasNextPage = true }
821+
state <- H.get
822+
case Job.parseDateTimeLocal newSince, Job.parseDateTimeLocal state.untilStr of
823+
Just _, Just _ -> handleAction FetchJobs
824+
_, _ -> pure unit
825+
notifyFiltersChanged
826+
827+
-- | Update the combined untilStr from a date or time part change, fetch if
828+
-- | both endpoints parse, and sync the URL.
829+
updateCustomUntil :: forall m. MonadAff m => String -> H.HalogenM State Action () Output m Unit
830+
updateCustomUntil newUntil = do
831+
H.modify_ _ { untilStr = newUntil, since = Nothing, until = Nothing, currentPage = 1, pageCursors = [], hasNextPage = true }
832+
state <- H.get
833+
case Job.parseDateTimeLocal state.sinceStr, Job.parseDateTimeLocal newUntil of
834+
Just _, Just _ -> handleAction FetchJobs
835+
_, _ -> pure unit
836+
notifyFiltersChanged
837+
765838
-- | Notify the parent component that filter state has changed so the URL can
766839
-- | be updated.
767840
notifyFiltersChanged :: forall m. MonadAff m => H.HalogenM State Action () Output m Unit

dashboard/src/Dashboard/Router.purs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module Dashboard.Router
22
( component
3+
, getRouteFromHash
34
) where
45

56
import Prelude
@@ -58,7 +59,7 @@ data Action
5859
| GoHome MouseEvent
5960
| GoTab Route MouseEvent
6061

61-
component :: forall query output m. MonadAff m => H.Component query Unit output m
62+
component :: forall query output m. MonadAff m => H.Component query Route output m
6263
component =
6364
H.mkComponent
6465
{ initialState
@@ -69,10 +70,12 @@ component =
6970
}
7071
}
7172

72-
initialState :: Unit -> State
73-
initialState _ =
74-
{ route: JobsList Route.defaultParams
75-
, lastJobsListParams: Route.defaultParams
73+
initialState :: Route -> State
74+
initialState route =
75+
{ route
76+
, lastJobsListParams: case route of
77+
JobsList params -> params
78+
_ -> Route.defaultParams
7679
}
7780

7881
render :: forall m. MonadAff m => State -> H.ComponentHTML Action Slots m
@@ -133,8 +136,6 @@ render state =
133136
handleAction :: forall output m. MonadAff m => Action -> H.HalogenM State Action Slots output m Unit
134137
handleAction = case _ of
135138
Initialize -> do
136-
route <- liftEffect getRouteFromHash
137-
applyRoute route
138139
emitter <- liftEffect hashChangeEmitter
139140
void $ H.subscribe (map HandleRouteChange emitter)
140141

@@ -154,8 +155,7 @@ handleAction = case _ of
154155

155156
GoHome ev -> do
156157
liftEffect $ Event.preventDefault (MouseEvent.toEvent ev)
157-
state <- H.get
158-
liftEffect $ setHash (routeToHash (JobsList state.lastJobsListParams))
158+
liftEffect $ setHash (routeToHash (JobsList Route.defaultParams))
159159

160160
GoTab route ev -> do
161161
liftEffect $ Event.preventDefault (MouseEvent.toEvent ev)

dashboard/src/Main.purs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import Prelude
44

55
import Dashboard.Router as Router
66
import Effect (Effect)
7+
import Effect.Class (liftEffect)
78
import Halogen.Aff as HA
89
import Halogen.VDom.Driver (runUI)
910

1011
main :: Effect Unit
1112
main = HA.runHalogenAff do
1213
body <- HA.awaitBody
13-
runUI Router.component unit body
14+
initialRoute <- liftEffect Router.getRouteFromHash
15+
runUI Router.component initialRoute body

dashboard/static/style.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,9 @@ code, pre {
301301
border-color: #43434e;
302302
}
303303
}
304+
.jobs-toolbar__custom-range .toolbar-input {
305+
max-width: none;
306+
}
304307
.toolbar-btn {
305308
font-family: "Roboto", sans-serif;
306309
font-size: var(--font-size-sm);

0 commit comments

Comments
 (0)