Skip to content

Commit 3f4f1ec

Browse files
authored
Merge pull request #187 from citizennet/AS-1358/add-datetime-range
AS-1358 Add DateTime Range to DateTimePicker
2 parents 4511128 + 9d5bf6a commit 3f4f1ec

File tree

4 files changed

+232
-82
lines changed

4 files changed

+232
-82
lines changed

src/DatePicker.purs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ embeddedReceive ::
386386
CompositeComponentM m Unit
387387
embeddedReceive input = do
388388
old <- H.get
389-
H.modify_ _ { interval = input.interval }
389+
H.modify_ _ { disabled = input.disabled, interval = input.interval }
390390
case input.interval of
391391
Nothing -> pure unit
392392
Just interval -> do
@@ -484,7 +484,7 @@ handleAction = case _ of
484484
PassingOutput output ->
485485
H.raise output
486486
PassingReceive input -> do
487-
H.modify_ _ { interval = input.interval }
487+
H.modify_ _ { disabled = input.disabled, interval = input.interval }
488488

489489
-- NOTE passing query to the embedded component
490490
handleQuery :: forall m a. Query a -> ComponentM m (Maybe a)

src/DateTimePicker.purs

Lines changed: 84 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module Ocelot.DateTimePicker
66
, ComponentM
77
, ComponentRender
88
, Input
9+
, Interval
910
, Output(..)
1011
, Query(..)
1112
, Slot
@@ -14,8 +15,11 @@ module Ocelot.DateTimePicker
1415
) where
1516

1617
import Prelude
17-
import Data.DateTime (Date, DateTime(..), Month, Time, Year, date, time)
18+
import Data.DateTime (Date, DateTime(..), Month, Time, Year)
19+
import Data.DateTime as Date.DateTime
20+
import Data.Foldable as Data.Foldable
1821
import Data.Maybe (Maybe(..))
22+
import Data.Maybe as Data.Maybe
1923
import Data.Tuple.Nested (type (/\))
2024
import Effect.Aff.Class (class MonadAff)
2125
import Halogen as H
@@ -31,6 +35,7 @@ import Type.Proxy (Proxy(..))
3135
data Action
3236
= HandleDate DatePicker.Output
3337
| HandleTime TimePicker.Output
38+
| Receive Input
3439

