This repository was archived by the owner on Jun 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathDuration.purs
More file actions
127 lines (106 loc) · 4.85 KB
/
Duration.purs
File metadata and controls
127 lines (106 loc) · 4.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
module Halogen.Datepicker.Component.Duration where
import Prelude
import Data.Array (fold)
import Data.Bifunctor (lmap)
import Data.Either (Either(..))
import Data.Functor.Coproduct (Coproduct, coproduct, right)
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow)
import Data.Interval (Duration)
import Data.Interval.Duration.Iso (IsoDuration, mkIsoDuration, unIsoDuration, Errors)
import Data.Maybe (Maybe(..), fromMaybe)
import Data.Monoid (mempty)
import Data.Monoid.Endo (Endo(..))
import Data.Newtype (unwrap)
import Data.String (take)
import Data.Traversable (for)
import Data.Tuple (Tuple(..))
import Halogen as H
import Halogen.Datepicker.Component.Types (BasePickerQuery(..), PickerMessage, PickerQuery(..), PickerValue)
import Halogen.Datepicker.Config (Config, defaultConfig)
import Halogen.Datepicker.Format.Duration as F
import NumberInput.Halogen.Component as Num
import NumberInput.Range (minRange)
import Halogen.Datepicker.Internal.Utils (mapParentHTMLQuery, foldSteps, componentProps, transitionState, asRight, mustBeMounted, pickerProps)
import Halogen.Datepicker.Internal.Elements (toNumConf)
import Halogen.HTML as HH
import Halogen.HTML.Events as HE
type State = PickerValue DurationError IsoDuration
type Message = PickerMessage State
type Query = Coproduct QueryIn DurationQuery
type QueryIn = PickerQuery Unit State
data DurationQuery a = UpdateCommand F.Command (Maybe Number) a
data DurationError = InvalidIsoDuration (Maybe Errors)
derive instance durationErrorEq ∷ Eq DurationError
derive instance durationErrorOrd ∷ Ord DurationError
derive instance durationErrorGeneric ∷ Generic DurationError _
instance durationErrorShow ∷ Show DurationError where
show = genericShow
type Slot = F.Command
type ChildQuery = Num.Query Number
type HTML m = H.ParentHTML DurationQuery ChildQuery Slot m
type DSL m = H.ParentDSL State Query ChildQuery Slot Message m
picker ∷ ∀ m. F.Format → H.Component HH.HTML Query Unit Message m
picker = pickerWithConfig defaultConfig
pickerWithConfig ∷ ∀ m. Config → F.Format → H.Component HH.HTML Query Unit Message m
pickerWithConfig config format = H.parentComponent
{ initialState: const Nothing
, render: render config format >>> mapParentHTMLQuery right
, eval: coproduct (evalPicker format) (evalDuration format)
, receiver: const Nothing
}
render ∷ ∀ m. Config → F.Format → State → HTML m
render config format duration = HH.ul (pickerProps config duration) (unwrap format <#> renderCommand config)
renderCommand ∷ ∀ m. Config → F.Command → HTML m
renderCommand config cmd = HH.li (componentProps config)
[ HH.slot
cmd
(Num.input Num.numberHasNumberInputVal $ toNumConf config { title: show cmd, placeholder: take 1 (show cmd), range: minRange 0.0 })
unit
(HE.input $ \(Num.NotifyChange n) → UpdateCommand cmd n)]
getComponent ∷ F.Command → IsoDuration → Number
getComponent cmd d = fromMaybe 0.0 $ F.toGetter cmd (unIsoDuration d)
overIsoDuration ∷ (Duration → Duration) → IsoDuration → Either Errors IsoDuration
overIsoDuration f d = mkIsoDuration $ f $ unIsoDuration d
evalDuration ∷ ∀ m. F.Format → DurationQuery ~> DSL m
evalDuration format (UpdateCommand cmd val next) = do
transitionState case _ of
Just (Right prevDuration) → pure case val of
Just n → overIsoDuration (F.toSetter cmd n) prevDuration # lmap \err ->
Tuple false (InvalidIsoDuration (Just err))
Nothing -> Left (Tuple false (InvalidIsoDuration Nothing))
_ → buildDuration format
pure next
type BuildStep = Maybe (Endo Duration)
buildDuration ∷ ∀ m
. F.Format
→ DSL m (Either (Tuple Boolean DurationError) IsoDuration)
buildDuration format = do
steps ← for (unwrap format) mkBuildStep
pure case runStep $ foldSteps steps of
Just (Right x) → Right x
Just (Left err) → Left (Tuple false (InvalidIsoDuration (Just err)))
Nothing → Left (Tuple false (InvalidIsoDuration Nothing))
where
mkBuildStep ∷ F.Command → DSL m BuildStep
mkBuildStep cmd = do
num ← query cmd $ H.request (Num.GetValue)
pure $ num <#> F.toSetter cmd >>> Endo
runStep ∷ BuildStep -> Maybe (Either Errors IsoDuration)
runStep step = step <#> \(Endo f) -> mkIsoDuration $ f mempty
evalPicker ∷ ∀ m. F.Format → QueryIn ~> DSL m
evalPicker _ (ResetError next) = do
H.put Nothing
pure next
evalPicker format (Base (SetValue duration reply)) = do
propagateChange format duration
H.put duration
pure $ reply unit
evalPicker _ (Base (GetValue reply)) = H.get <#> reply
propagateChange ∷ ∀ m . F.Format → State → DSL m Unit
propagateChange format duration = do
map fold $ for (unwrap format) \cmd → do
let n = duration >>= asRight >>= unIsoDuration >>> F.toGetter cmd
query cmd $ H.action $ Num.SetValue n
query ∷ ∀ m. Slot → ChildQuery ~> DSL m
query cmd q = H.query cmd q >>= mustBeMounted