1port module Views.SilenceForm.Updates exposing (update)
2
3import Alerts.Api
4import Browser.Navigation as Navigation
5import Silences.Api
6import Task
7import Time
8import Types exposing (Msg(..))
9import Utils.Date exposing (timeFromString)
10import Utils.Filter exposing (silencePreviewFilter)
11import Utils.FormValidation exposing (fromResult, stringNotEmpty, updateValue, validate)
12import Utils.List
13import Utils.Types exposing (ApiData(..))
14import Views.SilenceForm.Types
15    exposing
16        ( Model
17        , SilenceForm
18        , SilenceFormFieldMsg(..)
19        , SilenceFormMsg(..)
20        , emptyMatcher
21        , fromMatchersAndCommentAndTime
22        , fromSilence
23        , parseEndsAt
24        , toSilence
25        , validateForm
26        )
27
28
29updateForm : SilenceFormFieldMsg -> SilenceForm -> SilenceForm
30updateForm msg form =
31    case msg of
32        AddMatcher ->
33            { form | matchers = form.matchers ++ [ emptyMatcher ] }
34
35        UpdateStartsAt time ->
36            let
37                startsAt =
38                    Utils.Date.timeFromString time
39
40                endsAt =
41                    Utils.Date.timeFromString form.endsAt.value
42
43                durationValue =
44                    case Result.map2 Utils.Date.timeDifference startsAt endsAt of
45                        Ok duration ->
46                            case Utils.Date.durationFormat duration of
47                                Just value ->
48                                    value
49
50                                Nothing ->
51                                    form.duration.value
52
53                        Err _ ->
54                            form.duration.value
55            in
56            { form
57                | startsAt = updateValue time form.startsAt
58                , duration = updateValue durationValue form.duration
59            }
60
61        UpdateEndsAt time ->
62            let
63                endsAt =
64                    Utils.Date.timeFromString time
65
66                startsAt =
67                    Utils.Date.timeFromString form.startsAt.value
68
69                durationValue =
70                    case Result.map2 Utils.Date.timeDifference startsAt endsAt of
71                        Ok duration ->
72                            case Utils.Date.durationFormat duration of
73                                Just value ->
74                                    value
75
76                                Nothing ->
77                                    form.duration.value
78
79                        Err _ ->
80                            form.duration.value
81            in
82            { form
83                | endsAt = updateValue time form.endsAt
84                , duration = updateValue durationValue form.duration
85            }
86
87        UpdateDuration time ->
88            let
89                duration =
90                    Utils.Date.parseDuration time
91
92                startsAt =
93                    Utils.Date.timeFromString form.startsAt.value
94
95                endsAtValue =
96                    case Result.map2 Utils.Date.addDuration duration startsAt of
97                        Ok endsAt ->
98                            Utils.Date.timeToString endsAt
99
100                        Err _ ->
101                            form.endsAt.value
102            in
103            { form
104                | endsAt = updateValue endsAtValue form.endsAt
105                , duration = updateValue time form.duration
106            }
107
108        ValidateTime ->
109            { form
110                | startsAt = validate Utils.Date.timeFromString form.startsAt
111                , endsAt = validate (parseEndsAt form.startsAt.value) form.endsAt
112                , duration = validate Utils.Date.parseDuration form.duration
113            }
114
115        UpdateCreatedBy createdBy ->
116            { form | createdBy = updateValue createdBy form.createdBy }
117
118        ValidateCreatedBy ->
119            { form | createdBy = validate stringNotEmpty form.createdBy }
120
121        UpdateComment comment ->
122            { form | comment = updateValue comment form.comment }
123
124        ValidateComment ->
125            { form | comment = validate stringNotEmpty form.comment }
126
127        DeleteMatcher index ->
128            { form | matchers = List.take index form.matchers ++ List.drop (index + 1) form.matchers }
129
130        UpdateMatcherName index name ->
131            let
132                matchers =
133                    Utils.List.replaceIndex index
134                        (\matcher -> { matcher | name = updateValue name matcher.name })
135                        form.matchers
136            in
137            { form | matchers = matchers }
138
139        ValidateMatcherName index ->
140            let
141                matchers =
142                    Utils.List.replaceIndex index
143                        (\matcher -> { matcher | name = validate stringNotEmpty matcher.name })
144                        form.matchers
145            in
146            { form | matchers = matchers }
147
148        UpdateMatcherValue index value ->
149            let
150                matchers =
151                    Utils.List.replaceIndex index
152                        (\matcher -> { matcher | value = updateValue value matcher.value })
153                        form.matchers
154            in
155            { form | matchers = matchers }
156
157        ValidateMatcherValue index ->
158            let
159                matchers =
160                    Utils.List.replaceIndex index
161                        (\matcher -> { matcher | value = matcher.value })
162                        form.matchers
163            in
164            { form | matchers = matchers }
165
166        UpdateMatcherRegex index isRegex ->
167            let
168                matchers =
169                    Utils.List.replaceIndex index
170                        (\matcher -> { matcher | isRegex = isRegex })
171                        form.matchers
172            in
173            { form | matchers = matchers }
174
175
176update : SilenceFormMsg -> Model -> String -> String -> ( Model, Cmd Msg )
177update msg model basePath apiUrl =
178    case msg of
179        CreateSilence ->
180            case toSilence model.form of
181                Just silence ->
182                    ( { model | silenceId = Loading }
183                    , Cmd.batch
184                        [ Silences.Api.create apiUrl silence |> Cmd.map (SilenceCreate >> MsgForSilenceForm)
185                        , persistDefaultCreator silence.createdBy
186                        , Task.succeed silence.createdBy |> Task.perform SetDefaultCreator
187                        ]
188                    )
189
190                Nothing ->
191                    ( { model
192                        | silenceId = Failure "Could not submit the form, Silence is not yet valid."
193                        , form = validateForm model.form
194                      }
195                    , Cmd.none
196                    )
197
198        SilenceCreate silenceId ->
199            let
200                cmd =
201                    case silenceId of
202                        Success id ->
203                            Navigation.pushUrl model.key (basePath ++ "#/silences/" ++ id)
204
205                        _ ->
206                            Cmd.none
207            in
208            ( { model | silenceId = silenceId }, cmd )
209
210        NewSilenceFromMatchersAndComment defaultCreator params ->
211            ( model, Task.perform (NewSilenceFromMatchersAndCommentAndTime defaultCreator params.matchers params.comment >> MsgForSilenceForm) Time.now )
212
213        NewSilenceFromMatchersAndCommentAndTime defaultCreator matchers comment time ->
214            ( { form = fromMatchersAndCommentAndTime defaultCreator matchers comment time
215              , alerts = Initial
216              , activeAlertId = Nothing
217              , silenceId = Initial
218              , key = model.key
219              }
220            , Cmd.none
221            )
222
223        FetchSilence silenceId ->
224            ( model, Silences.Api.getSilence apiUrl silenceId (SilenceFetch >> MsgForSilenceForm) )
225
226        SilenceFetch (Success silence) ->
227            ( { model | form = fromSilence silence }
228            , Task.perform identity (Task.succeed (MsgForSilenceForm PreviewSilence))
229            )
230
231        SilenceFetch _ ->
232            ( model, Cmd.none )
233
234        PreviewSilence ->
235            case toSilence model.form of
236                Just silence ->
237                    ( { model | alerts = Loading }
238                    , Alerts.Api.fetchAlerts
239                        apiUrl
240                        (silencePreviewFilter silence.matchers)
241                        |> Cmd.map (AlertGroupsPreview >> MsgForSilenceForm)
242                    )
243
244                Nothing ->
245                    ( { model
246                        | alerts = Failure "Can not display affected Alerts, Silence is not yet valid."
247                        , form = validateForm model.form
248                      }
249                    , Cmd.none
250                    )
251
252        AlertGroupsPreview alerts ->
253            ( { model | alerts = alerts }
254            , Cmd.none
255            )
256
257        SetActiveAlert maybeAlertId ->
258            ( { model | activeAlertId = maybeAlertId }
259            , Cmd.none
260            )
261
262        UpdateField fieldMsg ->
263            ( { form = updateForm fieldMsg model.form
264              , alerts = Initial
265              , silenceId = Initial
266              , key = model.key
267              , activeAlertId = model.activeAlertId
268              }
269            , Cmd.none
270            )
271
272
273port persistDefaultCreator : String -> Cmd msg
274