3540
type ChildSlots =
3641
( datepicker :: DatePicker.Slot Unit
@@ -46,9 +51,15 @@ type ComponentM m a = H.HalogenM State Action ChildSlots Output m a
4651
type ComponentRender m = State -> ComponentHTML m
4752

4853
type Input =
49-
{ selection :: Maybe DateTime
54+
{ disabled :: Boolean
55+
, interval :: Maybe Interval
56+
, selection :: Maybe DateTime
5057
, targetDate :: Maybe (Year /\ Month)
51-
, disabled :: Boolean
58+
}
59+
60+
type Interval =
61+
{ start :: Maybe DateTime
62+
, end :: Maybe DateTime
5263
}
5364

5465
data Output
@@ -67,9 +78,10 @@ type Slot = H.Slot Query Output
6778

6879
type State =
6980
{ date :: Maybe Date
70-
, time :: Maybe Time
71-
, targetDate :: Maybe (Year /\ Month)
7281
, disabled :: Boolean
82+
, interval :: Maybe Interval
83+
, targetDate :: Maybe (Year /\ Month)
84+
, time :: Maybe Time
7385
}
7486

7587
------------
@@ -82,6 +94,7 @@ component = H.mkComponent
8294
, eval: H.mkEval H.defaultEval
8395
{ handleAction = handleAction
8496
, handleQuery = handleQuery
97+
, receive = Just <<< Receive
8598
}
8699
}
87100

@@ -95,16 +108,18 @@ handleAction :: forall m. Action -> ComponentM m Unit
95108
handleAction = case _ of
96109
HandleDate msg -> case msg of
97110
DatePicker.SelectionChanged date' -> do
98-
time' <- H.gets _.time
99-
H.raise $ SelectionChanged (DateTime <$> date' <*> time')
111+
state <- H.get
112+
raiseSelectionChanged state.interval date' state.time
100113
H.modify_ _ { date = date' }
101114
_ -> H.raise $ DateOutput msg
102115
HandleTime msg -> case msg of
103116
TimePicker.SelectionChanged time' -> do
104-
date' <- H.gets _.date
105-
H.raise $ SelectionChanged (DateTime <$> date' <*> time')
117+
state <- H.get
118+
raiseSelectionChanged state.interval state.date time'
106119
H.modify_ _ { time = time' }
107120
_ -> H.raise $ TimeOutput msg
121+
Receive input -> do
122+
H.modify_ _ { interval = input.interval }
108123

109124
handleQuery :: forall m a. Query a -> ComponentM m (Maybe a)
110125
handleQuery = case _ of
@@ -116,42 +131,87 @@ handleQuery = case _ of
116131
void $ H.tell _datepicker unit $ DatePicker.SetDisabled disabled
117132
void $ H.tell _timepicker unit $ TimePicker.SetDisabled disabled
118133
SetSelection dateTime a -> Just a <$ do
119-
let date' = date <$> dateTime
120-
time' = time <$> dateTime
134+
let date' = dateTime <#> Date.DateTime.date
135+
time' = dateTime <#> Date.DateTime.time
121136
void $ H.tell _datepicker unit $ DatePicker.SetSelection date'
122137
void $ H.tell _timepicker unit $ TimePicker.SetSelection time'
123138
H.modify_ _ { date = date', time = time' }
124139
SendDateQuery q a -> Just a <$ H.query _datepicker unit q
125140
SendTimeQuery q a -> Just a <$ H.query _timepicker unit q
126141

127142
initialState :: Input -> State
128-
initialState { selection, targetDate, disabled } =
129-
{ date: date <$> selection
130-
, time: time <$> selection
131-
, targetDate
132-
, disabled
143+
initialState input =
144+
{ date: input.selection <#> Date.DateTime.date
145+
, disabled: input.disabled
146+
, interval: input.interval
147+
, targetDate: input.targetDate
148+
, time: input.selection <#> Date.DateTime.time
133149
}
134150

151+
-- check if a datetime is within a **closed** interval
152+
isWithinInterval :: Interval -> DateTime -> Boolean
153+
isWithinInterval interval x =
154+
Data.Foldable.and
155+
[ Data.Maybe.maybe true (_ <= x) interval.start
156+
, Data.Maybe.maybe true (x <= _) interval.end
157+
]
158+
159+
raiseSelectionChanged ::
160+
forall m.
161+
Maybe Interval ->
162+
Maybe Date ->
163+
Maybe Time ->
164+
ComponentM m Unit
165+
raiseSelectionChanged mInterval mDate mTime = case mInterval of
166+
Nothing -> H.raise $ SelectionChanged mDateTime
167+
Just interval -> case mDateTime of
168+
Nothing -> H.raise $ SelectionChanged mDateTime
169+
Just dateTime
170+
| isWithinInterval interval dateTime -> H.raise $ SelectionChanged mDateTime
171+
| otherwise -> pure unit -- NOTE transient state during parent-child synchronization
172+
where
173+
mDateTime :: Maybe DateTime
174+
mDateTime = DateTime <$> mDate <*> mTime
175+
176+
135177
render :: forall m. MonadAff m => ComponentRender m
136-
render { date, time, targetDate, disabled } =
178+
render state =
137179
HH.div
138180
[ css "flex" ]
139181
[ HH.div
140182
[ css "w-1/2 mr-2" ]
141183
[ HH.slot _datepicker unit DatePicker.component
142-
{ disabled
143-
, interval: Nothing -- TODO AS-1344
144-
, selection: date
145-
, targetDate
184+
{ disabled: state.disabled
185+
, interval: do
186+
interval <- state.interval
187+
pure
188+
{ start: interval.start <#> Date.DateTime.date
189+
, end: interval.end <#> Date.DateTime.date
190+
}
191+
, selection: state.date
192+
, targetDate: state.targetDate
146193
}
147194
HandleDate
148195
]
149196
, HH.div
150197
[ css "flex-1" ]
151198
[ HH.slot _timepicker unit TimePicker.component
152-
{ disabled
153-
, interval: Nothing -- TODO AS-1344
154-
, selection: time
199+
{ disabled: state.disabled
200+
, interval: do
201+
interval <- state.interval
202+
pure
203+
{ start:
204+
if (interval.start <#> Date.DateTime.date) == state.date then
205+
interval.start <#> Date.DateTime.time
206+
else
207+
Nothing
208+
, end:
209+
if (interval.end <#> Date.DateTime.date) == state.date then
210+
interval.end <#> Date.DateTime.time
211+
else
212+
Nothing
213+
}
214+
, selection: state.time
155215
}
156216
HandleTime
157217
]

src/TimePicker.purs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ embeddedInput state =
248248
embeddedReceive :: forall m. CompositeInput -> CompositeComponentM m Unit
249249
embeddedReceive input = do
250250
old <- H.get
251-
H.modify_ _ { interval = input.interval }
251+
H.modify_ _ { disabled = input.disabled, interval = input.interval }
252252
case input.interval of
253253
Nothing -> pure unit
254254
Just interval -> do
@@ -342,7 +342,7 @@ handleAction = case _ of
342342
PassingOutput output ->
343343
H.raise output
344344
PassingReceive input -> do
345-
H.modify_ _ { interval = input.interval }
345+
H.modify_ _ { disabled = input.disabled, interval = input.interval }
346346

347347
handleQuery :: forall m a. Query a -> ComponentM m (Maybe a)
348348
handleQuery = case _ of

0 commit comments

Comments
 (0)