mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-22 18:38:26 +00:00
Add support for more generic notification
This is a start to have different kinds of notifications. It is possible to be notified via e-mail, matrix or gotify. It also extends the current "periodic query" for due items by allowing notification over different channels. A "generic periodic query" variant is added as well.
This commit is contained in:
33
modules/webapp/src/main/elm/Data/ChannelRef.elm
Normal file
33
modules/webapp/src/main/elm/Data/ChannelRef.elm
Normal file
@ -0,0 +1,33 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Data.ChannelRef exposing (..)
|
||||
|
||||
import Data.ChannelType exposing (ChannelType)
|
||||
import Json.Decode as D
|
||||
import Json.Encode as E
|
||||
|
||||
|
||||
type alias ChannelRef =
|
||||
{ id : String
|
||||
, channelType : ChannelType
|
||||
}
|
||||
|
||||
|
||||
decoder : D.Decoder ChannelRef
|
||||
decoder =
|
||||
D.map2 ChannelRef
|
||||
(D.field "id" D.string)
|
||||
(D.field "channelType" Data.ChannelType.decoder)
|
||||
|
||||
|
||||
encode : ChannelRef -> E.Value
|
||||
encode cref =
|
||||
E.object
|
||||
[ ( "id", E.string cref.id )
|
||||
, ( "channelType", Data.ChannelType.encode cref.channelType )
|
||||
]
|
117
modules/webapp/src/main/elm/Data/ChannelType.elm
Normal file
117
modules/webapp/src/main/elm/Data/ChannelType.elm
Normal file
@ -0,0 +1,117 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Data.ChannelType exposing
|
||||
( ChannelType(..)
|
||||
, all
|
||||
, asString
|
||||
, decoder
|
||||
, encode
|
||||
, fromString
|
||||
, icon
|
||||
)
|
||||
|
||||
import Data.Icons as Icons
|
||||
import Html exposing (Html, i)
|
||||
import Html.Attributes exposing (class)
|
||||
import Json.Decode as D
|
||||
import Json.Encode as E
|
||||
|
||||
|
||||
type ChannelType
|
||||
= Mail
|
||||
| Gotify
|
||||
| Matrix
|
||||
| Http
|
||||
|
||||
|
||||
all : List ChannelType
|
||||
all =
|
||||
[ Matrix
|
||||
, Gotify
|
||||
, Mail
|
||||
, Http
|
||||
]
|
||||
|
||||
|
||||
fromString : String -> Maybe ChannelType
|
||||
fromString str =
|
||||
case String.toLower str of
|
||||
"mail" ->
|
||||
Just Mail
|
||||
|
||||
"matrix" ->
|
||||
Just Matrix
|
||||
|
||||
"gotify" ->
|
||||
Just Gotify
|
||||
|
||||
"http" ->
|
||||
Just Http
|
||||
|
||||
_ ->
|
||||
Nothing
|
||||
|
||||
|
||||
asString : ChannelType -> String
|
||||
asString et =
|
||||
case et of
|
||||
Mail ->
|
||||
"Mail"
|
||||
|
||||
Matrix ->
|
||||
"Matrix"
|
||||
|
||||
Gotify ->
|
||||
"Gotify"
|
||||
|
||||
Http ->
|
||||
"Http"
|
||||
|
||||
|
||||
decoder : D.Decoder ChannelType
|
||||
decoder =
|
||||
let
|
||||
unwrap me =
|
||||
case me of
|
||||
Just et ->
|
||||
D.succeed et
|
||||
|
||||
Nothing ->
|
||||
D.fail "Unknown event type!"
|
||||
in
|
||||
D.map fromString D.string
|
||||
|> D.andThen unwrap
|
||||
|
||||
|
||||
encode : ChannelType -> E.Value
|
||||
encode et =
|
||||
E.string (asString et)
|
||||
|
||||
|
||||
icon : ChannelType -> String -> Html msg
|
||||
icon ct classes =
|
||||
case ct of
|
||||
Matrix ->
|
||||
Icons.matrixIcon classes
|
||||
|
||||
Mail ->
|
||||
i
|
||||
[ class "fa fa-envelope"
|
||||
, class classes
|
||||
]
|
||||
[]
|
||||
|
||||
Gotify ->
|
||||
Icons.gotifyIcon classes
|
||||
|
||||
Http ->
|
||||
i
|
||||
[ class "fa fa-ethernet"
|
||||
, class classes
|
||||
]
|
||||
[]
|
90
modules/webapp/src/main/elm/Data/EventType.elm
Normal file
90
modules/webapp/src/main/elm/Data/EventType.elm
Normal file
@ -0,0 +1,90 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Data.EventType exposing (..)
|
||||
|
||||
import Json.Decode as D
|
||||
import Json.Encode as E
|
||||
|
||||
|
||||
type EventType
|
||||
= TagsChanged
|
||||
| SetFieldValue
|
||||
| DeleteFieldValue
|
||||
| JobSubmitted
|
||||
| JobDone
|
||||
|
||||
|
||||
all : List EventType
|
||||
all =
|
||||
[ TagsChanged
|
||||
, SetFieldValue
|
||||
, DeleteFieldValue
|
||||
, JobSubmitted
|
||||
, JobDone
|
||||
]
|
||||
|
||||
|
||||
fromString : String -> Maybe EventType
|
||||
fromString str =
|
||||
case String.toLower str of
|
||||
"tagschanged" ->
|
||||
Just TagsChanged
|
||||
|
||||
"setfieldvalue" ->
|
||||
Just SetFieldValue
|
||||
|
||||
"deletefieldvalue" ->
|
||||
Just DeleteFieldValue
|
||||
|
||||
"jobsubmitted" ->
|
||||
Just JobSubmitted
|
||||
|
||||
"jobdone" ->
|
||||
Just JobDone
|
||||
|
||||
_ ->
|
||||
Nothing
|
||||
|
||||
|
||||
asString : EventType -> String
|
||||
asString et =
|
||||
case et of
|
||||
TagsChanged ->
|
||||
"TagsChanged"
|
||||
|
||||
SetFieldValue ->
|
||||
"SetFieldValue"
|
||||
|
||||
DeleteFieldValue ->
|
||||
"DeleteFieldValue"
|
||||
|
||||
JobSubmitted ->
|
||||
"JobSubmitted"
|
||||
|
||||
JobDone ->
|
||||
"JobDone"
|
||||
|
||||
|
||||
decoder : D.Decoder EventType
|
||||
decoder =
|
||||
let
|
||||
unwrap me =
|
||||
case me of
|
||||
Just et ->
|
||||
D.succeed et
|
||||
|
||||
Nothing ->
|
||||
D.fail "Unknown event type!"
|
||||
in
|
||||
D.map fromString D.string
|
||||
|> D.andThen unwrap
|
||||
|
||||
|
||||
encode : EventType -> E.Value
|
||||
encode et =
|
||||
E.string (asString et)
|
@ -47,7 +47,9 @@ module Data.Icons exposing
|
||||
, folder2
|
||||
, folderIcon
|
||||
, folderIcon2
|
||||
, gotifyIcon
|
||||
, itemDatesIcon
|
||||
, matrixIcon
|
||||
, organization
|
||||
, organization2
|
||||
, organizationIcon
|
||||
@ -73,8 +75,10 @@ module Data.Icons exposing
|
||||
)
|
||||
|
||||
import Data.CustomFieldType exposing (CustomFieldType)
|
||||
import Html exposing (Html, i)
|
||||
import Html.Attributes exposing (class)
|
||||
import Html exposing (Html, i, img)
|
||||
import Html.Attributes exposing (class, src)
|
||||
import Svg
|
||||
import Svg.Attributes as SA
|
||||
|
||||
|
||||
share : String
|
||||
@ -447,3 +451,32 @@ equipmentIcon classes =
|
||||
equipmentIcon2 : String -> Html msg
|
||||
equipmentIcon2 classes =
|
||||
i [ class (equipment2 ++ " " ++ classes) ] []
|
||||
|
||||
|
||||
matrixIcon : String -> Html msg
|
||||
matrixIcon classes =
|
||||
Svg.svg
|
||||
[ SA.width "520"
|
||||
, SA.height "520"
|
||||
, SA.viewBox "0 0 520 520"
|
||||
, SA.class classes
|
||||
]
|
||||
[ Svg.path
|
||||
[ SA.d "M13.7,11.9v496.2h35.7V520H0V0h49.4v11.9H13.7z" ]
|
||||
[]
|
||||
, Svg.path
|
||||
[ SA.d "M166.3,169.2v25.1h0.7c6.7-9.6,14.8-17,24.2-22.2c9.4-5.3,20.3-7.9,32.5-7.9c11.7,0,22.4,2.3,32.1,6.8\n\tc9.7,4.5,17,12.6,22.1,24c5.5-8.1,13-15.3,22.4-21.5c9.4-6.2,20.6-9.3,33.5-9.3c9.8,0,18.9,1.2,27.3,3.6c8.4,2.4,15.5,6.2,21.5,11.5\n\tc6,5.3,10.6,12.1,14,20.6c3.3,8.5,5,18.7,5,30.7v124.1h-50.9V249.6c0-6.2-0.2-12.1-0.7-17.6c-0.5-5.5-1.8-10.3-3.9-14.3\n\tc-2.2-4.1-5.3-7.3-9.5-9.7c-4.2-2.4-9.9-3.6-17-3.6c-7.2,0-13,1.4-17.4,4.1c-4.4,2.8-7.9,6.3-10.4,10.8c-2.5,4.4-4.2,9.4-5,15.1\n\tc-0.8,5.6-1.3,11.3-1.3,17v103.3h-50.9v-104c0-5.5-0.1-10.9-0.4-16.3c-0.2-5.4-1.3-10.3-3.1-14.9c-1.8-4.5-4.8-8.2-9-10.9\n\tc-4.2-2.7-10.3-4.1-18.5-4.1c-2.4,0-5.6,0.5-9.5,1.6c-3.9,1.1-7.8,3.1-11.5,6.1c-3.7,3-6.9,7.3-9.5,12.9c-2.6,5.6-3.9,13-3.9,22.1\n\tv107.6h-50.9V169.2H166.3z" ]
|
||||
[]
|
||||
, Svg.path
|
||||
[ SA.d "M506.3,508.1V11.9h-35.7V0H520v520h-49.4v-11.9H506.3z" ]
|
||||
[]
|
||||
]
|
||||
|
||||
|
||||
gotifyIcon : String -> Html msg
|
||||
gotifyIcon classes =
|
||||
img
|
||||
[ class classes
|
||||
, src "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAC80lEQVQ4y32SW0iTYRjHh7WL6K4gCKILbwQzJeomQcKLKEtJvAo0M8vDPG+WFlagaKgdzYgiUYRSUuzCwMN0NtOJ29xJN+fUj3nKedhe9+mOmvv3ft+FZlkPPHwvfO//x/P8379AQOtUXOL70/HJjcFRl4tDr14vC7mY8PDEmchbh48eO0t/HxT8ry6IK9pEvQwKtRsoGvOj2LjJ9z29G9nyOcS/aB49HnYu+Z+AYtOWlxOL1WsQqwj/LRhZR46aRb7WhfsTARSOsAhPSKndF0BFDl7INb2Y8d2Gwi4jnkh1KO3WI0s6BbHOTaEsYlJzW6Iiz6fsD6AXRDIrWgd1WHPYgZ+b2PZ5oDNPIr/TiDydBw8G5+Ega4iLjb37FyBTsYJ6uQZAAH+WTGNEunwBaQPL+GZZgLxX6qfSkF3AiBOiHgYW69yOKBAIQKlUYnFxERssCwldK0vrQc3ABOaYSa9QKDy5A+D2y5Va8GNpeQfg8/kQHR2N+vp6StvGI/kUbraPQ1z+ElVV1eagoKBDuxOoncjotUJnYfaMbrVaQQjB8qodonY9nja8Q93rUlQ+zrQJhQeO7PEgW7mG8i4NNXB1D8TvdqFGpkdquwHyr69gGapD3p1rTX+ZKKHvnzVkR1GHHh8HDejUmvF52IiS7jGkKegEKhbJzQMof/Y8EBEekR4cHBzPp/T3HEiomflaN24PEST1zOFGxyRyuswoo5N9kKnRqRqFyTyB+fl59Pf3Iyw0RCQQKx0O2vwE2YpV5HZbUCnV41P/CIb0RszOWMHaV+DbYPl1OHM1Gg3vzZWYS+WCfMWSgwtRroxBNWfSmzJ0fWmEZ53Flt8Pl8sFlj6j0+mE2+2GyWTC+Pg4709iYlIFB2C5/OcN2yFp60NTSwMM2mGoVGoYDAbYbDZ4PB54vV7MzMxAoVDwZ65KSkpaBQXDdobuTyiEZCg3yNs+Pdn2esj6OktmZ2eJWq0mMpmMMAxDqJjv6elpQoNGamtr+34BzIywNQI18UAAAAAASUVORK5CYII="
|
||||
]
|
||||
[]
|
||||
|
148
modules/webapp/src/main/elm/Data/NotificationChannel.elm
Normal file
148
modules/webapp/src/main/elm/Data/NotificationChannel.elm
Normal file
@ -0,0 +1,148 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Data.NotificationChannel exposing
|
||||
( NotificationChannel(..)
|
||||
, asString
|
||||
, channelType
|
||||
, decoder
|
||||
, empty
|
||||
, encode
|
||||
, setTypeGotify
|
||||
, setTypeHttp
|
||||
, setTypeMail
|
||||
, setTypeMatrix
|
||||
)
|
||||
|
||||
import Api.Model.NotificationGotify exposing (NotificationGotify)
|
||||
import Api.Model.NotificationHttp exposing (NotificationHttp)
|
||||
import Api.Model.NotificationMail exposing (NotificationMail)
|
||||
import Api.Model.NotificationMatrix exposing (NotificationMatrix)
|
||||
import Data.ChannelRef exposing (ChannelRef)
|
||||
import Data.ChannelType exposing (ChannelType)
|
||||
import Json.Decode as D
|
||||
import Json.Encode as E
|
||||
|
||||
|
||||
type NotificationChannel
|
||||
= Matrix NotificationMatrix
|
||||
| Mail NotificationMail
|
||||
| Gotify NotificationGotify
|
||||
| Http NotificationHttp
|
||||
| Ref ChannelRef
|
||||
|
||||
|
||||
empty : ChannelType -> NotificationChannel
|
||||
empty ct =
|
||||
let
|
||||
set =
|
||||
setType ct
|
||||
in
|
||||
case ct of
|
||||
Data.ChannelType.Mail ->
|
||||
Mail <| set Api.Model.NotificationMail.empty
|
||||
|
||||
Data.ChannelType.Matrix ->
|
||||
Matrix <| set Api.Model.NotificationMatrix.empty
|
||||
|
||||
Data.ChannelType.Gotify ->
|
||||
Gotify <| set Api.Model.NotificationGotify.empty
|
||||
|
||||
Data.ChannelType.Http ->
|
||||
Http <| set Api.Model.NotificationHttp.empty
|
||||
|
||||
|
||||
setType ct rec =
|
||||
{ rec | channelType = Data.ChannelType.asString ct }
|
||||
|
||||
|
||||
setTypeHttp : NotificationHttp -> NotificationHttp
|
||||
setTypeHttp h =
|
||||
setType Data.ChannelType.Http h
|
||||
|
||||
|
||||
setTypeMail : NotificationMail -> NotificationMail
|
||||
setTypeMail h =
|
||||
setType Data.ChannelType.Mail h
|
||||
|
||||
|
||||
setTypeMatrix : NotificationMatrix -> NotificationMatrix
|
||||
setTypeMatrix h =
|
||||
setType Data.ChannelType.Matrix h
|
||||
|
||||
|
||||
setTypeGotify : NotificationGotify -> NotificationGotify
|
||||
setTypeGotify h =
|
||||
setType Data.ChannelType.Gotify h
|
||||
|
||||
|
||||
decoder : D.Decoder NotificationChannel
|
||||
decoder =
|
||||
D.oneOf
|
||||
[ D.map Gotify Api.Model.NotificationGotify.decoder
|
||||
, D.map Mail Api.Model.NotificationMail.decoder
|
||||
, D.map Matrix Api.Model.NotificationMatrix.decoder
|
||||
, D.map Http Api.Model.NotificationHttp.decoder
|
||||
, D.map Ref Data.ChannelRef.decoder
|
||||
]
|
||||
|
||||
|
||||
encode : NotificationChannel -> E.Value
|
||||
encode channel =
|
||||
case channel of
|
||||
Matrix ch ->
|
||||
Api.Model.NotificationMatrix.encode ch
|
||||
|
||||
Mail ch ->
|
||||
Api.Model.NotificationMail.encode ch
|
||||
|
||||
Gotify ch ->
|
||||
Api.Model.NotificationGotify.encode ch
|
||||
|
||||
Http ch ->
|
||||
Api.Model.NotificationHttp.encode ch
|
||||
|
||||
Ref ch ->
|
||||
Data.ChannelRef.encode ch
|
||||
|
||||
|
||||
channelType : NotificationChannel -> Maybe ChannelType
|
||||
channelType ch =
|
||||
case ch of
|
||||
Matrix m ->
|
||||
Data.ChannelType.fromString m.channelType
|
||||
|
||||
Mail m ->
|
||||
Data.ChannelType.fromString m.channelType
|
||||
|
||||
Gotify m ->
|
||||
Data.ChannelType.fromString m.channelType
|
||||
|
||||
Http m ->
|
||||
Data.ChannelType.fromString m.channelType
|
||||
|
||||
Ref m ->
|
||||
Just m.channelType
|
||||
|
||||
|
||||
asString : NotificationChannel -> String
|
||||
asString channel =
|
||||
case channel of
|
||||
Matrix ch ->
|
||||
"Matrix @ " ++ ch.homeServer ++ "(" ++ ch.roomId ++ ")"
|
||||
|
||||
Mail ch ->
|
||||
"Mail @ " ++ ch.connection ++ " (" ++ String.join ", " ch.recipients ++ ")"
|
||||
|
||||
Gotify ch ->
|
||||
"Gotify @ " ++ ch.url
|
||||
|
||||
Http ch ->
|
||||
"Http @ " ++ ch.url
|
||||
|
||||
Ref ch ->
|
||||
"Ref(" ++ Data.ChannelType.asString ch.channelType ++ "/" ++ ch.id ++ ")"
|
62
modules/webapp/src/main/elm/Data/NotificationHook.elm
Normal file
62
modules/webapp/src/main/elm/Data/NotificationHook.elm
Normal file
@ -0,0 +1,62 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Data.NotificationHook exposing (NotificationHook, decoder, empty, encode)
|
||||
|
||||
import Data.ChannelType exposing (ChannelType)
|
||||
import Data.EventType exposing (EventType)
|
||||
import Data.NotificationChannel exposing (NotificationChannel)
|
||||
import Json.Decode as D
|
||||
import Json.Encode as E
|
||||
|
||||
|
||||
type alias NotificationHook =
|
||||
{ id : String
|
||||
, enabled : Bool
|
||||
, channel : NotificationChannel
|
||||
, allEvents : Bool
|
||||
, eventFilter : Maybe String
|
||||
, events : List EventType
|
||||
}
|
||||
|
||||
|
||||
empty : ChannelType -> NotificationHook
|
||||
empty ct =
|
||||
{ id = ""
|
||||
, enabled = True
|
||||
, channel = Data.NotificationChannel.empty ct
|
||||
, allEvents = False
|
||||
, eventFilter = Nothing
|
||||
, events = []
|
||||
}
|
||||
|
||||
|
||||
decoder : D.Decoder NotificationHook
|
||||
decoder =
|
||||
D.map6 NotificationHook
|
||||
(D.field "id" D.string)
|
||||
(D.field "enabled" D.bool)
|
||||
(D.field "channel" Data.NotificationChannel.decoder)
|
||||
(D.field "allEvents" D.bool)
|
||||
(D.field "eventFilter" (D.maybe D.string))
|
||||
(D.field "events" (D.list Data.EventType.decoder))
|
||||
|
||||
|
||||
encode : NotificationHook -> E.Value
|
||||
encode hook =
|
||||
E.object
|
||||
[ ( "id", E.string hook.id )
|
||||
, ( "enabled", E.bool hook.enabled )
|
||||
, ( "channel", Data.NotificationChannel.encode hook.channel )
|
||||
, ( "allEvents", E.bool hook.allEvents )
|
||||
, ( "eventFilter", Maybe.map E.string hook.eventFilter |> Maybe.withDefault E.null )
|
||||
, ( "events", E.list Data.EventType.encode hook.events )
|
||||
]
|
||||
|
||||
|
||||
|
||||
--- private
|
@ -0,0 +1,77 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Data.PeriodicDueItemsSettings exposing (..)
|
||||
|
||||
import Api.Model.Tag exposing (Tag)
|
||||
import Data.ChannelType exposing (ChannelType)
|
||||
import Data.NotificationChannel exposing (NotificationChannel)
|
||||
import Json.Decode as Decode
|
||||
import Json.Decode.Pipeline as P
|
||||
import Json.Encode as Encode
|
||||
|
||||
|
||||
|
||||
{--
|
||||
- Settings for notifying about due items.
|
||||
--}
|
||||
|
||||
|
||||
type alias PeriodicDueItemsSettings =
|
||||
{ id : String
|
||||
, enabled : Bool
|
||||
, summary : Maybe String
|
||||
, channel : NotificationChannel
|
||||
, schedule : String
|
||||
, remindDays : Int
|
||||
, capOverdue : Bool
|
||||
, tagsInclude : List Tag
|
||||
, tagsExclude : List Tag
|
||||
}
|
||||
|
||||
|
||||
empty : ChannelType -> PeriodicDueItemsSettings
|
||||
empty ct =
|
||||
{ id = ""
|
||||
, enabled = False
|
||||
, summary = Nothing
|
||||
, channel = Data.NotificationChannel.empty ct
|
||||
, schedule = ""
|
||||
, remindDays = 0
|
||||
, capOverdue = False
|
||||
, tagsInclude = []
|
||||
, tagsExclude = []
|
||||
}
|
||||
|
||||
|
||||
decoder : Decode.Decoder PeriodicDueItemsSettings
|
||||
decoder =
|
||||
Decode.succeed PeriodicDueItemsSettings
|
||||
|> P.required "id" Decode.string
|
||||
|> P.required "enabled" Decode.bool
|
||||
|> P.optional "summary" (Decode.maybe Decode.string) Nothing
|
||||
|> P.required "channel" Data.NotificationChannel.decoder
|
||||
|> P.required "schedule" Decode.string
|
||||
|> P.required "remindDays" Decode.int
|
||||
|> P.required "capOverdue" Decode.bool
|
||||
|> P.required "tagsInclude" (Decode.list Api.Model.Tag.decoder)
|
||||
|> P.required "tagsExclude" (Decode.list Api.Model.Tag.decoder)
|
||||
|
||||
|
||||
encode : PeriodicDueItemsSettings -> Encode.Value
|
||||
encode value =
|
||||
Encode.object
|
||||
[ ( "id", Encode.string value.id )
|
||||
, ( "enabled", Encode.bool value.enabled )
|
||||
, ( "summary", (Maybe.map Encode.string >> Maybe.withDefault Encode.null) value.summary )
|
||||
, ( "channel", Data.NotificationChannel.encode value.channel )
|
||||
, ( "schedule", Encode.string value.schedule )
|
||||
, ( "remindDays", Encode.int value.remindDays )
|
||||
, ( "capOverdue", Encode.bool value.capOverdue )
|
||||
, ( "tagsInclude", Encode.list Api.Model.Tag.encode value.tagsInclude )
|
||||
, ( "tagsExclude", Encode.list Api.Model.Tag.encode value.tagsExclude )
|
||||
]
|
57
modules/webapp/src/main/elm/Data/PeriodicQuerySettings.elm
Normal file
57
modules/webapp/src/main/elm/Data/PeriodicQuerySettings.elm
Normal file
@ -0,0 +1,57 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Data.PeriodicQuerySettings exposing (PeriodicQuerySettings, decoder, empty, encode)
|
||||
|
||||
import Data.ChannelType exposing (ChannelType)
|
||||
import Data.NotificationChannel exposing (NotificationChannel)
|
||||
import Json.Decode as D
|
||||
import Json.Encode as E
|
||||
|
||||
|
||||
type alias PeriodicQuerySettings =
|
||||
{ id : String
|
||||
, enabled : Bool
|
||||
, summary : Maybe String
|
||||
, channel : NotificationChannel
|
||||
, query : String
|
||||
, schedule : String
|
||||
}
|
||||
|
||||
|
||||
empty : ChannelType -> PeriodicQuerySettings
|
||||
empty ct =
|
||||
{ id = ""
|
||||
, enabled = False
|
||||
, summary = Nothing
|
||||
, channel = Data.NotificationChannel.empty ct
|
||||
, query = ""
|
||||
, schedule = ""
|
||||
}
|
||||
|
||||
|
||||
decoder : D.Decoder PeriodicQuerySettings
|
||||
decoder =
|
||||
D.map6 PeriodicQuerySettings
|
||||
(D.field "id" D.string)
|
||||
(D.field "enabled" D.bool)
|
||||
(D.field "summary" (D.maybe D.string))
|
||||
(D.field "channel" Data.NotificationChannel.decoder)
|
||||
(D.field "query" D.string)
|
||||
(D.field "schedule" D.string)
|
||||
|
||||
|
||||
encode : PeriodicQuerySettings -> E.Value
|
||||
encode s =
|
||||
E.object
|
||||
[ ( "id", E.string s.id )
|
||||
, ( "enabled", E.bool s.enabled )
|
||||
, ( "summary", Maybe.map E.string s.summary |> Maybe.withDefault E.null )
|
||||
, ( "channel", Data.NotificationChannel.encode s.channel )
|
||||
, ( "query", E.string s.query )
|
||||
, ( "schedule", E.string s.schedule )
|
||||
]
|
Reference in New Issue
Block a user