mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-22 02:18: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:
@ -10,6 +10,7 @@
|
||||
"CurrySoftware/elm-datepicker": "4.0.0",
|
||||
"NoRedInk/elm-json-decode-pipeline": "1.0.0",
|
||||
"NoRedInk/elm-simple-fuzzy": "1.0.3",
|
||||
"ThinkAlexandria/elm-pretty-print-json": "1.0.1",
|
||||
"elm/browser": "1.0.2",
|
||||
"elm/core": "1.0.5",
|
||||
"elm/file": "1.0.5",
|
||||
@ -35,9 +36,11 @@
|
||||
"elm/parser": "1.1.0",
|
||||
"elm/regex": "1.0.0",
|
||||
"elm/virtual-dom": "1.0.2",
|
||||
"elm-community/basics-extra": "4.1.0",
|
||||
"elm-community/list-extra": "8.2.4",
|
||||
"folkertdev/elm-flate": "2.0.4",
|
||||
"justgook/elm-image": "4.0.0"
|
||||
"justgook/elm-image": "4.0.0",
|
||||
"the-sett/elm-pretty-printer": "2.2.3"
|
||||
}
|
||||
},
|
||||
"test-dependencies": {
|
||||
|
@ -21,10 +21,12 @@ module Api exposing
|
||||
, checkCalEvent
|
||||
, confirmMultiple
|
||||
, confirmOtp
|
||||
, createHook
|
||||
, createImapSettings
|
||||
, createMailSettings
|
||||
, createNewFolder
|
||||
, createNotifyDueItems
|
||||
, createPeriodicQuery
|
||||
, createScanMailbox
|
||||
, deleteAllItems
|
||||
, deleteAttachment
|
||||
@ -34,11 +36,13 @@ module Api exposing
|
||||
, deleteCustomValueMultiple
|
||||
, deleteEquip
|
||||
, deleteFolder
|
||||
, deleteHook
|
||||
, deleteImapSettings
|
||||
, deleteItem
|
||||
, deleteMailSettings
|
||||
, deleteNotifyDueItems
|
||||
, deleteOrg
|
||||
, deletePeriodicQueryTask
|
||||
, deletePerson
|
||||
, deleteScanMailbox
|
||||
, deleteShare
|
||||
@ -58,6 +62,7 @@ module Api exposing
|
||||
, getEquipments
|
||||
, getFolderDetail
|
||||
, getFolders
|
||||
, getHooks
|
||||
, getImapSettings
|
||||
, getInsights
|
||||
, getItemProposals
|
||||
@ -69,6 +74,7 @@ module Api exposing
|
||||
, getOrgLight
|
||||
, getOrganizations
|
||||
, getOtpState
|
||||
, getPeriodicQuery
|
||||
, getPersonFull
|
||||
, getPersons
|
||||
, getPersonsLight
|
||||
@ -113,6 +119,7 @@ module Api exposing
|
||||
, reprocessMultiple
|
||||
, restoreAllItems
|
||||
, restoreItem
|
||||
, sampleEvent
|
||||
, saveClientSettings
|
||||
, searchShare
|
||||
, searchShareStats
|
||||
@ -150,18 +157,24 @@ module Api exposing
|
||||
, startClassifier
|
||||
, startEmptyTrash
|
||||
, startOnceNotifyDueItems
|
||||
, startOncePeriodicQuery
|
||||
, startOnceScanMailbox
|
||||
, startReIndex
|
||||
, submitNotifyDueItems
|
||||
, submitPeriodicQuery
|
||||
, testHook
|
||||
, toggleTags
|
||||
, twoFactor
|
||||
, unconfirmMultiple
|
||||
, updateHook
|
||||
, updateNotifyDueItems
|
||||
, updatePeriodicQuery
|
||||
, updateScanMailbox
|
||||
, updateShare
|
||||
, upload
|
||||
, uploadAmend
|
||||
, uploadSingle
|
||||
, verifyJsonFilter
|
||||
, verifyShare
|
||||
, versionInfo
|
||||
)
|
||||
@ -208,8 +221,8 @@ import Api.Model.JobQueueState exposing (JobQueueState)
|
||||
import Api.Model.MoveAttachment exposing (MoveAttachment)
|
||||
import Api.Model.NewCustomField exposing (NewCustomField)
|
||||
import Api.Model.NewFolder exposing (NewFolder)
|
||||
import Api.Model.NotificationSettings exposing (NotificationSettings)
|
||||
import Api.Model.NotificationSettingsList exposing (NotificationSettingsList)
|
||||
import Api.Model.NotificationChannelTestResult exposing (NotificationChannelTestResult)
|
||||
import Api.Model.NotificationSampleEventReq exposing (NotificationSampleEventReq)
|
||||
import Api.Model.OptionalDate exposing (OptionalDate)
|
||||
import Api.Model.OptionalId exposing (OptionalId)
|
||||
import Api.Model.OptionalText exposing (OptionalText)
|
||||
@ -239,6 +252,7 @@ import Api.Model.SourceAndTags exposing (SourceAndTags)
|
||||
import Api.Model.SourceList exposing (SourceList)
|
||||
import Api.Model.SourceTagIn
|
||||
import Api.Model.StringList exposing (StringList)
|
||||
import Api.Model.StringValue exposing (StringValue)
|
||||
import Api.Model.Tag exposing (Tag)
|
||||
import Api.Model.TagCloud exposing (TagCloud)
|
||||
import Api.Model.TagList exposing (TagList)
|
||||
@ -249,9 +263,13 @@ import Api.Model.VersionInfo exposing (VersionInfo)
|
||||
import Data.ContactType exposing (ContactType)
|
||||
import Data.CustomFieldOrder exposing (CustomFieldOrder)
|
||||
import Data.EquipmentOrder exposing (EquipmentOrder)
|
||||
import Data.EventType exposing (EventType)
|
||||
import Data.Flags exposing (Flags)
|
||||
import Data.FolderOrder exposing (FolderOrder)
|
||||
import Data.NotificationHook exposing (NotificationHook)
|
||||
import Data.OrganizationOrder exposing (OrganizationOrder)
|
||||
import Data.PeriodicDueItemsSettings exposing (PeriodicDueItemsSettings)
|
||||
import Data.PeriodicQuerySettings exposing (PeriodicQuerySettings)
|
||||
import Data.PersonOrder exposing (PersonOrder)
|
||||
import Data.Priority exposing (Priority)
|
||||
import Data.TagOrder exposing (TagOrder)
|
||||
@ -571,68 +589,153 @@ deleteNotifyDueItems flags id receive =
|
||||
|
||||
startOnceNotifyDueItems :
|
||||
Flags
|
||||
-> NotificationSettings
|
||||
-> PeriodicDueItemsSettings
|
||||
-> (Result Http.Error BasicResult -> msg)
|
||||
-> Cmd msg
|
||||
startOnceNotifyDueItems flags settings receive =
|
||||
Http2.authPost
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/usertask/notifydueitems/startonce"
|
||||
, account = getAccount flags
|
||||
, body = Http.jsonBody (Api.Model.NotificationSettings.encode settings)
|
||||
, body = Http.jsonBody (Data.PeriodicDueItemsSettings.encode settings)
|
||||
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||
}
|
||||
|
||||
|
||||
updateNotifyDueItems :
|
||||
Flags
|
||||
-> NotificationSettings
|
||||
-> PeriodicDueItemsSettings
|
||||
-> (Result Http.Error BasicResult -> msg)
|
||||
-> Cmd msg
|
||||
updateNotifyDueItems flags settings receive =
|
||||
Http2.authPut
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/usertask/notifydueitems"
|
||||
, account = getAccount flags
|
||||
, body = Http.jsonBody (Api.Model.NotificationSettings.encode settings)
|
||||
, body = Http.jsonBody (Data.PeriodicDueItemsSettings.encode settings)
|
||||
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||
}
|
||||
|
||||
|
||||
createNotifyDueItems :
|
||||
Flags
|
||||
-> NotificationSettings
|
||||
-> PeriodicDueItemsSettings
|
||||
-> (Result Http.Error BasicResult -> msg)
|
||||
-> Cmd msg
|
||||
createNotifyDueItems flags settings receive =
|
||||
Http2.authPost
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/usertask/notifydueitems"
|
||||
, account = getAccount flags
|
||||
, body = Http.jsonBody (Api.Model.NotificationSettings.encode settings)
|
||||
, body = Http.jsonBody (Data.PeriodicDueItemsSettings.encode settings)
|
||||
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||
}
|
||||
|
||||
|
||||
getNotifyDueItems :
|
||||
Flags
|
||||
-> (Result Http.Error NotificationSettingsList -> msg)
|
||||
-> (Result Http.Error (List PeriodicDueItemsSettings) -> msg)
|
||||
-> Cmd msg
|
||||
getNotifyDueItems flags receive =
|
||||
Http2.authGet
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/usertask/notifydueitems"
|
||||
, account = getAccount flags
|
||||
, expect = Http.expectJson receive Api.Model.NotificationSettingsList.decoder
|
||||
, expect = Http.expectJson receive (JsonDecode.list Data.PeriodicDueItemsSettings.decoder)
|
||||
}
|
||||
|
||||
|
||||
submitNotifyDueItems :
|
||||
Flags
|
||||
-> NotificationSettings
|
||||
-> PeriodicDueItemsSettings
|
||||
-> (Result Http.Error BasicResult -> msg)
|
||||
-> Cmd msg
|
||||
submitNotifyDueItems flags settings receive =
|
||||
Http2.authPost
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/usertask/notifydueitems"
|
||||
, account = getAccount flags
|
||||
, body = Http.jsonBody (Api.Model.NotificationSettings.encode settings)
|
||||
, body = Http.jsonBody (Data.PeriodicDueItemsSettings.encode settings)
|
||||
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||
}
|
||||
|
||||
|
||||
|
||||
--- PeriodicQueryTask
|
||||
|
||||
|
||||
deletePeriodicQueryTask :
|
||||
Flags
|
||||
-> String
|
||||
-> (Result Http.Error BasicResult -> msg)
|
||||
-> Cmd msg
|
||||
deletePeriodicQueryTask flags id receive =
|
||||
Http2.authDelete
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/usertask/periodicquery/" ++ id
|
||||
, account = getAccount flags
|
||||
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||
}
|
||||
|
||||
|
||||
startOncePeriodicQuery :
|
||||
Flags
|
||||
-> PeriodicQuerySettings
|
||||
-> (Result Http.Error BasicResult -> msg)
|
||||
-> Cmd msg
|
||||
startOncePeriodicQuery flags settings receive =
|
||||
Http2.authPost
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/usertask/periodicquery/startonce"
|
||||
, account = getAccount flags
|
||||
, body = Http.jsonBody (Data.PeriodicQuerySettings.encode settings)
|
||||
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||
}
|
||||
|
||||
|
||||
updatePeriodicQuery :
|
||||
Flags
|
||||
-> PeriodicQuerySettings
|
||||
-> (Result Http.Error BasicResult -> msg)
|
||||
-> Cmd msg
|
||||
updatePeriodicQuery flags settings receive =
|
||||
Http2.authPut
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/usertask/periodicquery"
|
||||
, account = getAccount flags
|
||||
, body = Http.jsonBody (Data.PeriodicQuerySettings.encode settings)
|
||||
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||
}
|
||||
|
||||
|
||||
createPeriodicQuery :
|
||||
Flags
|
||||
-> PeriodicQuerySettings
|
||||
-> (Result Http.Error BasicResult -> msg)
|
||||
-> Cmd msg
|
||||
createPeriodicQuery flags settings receive =
|
||||
Http2.authPost
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/usertask/periodicquery"
|
||||
, account = getAccount flags
|
||||
, body = Http.jsonBody (Data.PeriodicQuerySettings.encode settings)
|
||||
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||
}
|
||||
|
||||
|
||||
getPeriodicQuery :
|
||||
Flags
|
||||
-> (Result Http.Error (List PeriodicQuerySettings) -> msg)
|
||||
-> Cmd msg
|
||||
getPeriodicQuery flags receive =
|
||||
Http2.authGet
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/usertask/periodicquery"
|
||||
, account = getAccount flags
|
||||
, expect = Http.expectJson receive (JsonDecode.list Data.PeriodicQuerySettings.decoder)
|
||||
}
|
||||
|
||||
|
||||
submitPeriodicQuery :
|
||||
Flags
|
||||
-> PeriodicQuerySettings
|
||||
-> (Result Http.Error BasicResult -> msg)
|
||||
-> Cmd msg
|
||||
submitPeriodicQuery flags settings receive =
|
||||
Http2.authPost
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/usertask/periodicquery"
|
||||
, account = getAccount flags
|
||||
, body = Http.jsonBody (Data.PeriodicQuerySettings.encode settings)
|
||||
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||
}
|
||||
|
||||
@ -2353,6 +2456,88 @@ shareFileURL attachId =
|
||||
|
||||
|
||||
|
||||
--- NotificationHook
|
||||
|
||||
|
||||
getHooks : Flags -> (Result Http.Error (List NotificationHook) -> msg) -> Cmd msg
|
||||
getHooks flags receive =
|
||||
Http2.authGet
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/notification/hook"
|
||||
, account = getAccount flags
|
||||
, expect = Http.expectJson receive (JsonDecode.list Data.NotificationHook.decoder)
|
||||
}
|
||||
|
||||
|
||||
deleteHook : Flags -> String -> (Result Http.Error BasicResult -> msg) -> Cmd msg
|
||||
deleteHook flags id receive =
|
||||
Http2.authDelete
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/notification/hook/" ++ id
|
||||
, account = getAccount flags
|
||||
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||
}
|
||||
|
||||
|
||||
createHook : Flags -> NotificationHook -> (Result Http.Error BasicResult -> msg) -> Cmd msg
|
||||
createHook flags hook receive =
|
||||
Http2.authPost
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/notification/hook"
|
||||
, account = getAccount flags
|
||||
, body = Http.jsonBody (Data.NotificationHook.encode hook)
|
||||
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||
}
|
||||
|
||||
|
||||
updateHook : Flags -> NotificationHook -> (Result Http.Error BasicResult -> msg) -> Cmd msg
|
||||
updateHook flags hook receive =
|
||||
Http2.authPut
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/notification/hook"
|
||||
, account = getAccount flags
|
||||
, body = Http.jsonBody (Data.NotificationHook.encode hook)
|
||||
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||
}
|
||||
|
||||
|
||||
sampleEvent : Flags -> EventType -> (Result Http.Error String -> msg) -> Cmd msg
|
||||
sampleEvent flags evt receive =
|
||||
Http2.authPost
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/notification/event/sample"
|
||||
, account = getAccount flags
|
||||
, body =
|
||||
Http.jsonBody
|
||||
(Api.Model.NotificationSampleEventReq.encode
|
||||
(NotificationSampleEventReq <|
|
||||
Data.EventType.asString evt
|
||||
)
|
||||
)
|
||||
, expect = Http.expectString receive
|
||||
}
|
||||
|
||||
|
||||
testHook :
|
||||
Flags
|
||||
-> NotificationHook
|
||||
-> (Result Http.Error NotificationChannelTestResult -> msg)
|
||||
-> Cmd msg
|
||||
testHook flags hook receive =
|
||||
Http2.authPost
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/notification/hook/sendTestEvent"
|
||||
, account = getAccount flags
|
||||
, body = Http.jsonBody (Data.NotificationHook.encode hook)
|
||||
, expect = Http.expectJson receive Api.Model.NotificationChannelTestResult.decoder
|
||||
}
|
||||
|
||||
|
||||
verifyJsonFilter : Flags -> String -> (Result Http.Error BasicResult -> msg) -> Cmd msg
|
||||
verifyJsonFilter flags query receive =
|
||||
Http2.authPost
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/notification/hook/verifyJsonFilter"
|
||||
, account = getAccount flags
|
||||
, body = Http.jsonBody (Api.Model.StringValue.encode (StringValue query))
|
||||
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||
}
|
||||
|
||||
|
||||
|
||||
--- Helper
|
||||
|
||||
|
||||
|
280
modules/webapp/src/main/elm/Comp/ChannelForm.elm
Normal file
280
modules/webapp/src/main/elm/Comp/ChannelForm.elm
Normal file
@ -0,0 +1,280 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Comp.ChannelForm exposing (..)
|
||||
|
||||
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 Comp.NotificationGotifyForm
|
||||
import Comp.NotificationHttpForm
|
||||
import Comp.NotificationMailForm
|
||||
import Comp.NotificationMatrixForm
|
||||
import Data.ChannelType exposing (ChannelType)
|
||||
import Data.Flags exposing (Flags)
|
||||
import Data.NotificationChannel exposing (NotificationChannel)
|
||||
import Data.UiSettings exposing (UiSettings)
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Messages.Comp.ChannelForm exposing (Texts)
|
||||
|
||||
|
||||
type alias MatrixModel =
|
||||
{ form : Comp.NotificationMatrixForm.Model
|
||||
, value : Maybe NotificationMatrix
|
||||
}
|
||||
|
||||
|
||||
type alias GotifyModel =
|
||||
{ form : Comp.NotificationGotifyForm.Model
|
||||
, value : Maybe NotificationGotify
|
||||
}
|
||||
|
||||
|
||||
type alias MailModel =
|
||||
{ form : Comp.NotificationMailForm.Model
|
||||
, value : Maybe NotificationMail
|
||||
}
|
||||
|
||||
|
||||
type alias HttpModel =
|
||||
{ form : Comp.NotificationHttpForm.Model
|
||||
, value : Maybe NotificationHttp
|
||||
}
|
||||
|
||||
|
||||
type alias RefModel =
|
||||
{ channelType : ChannelType
|
||||
}
|
||||
|
||||
|
||||
type Model
|
||||
= Matrix MatrixModel
|
||||
| Gotify GotifyModel
|
||||
| Mail MailModel
|
||||
| Http HttpModel
|
||||
| Ref RefModel
|
||||
|
||||
|
||||
type Msg
|
||||
= MatrixMsg Comp.NotificationMatrixForm.Msg
|
||||
| GotifyMsg Comp.NotificationGotifyForm.Msg
|
||||
| MailMsg Comp.NotificationMailForm.Msg
|
||||
| HttpMsg Comp.NotificationHttpForm.Msg
|
||||
|
||||
|
||||
init : Flags -> ChannelType -> ( Model, Cmd Msg )
|
||||
init flags ct =
|
||||
case ct of
|
||||
Data.ChannelType.Matrix ->
|
||||
( Matrix
|
||||
{ form = Comp.NotificationMatrixForm.init
|
||||
, value = Nothing
|
||||
}
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
Data.ChannelType.Gotify ->
|
||||
( Gotify
|
||||
{ form = Comp.NotificationGotifyForm.init
|
||||
, value = Nothing
|
||||
}
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
Data.ChannelType.Mail ->
|
||||
let
|
||||
( mm, mc ) =
|
||||
Comp.NotificationMailForm.init flags
|
||||
in
|
||||
( Mail
|
||||
{ form = mm
|
||||
, value = Nothing
|
||||
}
|
||||
, Cmd.map MailMsg mc
|
||||
)
|
||||
|
||||
Data.ChannelType.Http ->
|
||||
( Http
|
||||
{ form = Comp.NotificationHttpForm.init
|
||||
, value = Nothing
|
||||
}
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
|
||||
initWith : Flags -> NotificationChannel -> ( Model, Cmd Msg )
|
||||
initWith flags channel =
|
||||
case channel of
|
||||
Data.NotificationChannel.Matrix m ->
|
||||
( Matrix
|
||||
{ form = Comp.NotificationMatrixForm.initWith m
|
||||
, value = Just m
|
||||
}
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
Data.NotificationChannel.Gotify m ->
|
||||
( Gotify
|
||||
{ form = Comp.NotificationGotifyForm.initWith m
|
||||
, value = Just m
|
||||
}
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
Data.NotificationChannel.Mail m ->
|
||||
let
|
||||
( mm, mc ) =
|
||||
Comp.NotificationMailForm.initWith flags m
|
||||
in
|
||||
( Mail
|
||||
{ form = mm
|
||||
, value = Just m
|
||||
}
|
||||
, Cmd.map MailMsg mc
|
||||
)
|
||||
|
||||
Data.NotificationChannel.Http m ->
|
||||
( Http
|
||||
{ form = Comp.NotificationHttpForm.initWith m
|
||||
, value = Just m
|
||||
}
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
Data.NotificationChannel.Ref m ->
|
||||
( Ref { channelType = m.channelType }
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
|
||||
channelType : Model -> ChannelType
|
||||
channelType model =
|
||||
case model of
|
||||
Matrix _ ->
|
||||
Data.ChannelType.Matrix
|
||||
|
||||
Gotify _ ->
|
||||
Data.ChannelType.Gotify
|
||||
|
||||
Mail _ ->
|
||||
Data.ChannelType.Mail
|
||||
|
||||
Http _ ->
|
||||
Data.ChannelType.Http
|
||||
|
||||
Ref ref ->
|
||||
ref.channelType
|
||||
|
||||
|
||||
getChannel : Model -> Maybe NotificationChannel
|
||||
getChannel model =
|
||||
case model of
|
||||
Matrix mm ->
|
||||
Maybe.map Data.NotificationChannel.Matrix mm.value
|
||||
|
||||
Gotify mm ->
|
||||
Maybe.map Data.NotificationChannel.Gotify mm.value
|
||||
|
||||
Mail mm ->
|
||||
Maybe.map Data.NotificationChannel.Mail mm.value
|
||||
|
||||
Http mm ->
|
||||
Maybe.map Data.NotificationChannel.Http mm.value
|
||||
|
||||
Ref _ ->
|
||||
Nothing
|
||||
|
||||
|
||||
|
||||
--- Update
|
||||
|
||||
|
||||
update : Flags -> Msg -> Model -> ( Model, Cmd Msg )
|
||||
update flags msg model =
|
||||
case msg of
|
||||
MatrixMsg lm ->
|
||||
case model of
|
||||
Matrix matrix ->
|
||||
let
|
||||
( mm, mv ) =
|
||||
Comp.NotificationMatrixForm.update lm matrix.form
|
||||
in
|
||||
( Matrix { form = mm, value = mv }, Cmd.none )
|
||||
|
||||
_ ->
|
||||
( model, Cmd.none )
|
||||
|
||||
GotifyMsg lm ->
|
||||
case model of
|
||||
Gotify gotify ->
|
||||
let
|
||||
( mm, mv ) =
|
||||
Comp.NotificationGotifyForm.update lm gotify.form
|
||||
in
|
||||
( Gotify { form = mm, value = mv }, Cmd.none )
|
||||
|
||||
_ ->
|
||||
( model, Cmd.none )
|
||||
|
||||
MailMsg lm ->
|
||||
case model of
|
||||
Mail mail ->
|
||||
let
|
||||
( mm, mc, mv ) =
|
||||
Comp.NotificationMailForm.update flags lm mail.form
|
||||
in
|
||||
( Mail { form = mm, value = mv }, Cmd.map MailMsg mc )
|
||||
|
||||
_ ->
|
||||
( model, Cmd.none )
|
||||
|
||||
HttpMsg lm ->
|
||||
case model of
|
||||
Http http ->
|
||||
let
|
||||
( mm, mv ) =
|
||||
Comp.NotificationHttpForm.update lm http.form
|
||||
in
|
||||
( Http { form = mm, value = mv }, Cmd.none )
|
||||
|
||||
_ ->
|
||||
( model, Cmd.none )
|
||||
|
||||
|
||||
|
||||
--- View
|
||||
|
||||
|
||||
view : Texts -> UiSettings -> Model -> Html Msg
|
||||
view texts settings model =
|
||||
case model of
|
||||
Matrix m ->
|
||||
Html.map MatrixMsg
|
||||
(Comp.NotificationMatrixForm.view texts.matrixForm m.form)
|
||||
|
||||
Gotify m ->
|
||||
Html.map GotifyMsg
|
||||
(Comp.NotificationGotifyForm.view texts.gotifyForm m.form)
|
||||
|
||||
Mail m ->
|
||||
Html.map MailMsg
|
||||
(Comp.NotificationMailForm.view texts.mailForm settings m.form)
|
||||
|
||||
Http m ->
|
||||
Html.map HttpMsg
|
||||
(Comp.NotificationHttpForm.view texts.httpForm m.form)
|
||||
|
||||
-- Note: currently when retrieving hooks, this is not
|
||||
-- send from the server. The server always sends
|
||||
-- concrete channel details. However, it is possible
|
||||
-- to create hooks with a reference to an existing
|
||||
-- channel, but this is not supported in this client.
|
||||
-- So this channel is ignored here.
|
||||
Ref _ ->
|
||||
span [ class "hidden" ] []
|
48
modules/webapp/src/main/elm/Comp/ChannelMenu.elm
Normal file
48
modules/webapp/src/main/elm/Comp/ChannelMenu.elm
Normal file
@ -0,0 +1,48 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Comp.ChannelMenu exposing (..)
|
||||
|
||||
import Comp.MenuBar as MB
|
||||
import Data.ChannelType exposing (ChannelType)
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onClick)
|
||||
import Messages.Data.ChannelType exposing (Texts)
|
||||
import Styles as S
|
||||
|
||||
|
||||
type alias Model msg =
|
||||
{ menuOpen : Bool
|
||||
, toggleMenu : msg
|
||||
, menuLabel : String
|
||||
, onItem : ChannelType -> msg
|
||||
}
|
||||
|
||||
|
||||
channelMenu : Texts -> Model msg -> MB.Item msg
|
||||
channelMenu texts model =
|
||||
MB.Dropdown
|
||||
{ linkIcon = "fa fa-plus"
|
||||
, label = model.menuLabel
|
||||
, linkClass = [ ( S.primaryButton, True ) ]
|
||||
, toggleMenu = model.toggleMenu
|
||||
, menuOpen = model.menuOpen
|
||||
, items =
|
||||
List.map (menuItem texts model) Data.ChannelType.all
|
||||
}
|
||||
|
||||
|
||||
menuItem : Texts -> Model msg -> ChannelType -> MB.DropdownMenu msg
|
||||
menuItem texts model ct =
|
||||
{ icon = Data.ChannelType.icon ct "w-6 h-6 text-center inline-block"
|
||||
, label = texts ct
|
||||
, attrs =
|
||||
[ href ""
|
||||
, onClick (model.onItem ct)
|
||||
]
|
||||
}
|
@ -14,6 +14,7 @@ module Comp.Dropdown exposing
|
||||
, isDropdownChangeMsg
|
||||
, makeModel
|
||||
, makeMultiple
|
||||
, makeMultipleList
|
||||
, makeSingle
|
||||
, makeSingleList
|
||||
, mkOption
|
||||
@ -116,6 +117,26 @@ makeMultiple =
|
||||
}
|
||||
|
||||
|
||||
makeMultipleList :
|
||||
{ options : List a
|
||||
, selected : List a
|
||||
}
|
||||
-> Model a
|
||||
makeMultipleList opts =
|
||||
let
|
||||
m =
|
||||
makeMultiple
|
||||
|
||||
m2 =
|
||||
{ m | available = List.map (makeItem m) opts.options }
|
||||
|
||||
m3 =
|
||||
List.map (makeItem m2) opts.selected
|
||||
|> List.foldl (\el -> \model -> selectItem model el) m2
|
||||
in
|
||||
m3
|
||||
|
||||
|
||||
getSelected : Model a -> List a
|
||||
getSelected model =
|
||||
List.map .value model.selected
|
||||
|
@ -5,7 +5,7 @@
|
||||
-}
|
||||
|
||||
|
||||
module Comp.NotificationForm exposing
|
||||
module Comp.DueItemsTaskForm exposing
|
||||
( Action(..)
|
||||
, Model
|
||||
, Msg
|
||||
@ -17,19 +17,21 @@ module Comp.NotificationForm exposing
|
||||
|
||||
import Api
|
||||
import Api.Model.EmailSettingsList exposing (EmailSettingsList)
|
||||
import Api.Model.NotificationSettings exposing (NotificationSettings)
|
||||
import Api.Model.Tag exposing (Tag)
|
||||
import Api.Model.TagList exposing (TagList)
|
||||
import Comp.Basic as B
|
||||
import Comp.CalEventInput
|
||||
import Comp.ChannelForm
|
||||
import Comp.Dropdown
|
||||
import Comp.EmailInput
|
||||
import Comp.IntField
|
||||
import Comp.MenuBar as MB
|
||||
import Comp.YesNoDimmer
|
||||
import Data.CalEvent exposing (CalEvent)
|
||||
import Data.ChannelType exposing (ChannelType)
|
||||
import Data.DropdownStyle as DS
|
||||
import Data.Flags exposing (Flags)
|
||||
import Data.NotificationChannel
|
||||
import Data.PeriodicDueItemsSettings exposing (PeriodicDueItemsSettings)
|
||||
import Data.TagOrder
|
||||
import Data.UiSettings exposing (UiSettings)
|
||||
import Data.Validated exposing (Validated(..))
|
||||
@ -38,7 +40,7 @@ import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onInput)
|
||||
import Http
|
||||
import Markdown
|
||||
import Messages.Comp.NotificationForm exposing (Texts)
|
||||
import Messages.Comp.DueItemsTaskForm exposing (Texts)
|
||||
import Styles as S
|
||||
import Util.Maybe
|
||||
import Util.Tag
|
||||
@ -46,12 +48,10 @@ import Util.Update
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ settings : NotificationSettings
|
||||
, connectionModel : Comp.Dropdown.Model String
|
||||
{ settings : PeriodicDueItemsSettings
|
||||
, channelModel : Comp.ChannelForm.Model
|
||||
, tagInclModel : Comp.Dropdown.Model Tag
|
||||
, tagExclModel : Comp.Dropdown.Model Tag
|
||||
, recipients : List String
|
||||
, recipientsModel : Comp.EmailInput.Model
|
||||
, remindDays : Maybe Int
|
||||
, remindDaysModel : Comp.IntField.Model
|
||||
, capOverdue : Bool
|
||||
@ -72,15 +72,14 @@ type FormState
|
||||
|
||||
|
||||
type ValidateError
|
||||
= ValidateConnectionMissing
|
||||
| ValidateRemindDaysRequired
|
||||
| ValidateRecipientsRequired
|
||||
= ValidateRemindDaysRequired
|
||||
| ValidateCalEventInvalid
|
||||
| ValidateChannelRequired
|
||||
|
||||
|
||||
type Action
|
||||
= SubmitAction NotificationSettings
|
||||
| StartOnceAction NotificationSettings
|
||||
= SubmitAction PeriodicDueItemsSettings
|
||||
| StartOnceAction PeriodicDueItemsSettings
|
||||
| CancelAction
|
||||
| DeleteAction String
|
||||
| NoAction
|
||||
@ -90,9 +89,6 @@ type Msg
|
||||
= Submit
|
||||
| TagIncMsg (Comp.Dropdown.Msg Tag)
|
||||
| TagExcMsg (Comp.Dropdown.Msg Tag)
|
||||
| ConnMsg (Comp.Dropdown.Msg String)
|
||||
| ConnResp (Result Http.Error EmailSettingsList)
|
||||
| RecipientMsg Comp.EmailInput.Msg
|
||||
| GetTagsResp (Result Http.Error TagList)
|
||||
| RemindDaysMsg Comp.IntField.Msg
|
||||
| ToggleEnabled
|
||||
@ -103,26 +99,25 @@ type Msg
|
||||
| RequestDelete
|
||||
| YesNoDeleteMsg Comp.YesNoDimmer.Msg
|
||||
| SetSummary String
|
||||
| ChannelMsg Comp.ChannelForm.Msg
|
||||
|
||||
|
||||
initWith : Flags -> NotificationSettings -> ( Model, Cmd Msg )
|
||||
initWith : Flags -> PeriodicDueItemsSettings -> ( Model, Cmd Msg )
|
||||
initWith flags s =
|
||||
let
|
||||
( im, ic ) =
|
||||
init flags
|
||||
ct =
|
||||
Data.NotificationChannel.channelType s.channel
|
||||
|> Maybe.withDefault Data.ChannelType.Matrix
|
||||
|
||||
smtp =
|
||||
Util.Maybe.fromString s.smtpConnection
|
||||
|> Maybe.map List.singleton
|
||||
|> Maybe.withDefault []
|
||||
( im, ic ) =
|
||||
init flags ct
|
||||
|
||||
removeAction ( tm, _, tc ) =
|
||||
( tm, tc )
|
||||
|
||||
( nm, nc ) =
|
||||
Util.Update.andThen1
|
||||
[ update flags (ConnMsg (Comp.Dropdown.SetSelection smtp)) >> removeAction
|
||||
, update flags (TagIncMsg (Comp.Dropdown.SetSelection s.tagsInclude)) >> removeAction
|
||||
[ update flags (TagIncMsg (Comp.Dropdown.SetSelection s.tagsInclude)) >> removeAction
|
||||
, update flags (TagExcMsg (Comp.Dropdown.SetSelection s.tagsExclude)) >> removeAction
|
||||
]
|
||||
im
|
||||
@ -133,10 +128,13 @@ initWith flags s =
|
||||
|
||||
( sm, sc ) =
|
||||
Comp.CalEventInput.init flags newSchedule
|
||||
|
||||
( cfm, cfc ) =
|
||||
Comp.ChannelForm.initWith flags s.channel
|
||||
in
|
||||
( { nm
|
||||
| settings = s
|
||||
, recipients = s.recipients
|
||||
, channelModel = cfm
|
||||
, remindDays = Just s.remindDays
|
||||
, enabled = s.enabled
|
||||
, capOverdue = s.capOverdue
|
||||
@ -151,25 +149,27 @@ initWith flags s =
|
||||
[ nc
|
||||
, ic
|
||||
, Cmd.map CalEventMsg sc
|
||||
, Cmd.map ChannelMsg cfc
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
init : Flags -> ( Model, Cmd Msg )
|
||||
init flags =
|
||||
init : Flags -> ChannelType -> ( Model, Cmd Msg )
|
||||
init flags ct =
|
||||
let
|
||||
initialSchedule =
|
||||
Data.CalEvent.everyMonth
|
||||
|
||||
( sm, scmd ) =
|
||||
Comp.CalEventInput.init flags initialSchedule
|
||||
|
||||
( cfm, cfc ) =
|
||||
Comp.ChannelForm.init flags ct
|
||||
in
|
||||
( { settings = Api.Model.NotificationSettings.empty
|
||||
, connectionModel = Comp.Dropdown.makeSingle
|
||||
( { settings = Data.PeriodicDueItemsSettings.empty ct
|
||||
, channelModel = cfm
|
||||
, tagInclModel = Util.Tag.makeDropdownModel
|
||||
, tagExclModel = Util.Tag.makeDropdownModel
|
||||
, recipients = []
|
||||
, recipientsModel = Comp.EmailInput.init
|
||||
, remindDays = Just 1
|
||||
, remindDaysModel = Comp.IntField.init (Just 1) Nothing True
|
||||
, enabled = False
|
||||
@ -177,14 +177,14 @@ init flags =
|
||||
, schedule = Just initialSchedule
|
||||
, scheduleModel = sm
|
||||
, formState = FormStateInitial
|
||||
, loading = 2
|
||||
, loading = 1
|
||||
, yesNoDelete = Comp.YesNoDimmer.emptyModel
|
||||
, summary = Nothing
|
||||
}
|
||||
, Cmd.batch
|
||||
[ Api.getMailSettings flags "" ConnResp
|
||||
, Api.getTags flags "" Data.TagOrder.NameAsc GetTagsResp
|
||||
[ Api.getTags flags "" Data.TagOrder.NameAsc GetTagsResp
|
||||
, Cmd.map CalEventMsg scmd
|
||||
, Cmd.map ChannelMsg cfc
|
||||
]
|
||||
)
|
||||
|
||||
@ -193,25 +193,12 @@ init flags =
|
||||
--- Update
|
||||
|
||||
|
||||
makeSettings : Model -> Result ValidateError NotificationSettings
|
||||
makeSettings : Model -> Result ValidateError PeriodicDueItemsSettings
|
||||
makeSettings model =
|
||||
let
|
||||
prev =
|
||||
model.settings
|
||||
|
||||
conn =
|
||||
Comp.Dropdown.getSelected model.connectionModel
|
||||
|> List.head
|
||||
|> Maybe.map Ok
|
||||
|> Maybe.withDefault (Err ValidateConnectionMissing)
|
||||
|
||||
recp =
|
||||
if List.isEmpty model.recipients then
|
||||
Err ValidateRecipientsRequired
|
||||
|
||||
else
|
||||
Ok model.recipients
|
||||
|
||||
rmdays =
|
||||
Maybe.map Ok model.remindDays
|
||||
|> Maybe.withDefault (Err ValidateRemindDaysRequired)
|
||||
@ -224,27 +211,30 @@ makeSettings model =
|
||||
Nothing ->
|
||||
Err ValidateCalEventInvalid
|
||||
|
||||
make smtp rec days timer =
|
||||
channelM =
|
||||
Result.fromMaybe
|
||||
ValidateChannelRequired
|
||||
(Comp.ChannelForm.getChannel model.channelModel)
|
||||
|
||||
make days timer channel =
|
||||
{ prev
|
||||
| smtpConnection = smtp
|
||||
, tagsInclude = Comp.Dropdown.getSelected model.tagInclModel
|
||||
| tagsInclude = Comp.Dropdown.getSelected model.tagInclModel
|
||||
, tagsExclude = Comp.Dropdown.getSelected model.tagExclModel
|
||||
, recipients = rec
|
||||
, remindDays = days
|
||||
, capOverdue = model.capOverdue
|
||||
, enabled = model.enabled
|
||||
, schedule = Data.CalEvent.makeEvent timer
|
||||
, summary = model.summary
|
||||
, channel = channel
|
||||
}
|
||||
in
|
||||
Result.map4 make
|
||||
conn
|
||||
recp
|
||||
Result.map3 make
|
||||
rmdays
|
||||
schedule_
|
||||
channelM
|
||||
|
||||
|
||||
withValidSettings : (NotificationSettings -> Action) -> Model -> ( Model, Action, Cmd Msg )
|
||||
withValidSettings : (PeriodicDueItemsSettings -> Action) -> Model -> ( Model, Action, Cmd Msg )
|
||||
withValidSettings mkcmd model =
|
||||
case makeSettings model of
|
||||
Ok set ->
|
||||
@ -263,6 +253,16 @@ withValidSettings mkcmd model =
|
||||
update : Flags -> Msg -> Model -> ( Model, Action, Cmd Msg )
|
||||
update flags msg model =
|
||||
case msg of
|
||||
ChannelMsg lm ->
|
||||
let
|
||||
( cfm, cfc ) =
|
||||
Comp.ChannelForm.update flags lm model.channelModel
|
||||
in
|
||||
( { model | channelModel = cfm }
|
||||
, NoAction
|
||||
, Cmd.map ChannelMsg cfc
|
||||
)
|
||||
|
||||
CalEventMsg lmsg ->
|
||||
let
|
||||
( cm, cc, cs ) =
|
||||
@ -280,67 +280,6 @@ update flags msg model =
|
||||
, Cmd.map CalEventMsg cc
|
||||
)
|
||||
|
||||
RecipientMsg m ->
|
||||
let
|
||||
( em, ec, rec ) =
|
||||
Comp.EmailInput.update flags model.recipients m model.recipientsModel
|
||||
in
|
||||
( { model
|
||||
| recipients = rec
|
||||
, recipientsModel = em
|
||||
, formState = FormStateInitial
|
||||
}
|
||||
, NoAction
|
||||
, Cmd.map RecipientMsg ec
|
||||
)
|
||||
|
||||
ConnMsg m ->
|
||||
let
|
||||
( cm, cc ) =
|
||||
Comp.Dropdown.update m model.connectionModel
|
||||
in
|
||||
( { model
|
||||
| connectionModel = cm
|
||||
, formState = FormStateInitial
|
||||
}
|
||||
, NoAction
|
||||
, Cmd.map ConnMsg cc
|
||||
)
|
||||
|
||||
ConnResp (Ok list) ->
|
||||
let
|
||||
names =
|
||||
List.map .name list.items
|
||||
|
||||
cm =
|
||||
Comp.Dropdown.makeSingleList
|
||||
{ options = names
|
||||
, selected = List.head names
|
||||
}
|
||||
in
|
||||
( { model
|
||||
| connectionModel = cm
|
||||
, loading = model.loading - 1
|
||||
, formState =
|
||||
if names == [] then
|
||||
FormStateInvalid ValidateConnectionMissing
|
||||
|
||||
else
|
||||
FormStateInitial
|
||||
}
|
||||
, NoAction
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
ConnResp (Err err) ->
|
||||
( { model
|
||||
| formState = FormStateHttpError err
|
||||
, loading = model.loading - 1
|
||||
}
|
||||
, NoAction
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
TagIncMsg m ->
|
||||
let
|
||||
( m2, c2 ) =
|
||||
@ -509,12 +448,10 @@ view2 texts extraClasses settings model =
|
||||
, icon = Just "fa fa-play"
|
||||
}
|
||||
|
||||
connectionCfg =
|
||||
{ makeOption = \a -> { text = a, additional = "" }
|
||||
, placeholder = texts.selectConnection
|
||||
, labelColor = \_ -> \_ -> ""
|
||||
, style = DS.mainStyle
|
||||
}
|
||||
formHeader txt =
|
||||
h2 [ class S.formHeader, class "mt-2" ]
|
||||
[ text txt
|
||||
]
|
||||
in
|
||||
div
|
||||
[ class "flex flex-col md:relative"
|
||||
@ -539,7 +476,7 @@ view2 texts extraClasses settings model =
|
||||
}
|
||||
, MB.SecondaryButton
|
||||
{ tagger = Cancel
|
||||
, label = texts.basics.cancel
|
||||
, label = texts.basics.backToList
|
||||
, title = texts.basics.backToList
|
||||
, icon = Just "fa fa-arrow-left"
|
||||
}
|
||||
@ -575,17 +512,14 @@ view2 texts extraClasses settings model =
|
||||
FormStateHttpError err ->
|
||||
text (texts.httpError err)
|
||||
|
||||
FormStateInvalid ValidateConnectionMissing ->
|
||||
text texts.connectionMissing
|
||||
|
||||
FormStateInvalid ValidateCalEventInvalid ->
|
||||
text texts.invalidCalEvent
|
||||
|
||||
FormStateInvalid ValidateRemindDaysRequired ->
|
||||
text texts.remindDaysRequired
|
||||
|
||||
FormStateInvalid ValidateRecipientsRequired ->
|
||||
text texts.recipientsRequired
|
||||
FormStateInvalid ValidateChannelRequired ->
|
||||
text texts.channelRequired
|
||||
]
|
||||
, div [ class "mb-4" ]
|
||||
[ MB.viewItem <|
|
||||
@ -613,37 +547,11 @@ view2 texts extraClasses settings model =
|
||||
]
|
||||
]
|
||||
, div [ class "mb-4" ]
|
||||
[ label [ class S.inputLabel ]
|
||||
[ text texts.sendVia
|
||||
, B.inputRequired
|
||||
]
|
||||
, Html.map ConnMsg
|
||||
(Comp.Dropdown.view2
|
||||
connectionCfg
|
||||
settings
|
||||
model.connectionModel
|
||||
)
|
||||
, span [ class "opacity-50 text-sm" ]
|
||||
[ text texts.sendViaInfo
|
||||
]
|
||||
]
|
||||
, div [ class "mb-4" ]
|
||||
[ label
|
||||
[ class S.inputLabel
|
||||
]
|
||||
[ text texts.recipients
|
||||
, B.inputRequired
|
||||
]
|
||||
, Html.map RecipientMsg
|
||||
(Comp.EmailInput.view2
|
||||
{ style = DS.mainStyle, placeholder = texts.recipients }
|
||||
model.recipients
|
||||
model.recipientsModel
|
||||
)
|
||||
, span [ class "opacity-50 text-sm" ]
|
||||
[ text texts.recipientsInfo
|
||||
]
|
||||
[ formHeader (texts.channelHeader (Comp.ChannelForm.channelType model.channelModel))
|
||||
, Html.map ChannelMsg
|
||||
(Comp.ChannelForm.view texts.channelForm settings model.channelModel)
|
||||
]
|
||||
, formHeader texts.queryLabel
|
||||
, div [ class "mb-4" ]
|
||||
[ label [ class S.inputLabel ]
|
||||
[ text texts.tagsInclude ]
|
||||
@ -666,7 +574,7 @@ view2 texts extraClasses settings model =
|
||||
settings
|
||||
model.tagExclModel
|
||||
)
|
||||
, span [ class "small-info" ]
|
||||
, span [ class "opacity-50 text-sm" ]
|
||||
[ text texts.tagsExcludeInfo
|
||||
]
|
||||
]
|
||||
@ -692,7 +600,8 @@ view2 texts extraClasses settings model =
|
||||
]
|
||||
]
|
||||
, div [ class "mb-4" ]
|
||||
[ label [ class S.inputLabel ]
|
||||
[ formHeader texts.schedule
|
||||
, label [ class S.inputLabel ]
|
||||
[ text texts.schedule
|
||||
, a
|
||||
[ class "float-right"
|
@ -5,7 +5,7 @@
|
||||
-}
|
||||
|
||||
|
||||
module Comp.NotificationList exposing
|
||||
module Comp.DueItemsTaskList exposing
|
||||
( Action(..)
|
||||
, Model
|
||||
, Msg
|
||||
@ -14,11 +14,13 @@ module Comp.NotificationList exposing
|
||||
, view2
|
||||
)
|
||||
|
||||
import Api.Model.NotificationSettings exposing (NotificationSettings)
|
||||
import Comp.Basic as B
|
||||
import Data.ChannelType
|
||||
import Data.NotificationChannel
|
||||
import Data.PeriodicDueItemsSettings exposing (PeriodicDueItemsSettings)
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Messages.Comp.NotificationTable exposing (Texts)
|
||||
import Messages.Comp.DueItemsTaskList exposing (Texts)
|
||||
import Styles as S
|
||||
import Util.Html
|
||||
|
||||
@ -28,12 +30,12 @@ type alias Model =
|
||||
|
||||
|
||||
type Msg
|
||||
= EditSettings NotificationSettings
|
||||
= EditSettings PeriodicDueItemsSettings
|
||||
|
||||
|
||||
type Action
|
||||
= NoAction
|
||||
| EditAction NotificationSettings
|
||||
| EditAction PeriodicDueItemsSettings
|
||||
|
||||
|
||||
init : Model
|
||||
@ -52,7 +54,7 @@ update msg model =
|
||||
--- View2
|
||||
|
||||
|
||||
view2 : Texts -> Model -> List NotificationSettings -> Html Msg
|
||||
view2 : Texts -> Model -> List PeriodicDueItemsSettings -> Html Msg
|
||||
view2 texts _ items =
|
||||
div []
|
||||
[ table [ class S.tableMain ]
|
||||
@ -67,8 +69,6 @@ view2 texts _ items =
|
||||
[ text texts.schedule ]
|
||||
, th [ class "text-left mr-2" ]
|
||||
[ text texts.connection ]
|
||||
, th [ class "text-left hidden sm:table-cell mr-2" ]
|
||||
[ text texts.recipients ]
|
||||
]
|
||||
]
|
||||
, tbody []
|
||||
@ -77,7 +77,7 @@ view2 texts _ items =
|
||||
]
|
||||
|
||||
|
||||
viewItem2 : Texts -> NotificationSettings -> Html Msg
|
||||
viewItem2 : Texts -> PeriodicDueItemsSettings -> Html Msg
|
||||
viewItem2 texts item =
|
||||
tr []
|
||||
[ B.editLinkTableCell texts.basics.edit (EditSettings item)
|
||||
@ -94,9 +94,9 @@ viewItem2 texts item =
|
||||
]
|
||||
]
|
||||
, td [ class "text-left mr-2" ]
|
||||
[ text item.smtpConnection
|
||||
]
|
||||
, td [ class "text-left hidden sm:table-cell mr-2" ]
|
||||
[ String.join ", " item.recipients |> text
|
||||
[ Data.NotificationChannel.channelType item.channel
|
||||
|> Maybe.map Data.ChannelType.asString
|
||||
|> Maybe.withDefault "-"
|
||||
|> text
|
||||
]
|
||||
]
|
@ -5,7 +5,7 @@
|
||||
-}
|
||||
|
||||
|
||||
module Comp.NotificationManage exposing
|
||||
module Comp.DueItemsTaskManage exposing
|
||||
( Model
|
||||
, Msg
|
||||
, init
|
||||
@ -15,25 +15,27 @@ module Comp.NotificationManage exposing
|
||||
|
||||
import Api
|
||||
import Api.Model.BasicResult exposing (BasicResult)
|
||||
import Api.Model.NotificationSettings exposing (NotificationSettings)
|
||||
import Api.Model.NotificationSettingsList exposing (NotificationSettingsList)
|
||||
import Comp.ChannelMenu
|
||||
import Comp.DueItemsTaskForm
|
||||
import Comp.DueItemsTaskList
|
||||
import Comp.MenuBar as MB
|
||||
import Comp.NotificationForm
|
||||
import Comp.NotificationList
|
||||
import Data.ChannelType exposing (ChannelType)
|
||||
import Data.Flags exposing (Flags)
|
||||
import Data.PeriodicDueItemsSettings exposing (PeriodicDueItemsSettings)
|
||||
import Data.UiSettings exposing (UiSettings)
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Http
|
||||
import Messages.Comp.NotificationManage exposing (Texts)
|
||||
import Messages.Comp.DueItemsTaskManage exposing (Texts)
|
||||
import Styles as S
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ listModel : Comp.NotificationList.Model
|
||||
, detailModel : Maybe Comp.NotificationForm.Model
|
||||
, items : List NotificationSettings
|
||||
{ listModel : Comp.DueItemsTaskList.Model
|
||||
, detailModel : Maybe Comp.DueItemsTaskForm.Model
|
||||
, items : List PeriodicDueItemsSettings
|
||||
, formState : FormState
|
||||
, channelMenuOpen : Bool
|
||||
}
|
||||
|
||||
|
||||
@ -52,19 +54,21 @@ type FormState
|
||||
|
||||
|
||||
type Msg
|
||||
= ListMsg Comp.NotificationList.Msg
|
||||
| DetailMsg Comp.NotificationForm.Msg
|
||||
| GetDataResp (Result Http.Error NotificationSettingsList)
|
||||
| NewTask
|
||||
= ListMsg Comp.DueItemsTaskList.Msg
|
||||
| DetailMsg Comp.DueItemsTaskForm.Msg
|
||||
| GetDataResp (Result Http.Error (List PeriodicDueItemsSettings))
|
||||
| NewTaskInit ChannelType
|
||||
| SubmitResp SubmitType (Result Http.Error BasicResult)
|
||||
| ToggleChannelMenu
|
||||
|
||||
|
||||
initModel : Model
|
||||
initModel =
|
||||
{ listModel = Comp.NotificationList.init
|
||||
{ listModel = Comp.DueItemsTaskList.init
|
||||
, detailModel = Nothing
|
||||
, items = []
|
||||
, formState = FormStateInitial
|
||||
, channelMenuOpen = False
|
||||
}
|
||||
|
||||
|
||||
@ -85,9 +89,14 @@ init flags =
|
||||
update : Flags -> Msg -> Model -> ( Model, Cmd Msg )
|
||||
update flags msg model =
|
||||
case msg of
|
||||
GetDataResp (Ok res) ->
|
||||
ToggleChannelMenu ->
|
||||
( { model | channelMenuOpen = not model.channelMenuOpen }
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
GetDataResp (Ok items) ->
|
||||
( { model
|
||||
| items = res.items
|
||||
| items = items
|
||||
, formState = FormStateInitial
|
||||
}
|
||||
, Cmd.none
|
||||
@ -101,17 +110,17 @@ update flags msg model =
|
||||
ListMsg lm ->
|
||||
let
|
||||
( mm, action ) =
|
||||
Comp.NotificationList.update lm model.listModel
|
||||
Comp.DueItemsTaskList.update lm model.listModel
|
||||
|
||||
( detail, cmd ) =
|
||||
case action of
|
||||
Comp.NotificationList.NoAction ->
|
||||
Comp.DueItemsTaskList.NoAction ->
|
||||
( Nothing, Cmd.none )
|
||||
|
||||
Comp.NotificationList.EditAction settings ->
|
||||
Comp.DueItemsTaskList.EditAction settings ->
|
||||
let
|
||||
( dm, dc ) =
|
||||
Comp.NotificationForm.initWith flags settings
|
||||
Comp.DueItemsTaskForm.initWith flags settings
|
||||
in
|
||||
( Just dm, Cmd.map DetailMsg dc )
|
||||
in
|
||||
@ -127,11 +136,11 @@ update flags msg model =
|
||||
Just dm ->
|
||||
let
|
||||
( mm, action, mc ) =
|
||||
Comp.NotificationForm.update flags lm dm
|
||||
Comp.DueItemsTaskForm.update flags lm dm
|
||||
|
||||
( model_, cmd_ ) =
|
||||
case action of
|
||||
Comp.NotificationForm.NoAction ->
|
||||
Comp.DueItemsTaskForm.NoAction ->
|
||||
( { model
|
||||
| detailModel = Just mm
|
||||
, formState = FormStateInitial
|
||||
@ -139,7 +148,7 @@ update flags msg model =
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
Comp.NotificationForm.SubmitAction settings ->
|
||||
Comp.DueItemsTaskForm.SubmitAction settings ->
|
||||
( { model
|
||||
| detailModel = Just mm
|
||||
, formState = FormStateInitial
|
||||
@ -151,7 +160,7 @@ update flags msg model =
|
||||
Api.updateNotifyDueItems flags settings (SubmitResp SubmitUpdate)
|
||||
)
|
||||
|
||||
Comp.NotificationForm.CancelAction ->
|
||||
Comp.DueItemsTaskForm.CancelAction ->
|
||||
( { model
|
||||
| detailModel = Nothing
|
||||
, formState = FormStateInitial
|
||||
@ -159,7 +168,7 @@ update flags msg model =
|
||||
, initCmd flags
|
||||
)
|
||||
|
||||
Comp.NotificationForm.StartOnceAction settings ->
|
||||
Comp.DueItemsTaskForm.StartOnceAction settings ->
|
||||
( { model
|
||||
| detailModel = Just mm
|
||||
, formState = FormStateInitial
|
||||
@ -167,7 +176,7 @@ update flags msg model =
|
||||
, Api.startOnceNotifyDueItems flags settings (SubmitResp SubmitStartOnce)
|
||||
)
|
||||
|
||||
Comp.NotificationForm.DeleteAction id ->
|
||||
Comp.DueItemsTaskForm.DeleteAction id ->
|
||||
( { model
|
||||
| detailModel = Just mm
|
||||
, formState = FormStateInitial
|
||||
@ -185,12 +194,12 @@ update flags msg model =
|
||||
Nothing ->
|
||||
( model, Cmd.none )
|
||||
|
||||
NewTask ->
|
||||
NewTaskInit ct ->
|
||||
let
|
||||
( mm, mc ) =
|
||||
Comp.NotificationForm.init flags
|
||||
Comp.DueItemsTaskForm.init flags ct
|
||||
in
|
||||
( { model | detailModel = Just mm }, Cmd.map DetailMsg mc )
|
||||
( { model | detailModel = Just mm, channelMenuOpen = False }, Cmd.map DetailMsg mc )
|
||||
|
||||
SubmitResp submitType (Ok res) ->
|
||||
( { model
|
||||
@ -277,29 +286,32 @@ isSuccess state =
|
||||
False
|
||||
|
||||
|
||||
viewForm2 : Texts -> UiSettings -> Comp.NotificationForm.Model -> List (Html Msg)
|
||||
viewForm2 : Texts -> UiSettings -> Comp.DueItemsTaskForm.Model -> List (Html Msg)
|
||||
viewForm2 texts settings model =
|
||||
[ Html.map DetailMsg
|
||||
(Comp.NotificationForm.view2 texts.notificationForm "flex flex-col" settings model)
|
||||
(Comp.DueItemsTaskForm.view2 texts.notificationForm "flex flex-col" settings model)
|
||||
]
|
||||
|
||||
|
||||
viewList2 : Texts -> Model -> List (Html Msg)
|
||||
viewList2 texts model =
|
||||
let
|
||||
menuModel =
|
||||
{ menuOpen = model.channelMenuOpen
|
||||
, toggleMenu = ToggleChannelMenu
|
||||
, menuLabel = texts.newTask
|
||||
, onItem = NewTaskInit
|
||||
}
|
||||
in
|
||||
[ MB.view
|
||||
{ start =
|
||||
[ MB.PrimaryButton
|
||||
{ tagger = NewTask
|
||||
, label = texts.newTask
|
||||
, icon = Just "fa fa-plus"
|
||||
, title = texts.createNewTask
|
||||
}
|
||||
{ start = []
|
||||
, end =
|
||||
[ Comp.ChannelMenu.channelMenu texts.channelType menuModel
|
||||
]
|
||||
, end = []
|
||||
, rootClasses = "mb-4"
|
||||
}
|
||||
, Html.map ListMsg
|
||||
(Comp.NotificationList.view2 texts.notificationTable
|
||||
(Comp.DueItemsTaskList.view2 texts.notificationTable
|
||||
model.listModel
|
||||
model.items
|
||||
)
|
182
modules/webapp/src/main/elm/Comp/EventSample.elm
Normal file
182
modules/webapp/src/main/elm/Comp/EventSample.elm
Normal file
@ -0,0 +1,182 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Comp.EventSample exposing (Model, Msg, init, initWith, update, viewJson, viewMessage)
|
||||
|
||||
import Api
|
||||
import Comp.FixedDropdown
|
||||
import Data.DropdownStyle as DS
|
||||
import Data.EventType exposing (EventType)
|
||||
import Data.Flags exposing (Flags)
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Http
|
||||
import Json.Decode as D
|
||||
import Json.Print
|
||||
import Markdown
|
||||
import Messages.Comp.EventSample exposing (Texts)
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ eventTypeDropdown : Comp.FixedDropdown.Model EventType
|
||||
, selectedEventType : Maybe EventType
|
||||
, content : String
|
||||
}
|
||||
|
||||
|
||||
init : Model
|
||||
init =
|
||||
{ eventTypeDropdown = Comp.FixedDropdown.init Data.EventType.all
|
||||
, selectedEventType = Nothing
|
||||
, content = ""
|
||||
}
|
||||
|
||||
|
||||
initWith : Flags -> EventType -> ( Model, Cmd Msg )
|
||||
initWith flags evt =
|
||||
( { init | selectedEventType = Just evt }
|
||||
, Api.sampleEvent flags evt SampleEvent
|
||||
)
|
||||
|
||||
|
||||
type Msg
|
||||
= EventTypeMsg (Comp.FixedDropdown.Msg EventType)
|
||||
| SampleEvent (Result Http.Error String)
|
||||
|
||||
|
||||
|
||||
--- Update
|
||||
|
||||
|
||||
update : Flags -> Msg -> Model -> ( Model, Cmd Msg )
|
||||
update flags msg model =
|
||||
case msg of
|
||||
EventTypeMsg lm ->
|
||||
let
|
||||
( evm, evt ) =
|
||||
Comp.FixedDropdown.update lm model.eventTypeDropdown
|
||||
|
||||
sampleCmd =
|
||||
case evt of
|
||||
Just ev ->
|
||||
Api.sampleEvent flags ev SampleEvent
|
||||
|
||||
Nothing ->
|
||||
Cmd.none
|
||||
in
|
||||
( { model
|
||||
| eventTypeDropdown = evm
|
||||
, selectedEventType = evt
|
||||
}
|
||||
, sampleCmd
|
||||
)
|
||||
|
||||
SampleEvent (Ok str) ->
|
||||
( { model | content = str }, Cmd.none )
|
||||
|
||||
SampleEvent (Err err) ->
|
||||
( model, Cmd.none )
|
||||
|
||||
|
||||
|
||||
--- View
|
||||
|
||||
|
||||
styleBase : String
|
||||
styleBase =
|
||||
"bg-gray-100 dark:bg-bluegray-900 text-gray-900 dark:text-gray-100 text-sm leading-5"
|
||||
|
||||
|
||||
stylePayload : String
|
||||
stylePayload =
|
||||
"px-2 font-mono overflow-auto max-h-96 h-full whitespace-pre"
|
||||
|
||||
|
||||
styleMessage : String
|
||||
styleMessage =
|
||||
"-my-2 "
|
||||
|
||||
|
||||
jsonPrettyCfg =
|
||||
{ indent = 2
|
||||
, columns = 80
|
||||
}
|
||||
|
||||
|
||||
dropdownCfg texts =
|
||||
{ display = texts.eventType >> .name
|
||||
, icon = \_ -> Nothing
|
||||
, selectPlaceholder = texts.selectEvent
|
||||
, style = DS.mainStyleWith "w-48"
|
||||
}
|
||||
|
||||
|
||||
viewJson : Texts -> Model -> Html Msg
|
||||
viewJson texts model =
|
||||
let
|
||||
json =
|
||||
Result.withDefault ""
|
||||
(Json.Print.prettyString jsonPrettyCfg model.content)
|
||||
in
|
||||
div
|
||||
[ class "flex flex-col w-full relative"
|
||||
]
|
||||
[ div [ class "flex inline-flex items-center absolute top-2 right-4" ]
|
||||
[ Html.map EventTypeMsg
|
||||
(Comp.FixedDropdown.viewStyled2 (dropdownCfg texts)
|
||||
False
|
||||
model.selectedEventType
|
||||
model.eventTypeDropdown
|
||||
)
|
||||
]
|
||||
, div
|
||||
[ class "flex pt-5"
|
||||
, class styleBase
|
||||
, class stylePayload
|
||||
, classList [ ( "hidden", json == "" ) ]
|
||||
]
|
||||
[ text json
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
viewMessage : Texts -> Model -> Html Msg
|
||||
viewMessage texts model =
|
||||
let
|
||||
titleDecoder =
|
||||
D.at [ "message", "title" ] D.string
|
||||
|
||||
bodyDecoder =
|
||||
D.at [ "message", "body" ] D.string
|
||||
|
||||
title =
|
||||
D.decodeString titleDecoder model.content
|
||||
|
||||
body =
|
||||
D.decodeString bodyDecoder model.content
|
||||
in
|
||||
div
|
||||
[ class "flex flex-col w-full relative"
|
||||
]
|
||||
[ div [ class "flex inline-flex items-center absolute top-2 right-4" ]
|
||||
[ Html.map EventTypeMsg
|
||||
(Comp.FixedDropdown.viewStyled2 (dropdownCfg texts)
|
||||
False
|
||||
model.selectedEventType
|
||||
model.eventTypeDropdown
|
||||
)
|
||||
]
|
||||
, div
|
||||
[ class "flex flex-col py-5 px-2 markdown-preview"
|
||||
, class styleBase
|
||||
]
|
||||
[ Markdown.toHtml [ class styleMessage ]
|
||||
(Result.withDefault "" title)
|
||||
, Markdown.toHtml [ class styleMessage ]
|
||||
(Result.withDefault "" body)
|
||||
]
|
||||
]
|
@ -217,6 +217,7 @@ attachHeader texts settings model _ attach =
|
||||
, MB.viewItem <|
|
||||
MB.Dropdown
|
||||
{ linkIcon = "fa fa-bars"
|
||||
, label = ""
|
||||
, linkClass =
|
||||
[ ( "ml-2", True )
|
||||
, ( S.secondaryBasicButton, True )
|
||||
@ -225,21 +226,21 @@ attachHeader texts settings model _ attach =
|
||||
, toggleMenu = ToggleAttachmentDropdown
|
||||
, menuOpen = model.attachmentDropdownOpen
|
||||
, items =
|
||||
[ { icon = "fa fa-download"
|
||||
[ { icon = i [ class "fa fa-download" ] []
|
||||
, label = texts.downloadFile
|
||||
, attrs =
|
||||
[ download attachName
|
||||
, href fileUrl
|
||||
]
|
||||
}
|
||||
, { icon = "fa fa-file"
|
||||
, { icon = i [ class "fa fa-file" ] []
|
||||
, label = texts.renameFile
|
||||
, attrs =
|
||||
[ href "#"
|
||||
, onClick (EditAttachNameStart attach.id)
|
||||
]
|
||||
}
|
||||
, { icon = "fa fa-file-archive"
|
||||
, { icon = i [ class "fa fa-file-archive" ] []
|
||||
, label = texts.downloadOriginalArchiveFile
|
||||
, attrs =
|
||||
[ href (fileUrl ++ "/archive")
|
||||
@ -247,7 +248,7 @@ attachHeader texts settings model _ attach =
|
||||
, classList [ ( "hidden", not hasArchive ) ]
|
||||
]
|
||||
}
|
||||
, { icon = "fa fa-external-link-alt"
|
||||
, { icon = i [ class "fa fa-external-link-alt" ] []
|
||||
, label = texts.originalFile
|
||||
, attrs =
|
||||
[ href (fileUrl ++ "/original")
|
||||
@ -257,31 +258,31 @@ attachHeader texts settings model _ attach =
|
||||
}
|
||||
, { icon =
|
||||
if isAttachMetaOpen model attach.id then
|
||||
"fa fa-toggle-on"
|
||||
i [ class "fa fa-toggle-on" ] []
|
||||
|
||||
else
|
||||
"fa fa-toggle-off"
|
||||
i [ class "fa fa-toggle-off" ] []
|
||||
, label = texts.viewExtractedData
|
||||
, attrs =
|
||||
[ onClick (AttachMetaClick attach.id)
|
||||
, href "#"
|
||||
]
|
||||
}
|
||||
, { icon = "fa fa-redo-alt"
|
||||
, { icon = i [ class "fa fa-redo-alt" ] []
|
||||
, label = texts.reprocessFile
|
||||
, attrs =
|
||||
[ onClick (RequestReprocessFile attach.id)
|
||||
, href "#"
|
||||
]
|
||||
}
|
||||
, { icon = Icons.showQr
|
||||
, { icon = i [ class Icons.showQr ] []
|
||||
, label = texts.showQrCode
|
||||
, attrs =
|
||||
[ onClick (ToggleShowQrAttach attach.id)
|
||||
, href "#"
|
||||
]
|
||||
}
|
||||
, { icon = "fa fa-trash"
|
||||
, { icon = i [ class "fa fa-trash" ] []
|
||||
, label = texts.deleteThisFile
|
||||
, attrs =
|
||||
[ onClick (RequestDeleteAttachment attach.id)
|
||||
|
@ -8,6 +8,7 @@
|
||||
module Comp.MenuBar exposing
|
||||
( ButtonData
|
||||
, CheckboxData
|
||||
, DropdownMenu
|
||||
, Item(..)
|
||||
, MenuBar
|
||||
, TextInputData
|
||||
@ -85,6 +86,7 @@ type alias LabelData =
|
||||
type alias DropdownData msg =
|
||||
{ linkIcon : String
|
||||
, linkClass : List ( String, Bool )
|
||||
, label : String
|
||||
, toggleMenu : msg
|
||||
, menuOpen : Bool
|
||||
, items : List (DropdownMenu msg)
|
||||
@ -92,7 +94,7 @@ type alias DropdownData msg =
|
||||
|
||||
|
||||
type alias DropdownMenu msg =
|
||||
{ icon : String
|
||||
{ icon : Html msg
|
||||
, label : String
|
||||
, attrs : List (Attribute msg)
|
||||
}
|
||||
@ -175,11 +177,7 @@ makeDropdown model =
|
||||
menuItem m =
|
||||
a
|
||||
(class itemStyle :: m.attrs)
|
||||
[ i
|
||||
[ class m.icon
|
||||
, classList [ ( "hidden", m.icon == "" ) ]
|
||||
]
|
||||
[]
|
||||
[ m.icon
|
||||
, span
|
||||
[ class "ml-2"
|
||||
, classList [ ( "hidden", m.label == "" ) ]
|
||||
@ -196,6 +194,13 @@ makeDropdown model =
|
||||
, onClick model.toggleMenu
|
||||
]
|
||||
[ i [ class model.linkIcon ] []
|
||||
, if model.label == "" then
|
||||
span [ class "hidden" ] []
|
||||
|
||||
else
|
||||
span [ class "ml-2" ]
|
||||
[ text model.label
|
||||
]
|
||||
]
|
||||
, div
|
||||
[ class menuStyle
|
||||
|
117
modules/webapp/src/main/elm/Comp/NotificationGotifyForm.elm
Normal file
117
modules/webapp/src/main/elm/Comp/NotificationGotifyForm.elm
Normal file
@ -0,0 +1,117 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Comp.NotificationGotifyForm exposing (Model, Msg, init, initWith, update, view)
|
||||
|
||||
import Api.Model.NotificationGotify exposing (NotificationGotify)
|
||||
import Comp.Basic as B
|
||||
import Data.NotificationChannel
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onInput)
|
||||
import Messages.Comp.NotificationGotifyForm exposing (Texts)
|
||||
import Styles as S
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ hook : NotificationGotify
|
||||
}
|
||||
|
||||
|
||||
init : Model
|
||||
init =
|
||||
{ hook = Data.NotificationChannel.setTypeGotify Api.Model.NotificationGotify.empty
|
||||
}
|
||||
|
||||
|
||||
initWith : NotificationGotify -> Model
|
||||
initWith hook =
|
||||
{ hook = Data.NotificationChannel.setTypeGotify hook
|
||||
}
|
||||
|
||||
|
||||
type Msg
|
||||
= SetUrl String
|
||||
| SetAppKey String
|
||||
|
||||
|
||||
|
||||
--- Update
|
||||
|
||||
|
||||
update : Msg -> Model -> ( Model, Maybe NotificationGotify )
|
||||
update msg model =
|
||||
let
|
||||
newHook =
|
||||
updateHook msg model.hook
|
||||
in
|
||||
( { model | hook = newHook }, check newHook )
|
||||
|
||||
|
||||
check : NotificationGotify -> Maybe NotificationGotify
|
||||
check hook =
|
||||
Just hook
|
||||
|
||||
|
||||
updateHook : Msg -> NotificationGotify -> NotificationGotify
|
||||
updateHook msg hook =
|
||||
case msg of
|
||||
SetUrl s ->
|
||||
{ hook | url = s }
|
||||
|
||||
SetAppKey s ->
|
||||
{ hook | appKey = s }
|
||||
|
||||
|
||||
|
||||
--- View
|
||||
|
||||
|
||||
view : Texts -> Model -> Html Msg
|
||||
view texts model =
|
||||
div []
|
||||
[ div
|
||||
[ class "mb-2"
|
||||
]
|
||||
[ label
|
||||
[ for "gotifyurl"
|
||||
, class S.inputLabel
|
||||
]
|
||||
[ text texts.gotifyUrl
|
||||
, B.inputRequired
|
||||
]
|
||||
, input
|
||||
[ type_ "text"
|
||||
, onInput SetUrl
|
||||
, placeholder texts.gotifyUrl
|
||||
, value model.hook.url
|
||||
, name "gotifyurl"
|
||||
, class S.textInput
|
||||
]
|
||||
[]
|
||||
]
|
||||
, div
|
||||
[ class "mb-2"
|
||||
]
|
||||
[ label
|
||||
[ for "appkey"
|
||||
, class S.inputLabel
|
||||
]
|
||||
[ text texts.appKey
|
||||
, B.inputRequired
|
||||
]
|
||||
, input
|
||||
[ type_ "text"
|
||||
, onInput SetAppKey
|
||||
, placeholder texts.appKey
|
||||
, value model.hook.appKey
|
||||
, name "appkey"
|
||||
, class S.textInput
|
||||
]
|
||||
[]
|
||||
]
|
||||
]
|
317
modules/webapp/src/main/elm/Comp/NotificationHookForm.elm
Normal file
317
modules/webapp/src/main/elm/Comp/NotificationHookForm.elm
Normal file
@ -0,0 +1,317 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Comp.NotificationHookForm exposing
|
||||
( Model
|
||||
, Msg(..)
|
||||
, channelType
|
||||
, getHook
|
||||
, init
|
||||
, initWith
|
||||
, update
|
||||
, view
|
||||
)
|
||||
|
||||
import Comp.Basic as B
|
||||
import Comp.ChannelForm
|
||||
import Comp.Dropdown
|
||||
import Comp.EventSample
|
||||
import Comp.MenuBar as MB
|
||||
import Comp.NotificationTest
|
||||
import Data.ChannelType exposing (ChannelType)
|
||||
import Data.DropdownStyle as DS
|
||||
import Data.EventType exposing (EventType)
|
||||
import Data.Flags exposing (Flags)
|
||||
import Data.NotificationHook exposing (NotificationHook)
|
||||
import Data.UiSettings exposing (UiSettings)
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onInput)
|
||||
import Messages.Comp.NotificationHookForm exposing (Texts)
|
||||
import Styles as S
|
||||
import Util.Maybe
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ hook : NotificationHook
|
||||
, enabled : Bool
|
||||
, channelModel : Comp.ChannelForm.Model
|
||||
, eventsDropdown : Comp.Dropdown.Model EventType
|
||||
, eventSampleModel : Comp.EventSample.Model
|
||||
, testDeliveryModel : Comp.NotificationTest.Model
|
||||
, allEvents : Bool
|
||||
, eventFilter : Maybe String
|
||||
}
|
||||
|
||||
|
||||
init : Flags -> ChannelType -> ( Model, Cmd Msg )
|
||||
init flags ct =
|
||||
let
|
||||
( cm, cc ) =
|
||||
Comp.ChannelForm.init flags ct
|
||||
|
||||
( esm, esc ) =
|
||||
Comp.EventSample.initWith flags Data.EventType.TagsChanged
|
||||
in
|
||||
( { hook = Data.NotificationHook.empty ct
|
||||
, enabled = True
|
||||
, channelModel = cm
|
||||
, eventsDropdown =
|
||||
Comp.Dropdown.makeMultipleList
|
||||
{ options = Data.EventType.all
|
||||
, selected = []
|
||||
}
|
||||
, eventSampleModel = esm
|
||||
, testDeliveryModel = Comp.NotificationTest.init
|
||||
, allEvents = False
|
||||
, eventFilter = Nothing
|
||||
}
|
||||
, Cmd.batch
|
||||
[ Cmd.map ChannelFormMsg cc
|
||||
, Cmd.map EventSampleMsg esc
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
initWith : Flags -> NotificationHook -> ( Model, Cmd Msg )
|
||||
initWith flags h =
|
||||
let
|
||||
( cm, cc ) =
|
||||
Comp.ChannelForm.initWith flags h.channel
|
||||
|
||||
( esm, esc ) =
|
||||
Comp.EventSample.initWith flags Data.EventType.TagsChanged
|
||||
in
|
||||
( { hook = h
|
||||
, enabled = h.enabled
|
||||
, channelModel = cm
|
||||
, eventsDropdown =
|
||||
Comp.Dropdown.makeMultipleList
|
||||
{ options = Data.EventType.all
|
||||
, selected = h.events
|
||||
}
|
||||
, eventSampleModel = esm
|
||||
, testDeliveryModel = Comp.NotificationTest.init
|
||||
, allEvents = h.allEvents
|
||||
, eventFilter = h.eventFilter
|
||||
}
|
||||
, Cmd.batch
|
||||
[ Cmd.map ChannelFormMsg cc
|
||||
, Cmd.map EventSampleMsg esc
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
channelType : Model -> ChannelType
|
||||
channelType model =
|
||||
Comp.ChannelForm.channelType model.channelModel
|
||||
|
||||
|
||||
getHook : Model -> Maybe NotificationHook
|
||||
getHook model =
|
||||
let
|
||||
events =
|
||||
let
|
||||
ev =
|
||||
Comp.Dropdown.getSelected model.eventsDropdown
|
||||
in
|
||||
if List.isEmpty ev && not model.allEvents then
|
||||
Nothing
|
||||
|
||||
else
|
||||
Just ev
|
||||
|
||||
channel =
|
||||
Comp.ChannelForm.getChannel model.channelModel
|
||||
|
||||
mkHook ev ch =
|
||||
NotificationHook model.hook.id model.enabled ch model.allEvents model.eventFilter ev
|
||||
in
|
||||
Maybe.map2 mkHook events channel
|
||||
|
||||
|
||||
type Msg
|
||||
= ToggleEnabled
|
||||
| ChannelFormMsg Comp.ChannelForm.Msg
|
||||
| EventMsg (Comp.Dropdown.Msg EventType)
|
||||
| EventSampleMsg Comp.EventSample.Msg
|
||||
| DeliveryTestMsg Comp.NotificationTest.Msg
|
||||
| ToggleAllEvents
|
||||
| SetEventFilter String
|
||||
|
||||
|
||||
update : Flags -> Msg -> Model -> ( Model, Cmd Msg )
|
||||
update flags msg model =
|
||||
case msg of
|
||||
SetEventFilter str ->
|
||||
( { model | eventFilter = Util.Maybe.fromString str }, Cmd.none )
|
||||
|
||||
ToggleAllEvents ->
|
||||
( { model | allEvents = not model.allEvents }
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
ToggleEnabled ->
|
||||
( { model | enabled = not model.enabled }
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
ChannelFormMsg lm ->
|
||||
let
|
||||
( cm, cc ) =
|
||||
Comp.ChannelForm.update flags lm model.channelModel
|
||||
in
|
||||
( { model | channelModel = cm }, Cmd.map ChannelFormMsg cc )
|
||||
|
||||
EventMsg lm ->
|
||||
if model.allEvents then
|
||||
( model, Cmd.none )
|
||||
|
||||
else
|
||||
let
|
||||
( em, ec ) =
|
||||
Comp.Dropdown.update lm model.eventsDropdown
|
||||
in
|
||||
( { model | eventsDropdown = em }, Cmd.map EventMsg ec )
|
||||
|
||||
EventSampleMsg lm ->
|
||||
let
|
||||
( esm, esc ) =
|
||||
Comp.EventSample.update flags lm model.eventSampleModel
|
||||
in
|
||||
( { model | eventSampleModel = esm }, Cmd.map EventSampleMsg esc )
|
||||
|
||||
DeliveryTestMsg lm ->
|
||||
case getHook model of
|
||||
Just hook ->
|
||||
let
|
||||
( ntm, ntc ) =
|
||||
Comp.NotificationTest.update flags hook lm model.testDeliveryModel
|
||||
in
|
||||
( { model | testDeliveryModel = ntm }, Cmd.map DeliveryTestMsg ntc )
|
||||
|
||||
Nothing ->
|
||||
( model, Cmd.none )
|
||||
|
||||
|
||||
|
||||
--- View
|
||||
|
||||
|
||||
view : Texts -> UiSettings -> Model -> Html Msg
|
||||
view texts settings model =
|
||||
let
|
||||
connectionCfg =
|
||||
{ makeOption = \a -> { text = (texts.eventType a).name, additional = (texts.eventType a).info }
|
||||
, placeholder = texts.selectEvents
|
||||
, labelColor = \_ -> \_ -> ""
|
||||
, style = DS.mainStyle
|
||||
}
|
||||
|
||||
formHeader txt =
|
||||
h2 [ class S.formHeader, class "mt-2" ]
|
||||
[ text txt
|
||||
]
|
||||
in
|
||||
div
|
||||
[ class "flex flex-col" ]
|
||||
[ div [ class "mb-4" ]
|
||||
[ MB.viewItem <|
|
||||
MB.Checkbox
|
||||
{ tagger = \_ -> ToggleEnabled
|
||||
, label = texts.enableDisable
|
||||
, value = model.enabled
|
||||
, id = "notify-enabled"
|
||||
}
|
||||
]
|
||||
, div [ class "mb-4" ]
|
||||
[ formHeader (texts.channelHeader (Comp.ChannelForm.channelType model.channelModel))
|
||||
, Html.map ChannelFormMsg
|
||||
(Comp.ChannelForm.view texts.channelForm settings model.channelModel)
|
||||
]
|
||||
, div [ class "mb-4" ]
|
||||
[ formHeader texts.events
|
||||
, MB.viewItem <|
|
||||
MB.Checkbox
|
||||
{ tagger = \_ -> ToggleAllEvents
|
||||
, label = texts.toggleAllEvents
|
||||
, value = model.allEvents
|
||||
, id = "notify-on-all-events"
|
||||
}
|
||||
]
|
||||
, div
|
||||
[ class "mb-4"
|
||||
, classList [ ( "disabled", model.allEvents ) ]
|
||||
]
|
||||
[ label [ class S.inputLabel ]
|
||||
[ text texts.events
|
||||
, B.inputRequired
|
||||
]
|
||||
, Html.map EventMsg
|
||||
(Comp.Dropdown.view2
|
||||
connectionCfg
|
||||
settings
|
||||
model.eventsDropdown
|
||||
)
|
||||
, span [ class "opacity-50 text-sm" ]
|
||||
[ text texts.eventsInfo
|
||||
]
|
||||
]
|
||||
, div [ class "mb-4" ]
|
||||
[ label [ class S.inputLabel ]
|
||||
[ text texts.eventFilter
|
||||
, a
|
||||
[ class "float-right"
|
||||
, class S.link
|
||||
, href "https://docspell.org/docs/jsonminiquery/"
|
||||
, target "_blank"
|
||||
]
|
||||
[ i [ class "fa fa-question" ] []
|
||||
, span [ class "pl-2" ]
|
||||
[ text texts.eventFilterClickForHelp
|
||||
]
|
||||
]
|
||||
]
|
||||
, input
|
||||
[ type_ "text"
|
||||
, onInput SetEventFilter
|
||||
, class S.textInput
|
||||
, Maybe.withDefault "" model.eventFilter
|
||||
|> value
|
||||
]
|
||||
[]
|
||||
, span [ class "opacity-50 text-sm" ]
|
||||
[ text texts.eventFilterInfo
|
||||
]
|
||||
]
|
||||
, div
|
||||
[ class "mt-4"
|
||||
, classList [ ( "hidden", channelType model /= Data.ChannelType.Http ) ]
|
||||
]
|
||||
[ h3 [ class S.header3 ]
|
||||
[ text texts.samplePayload
|
||||
]
|
||||
, Html.map EventSampleMsg
|
||||
(Comp.EventSample.viewJson texts.eventSample model.eventSampleModel)
|
||||
]
|
||||
, div
|
||||
[ class "mt-4"
|
||||
, classList [ ( "hidden", channelType model == Data.ChannelType.Http ) ]
|
||||
]
|
||||
[ formHeader texts.samplePayload
|
||||
, Html.map EventSampleMsg
|
||||
(Comp.EventSample.viewMessage texts.eventSample model.eventSampleModel)
|
||||
]
|
||||
, div [ class "mt-4" ]
|
||||
[ formHeader "Test Delviery"
|
||||
, Html.map DeliveryTestMsg
|
||||
(Comp.NotificationTest.view
|
||||
{ runDisabled = getHook model == Nothing }
|
||||
model.testDeliveryModel
|
||||
)
|
||||
]
|
||||
]
|
475
modules/webapp/src/main/elm/Comp/NotificationHookManage.elm
Normal file
475
modules/webapp/src/main/elm/Comp/NotificationHookManage.elm
Normal file
@ -0,0 +1,475 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Comp.NotificationHookManage exposing
|
||||
( Model
|
||||
, Msg
|
||||
, init
|
||||
, update
|
||||
, view
|
||||
)
|
||||
|
||||
import Api
|
||||
import Api.Model.BasicResult exposing (BasicResult)
|
||||
import Comp.Basic as B
|
||||
import Comp.ChannelMenu
|
||||
import Comp.MenuBar as MB
|
||||
import Comp.NotificationHookForm
|
||||
import Comp.NotificationHookTable
|
||||
import Data.ChannelType exposing (ChannelType)
|
||||
import Data.Flags exposing (Flags)
|
||||
import Data.NotificationHook exposing (NotificationHook)
|
||||
import Data.UiSettings exposing (UiSettings)
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onClick)
|
||||
import Http
|
||||
import Messages.Comp.NotificationHookManage exposing (Texts)
|
||||
import Styles as S
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ listModel : Comp.NotificationHookTable.Model
|
||||
, detailModel : Maybe Comp.NotificationHookForm.Model
|
||||
, items : List NotificationHook
|
||||
, deleteConfirm : DeleteConfirm
|
||||
, loading : Bool
|
||||
, formState : FormState
|
||||
, newHookMenuOpen : Bool
|
||||
, jsonFilterError : Maybe String
|
||||
}
|
||||
|
||||
|
||||
type DeleteConfirm
|
||||
= DeleteConfirmOff
|
||||
| DeleteConfirmOn
|
||||
|
||||
|
||||
type SubmitType
|
||||
= SubmitDelete
|
||||
| SubmitUpdate
|
||||
| SubmitCreate
|
||||
|
||||
|
||||
type FormState
|
||||
= FormStateInitial
|
||||
| FormErrorHttp Http.Error
|
||||
| FormSubmitSuccessful SubmitType
|
||||
| FormErrorSubmit String
|
||||
| FormErrorInvalid
|
||||
|
||||
|
||||
type Msg
|
||||
= TableMsg Comp.NotificationHookTable.Msg
|
||||
| DetailMsg Comp.NotificationHookForm.Msg
|
||||
| GetDataResp (Result Http.Error (List NotificationHook))
|
||||
| ToggleNewHookMenu
|
||||
| SubmitResp SubmitType (Result Http.Error BasicResult)
|
||||
| NewHookInit ChannelType
|
||||
| BackToTable
|
||||
| Submit
|
||||
| RequestDelete
|
||||
| CancelDelete
|
||||
| DeleteHookNow String
|
||||
| VerifyFilterResp NotificationHook (Result Http.Error BasicResult)
|
||||
|
||||
|
||||
initModel : Model
|
||||
initModel =
|
||||
{ listModel = Comp.NotificationHookTable.init
|
||||
, detailModel = Nothing
|
||||
, items = []
|
||||
, loading = False
|
||||
, formState = FormStateInitial
|
||||
, newHookMenuOpen = False
|
||||
, deleteConfirm = DeleteConfirmOff
|
||||
, jsonFilterError = Nothing
|
||||
}
|
||||
|
||||
|
||||
initCmd : Flags -> Cmd Msg
|
||||
initCmd flags =
|
||||
Api.getHooks flags GetDataResp
|
||||
|
||||
|
||||
init : Flags -> ( Model, Cmd Msg )
|
||||
init flags =
|
||||
( initModel, initCmd flags )
|
||||
|
||||
|
||||
|
||||
--- Update
|
||||
|
||||
|
||||
update : Flags -> Msg -> Model -> ( Model, Cmd Msg )
|
||||
update flags msg model =
|
||||
case msg of
|
||||
VerifyFilterResp hook (Ok res) ->
|
||||
if res.success then
|
||||
postHook flags hook model
|
||||
|
||||
else
|
||||
( { model
|
||||
| loading = False
|
||||
, formState = FormErrorInvalid
|
||||
, jsonFilterError = Just res.message
|
||||
}
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
VerifyFilterResp _ (Err err) ->
|
||||
( { model | formState = FormErrorHttp err }
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
GetDataResp (Ok res) ->
|
||||
( { model
|
||||
| items = res
|
||||
, formState = FormStateInitial
|
||||
}
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
GetDataResp (Err err) ->
|
||||
( { model | formState = FormErrorHttp err }
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
TableMsg lm ->
|
||||
let
|
||||
( mm, action ) =
|
||||
Comp.NotificationHookTable.update flags lm model.listModel
|
||||
|
||||
( detail, cmd ) =
|
||||
case action of
|
||||
Comp.NotificationHookTable.NoAction ->
|
||||
( Nothing, Cmd.none )
|
||||
|
||||
Comp.NotificationHookTable.EditAction hook ->
|
||||
let
|
||||
( dm, dc ) =
|
||||
Comp.NotificationHookForm.initWith flags hook
|
||||
in
|
||||
( Just dm, Cmd.map DetailMsg dc )
|
||||
in
|
||||
( { model
|
||||
| listModel = mm
|
||||
, detailModel = detail
|
||||
}
|
||||
, cmd
|
||||
)
|
||||
|
||||
DetailMsg lm ->
|
||||
case model.detailModel of
|
||||
Just dm ->
|
||||
let
|
||||
( mm, mc ) =
|
||||
Comp.NotificationHookForm.update flags lm dm
|
||||
in
|
||||
( { model | detailModel = Just mm }
|
||||
, Cmd.map DetailMsg mc
|
||||
)
|
||||
|
||||
Nothing ->
|
||||
( model, Cmd.none )
|
||||
|
||||
ToggleNewHookMenu ->
|
||||
( { model | newHookMenuOpen = not model.newHookMenuOpen }, Cmd.none )
|
||||
|
||||
SubmitResp submitType (Ok res) ->
|
||||
( { model
|
||||
| formState =
|
||||
if res.success then
|
||||
FormSubmitSuccessful submitType
|
||||
|
||||
else
|
||||
FormErrorSubmit res.message
|
||||
, detailModel =
|
||||
if submitType == SubmitDelete then
|
||||
Nothing
|
||||
|
||||
else
|
||||
model.detailModel
|
||||
, loading = False
|
||||
}
|
||||
, if submitType == SubmitDelete then
|
||||
initCmd flags
|
||||
|
||||
else
|
||||
Cmd.none
|
||||
)
|
||||
|
||||
SubmitResp _ (Err err) ->
|
||||
( { model | formState = FormErrorHttp err, loading = False }
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
NewHookInit ct ->
|
||||
let
|
||||
( mm, mc ) =
|
||||
Comp.NotificationHookForm.init flags ct
|
||||
in
|
||||
( { model | detailModel = Just mm, newHookMenuOpen = False }, Cmd.map DetailMsg mc )
|
||||
|
||||
BackToTable ->
|
||||
( { model | detailModel = Nothing }, initCmd flags )
|
||||
|
||||
Submit ->
|
||||
case model.detailModel of
|
||||
Just dm ->
|
||||
case Comp.NotificationHookForm.getHook dm of
|
||||
Just data ->
|
||||
case data.eventFilter of
|
||||
Nothing ->
|
||||
postHook flags data model
|
||||
|
||||
Just jf ->
|
||||
( { model | loading = True }, Api.verifyJsonFilter flags jf (VerifyFilterResp data) )
|
||||
|
||||
Nothing ->
|
||||
( { model | formState = FormErrorInvalid }, Cmd.none )
|
||||
|
||||
Nothing ->
|
||||
( model, Cmd.none )
|
||||
|
||||
RequestDelete ->
|
||||
( { model | deleteConfirm = DeleteConfirmOn }, Cmd.none )
|
||||
|
||||
CancelDelete ->
|
||||
( { model | deleteConfirm = DeleteConfirmOff }, Cmd.none )
|
||||
|
||||
DeleteHookNow id ->
|
||||
( { model | deleteConfirm = DeleteConfirmOff, loading = True }
|
||||
, Api.deleteHook flags id (SubmitResp SubmitDelete)
|
||||
)
|
||||
|
||||
|
||||
postHook : Flags -> NotificationHook -> Model -> ( Model, Cmd Msg )
|
||||
postHook flags hook model =
|
||||
if hook.id == "" then
|
||||
( { model | loading = True }, Api.createHook flags hook (SubmitResp SubmitCreate) )
|
||||
|
||||
else
|
||||
( { model | loading = True }, Api.updateHook flags hook (SubmitResp SubmitUpdate) )
|
||||
|
||||
|
||||
|
||||
--- View2
|
||||
|
||||
|
||||
view : Texts -> UiSettings -> Model -> Html Msg
|
||||
view texts settings model =
|
||||
div [ class "flex flex-col" ]
|
||||
(case model.detailModel of
|
||||
Just msett ->
|
||||
viewForm texts settings model msett
|
||||
|
||||
Nothing ->
|
||||
viewList texts model
|
||||
)
|
||||
|
||||
|
||||
viewState : Texts -> Model -> Html Msg
|
||||
viewState texts model =
|
||||
div
|
||||
[ classList
|
||||
[ ( S.errorMessage, model.formState /= FormStateInitial )
|
||||
, ( S.successMessage, isSuccess model.formState )
|
||||
, ( "hidden", model.formState == FormStateInitial )
|
||||
]
|
||||
, class "mb-2"
|
||||
]
|
||||
[ case model.formState of
|
||||
FormStateInitial ->
|
||||
text ""
|
||||
|
||||
FormSubmitSuccessful SubmitCreate ->
|
||||
text texts.hookCreated
|
||||
|
||||
FormSubmitSuccessful SubmitUpdate ->
|
||||
text texts.hookUpdated
|
||||
|
||||
FormSubmitSuccessful SubmitDelete ->
|
||||
text texts.hookDeleted
|
||||
|
||||
FormErrorSubmit m ->
|
||||
text m
|
||||
|
||||
FormErrorHttp err ->
|
||||
text (texts.httpError err)
|
||||
|
||||
FormErrorInvalid ->
|
||||
case model.jsonFilterError of
|
||||
Just m ->
|
||||
text (texts.invalidJsonFilter m)
|
||||
|
||||
Nothing ->
|
||||
text texts.formInvalid
|
||||
]
|
||||
|
||||
|
||||
isSuccess : FormState -> Bool
|
||||
isSuccess state =
|
||||
case state of
|
||||
FormSubmitSuccessful _ ->
|
||||
True
|
||||
|
||||
_ ->
|
||||
False
|
||||
|
||||
|
||||
viewForm : Texts -> UiSettings -> Model -> Comp.NotificationHookForm.Model -> List (Html Msg)
|
||||
viewForm texts settings outerModel model =
|
||||
let
|
||||
newHook =
|
||||
model.hook.id == ""
|
||||
|
||||
headline =
|
||||
case Comp.NotificationHookForm.channelType model of
|
||||
Data.ChannelType.Matrix ->
|
||||
span []
|
||||
[ text texts.integrate
|
||||
, a
|
||||
[ href "https://matrix.org"
|
||||
, target "_blank"
|
||||
, class S.link
|
||||
, class "mx-3"
|
||||
]
|
||||
[ i [ class "fa fa-external-link-alt mr-1" ] []
|
||||
, text "Matrix"
|
||||
]
|
||||
, text texts.intoDocspell
|
||||
]
|
||||
|
||||
Data.ChannelType.Mail ->
|
||||
span []
|
||||
[ text texts.notifyEmailInfo
|
||||
]
|
||||
|
||||
Data.ChannelType.Gotify ->
|
||||
span []
|
||||
[ text texts.integrate
|
||||
, a
|
||||
[ href "https://gotify.net"
|
||||
, target "_blank"
|
||||
, class S.link
|
||||
, class "mx-3"
|
||||
]
|
||||
[ i [ class "fa fa-external-link-alt mr-1" ] []
|
||||
, text "Gotify"
|
||||
]
|
||||
, text texts.intoDocspell
|
||||
]
|
||||
|
||||
Data.ChannelType.Http ->
|
||||
span []
|
||||
[ text texts.postRequestInfo
|
||||
]
|
||||
in
|
||||
[ h1 [ class S.header2 ]
|
||||
[ Data.ChannelType.icon (Comp.NotificationHookForm.channelType model) "w-8 h-8 inline-block mr-4"
|
||||
, if newHook then
|
||||
text texts.addWebhook
|
||||
|
||||
else
|
||||
text texts.updateWebhook
|
||||
]
|
||||
, div [ class "pt-2 pb-4 font-medium" ]
|
||||
[ headline
|
||||
]
|
||||
, MB.view
|
||||
{ start =
|
||||
[ MB.CustomElement <|
|
||||
B.primaryButton
|
||||
{ handler = onClick Submit
|
||||
, title = texts.basics.submitThisForm
|
||||
, icon = "fa fa-save"
|
||||
, label = texts.basics.submit
|
||||
, disabled = False
|
||||
, attrs = [ href "#" ]
|
||||
}
|
||||
, MB.SecondaryButton
|
||||
{ tagger = BackToTable
|
||||
, title = texts.basics.backToList
|
||||
, icon = Just "fa fa-arrow-left"
|
||||
, label = texts.basics.backToList
|
||||
}
|
||||
]
|
||||
, end =
|
||||
if not newHook then
|
||||
[ MB.DeleteButton
|
||||
{ tagger = RequestDelete
|
||||
, title = texts.deleteThisHook
|
||||
, icon = Just "fa fa-trash"
|
||||
, label = texts.basics.delete
|
||||
}
|
||||
]
|
||||
|
||||
else
|
||||
[]
|
||||
, rootClasses = "mb-4"
|
||||
}
|
||||
, div [ class "mt-2" ]
|
||||
[ viewState texts outerModel
|
||||
]
|
||||
, Html.map DetailMsg
|
||||
(Comp.NotificationHookForm.view texts.notificationForm settings model)
|
||||
, B.loadingDimmer
|
||||
{ active = outerModel.loading
|
||||
, label = texts.basics.loading
|
||||
}
|
||||
, B.contentDimmer
|
||||
(outerModel.deleteConfirm == DeleteConfirmOn)
|
||||
(div [ class "flex flex-col" ]
|
||||
[ div [ class "text-lg" ]
|
||||
[ i [ class "fa fa-info-circle mr-2" ] []
|
||||
, text texts.reallyDeleteHook
|
||||
]
|
||||
, div [ class "mt-4 flex flex-row items-center" ]
|
||||
[ B.deleteButton
|
||||
{ label = texts.basics.yes
|
||||
, icon = "fa fa-check"
|
||||
, disabled = False
|
||||
, handler = onClick (DeleteHookNow model.hook.id)
|
||||
, attrs = [ href "#" ]
|
||||
}
|
||||
, B.secondaryButton
|
||||
{ label = texts.basics.no
|
||||
, icon = "fa fa-times"
|
||||
, disabled = False
|
||||
, handler = onClick CancelDelete
|
||||
, attrs = [ href "#", class "ml-2" ]
|
||||
}
|
||||
]
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
viewList : Texts -> Model -> List (Html Msg)
|
||||
viewList texts model =
|
||||
let
|
||||
menuModel =
|
||||
{ menuOpen = model.newHookMenuOpen
|
||||
, toggleMenu = ToggleNewHookMenu
|
||||
, menuLabel = texts.newHook
|
||||
, onItem = NewHookInit
|
||||
}
|
||||
in
|
||||
[ MB.view
|
||||
{ start = []
|
||||
, end =
|
||||
[ Comp.ChannelMenu.channelMenu texts.channelType menuModel
|
||||
]
|
||||
, rootClasses = "mb-4"
|
||||
}
|
||||
, Html.map TableMsg
|
||||
(Comp.NotificationHookTable.view texts.notificationTable
|
||||
model.listModel
|
||||
model.items
|
||||
)
|
||||
]
|
106
modules/webapp/src/main/elm/Comp/NotificationHookTable.elm
Normal file
106
modules/webapp/src/main/elm/Comp/NotificationHookTable.elm
Normal file
@ -0,0 +1,106 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Comp.NotificationHookTable exposing
|
||||
( Action(..)
|
||||
, Model
|
||||
, Msg(..)
|
||||
, init
|
||||
, update
|
||||
, view
|
||||
)
|
||||
|
||||
import Comp.Basic as B
|
||||
import Data.ChannelType
|
||||
import Data.EventType
|
||||
import Data.Flags exposing (Flags)
|
||||
import Data.NotificationChannel
|
||||
import Data.NotificationHook exposing (NotificationHook)
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onClick)
|
||||
import Messages.Comp.NotificationHookTable exposing (Texts)
|
||||
import Styles as S
|
||||
import Util.Html
|
||||
|
||||
|
||||
type alias Model =
|
||||
{}
|
||||
|
||||
|
||||
type Action
|
||||
= NoAction
|
||||
| EditAction NotificationHook
|
||||
|
||||
|
||||
init : Model
|
||||
init =
|
||||
{}
|
||||
|
||||
|
||||
type Msg
|
||||
= Select NotificationHook
|
||||
|
||||
|
||||
update : Flags -> Msg -> Model -> ( Model, Action )
|
||||
update _ msg model =
|
||||
case msg of
|
||||
Select hook ->
|
||||
( model, EditAction hook )
|
||||
|
||||
|
||||
|
||||
--- View
|
||||
|
||||
|
||||
view : Texts -> Model -> List NotificationHook -> Html Msg
|
||||
view texts model hooks =
|
||||
table [ class S.tableMain ]
|
||||
[ thead []
|
||||
[ tr []
|
||||
[ th [ class "" ] []
|
||||
, th [ class "text-center mr-2" ]
|
||||
[ i [ class "fa fa-check" ] []
|
||||
]
|
||||
, th [ class "text-left" ]
|
||||
[ text texts.channel
|
||||
]
|
||||
, th [ class "text-left hidden sm:table-cell" ]
|
||||
[ text texts.events
|
||||
]
|
||||
]
|
||||
]
|
||||
, tbody []
|
||||
(List.map (renderNotificationHookLine texts model) hooks)
|
||||
]
|
||||
|
||||
|
||||
renderNotificationHookLine : Texts -> Model -> NotificationHook -> Html Msg
|
||||
renderNotificationHookLine texts model hook =
|
||||
let
|
||||
eventName =
|
||||
texts.eventType >> .name
|
||||
in
|
||||
tr
|
||||
[ class S.tableRow
|
||||
]
|
||||
[ B.editLinkTableCell texts.basics.edit (Select hook)
|
||||
, td [ class "w-px whitespace-nowrap px-2 text-center" ]
|
||||
[ Util.Html.checkbox2 hook.enabled
|
||||
]
|
||||
, td [ class "text-left py-4 md:py-2" ]
|
||||
[ Data.NotificationChannel.channelType hook.channel
|
||||
|> Maybe.map Data.ChannelType.asString
|
||||
|> Maybe.withDefault "-"
|
||||
|> text
|
||||
]
|
||||
, td [ class "text-left hidden sm:table-cell" ]
|
||||
[ List.map eventName hook.events
|
||||
|> String.join ", "
|
||||
|> text
|
||||
]
|
||||
]
|
99
modules/webapp/src/main/elm/Comp/NotificationHttpForm.elm
Normal file
99
modules/webapp/src/main/elm/Comp/NotificationHttpForm.elm
Normal file
@ -0,0 +1,99 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Comp.NotificationHttpForm exposing (Model, Msg, init, initWith, update, view)
|
||||
|
||||
import Api.Model.NotificationHttp exposing (NotificationHttp)
|
||||
import Comp.Basic as B
|
||||
import Data.NotificationChannel
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onInput)
|
||||
import Messages.Comp.NotificationHttpForm exposing (Texts)
|
||||
import Styles as S
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ hook : NotificationHttp
|
||||
}
|
||||
|
||||
|
||||
init : Model
|
||||
init =
|
||||
{ hook =
|
||||
Data.NotificationChannel.setTypeHttp
|
||||
Api.Model.NotificationHttp.empty
|
||||
}
|
||||
|
||||
|
||||
initWith : NotificationHttp -> Model
|
||||
initWith hook =
|
||||
{ hook = Data.NotificationChannel.setTypeHttp hook
|
||||
}
|
||||
|
||||
|
||||
type Msg
|
||||
= SetUrl String
|
||||
|
||||
|
||||
|
||||
--- Update
|
||||
|
||||
|
||||
update : Msg -> Model -> ( Model, Maybe NotificationHttp )
|
||||
update msg model =
|
||||
let
|
||||
newHook =
|
||||
updateHook msg model.hook
|
||||
in
|
||||
( { model | hook = newHook }, check newHook )
|
||||
|
||||
|
||||
check : NotificationHttp -> Maybe NotificationHttp
|
||||
check hook =
|
||||
if hook.url == "" then
|
||||
Nothing
|
||||
|
||||
else
|
||||
Just hook
|
||||
|
||||
|
||||
updateHook : Msg -> NotificationHttp -> NotificationHttp
|
||||
updateHook msg hook =
|
||||
case msg of
|
||||
SetUrl s ->
|
||||
{ hook | url = s }
|
||||
|
||||
|
||||
|
||||
--- View
|
||||
|
||||
|
||||
view : Texts -> Model -> Html Msg
|
||||
view texts model =
|
||||
div []
|
||||
[ div
|
||||
[ class "mb-2"
|
||||
]
|
||||
[ label
|
||||
[ for "httpurl"
|
||||
, class S.inputLabel
|
||||
]
|
||||
[ text texts.httpUrl
|
||||
, B.inputRequired
|
||||
]
|
||||
, input
|
||||
[ type_ "text"
|
||||
, onInput SetUrl
|
||||
, placeholder texts.httpUrl
|
||||
, value model.hook.url
|
||||
, name "httpurl"
|
||||
, class S.textInput
|
||||
]
|
||||
[]
|
||||
]
|
||||
]
|
236
modules/webapp/src/main/elm/Comp/NotificationMailForm.elm
Normal file
236
modules/webapp/src/main/elm/Comp/NotificationMailForm.elm
Normal file
@ -0,0 +1,236 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Comp.NotificationMailForm exposing (Model, Msg, init, initWith, update, view)
|
||||
|
||||
import Api
|
||||
import Api.Model.EmailSettingsList exposing (EmailSettingsList)
|
||||
import Api.Model.NotificationMail exposing (NotificationMail)
|
||||
import Comp.Basic as B
|
||||
import Comp.Dropdown
|
||||
import Comp.EmailInput
|
||||
import Data.DropdownStyle as DS
|
||||
import Data.Flags exposing (Flags)
|
||||
import Data.NotificationChannel
|
||||
import Data.UiSettings exposing (UiSettings)
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onInput)
|
||||
import Http
|
||||
import Messages.Comp.NotificationMailForm exposing (Texts)
|
||||
import Styles as S
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ hook : NotificationMail
|
||||
, connectionModel : Comp.Dropdown.Model String
|
||||
, recipients : List String
|
||||
, recipientsModel : Comp.EmailInput.Model
|
||||
, formState : FormState
|
||||
}
|
||||
|
||||
|
||||
type FormState
|
||||
= FormStateInitial
|
||||
| FormStateHttpError Http.Error
|
||||
| FormStateInvalid ValidateError
|
||||
|
||||
|
||||
type ValidateError
|
||||
= ValidateConnectionMissing
|
||||
|
||||
|
||||
init : Flags -> ( Model, Cmd Msg )
|
||||
init flags =
|
||||
( { hook = Data.NotificationChannel.setTypeMail Api.Model.NotificationMail.empty
|
||||
, connectionModel = Comp.Dropdown.makeSingle
|
||||
, recipients = []
|
||||
, recipientsModel = Comp.EmailInput.init
|
||||
, formState = FormStateInitial
|
||||
}
|
||||
, Cmd.batch
|
||||
[ Api.getMailSettings flags "" ConnResp
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
initWith : Flags -> NotificationMail -> ( Model, Cmd Msg )
|
||||
initWith flags hook =
|
||||
let
|
||||
( mm, mc ) =
|
||||
init flags
|
||||
|
||||
( cm, _ ) =
|
||||
Comp.Dropdown.update (Comp.Dropdown.SetSelection [ hook.connection ]) mm.connectionModel
|
||||
in
|
||||
( { mm
|
||||
| hook = Data.NotificationChannel.setTypeMail hook
|
||||
, recipients = hook.recipients
|
||||
, connectionModel = cm
|
||||
}
|
||||
, mc
|
||||
)
|
||||
|
||||
|
||||
type Msg
|
||||
= ConnResp (Result Http.Error EmailSettingsList)
|
||||
| ConnMsg (Comp.Dropdown.Msg String)
|
||||
| RecipientMsg Comp.EmailInput.Msg
|
||||
|
||||
|
||||
|
||||
--- Update
|
||||
|
||||
|
||||
check : Model -> Maybe NotificationMail
|
||||
check model =
|
||||
let
|
||||
formState =
|
||||
if model.formState == FormStateInitial then
|
||||
Just ()
|
||||
|
||||
else
|
||||
Nothing
|
||||
|
||||
recipients =
|
||||
if List.isEmpty model.recipients then
|
||||
Nothing
|
||||
|
||||
else
|
||||
Just model.recipients
|
||||
|
||||
connection =
|
||||
Comp.Dropdown.getSelected model.connectionModel
|
||||
|> List.head
|
||||
|
||||
h =
|
||||
model.hook
|
||||
|
||||
makeHook _ rec conn =
|
||||
{ h | connection = conn, recipients = rec }
|
||||
in
|
||||
Maybe.map3 makeHook formState recipients connection
|
||||
|
||||
|
||||
update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Maybe NotificationMail )
|
||||
update flags msg model =
|
||||
case msg of
|
||||
ConnResp (Ok list) ->
|
||||
let
|
||||
names =
|
||||
List.map .name list.items
|
||||
|
||||
cm =
|
||||
Comp.Dropdown.makeSingleList
|
||||
{ options = names
|
||||
, selected = List.head names
|
||||
}
|
||||
|
||||
model_ =
|
||||
{ model
|
||||
| connectionModel = cm
|
||||
, formState =
|
||||
if names == [] then
|
||||
FormStateInvalid ValidateConnectionMissing
|
||||
|
||||
else
|
||||
FormStateInitial
|
||||
}
|
||||
in
|
||||
( model_
|
||||
, Cmd.none
|
||||
, check model_
|
||||
)
|
||||
|
||||
ConnResp (Err err) ->
|
||||
( { model | formState = FormStateHttpError err }
|
||||
, Cmd.none
|
||||
, Nothing
|
||||
)
|
||||
|
||||
ConnMsg lm ->
|
||||
let
|
||||
( cm, cc ) =
|
||||
Comp.Dropdown.update lm model.connectionModel
|
||||
|
||||
model_ =
|
||||
{ model
|
||||
| connectionModel = cm
|
||||
, formState = FormStateInitial
|
||||
}
|
||||
in
|
||||
( model_
|
||||
, Cmd.map ConnMsg cc
|
||||
, check model_
|
||||
)
|
||||
|
||||
RecipientMsg lm ->
|
||||
let
|
||||
( em, ec, rec ) =
|
||||
Comp.EmailInput.update flags model.recipients lm model.recipientsModel
|
||||
|
||||
model_ =
|
||||
{ model
|
||||
| recipients = rec
|
||||
, recipientsModel = em
|
||||
, formState = FormStateInitial
|
||||
}
|
||||
in
|
||||
( model_
|
||||
, Cmd.map RecipientMsg ec
|
||||
, check model_
|
||||
)
|
||||
|
||||
|
||||
|
||||
--- View
|
||||
|
||||
|
||||
view : Texts -> UiSettings -> Model -> Html Msg
|
||||
view texts settings model =
|
||||
let
|
||||
connectionCfg =
|
||||
{ makeOption = \a -> { text = a, additional = "" }
|
||||
, placeholder = texts.selectConnection
|
||||
, labelColor = \_ -> \_ -> ""
|
||||
, style = DS.mainStyle
|
||||
}
|
||||
in
|
||||
div []
|
||||
[ div [ class "mb-4" ]
|
||||
[ label [ class S.inputLabel ]
|
||||
[ text texts.sendVia
|
||||
, B.inputRequired
|
||||
]
|
||||
, Html.map ConnMsg
|
||||
(Comp.Dropdown.view2
|
||||
connectionCfg
|
||||
settings
|
||||
model.connectionModel
|
||||
)
|
||||
, span [ class "opacity-50 text-sm" ]
|
||||
[ text texts.sendViaInfo
|
||||
]
|
||||
]
|
||||
, div [ class "" ]
|
||||
[ label
|
||||
[ class S.inputLabel
|
||||
]
|
||||
[ text texts.recipients
|
||||
, B.inputRequired
|
||||
]
|
||||
, Html.map RecipientMsg
|
||||
(Comp.EmailInput.view2
|
||||
{ style = DS.mainStyle, placeholder = texts.recipients }
|
||||
model.recipients
|
||||
model.recipientsModel
|
||||
)
|
||||
, span [ class "opacity-50 text-sm" ]
|
||||
[ text texts.recipientsInfo
|
||||
]
|
||||
]
|
||||
]
|
140
modules/webapp/src/main/elm/Comp/NotificationMatrixForm.elm
Normal file
140
modules/webapp/src/main/elm/Comp/NotificationMatrixForm.elm
Normal file
@ -0,0 +1,140 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Comp.NotificationMatrixForm exposing (Model, Msg, init, initWith, update, view)
|
||||
|
||||
import Api.Model.NotificationMatrix exposing (NotificationMatrix)
|
||||
import Comp.Basic as B
|
||||
import Data.NotificationChannel
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onInput)
|
||||
import Messages.Comp.NotificationMatrixForm exposing (Texts)
|
||||
import Styles as S
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ hook : NotificationMatrix
|
||||
}
|
||||
|
||||
|
||||
init : Model
|
||||
init =
|
||||
{ hook = Data.NotificationChannel.setTypeMatrix Api.Model.NotificationMatrix.empty
|
||||
}
|
||||
|
||||
|
||||
initWith : NotificationMatrix -> Model
|
||||
initWith hook =
|
||||
{ hook = Data.NotificationChannel.setTypeMatrix hook
|
||||
}
|
||||
|
||||
|
||||
type Msg
|
||||
= SetHomeServer String
|
||||
| SetRoomId String
|
||||
| SetAccessKey String
|
||||
|
||||
|
||||
|
||||
--- Update
|
||||
|
||||
|
||||
update : Msg -> Model -> ( Model, Maybe NotificationMatrix )
|
||||
update msg model =
|
||||
let
|
||||
newHook =
|
||||
updateHook msg model.hook
|
||||
in
|
||||
( { model | hook = newHook }, check newHook )
|
||||
|
||||
|
||||
check : NotificationMatrix -> Maybe NotificationMatrix
|
||||
check hook =
|
||||
Just hook
|
||||
|
||||
|
||||
updateHook : Msg -> NotificationMatrix -> NotificationMatrix
|
||||
updateHook msg hook =
|
||||
case msg of
|
||||
SetHomeServer s ->
|
||||
{ hook | homeServer = s }
|
||||
|
||||
SetRoomId s ->
|
||||
{ hook | roomId = s }
|
||||
|
||||
SetAccessKey s ->
|
||||
{ hook | accessToken = s }
|
||||
|
||||
|
||||
|
||||
--- View
|
||||
|
||||
|
||||
view : Texts -> Model -> Html Msg
|
||||
view texts model =
|
||||
div []
|
||||
[ div
|
||||
[ class "mb-2"
|
||||
]
|
||||
[ label
|
||||
[ for "homeserver"
|
||||
, class S.inputLabel
|
||||
]
|
||||
[ text texts.homeServer
|
||||
, B.inputRequired
|
||||
]
|
||||
, input
|
||||
[ type_ "text"
|
||||
, onInput SetHomeServer
|
||||
, placeholder texts.homeServer
|
||||
, value model.hook.homeServer
|
||||
, name "homeserver"
|
||||
, class S.textInput
|
||||
]
|
||||
[]
|
||||
]
|
||||
, div
|
||||
[ class "mb-2"
|
||||
]
|
||||
[ label
|
||||
[ for "roomid"
|
||||
, class S.inputLabel
|
||||
]
|
||||
[ text texts.roomId
|
||||
, B.inputRequired
|
||||
]
|
||||
, input
|
||||
[ type_ "text"
|
||||
, onInput SetRoomId
|
||||
, placeholder texts.roomId
|
||||
, value model.hook.roomId
|
||||
, name "roomid"
|
||||
, class S.textInput
|
||||
]
|
||||
[]
|
||||
]
|
||||
, div
|
||||
[ class "mb-2"
|
||||
]
|
||||
[ label
|
||||
[ for "accesskey"
|
||||
, class S.inputLabel
|
||||
]
|
||||
[ text texts.accessKey
|
||||
, B.inputRequired
|
||||
]
|
||||
, textarea
|
||||
[ onInput SetAccessKey
|
||||
, placeholder texts.accessKey
|
||||
, value model.hook.accessToken
|
||||
, name "accesskey"
|
||||
, class S.textAreaInput
|
||||
]
|
||||
[]
|
||||
]
|
||||
]
|
146
modules/webapp/src/main/elm/Comp/NotificationTest.elm
Normal file
146
modules/webapp/src/main/elm/Comp/NotificationTest.elm
Normal file
@ -0,0 +1,146 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Comp.NotificationTest exposing (Model, Msg, ViewConfig, init, update, view)
|
||||
|
||||
import Api
|
||||
import Api.Model.NotificationChannelTestResult exposing (NotificationChannelTestResult)
|
||||
import Comp.Basic as B
|
||||
import Comp.MenuBar as MB
|
||||
import Data.Flags exposing (Flags)
|
||||
import Data.NotificationHook exposing (NotificationHook)
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onClick)
|
||||
import Http
|
||||
|
||||
|
||||
type Model
|
||||
= ModelInit
|
||||
| ModelResp NotificationChannelTestResult
|
||||
| ModelHttpError Http.Error
|
||||
| ModelLoading
|
||||
|
||||
|
||||
init : Model
|
||||
init =
|
||||
ModelInit
|
||||
|
||||
|
||||
type Msg
|
||||
= RunTest
|
||||
| TestResp (Result Http.Error NotificationChannelTestResult)
|
||||
|
||||
|
||||
hasResponse : Model -> Bool
|
||||
hasResponse model =
|
||||
case model of
|
||||
ModelResp _ ->
|
||||
True
|
||||
|
||||
_ ->
|
||||
False
|
||||
|
||||
|
||||
|
||||
--- Update
|
||||
|
||||
|
||||
update : Flags -> NotificationHook -> Msg -> Model -> ( Model, Cmd Msg )
|
||||
update flags hook msg model =
|
||||
case msg of
|
||||
RunTest ->
|
||||
case model of
|
||||
ModelLoading ->
|
||||
( model, Cmd.none )
|
||||
|
||||
_ ->
|
||||
( ModelLoading, Api.testHook flags hook TestResp )
|
||||
|
||||
TestResp (Ok res) ->
|
||||
( ModelResp res, Cmd.none )
|
||||
|
||||
TestResp (Err err) ->
|
||||
( ModelHttpError err, Cmd.none )
|
||||
|
||||
|
||||
|
||||
--- View
|
||||
|
||||
|
||||
type alias ViewConfig =
|
||||
{ runDisabled : Bool
|
||||
}
|
||||
|
||||
|
||||
styleBase : String
|
||||
styleBase =
|
||||
"bg-gray-100 dark:bg-bluegray-900 text-gray-900 dark:text-gray-100 text-sm leading-5"
|
||||
|
||||
|
||||
stylePayload : String
|
||||
stylePayload =
|
||||
"px-2 font-mono overflow-auto h-full whitespace-pre "
|
||||
|
||||
|
||||
view : ViewConfig -> Model -> Html Msg
|
||||
view cfg model =
|
||||
div
|
||||
[ class "flex flex-col w-full"
|
||||
]
|
||||
[ MB.view
|
||||
{ start =
|
||||
case model of
|
||||
ModelResp res ->
|
||||
[ MB.CustomElement <|
|
||||
if res.success then
|
||||
div [ class "text-3xl text-green-500" ]
|
||||
[ i [ class "fa fa-check" ] []
|
||||
]
|
||||
|
||||
else
|
||||
div [ class "text-3xl text-red-500" ]
|
||||
[ i [ class "fa fa-times" ] []
|
||||
]
|
||||
]
|
||||
|
||||
_ ->
|
||||
[]
|
||||
, end =
|
||||
[ MB.CustomElement <|
|
||||
B.primaryButton
|
||||
{ label = "Test Delivery"
|
||||
, disabled = cfg.runDisabled || model == ModelLoading
|
||||
, icon =
|
||||
if model == ModelLoading then
|
||||
"fa fa-cog animate-spin"
|
||||
|
||||
else
|
||||
"fa fa-cog"
|
||||
, handler = onClick RunTest
|
||||
, attrs = [ href "#" ]
|
||||
}
|
||||
]
|
||||
, rootClasses = "mb-1"
|
||||
}
|
||||
, case model of
|
||||
ModelResp res ->
|
||||
div
|
||||
[ class "flex flex-col py-5 px-2"
|
||||
, class styleBase
|
||||
, class stylePayload
|
||||
]
|
||||
[ text (String.join "\n" res.messages)
|
||||
]
|
||||
|
||||
ModelHttpError err ->
|
||||
div [ class "" ]
|
||||
[]
|
||||
|
||||
_ ->
|
||||
span [ class "hidden" ] []
|
||||
]
|
484
modules/webapp/src/main/elm/Comp/PeriodicQueryTaskForm.elm
Normal file
484
modules/webapp/src/main/elm/Comp/PeriodicQueryTaskForm.elm
Normal file
@ -0,0 +1,484 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Comp.PeriodicQueryTaskForm exposing
|
||||
( Action(..)
|
||||
, Model
|
||||
, Msg
|
||||
, UpdateResult
|
||||
, init
|
||||
, initWith
|
||||
, update
|
||||
, view
|
||||
)
|
||||
|
||||
import Comp.Basic as B
|
||||
import Comp.CalEventInput
|
||||
import Comp.ChannelForm
|
||||
import Comp.MenuBar as MB
|
||||
import Comp.PowerSearchInput
|
||||
import Data.CalEvent exposing (CalEvent)
|
||||
import Data.ChannelType exposing (ChannelType)
|
||||
import Data.Flags exposing (Flags)
|
||||
import Data.PeriodicQuerySettings exposing (PeriodicQuerySettings)
|
||||
import Data.UiSettings exposing (UiSettings)
|
||||
import Data.Validated exposing (Validated(..))
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onInput)
|
||||
import Http
|
||||
import Messages.Comp.PeriodicQueryTaskForm exposing (Texts)
|
||||
import Styles as S
|
||||
import Util.Maybe
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ settings : PeriodicQuerySettings
|
||||
, enabled : Bool
|
||||
, summary : Maybe String
|
||||
, schedule : Maybe CalEvent
|
||||
, scheduleModel : Comp.CalEventInput.Model
|
||||
, queryModel : Comp.PowerSearchInput.Model
|
||||
, channelModel : Comp.ChannelForm.Model
|
||||
, formState : FormState
|
||||
, loading : Int
|
||||
}
|
||||
|
||||
|
||||
type FormState
|
||||
= FormStateInitial
|
||||
| FormStateHttpError Http.Error
|
||||
| FormStateInvalid ValidateError
|
||||
|
||||
|
||||
type ValidateError
|
||||
= ValidateCalEventInvalid
|
||||
| ValidateQueryStringRequired
|
||||
| ValidateChannelRequired
|
||||
|
||||
|
||||
type Action
|
||||
= SubmitAction PeriodicQuerySettings
|
||||
| StartOnceAction PeriodicQuerySettings
|
||||
| CancelAction
|
||||
| DeleteAction String
|
||||
| NoAction
|
||||
|
||||
|
||||
type Msg
|
||||
= Submit
|
||||
| ToggleEnabled
|
||||
| CalEventMsg Comp.CalEventInput.Msg
|
||||
| QueryMsg Comp.PowerSearchInput.Msg
|
||||
| ChannelMsg Comp.ChannelForm.Msg
|
||||
| StartOnce
|
||||
| Cancel
|
||||
| RequestDelete
|
||||
| SetSummary String
|
||||
|
||||
|
||||
initWith : Flags -> PeriodicQuerySettings -> ( Model, Cmd Msg )
|
||||
initWith flags s =
|
||||
let
|
||||
newSchedule =
|
||||
Data.CalEvent.fromEvent s.schedule
|
||||
|> Maybe.withDefault Data.CalEvent.everyMonth
|
||||
|
||||
( sm, sc ) =
|
||||
Comp.CalEventInput.init flags newSchedule
|
||||
|
||||
res =
|
||||
Comp.PowerSearchInput.update
|
||||
(Comp.PowerSearchInput.setSearchString s.query)
|
||||
Comp.PowerSearchInput.init
|
||||
|
||||
( cfm, cfc ) =
|
||||
Comp.ChannelForm.initWith flags s.channel
|
||||
in
|
||||
( { settings = s
|
||||
, enabled = s.enabled
|
||||
, schedule = Just newSchedule
|
||||
, scheduleModel = sm
|
||||
, queryModel = res.model
|
||||
, channelModel = cfm
|
||||
, formState = FormStateInitial
|
||||
, loading = 0
|
||||
, summary = s.summary
|
||||
}
|
||||
, Cmd.batch
|
||||
[ Cmd.map CalEventMsg sc
|
||||
, Cmd.map QueryMsg res.cmd
|
||||
, Cmd.map ChannelMsg cfc
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
init : Flags -> ChannelType -> ( Model, Cmd Msg )
|
||||
init flags ct =
|
||||
let
|
||||
initialSchedule =
|
||||
Data.CalEvent.everyMonth
|
||||
|
||||
( sm, scmd ) =
|
||||
Comp.CalEventInput.init flags initialSchedule
|
||||
|
||||
( cfm, cfc ) =
|
||||
Comp.ChannelForm.init flags ct
|
||||
in
|
||||
( { settings = Data.PeriodicQuerySettings.empty ct
|
||||
, enabled = False
|
||||
, schedule = Just initialSchedule
|
||||
, scheduleModel = sm
|
||||
, queryModel = Comp.PowerSearchInput.init
|
||||
, channelModel = cfm
|
||||
, formState = FormStateInitial
|
||||
, loading = 0
|
||||
, summary = Nothing
|
||||
}
|
||||
, Cmd.batch
|
||||
[ Cmd.map CalEventMsg scmd
|
||||
, Cmd.map ChannelMsg cfc
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
|
||||
--- Update
|
||||
|
||||
|
||||
type alias UpdateResult =
|
||||
{ model : Model
|
||||
, action : Action
|
||||
, cmd : Cmd Msg
|
||||
, sub : Sub Msg
|
||||
}
|
||||
|
||||
|
||||
makeSettings : Model -> Result ValidateError PeriodicQuerySettings
|
||||
makeSettings model =
|
||||
let
|
||||
prev =
|
||||
model.settings
|
||||
|
||||
schedule_ =
|
||||
case model.schedule of
|
||||
Just s ->
|
||||
Ok s
|
||||
|
||||
Nothing ->
|
||||
Err ValidateCalEventInvalid
|
||||
|
||||
queryString =
|
||||
Result.fromMaybe ValidateQueryStringRequired model.queryModel.input
|
||||
|
||||
channelM =
|
||||
Result.fromMaybe
|
||||
ValidateChannelRequired
|
||||
(Comp.ChannelForm.getChannel model.channelModel)
|
||||
|
||||
make timer channel query =
|
||||
{ prev
|
||||
| enabled = model.enabled
|
||||
, schedule = Data.CalEvent.makeEvent timer
|
||||
, summary = model.summary
|
||||
, channel = channel
|
||||
, query = query
|
||||
}
|
||||
in
|
||||
Result.map3 make
|
||||
schedule_
|
||||
channelM
|
||||
queryString
|
||||
|
||||
|
||||
withValidSettings : (PeriodicQuerySettings -> Action) -> Model -> UpdateResult
|
||||
withValidSettings mkcmd model =
|
||||
case makeSettings model of
|
||||
Ok set ->
|
||||
{ model = { model | formState = FormStateInitial }
|
||||
, action = mkcmd set
|
||||
, cmd = Cmd.none
|
||||
, sub = Sub.none
|
||||
}
|
||||
|
||||
Err errs ->
|
||||
{ model = { model | formState = FormStateInvalid errs }
|
||||
, action = NoAction
|
||||
, cmd = Cmd.none
|
||||
, sub = Sub.none
|
||||
}
|
||||
|
||||
|
||||
update : Flags -> Msg -> Model -> UpdateResult
|
||||
update flags msg model =
|
||||
case msg of
|
||||
CalEventMsg lmsg ->
|
||||
let
|
||||
( cm, cc, cs ) =
|
||||
Comp.CalEventInput.update flags
|
||||
model.schedule
|
||||
lmsg
|
||||
model.scheduleModel
|
||||
in
|
||||
{ model =
|
||||
{ model
|
||||
| schedule = cs
|
||||
, scheduleModel = cm
|
||||
, formState = FormStateInitial
|
||||
}
|
||||
, action = NoAction
|
||||
, cmd = Cmd.map CalEventMsg cc
|
||||
, sub = Sub.none
|
||||
}
|
||||
|
||||
QueryMsg lm ->
|
||||
let
|
||||
res =
|
||||
Comp.PowerSearchInput.update lm model.queryModel
|
||||
in
|
||||
{ model = { model | queryModel = res.model }
|
||||
, action = NoAction
|
||||
, cmd = Cmd.map QueryMsg res.cmd
|
||||
, sub = Sub.map QueryMsg res.subs
|
||||
}
|
||||
|
||||
ChannelMsg lm ->
|
||||
let
|
||||
( cfm, cfc ) =
|
||||
Comp.ChannelForm.update flags lm model.channelModel
|
||||
in
|
||||
{ model = { model | channelModel = cfm }
|
||||
, action = NoAction
|
||||
, cmd = Cmd.map ChannelMsg cfc
|
||||
, sub = Sub.none
|
||||
}
|
||||
|
||||
ToggleEnabled ->
|
||||
{ model =
|
||||
{ model
|
||||
| enabled = not model.enabled
|
||||
, formState = FormStateInitial
|
||||
}
|
||||
, action = NoAction
|
||||
, cmd = Cmd.none
|
||||
, sub = Sub.none
|
||||
}
|
||||
|
||||
Submit ->
|
||||
withValidSettings
|
||||
SubmitAction
|
||||
model
|
||||
|
||||
StartOnce ->
|
||||
withValidSettings
|
||||
StartOnceAction
|
||||
model
|
||||
|
||||
Cancel ->
|
||||
{ model = model
|
||||
, action = CancelAction
|
||||
, cmd = Cmd.none
|
||||
, sub = Sub.none
|
||||
}
|
||||
|
||||
RequestDelete ->
|
||||
{ model = model
|
||||
, action = NoAction
|
||||
, cmd = Cmd.none
|
||||
, sub = Sub.none
|
||||
}
|
||||
|
||||
SetSummary str ->
|
||||
{ model = { model | summary = Util.Maybe.fromString str }
|
||||
, action = NoAction
|
||||
, cmd = Cmd.none
|
||||
, sub = Sub.none
|
||||
}
|
||||
|
||||
|
||||
|
||||
--- View2
|
||||
|
||||
|
||||
isFormError : Model -> Bool
|
||||
isFormError model =
|
||||
case model.formState of
|
||||
FormStateInitial ->
|
||||
False
|
||||
|
||||
_ ->
|
||||
True
|
||||
|
||||
|
||||
isFormSuccess : Model -> Bool
|
||||
isFormSuccess model =
|
||||
not (isFormError model)
|
||||
|
||||
|
||||
view : Texts -> String -> UiSettings -> Model -> Html Msg
|
||||
view texts extraClasses settings model =
|
||||
let
|
||||
startOnceBtn =
|
||||
MB.SecondaryButton
|
||||
{ tagger = StartOnce
|
||||
, label = texts.startOnce
|
||||
, title = texts.startTaskNow
|
||||
, icon = Just "fa fa-play"
|
||||
}
|
||||
|
||||
queryInput =
|
||||
div
|
||||
[ class "relative flex flex-grow flex-row" ]
|
||||
[ Html.map QueryMsg
|
||||
(Comp.PowerSearchInput.viewInput
|
||||
{ placeholder = texts.queryLabel
|
||||
, extraAttrs = []
|
||||
}
|
||||
model.queryModel
|
||||
)
|
||||
, Html.map QueryMsg
|
||||
(Comp.PowerSearchInput.viewResult [] model.queryModel)
|
||||
]
|
||||
|
||||
formHeader txt =
|
||||
h2 [ class S.formHeader, class "mt-2" ]
|
||||
[ text txt
|
||||
]
|
||||
in
|
||||
div
|
||||
[ class "flex flex-col md:relative"
|
||||
, class extraClasses
|
||||
]
|
||||
[ B.loadingDimmer
|
||||
{ active = model.loading > 0
|
||||
, label = texts.basics.loading
|
||||
}
|
||||
, MB.view
|
||||
{ start =
|
||||
[ MB.PrimaryButton
|
||||
{ tagger = Submit
|
||||
, label = texts.basics.submit
|
||||
, title = texts.basics.submitThisForm
|
||||
, icon = Just "fa fa-save"
|
||||
}
|
||||
, MB.SecondaryButton
|
||||
{ tagger = Cancel
|
||||
, label = texts.basics.backToList
|
||||
, title = texts.basics.backToList
|
||||
, icon = Just "fa fa-arrow-left"
|
||||
}
|
||||
]
|
||||
, end =
|
||||
if model.settings.id /= "" then
|
||||
[ startOnceBtn
|
||||
, MB.DeleteButton
|
||||
{ tagger = RequestDelete
|
||||
, label = texts.basics.delete
|
||||
, title = texts.deleteThisTask
|
||||
, icon = Just "fa fa-trash"
|
||||
}
|
||||
]
|
||||
|
||||
else
|
||||
[ startOnceBtn
|
||||
]
|
||||
, rootClasses = "mb-4"
|
||||
}
|
||||
, div
|
||||
[ classList
|
||||
[ ( S.successMessage, isFormSuccess model )
|
||||
, ( S.errorMessage, isFormError model )
|
||||
, ( "hidden", model.formState == FormStateInitial )
|
||||
]
|
||||
, class "mb-4"
|
||||
]
|
||||
[ case model.formState of
|
||||
FormStateInitial ->
|
||||
text ""
|
||||
|
||||
FormStateHttpError err ->
|
||||
text (texts.httpError err)
|
||||
|
||||
FormStateInvalid ValidateCalEventInvalid ->
|
||||
text texts.invalidCalEvent
|
||||
|
||||
FormStateInvalid ValidateChannelRequired ->
|
||||
text texts.channelRequired
|
||||
|
||||
FormStateInvalid ValidateQueryStringRequired ->
|
||||
text texts.queryStringRequired
|
||||
]
|
||||
, div [ class "mb-4" ]
|
||||
[ MB.viewItem <|
|
||||
MB.Checkbox
|
||||
{ tagger = \_ -> ToggleEnabled
|
||||
, label = texts.enableDisable
|
||||
, value = model.enabled
|
||||
, id = "notify-enabled"
|
||||
}
|
||||
]
|
||||
, div [ class "mb-4" ]
|
||||
[ label [ class S.inputLabel ]
|
||||
[ text texts.summary
|
||||
]
|
||||
, input
|
||||
[ type_ "text"
|
||||
, onInput SetSummary
|
||||
, class S.textInput
|
||||
, Maybe.withDefault "" model.summary
|
||||
|> value
|
||||
]
|
||||
[]
|
||||
, span [ class "opacity-50 text-sm" ]
|
||||
[ text texts.summaryInfo
|
||||
]
|
||||
]
|
||||
, div [ class "mb-4" ]
|
||||
[ formHeader (texts.channelHeader (Comp.ChannelForm.channelType model.channelModel))
|
||||
, Html.map ChannelMsg
|
||||
(Comp.ChannelForm.view texts.channelForm settings model.channelModel)
|
||||
]
|
||||
, div [ class "mb-4" ]
|
||||
[ formHeader texts.queryLabel
|
||||
, label
|
||||
[ for "sharequery"
|
||||
, class S.inputLabel
|
||||
]
|
||||
[ text texts.queryLabel
|
||||
, B.inputRequired
|
||||
]
|
||||
, queryInput
|
||||
]
|
||||
, div [ class "mb-4" ]
|
||||
[ formHeader texts.schedule
|
||||
, label [ class S.inputLabel ]
|
||||
[ text texts.schedule
|
||||
, B.inputRequired
|
||||
, a
|
||||
[ class "float-right"
|
||||
, class S.link
|
||||
, href "https://github.com/eikek/calev#what-are-calendar-events"
|
||||
, target "_blank"
|
||||
]
|
||||
[ i [ class "fa fa-question" ] []
|
||||
, span [ class "pl-2" ]
|
||||
[ text texts.scheduleClickForHelp
|
||||
]
|
||||
]
|
||||
]
|
||||
, Html.map CalEventMsg
|
||||
(Comp.CalEventInput.view2
|
||||
texts.calEventInput
|
||||
""
|
||||
model.schedule
|
||||
model.scheduleModel
|
||||
)
|
||||
, span [ class "opacity-50 text-sm" ]
|
||||
[ text texts.scheduleInfo
|
||||
]
|
||||
]
|
||||
]
|
102
modules/webapp/src/main/elm/Comp/PeriodicQueryTaskList.elm
Normal file
102
modules/webapp/src/main/elm/Comp/PeriodicQueryTaskList.elm
Normal file
@ -0,0 +1,102 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Comp.PeriodicQueryTaskList exposing
|
||||
( Action(..)
|
||||
, Model
|
||||
, Msg
|
||||
, init
|
||||
, update
|
||||
, view2
|
||||
)
|
||||
|
||||
import Comp.Basic as B
|
||||
import Data.ChannelType
|
||||
import Data.NotificationChannel
|
||||
import Data.PeriodicQuerySettings exposing (PeriodicQuerySettings)
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Messages.Comp.PeriodicQueryTaskList exposing (Texts)
|
||||
import Styles as S
|
||||
import Util.Html
|
||||
|
||||
|
||||
type alias Model =
|
||||
{}
|
||||
|
||||
|
||||
type Msg
|
||||
= EditSettings PeriodicQuerySettings
|
||||
|
||||
|
||||
type Action
|
||||
= NoAction
|
||||
| EditAction PeriodicQuerySettings
|
||||
|
||||
|
||||
init : Model
|
||||
init =
|
||||
{}
|
||||
|
||||
|
||||
update : Msg -> Model -> ( Model, Action )
|
||||
update msg model =
|
||||
case msg of
|
||||
EditSettings settings ->
|
||||
( model, EditAction settings )
|
||||
|
||||
|
||||
|
||||
--- View2
|
||||
|
||||
|
||||
view2 : Texts -> Model -> List PeriodicQuerySettings -> Html Msg
|
||||
view2 texts _ items =
|
||||
div []
|
||||
[ table [ class S.tableMain ]
|
||||
[ thead []
|
||||
[ tr []
|
||||
[ th [ class "" ] []
|
||||
, th [ class "text-center mr-2" ]
|
||||
[ i [ class "fa fa-check" ] []
|
||||
]
|
||||
, th [ class "text-left " ] [ text texts.summary ]
|
||||
, th [ class "text-left hidden sm:table-cell mr-2" ]
|
||||
[ text texts.schedule ]
|
||||
, th [ class "text-left mr-2" ]
|
||||
[ text texts.connection ]
|
||||
]
|
||||
]
|
||||
, tbody []
|
||||
(List.map (viewItem2 texts) items)
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
viewItem2 : Texts -> PeriodicQuerySettings -> Html Msg
|
||||
viewItem2 texts item =
|
||||
tr []
|
||||
[ B.editLinkTableCell texts.basics.edit (EditSettings item)
|
||||
, td [ class "w-px whitespace-nowrap px-2 text-center" ]
|
||||
[ Util.Html.checkbox2 item.enabled
|
||||
]
|
||||
, td [ class "text-left" ]
|
||||
[ Maybe.withDefault "" item.summary
|
||||
|> text
|
||||
]
|
||||
, td [ class "text-left hidden sm:table-cell mr-2" ]
|
||||
[ code [ class "font-mono text-sm" ]
|
||||
[ text item.schedule
|
||||
]
|
||||
]
|
||||
, td [ class "text-left py-4 md:py-2" ]
|
||||
[ Data.NotificationChannel.channelType item.channel
|
||||
|> Maybe.map Data.ChannelType.asString
|
||||
|> Maybe.withDefault "-"
|
||||
|> text
|
||||
]
|
||||
]
|
324
modules/webapp/src/main/elm/Comp/PeriodicQueryTaskManage.elm
Normal file
324
modules/webapp/src/main/elm/Comp/PeriodicQueryTaskManage.elm
Normal file
@ -0,0 +1,324 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Comp.PeriodicQueryTaskManage exposing
|
||||
( Model
|
||||
, Msg
|
||||
, init
|
||||
, update
|
||||
, view
|
||||
)
|
||||
|
||||
import Api
|
||||
import Api.Model.BasicResult exposing (BasicResult)
|
||||
import Comp.ChannelMenu
|
||||
import Comp.MenuBar as MB
|
||||
import Comp.PeriodicQueryTaskForm
|
||||
import Comp.PeriodicQueryTaskList
|
||||
import Data.ChannelType exposing (ChannelType)
|
||||
import Data.Flags exposing (Flags)
|
||||
import Data.PeriodicQuerySettings exposing (PeriodicQuerySettings)
|
||||
import Data.UiSettings exposing (UiSettings)
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onClick)
|
||||
import Http
|
||||
import Messages.Comp.PeriodicQueryTaskManage exposing (Texts)
|
||||
import Styles as S
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ listModel : Comp.PeriodicQueryTaskList.Model
|
||||
, detailModel : Maybe Comp.PeriodicQueryTaskForm.Model
|
||||
, items : List PeriodicQuerySettings
|
||||
, formState : FormState
|
||||
, channelMenuOpen : Bool
|
||||
}
|
||||
|
||||
|
||||
type SubmitType
|
||||
= SubmitDelete
|
||||
| SubmitUpdate
|
||||
| SubmitCreate
|
||||
| SubmitStartOnce
|
||||
|
||||
|
||||
type FormState
|
||||
= FormStateInitial
|
||||
| FormHttpError Http.Error
|
||||
| FormSubmitSuccessful SubmitType
|
||||
| FormSubmitFailed String
|
||||
|
||||
|
||||
type Msg
|
||||
= ListMsg Comp.PeriodicQueryTaskList.Msg
|
||||
| DetailMsg Comp.PeriodicQueryTaskForm.Msg
|
||||
| GetDataResp (Result Http.Error (List PeriodicQuerySettings))
|
||||
| NewTaskInit ChannelType
|
||||
| SubmitResp SubmitType (Result Http.Error BasicResult)
|
||||
| ToggleChannelMenu
|
||||
|
||||
|
||||
initModel : Model
|
||||
initModel =
|
||||
{ listModel = Comp.PeriodicQueryTaskList.init
|
||||
, detailModel = Nothing
|
||||
, items = []
|
||||
, formState = FormStateInitial
|
||||
, channelMenuOpen = False
|
||||
}
|
||||
|
||||
|
||||
initCmd : Flags -> Cmd Msg
|
||||
initCmd flags =
|
||||
Api.getPeriodicQuery flags GetDataResp
|
||||
|
||||
|
||||
init : Flags -> ( Model, Cmd Msg )
|
||||
init flags =
|
||||
( initModel, initCmd flags )
|
||||
|
||||
|
||||
|
||||
--- Update
|
||||
|
||||
|
||||
update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
|
||||
update flags msg model =
|
||||
case msg of
|
||||
GetDataResp (Ok items) ->
|
||||
( { model
|
||||
| items = items
|
||||
, formState = FormStateInitial
|
||||
}
|
||||
, Cmd.none
|
||||
, Sub.none
|
||||
)
|
||||
|
||||
GetDataResp (Err err) ->
|
||||
( { model | formState = FormHttpError err }
|
||||
, Cmd.none
|
||||
, Sub.none
|
||||
)
|
||||
|
||||
ListMsg lm ->
|
||||
let
|
||||
( mm, action ) =
|
||||
Comp.PeriodicQueryTaskList.update lm model.listModel
|
||||
|
||||
( detail, cmd ) =
|
||||
case action of
|
||||
Comp.PeriodicQueryTaskList.NoAction ->
|
||||
( Nothing, Cmd.none )
|
||||
|
||||
Comp.PeriodicQueryTaskList.EditAction settings ->
|
||||
let
|
||||
( dm, dc ) =
|
||||
Comp.PeriodicQueryTaskForm.initWith flags settings
|
||||
in
|
||||
( Just dm, Cmd.map DetailMsg dc )
|
||||
in
|
||||
( { model
|
||||
| listModel = mm
|
||||
, detailModel = detail
|
||||
}
|
||||
, cmd
|
||||
, Sub.none
|
||||
)
|
||||
|
||||
DetailMsg lm ->
|
||||
case model.detailModel of
|
||||
Just dm ->
|
||||
let
|
||||
--( mm, action, mc ) =
|
||||
result =
|
||||
Comp.PeriodicQueryTaskForm.update flags lm dm
|
||||
|
||||
( model_, cmd_ ) =
|
||||
case result.action of
|
||||
Comp.PeriodicQueryTaskForm.NoAction ->
|
||||
( { model
|
||||
| detailModel = Just result.model
|
||||
, formState = FormStateInitial
|
||||
}
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
Comp.PeriodicQueryTaskForm.SubmitAction settings ->
|
||||
( { model
|
||||
| detailModel = Just result.model
|
||||
, formState = FormStateInitial
|
||||
}
|
||||
, if settings.id == "" then
|
||||
Api.createPeriodicQuery flags settings (SubmitResp SubmitCreate)
|
||||
|
||||
else
|
||||
Api.updatePeriodicQuery flags settings (SubmitResp SubmitUpdate)
|
||||
)
|
||||
|
||||
Comp.PeriodicQueryTaskForm.CancelAction ->
|
||||
( { model
|
||||
| detailModel = Nothing
|
||||
, formState = FormStateInitial
|
||||
}
|
||||
, initCmd flags
|
||||
)
|
||||
|
||||
Comp.PeriodicQueryTaskForm.StartOnceAction settings ->
|
||||
( { model
|
||||
| detailModel = Just result.model
|
||||
, formState = FormStateInitial
|
||||
}
|
||||
, Api.startOncePeriodicQuery flags settings (SubmitResp SubmitStartOnce)
|
||||
)
|
||||
|
||||
Comp.PeriodicQueryTaskForm.DeleteAction id ->
|
||||
( { model
|
||||
| detailModel = Just result.model
|
||||
, formState = FormStateInitial
|
||||
}
|
||||
, Api.deletePeriodicQueryTask flags id (SubmitResp SubmitDelete)
|
||||
)
|
||||
in
|
||||
( model_
|
||||
, Cmd.batch
|
||||
[ Cmd.map DetailMsg result.cmd
|
||||
, cmd_
|
||||
]
|
||||
, Sub.map DetailMsg result.sub
|
||||
)
|
||||
|
||||
Nothing ->
|
||||
( model, Cmd.none, Sub.none )
|
||||
|
||||
NewTaskInit ct ->
|
||||
let
|
||||
( mm, mc ) =
|
||||
Comp.PeriodicQueryTaskForm.init flags ct
|
||||
in
|
||||
( { model | detailModel = Just mm, channelMenuOpen = False }, Cmd.map DetailMsg mc, Sub.none )
|
||||
|
||||
SubmitResp submitType (Ok res) ->
|
||||
( { model
|
||||
| formState =
|
||||
if res.success then
|
||||
FormSubmitSuccessful submitType
|
||||
|
||||
else
|
||||
FormSubmitFailed res.message
|
||||
, detailModel =
|
||||
if submitType == SubmitDelete then
|
||||
Nothing
|
||||
|
||||
else
|
||||
model.detailModel
|
||||
}
|
||||
, if submitType == SubmitDelete then
|
||||
initCmd flags
|
||||
|
||||
else
|
||||
Cmd.none
|
||||
, Sub.none
|
||||
)
|
||||
|
||||
SubmitResp _ (Err err) ->
|
||||
( { model | formState = FormHttpError err }
|
||||
, Cmd.none
|
||||
, Sub.none
|
||||
)
|
||||
|
||||
ToggleChannelMenu ->
|
||||
( { model | channelMenuOpen = not model.channelMenuOpen }, Cmd.none, Sub.none )
|
||||
|
||||
|
||||
|
||||
--- View2
|
||||
|
||||
|
||||
view : Texts -> UiSettings -> Model -> Html Msg
|
||||
view texts settings model =
|
||||
div [ class "flex flex-col" ]
|
||||
(div
|
||||
[ classList
|
||||
[ ( S.errorMessage, model.formState /= FormStateInitial )
|
||||
, ( S.successMessage, isSuccess model.formState )
|
||||
, ( "hidden", model.formState == FormStateInitial )
|
||||
]
|
||||
, class "mb-2"
|
||||
]
|
||||
[ case model.formState of
|
||||
FormStateInitial ->
|
||||
text ""
|
||||
|
||||
FormSubmitSuccessful SubmitCreate ->
|
||||
text texts.taskCreated
|
||||
|
||||
FormSubmitSuccessful SubmitUpdate ->
|
||||
text texts.taskUpdated
|
||||
|
||||
FormSubmitSuccessful SubmitStartOnce ->
|
||||
text texts.taskStarted
|
||||
|
||||
FormSubmitSuccessful SubmitDelete ->
|
||||
text texts.taskDeleted
|
||||
|
||||
FormSubmitFailed m ->
|
||||
text m
|
||||
|
||||
FormHttpError err ->
|
||||
text (texts.httpError err)
|
||||
]
|
||||
:: (case model.detailModel of
|
||||
Just msett ->
|
||||
viewForm2 texts settings msett
|
||||
|
||||
Nothing ->
|
||||
viewList2 texts model
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
isSuccess : FormState -> Bool
|
||||
isSuccess state =
|
||||
case state of
|
||||
FormSubmitSuccessful _ ->
|
||||
True
|
||||
|
||||
_ ->
|
||||
False
|
||||
|
||||
|
||||
viewForm2 : Texts -> UiSettings -> Comp.PeriodicQueryTaskForm.Model -> List (Html Msg)
|
||||
viewForm2 texts settings model =
|
||||
[ Html.map DetailMsg
|
||||
(Comp.PeriodicQueryTaskForm.view texts.notificationForm "flex flex-col" settings model)
|
||||
]
|
||||
|
||||
|
||||
viewList2 : Texts -> Model -> List (Html Msg)
|
||||
viewList2 texts model =
|
||||
let
|
||||
menuModel =
|
||||
{ menuOpen = model.channelMenuOpen
|
||||
, toggleMenu = ToggleChannelMenu
|
||||
, menuLabel = texts.newTask
|
||||
, onItem = NewTaskInit
|
||||
}
|
||||
in
|
||||
[ MB.view
|
||||
{ start = []
|
||||
, end =
|
||||
[ Comp.ChannelMenu.channelMenu texts.channelType menuModel
|
||||
]
|
||||
, rootClasses = "mb-4"
|
||||
}
|
||||
, Html.map ListMsg
|
||||
(Comp.PeriodicQueryTaskList.view2 texts.notificationTable
|
||||
model.listModel
|
||||
model.items
|
||||
)
|
||||
]
|
@ -287,7 +287,8 @@ viewForm2 texts flags settings model =
|
||||
viewList2 : Texts -> Model -> List (Html Msg)
|
||||
viewList2 texts model =
|
||||
[ MB.view
|
||||
{ start =
|
||||
{ start = []
|
||||
, end =
|
||||
[ MB.PrimaryButton
|
||||
{ tagger = NewTask
|
||||
, label = texts.newTask
|
||||
@ -295,7 +296,6 @@ viewList2 texts model =
|
||||
, title = texts.createNewTask
|
||||
}
|
||||
]
|
||||
, end = []
|
||||
, rootClasses = "mb-4"
|
||||
}
|
||||
, Html.map ListMsg
|
||||
|
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 )
|
||||
]
|
@ -14,6 +14,7 @@ import App.View2
|
||||
import Browser exposing (Document)
|
||||
import Browser.Navigation exposing (Key)
|
||||
import Data.Flags exposing (Flags)
|
||||
import Data.NotificationChannel
|
||||
import Data.UiSettings
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
|
47
modules/webapp/src/main/elm/Messages/Comp/ChannelForm.elm
Normal file
47
modules/webapp/src/main/elm/Messages/Comp/ChannelForm.elm
Normal file
@ -0,0 +1,47 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Messages.Comp.ChannelForm exposing
|
||||
( Texts
|
||||
, de
|
||||
, gb
|
||||
)
|
||||
|
||||
import Messages.Basics
|
||||
import Messages.Comp.NotificationGotifyForm
|
||||
import Messages.Comp.NotificationHttpForm
|
||||
import Messages.Comp.NotificationMailForm
|
||||
import Messages.Comp.NotificationMatrixForm
|
||||
|
||||
|
||||
type alias Texts =
|
||||
{ basics : Messages.Basics.Texts
|
||||
, matrixForm : Messages.Comp.NotificationMatrixForm.Texts
|
||||
, gotifyForm : Messages.Comp.NotificationGotifyForm.Texts
|
||||
, mailForm : Messages.Comp.NotificationMailForm.Texts
|
||||
, httpForm : Messages.Comp.NotificationHttpForm.Texts
|
||||
}
|
||||
|
||||
|
||||
gb : Texts
|
||||
gb =
|
||||
{ basics = Messages.Basics.gb
|
||||
, matrixForm = Messages.Comp.NotificationMatrixForm.gb
|
||||
, gotifyForm = Messages.Comp.NotificationGotifyForm.gb
|
||||
, mailForm = Messages.Comp.NotificationMailForm.gb
|
||||
, httpForm = Messages.Comp.NotificationHttpForm.gb
|
||||
}
|
||||
|
||||
|
||||
de : Texts
|
||||
de =
|
||||
{ basics = Messages.Basics.de
|
||||
, matrixForm = Messages.Comp.NotificationMatrixForm.de
|
||||
, gotifyForm = Messages.Comp.NotificationGotifyForm.de
|
||||
, mailForm = Messages.Comp.NotificationMailForm.de
|
||||
, httpForm = Messages.Comp.NotificationHttpForm.de
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
-}
|
||||
|
||||
|
||||
module Messages.Comp.NotificationForm exposing
|
||||
module Messages.Comp.DueItemsTaskForm exposing
|
||||
( Texts
|
||||
, de
|
||||
, gb
|
||||
@ -14,25 +14,23 @@ module Messages.Comp.NotificationForm exposing
|
||||
import Http
|
||||
import Messages.Basics
|
||||
import Messages.Comp.CalEventInput
|
||||
import Messages.Comp.ChannelForm
|
||||
import Messages.Comp.HttpError
|
||||
import Messages.Data.ChannelType
|
||||
|
||||
|
||||
type alias Texts =
|
||||
{ basics : Messages.Basics.Texts
|
||||
, calEventInput : Messages.Comp.CalEventInput.Texts
|
||||
, httpError : Http.Error -> String
|
||||
, channelForm : Messages.Comp.ChannelForm.Texts
|
||||
, reallyDeleteTask : String
|
||||
, startOnce : String
|
||||
, startTaskNow : String
|
||||
, selectConnection : String
|
||||
, deleteThisTask : String
|
||||
, enableDisable : String
|
||||
, summary : String
|
||||
, summaryInfo : String
|
||||
, sendVia : String
|
||||
, sendViaInfo : String
|
||||
, recipients : String
|
||||
, recipientsInfo : String
|
||||
, tagsInclude : String
|
||||
, tagsIncludeInfo : String
|
||||
, tagsExclude : String
|
||||
@ -48,6 +46,9 @@ type alias Texts =
|
||||
, invalidCalEvent : String
|
||||
, remindDaysRequired : String
|
||||
, recipientsRequired : String
|
||||
, queryLabel : String
|
||||
, channelRequired : String
|
||||
, channelHeader : Messages.Data.ChannelType.Texts
|
||||
}
|
||||
|
||||
|
||||
@ -56,18 +57,14 @@ gb =
|
||||
{ basics = Messages.Basics.gb
|
||||
, calEventInput = Messages.Comp.CalEventInput.gb
|
||||
, httpError = Messages.Comp.HttpError.gb
|
||||
, channelForm = Messages.Comp.ChannelForm.gb
|
||||
, reallyDeleteTask = "Really delete this notification task?"
|
||||
, startOnce = "Start Once"
|
||||
, startTaskNow = "Start this task now"
|
||||
, selectConnection = "Select connection..."
|
||||
, deleteThisTask = "Delete this task"
|
||||
, enableDisable = "Enable or disable this task."
|
||||
, summary = "Summary"
|
||||
, summaryInfo = "Some human readable name, only for displaying"
|
||||
, sendVia = "Send via"
|
||||
, sendViaInfo = "The SMTP connection to use when sending notification mails."
|
||||
, recipients = "Recipient(s)"
|
||||
, recipientsInfo = "One or more mail addresses, confirm each by pressing 'Return'."
|
||||
, tagsInclude = "Tags Include (and)"
|
||||
, tagsIncludeInfo = "Items must have all the tags specified here."
|
||||
, tagsExclude = "Tags Exclude (or)"
|
||||
@ -87,6 +84,9 @@ gb =
|
||||
, invalidCalEvent = "The calendar event is not valid."
|
||||
, remindDaysRequired = "Remind-Days is required."
|
||||
, recipientsRequired = "At least one recipient is required."
|
||||
, queryLabel = "Query"
|
||||
, channelRequired = "A valid channel must be given."
|
||||
, channelHeader = \ct -> "Connection details for " ++ Messages.Data.ChannelType.gb ct
|
||||
}
|
||||
|
||||
|
||||
@ -95,18 +95,14 @@ de =
|
||||
{ basics = Messages.Basics.de
|
||||
, calEventInput = Messages.Comp.CalEventInput.de
|
||||
, httpError = Messages.Comp.HttpError.de
|
||||
, channelForm = Messages.Comp.ChannelForm.gb
|
||||
, reallyDeleteTask = "Diesen Benachrichtigungsauftrag wirklich löschen?"
|
||||
, startOnce = "Jetzt starten"
|
||||
, startTaskNow = "Starte den Auftrag sofort"
|
||||
, selectConnection = "Verbindung auswählen…"
|
||||
, deleteThisTask = "Den Auftrag löschen"
|
||||
, enableDisable = "Auftrag aktivieren oder deaktivieren"
|
||||
, summary = "Kurzbeschreibung"
|
||||
, summaryInfo = "Eine kurze lesbare Zusammenfassung, nur für die Anzeige"
|
||||
, sendVia = "Senden via"
|
||||
, sendViaInfo = "Die SMTP-Verbindung, die zum Senden der Benachrichtigungs-E-Mails verwendet werden soll."
|
||||
, recipients = "Empfänger"
|
||||
, recipientsInfo = "Eine oder mehrere E-Mail-Adressen, jede mit 'Eingabe' bestätigen."
|
||||
, tagsInclude = "Tags verknüpft (&&)"
|
||||
, tagsIncludeInfo = "Dokumente müssen alle diese Tags haben."
|
||||
, tagsExclude = "Tags nicht verknüpft (||)"
|
||||
@ -126,4 +122,7 @@ de =
|
||||
, invalidCalEvent = "Das Kalenderereignis ist nicht gültig."
|
||||
, remindDaysRequired = "'Fällig in Tagen' ist erforderlich."
|
||||
, recipientsRequired = "Mindestens ein Empfänger muss angegeben werden."
|
||||
, queryLabel = "Abfrage"
|
||||
, channelRequired = "Ein Versandkanal muss angegeben werden."
|
||||
, channelHeader = \ct -> "Details für " ++ Messages.Data.ChannelType.de ct
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
-}
|
||||
|
||||
|
||||
module Messages.Comp.NotificationTable exposing
|
||||
module Messages.Comp.DueItemsTaskList exposing
|
||||
( Texts
|
||||
, de
|
||||
, gb
|
@ -5,7 +5,7 @@
|
||||
-}
|
||||
|
||||
|
||||
module Messages.Comp.NotificationManage exposing
|
||||
module Messages.Comp.DueItemsTaskManage exposing
|
||||
( Texts
|
||||
, de
|
||||
, gb
|
||||
@ -13,16 +13,18 @@ module Messages.Comp.NotificationManage exposing
|
||||
|
||||
import Http
|
||||
import Messages.Basics
|
||||
import Messages.Comp.DueItemsTaskForm
|
||||
import Messages.Comp.DueItemsTaskList
|
||||
import Messages.Comp.HttpError
|
||||
import Messages.Comp.NotificationForm
|
||||
import Messages.Comp.NotificationTable
|
||||
import Messages.Data.ChannelType
|
||||
|
||||
|
||||
type alias Texts =
|
||||
{ basics : Messages.Basics.Texts
|
||||
, notificationForm : Messages.Comp.NotificationForm.Texts
|
||||
, notificationTable : Messages.Comp.NotificationTable.Texts
|
||||
, notificationForm : Messages.Comp.DueItemsTaskForm.Texts
|
||||
, notificationTable : Messages.Comp.DueItemsTaskList.Texts
|
||||
, httpError : Http.Error -> String
|
||||
, channelType : Messages.Data.ChannelType.Texts
|
||||
, newTask : String
|
||||
, createNewTask : String
|
||||
, taskCreated : String
|
||||
@ -35,9 +37,10 @@ type alias Texts =
|
||||
gb : Texts
|
||||
gb =
|
||||
{ basics = Messages.Basics.gb
|
||||
, notificationForm = Messages.Comp.NotificationForm.gb
|
||||
, notificationTable = Messages.Comp.NotificationTable.gb
|
||||
, notificationForm = Messages.Comp.DueItemsTaskForm.gb
|
||||
, notificationTable = Messages.Comp.DueItemsTaskList.gb
|
||||
, httpError = Messages.Comp.HttpError.gb
|
||||
, channelType = Messages.Data.ChannelType.gb
|
||||
, newTask = "New Task"
|
||||
, createNewTask = "Create a new notification task"
|
||||
, taskCreated = "Task created."
|
||||
@ -50,9 +53,10 @@ gb =
|
||||
de : Texts
|
||||
de =
|
||||
{ basics = Messages.Basics.de
|
||||
, notificationForm = Messages.Comp.NotificationForm.de
|
||||
, notificationTable = Messages.Comp.NotificationTable.de
|
||||
, notificationForm = Messages.Comp.DueItemsTaskForm.de
|
||||
, notificationTable = Messages.Comp.DueItemsTaskList.de
|
||||
, httpError = Messages.Comp.HttpError.de
|
||||
, channelType = Messages.Data.ChannelType.de
|
||||
, newTask = "Neuer Auftrag"
|
||||
, createNewTask = "Erstelle einen neuen Benachrichtigungsauftrag"
|
||||
, taskCreated = "Auftrag erstellt."
|
40
modules/webapp/src/main/elm/Messages/Comp/EventSample.elm
Normal file
40
modules/webapp/src/main/elm/Messages/Comp/EventSample.elm
Normal file
@ -0,0 +1,40 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Messages.Comp.EventSample exposing
|
||||
( Texts
|
||||
, de
|
||||
, gb
|
||||
)
|
||||
|
||||
import Data.EventType exposing (EventType)
|
||||
import Http
|
||||
import Messages.Comp.HttpError
|
||||
import Messages.Data.EventType
|
||||
|
||||
|
||||
type alias Texts =
|
||||
{ eventType : EventType -> Messages.Data.EventType.Texts
|
||||
, httpError : Http.Error -> String
|
||||
, selectEvent : String
|
||||
}
|
||||
|
||||
|
||||
gb : Texts
|
||||
gb =
|
||||
{ eventType = Messages.Data.EventType.gb
|
||||
, httpError = Messages.Comp.HttpError.gb
|
||||
, selectEvent = "Select event…"
|
||||
}
|
||||
|
||||
|
||||
de : Texts
|
||||
de =
|
||||
{ eventType = Messages.Data.EventType.de
|
||||
, httpError = Messages.Comp.HttpError.de
|
||||
, selectEvent = "Ereignis wählen…"
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Messages.Comp.NotificationGotifyForm exposing
|
||||
( Texts
|
||||
, de
|
||||
, gb
|
||||
)
|
||||
|
||||
import Messages.Basics
|
||||
|
||||
|
||||
type alias Texts =
|
||||
{ basics : Messages.Basics.Texts
|
||||
, gotifyUrl : String
|
||||
, appKey : String
|
||||
}
|
||||
|
||||
|
||||
gb : Texts
|
||||
gb =
|
||||
{ basics = Messages.Basics.gb
|
||||
, gotifyUrl = "Gotify URL"
|
||||
, appKey = "App Key"
|
||||
}
|
||||
|
||||
|
||||
de : Texts
|
||||
de =
|
||||
{ basics = Messages.Basics.de
|
||||
, gotifyUrl = "Gotify URL"
|
||||
, appKey = "App Key"
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Messages.Comp.NotificationHookForm exposing
|
||||
( Texts
|
||||
, de
|
||||
, gb
|
||||
)
|
||||
|
||||
import Data.EventType exposing (EventType)
|
||||
import Messages.Basics
|
||||
import Messages.Comp.ChannelForm
|
||||
import Messages.Comp.EventSample
|
||||
import Messages.Data.ChannelType
|
||||
import Messages.Data.EventType
|
||||
|
||||
|
||||
type alias Texts =
|
||||
{ basics : Messages.Basics.Texts
|
||||
, channelForm : Messages.Comp.ChannelForm.Texts
|
||||
, eventType : EventType -> Messages.Data.EventType.Texts
|
||||
, eventSample : Messages.Comp.EventSample.Texts
|
||||
, channelHeader : Messages.Data.ChannelType.Texts
|
||||
, enableDisable : String
|
||||
, eventsInfo : String
|
||||
, selectEvents : String
|
||||
, events : String
|
||||
, samplePayload : String
|
||||
, toggleAllEvents : String
|
||||
, eventFilter : String
|
||||
, eventFilterInfo : String
|
||||
, eventFilterClickForHelp : String
|
||||
}
|
||||
|
||||
|
||||
gb : Texts
|
||||
gb =
|
||||
{ basics = Messages.Basics.gb
|
||||
, channelForm = Messages.Comp.ChannelForm.gb
|
||||
, eventType = Messages.Data.EventType.gb
|
||||
, eventSample = Messages.Comp.EventSample.gb
|
||||
, channelHeader = Messages.Data.ChannelType.gb
|
||||
, enableDisable = "Enabled / Disabled"
|
||||
, eventsInfo = "Select events that trigger this webhook"
|
||||
, selectEvents = "Select…"
|
||||
, events = "Events"
|
||||
, samplePayload = "Sample Payload"
|
||||
, toggleAllEvents = "Notify on all events"
|
||||
, eventFilter = "Event Filter Expression"
|
||||
, eventFilterInfo = "Optional specify an expression to filter events based on their JSON structure."
|
||||
, eventFilterClickForHelp = "Click here for help"
|
||||
}
|
||||
|
||||
|
||||
de : Texts
|
||||
de =
|
||||
{ basics = Messages.Basics.de
|
||||
, channelForm = Messages.Comp.ChannelForm.de
|
||||
, eventType = Messages.Data.EventType.de
|
||||
, eventSample = Messages.Comp.EventSample.de
|
||||
, channelHeader = Messages.Data.ChannelType.de
|
||||
, enableDisable = "Aktiviert / Deaktivert"
|
||||
, eventsInfo = "Wähle die Ereignisse, die diesen webhook auslösen"
|
||||
, selectEvents = "Wähle…"
|
||||
, events = "Ereignisse"
|
||||
, samplePayload = "Beispieldaten"
|
||||
, toggleAllEvents = "Bei allen Ereignissen"
|
||||
, eventFilter = "Ereignisfilter"
|
||||
, eventFilterInfo = "Optionaler Ausdruck zum filtern von Ereignissen auf Basis ihrer JSON Struktur."
|
||||
, eventFilterClickForHelp = "Klicke für Hilfe"
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Messages.Comp.NotificationHookManage exposing
|
||||
( Texts
|
||||
, de
|
||||
, gb
|
||||
)
|
||||
|
||||
import Html exposing (Html, text)
|
||||
import Http
|
||||
import Messages.Basics
|
||||
import Messages.Comp.HttpError
|
||||
import Messages.Comp.NotificationHookForm
|
||||
import Messages.Comp.NotificationHookTable
|
||||
import Messages.Data.ChannelType
|
||||
|
||||
|
||||
type alias Texts =
|
||||
{ basics : Messages.Basics.Texts
|
||||
, notificationForm : Messages.Comp.NotificationHookForm.Texts
|
||||
, notificationTable : Messages.Comp.NotificationHookTable.Texts
|
||||
, httpError : Http.Error -> String
|
||||
, channelType : Messages.Data.ChannelType.Texts
|
||||
, newHook : String
|
||||
, matrix : String
|
||||
, gotify : String
|
||||
, email : String
|
||||
, httpRequest : String
|
||||
, hookCreated : String
|
||||
, hookUpdated : String
|
||||
, hookStarted : String
|
||||
, hookDeleted : String
|
||||
, deleteThisHook : String
|
||||
, reallyDeleteHook : String
|
||||
, formInvalid : String
|
||||
, invalidJsonFilter : String -> String
|
||||
, integrate : String
|
||||
, intoDocspell : String
|
||||
, postRequestInfo : String
|
||||
, updateWebhook : String
|
||||
, addWebhook : String
|
||||
, notifyEmailInfo : String
|
||||
}
|
||||
|
||||
|
||||
gb : Texts
|
||||
gb =
|
||||
{ basics = Messages.Basics.gb
|
||||
, notificationForm = Messages.Comp.NotificationHookForm.gb
|
||||
, notificationTable = Messages.Comp.NotificationHookTable.gb
|
||||
, httpError = Messages.Comp.HttpError.gb
|
||||
, channelType = Messages.Data.ChannelType.gb
|
||||
, newHook = "New Webhook"
|
||||
, matrix = "Matrix"
|
||||
, gotify = "Gotify"
|
||||
, email = "E-Mail"
|
||||
, httpRequest = "HTTP Request"
|
||||
, hookCreated = "Webhook created"
|
||||
, hookUpdated = "Webhook updated"
|
||||
, hookStarted = "Webhook executed"
|
||||
, hookDeleted = "Webhook deleted"
|
||||
, deleteThisHook = "Delete this webhook"
|
||||
, reallyDeleteHook = "Really delete this webhook?"
|
||||
, formInvalid = "Please fill in all required fields"
|
||||
, invalidJsonFilter = \m -> "Event filter invalid: " ++ m
|
||||
, integrate = "Integrate"
|
||||
, intoDocspell = "into Docspell"
|
||||
, postRequestInfo = "Docspell will send POST requests with JSON payload."
|
||||
, updateWebhook = "Update webhook"
|
||||
, addWebhook = "Add new webhook"
|
||||
, notifyEmailInfo = "Get notified via e-mail."
|
||||
}
|
||||
|
||||
|
||||
de : Texts
|
||||
de =
|
||||
{ basics = Messages.Basics.de
|
||||
, notificationForm = Messages.Comp.NotificationHookForm.de
|
||||
, notificationTable = Messages.Comp.NotificationHookTable.de
|
||||
, httpError = Messages.Comp.HttpError.de
|
||||
, channelType = Messages.Data.ChannelType.de
|
||||
, newHook = "Neuer Webhook"
|
||||
, matrix = "Matrix"
|
||||
, gotify = "Gotify"
|
||||
, email = "E-Mail"
|
||||
, httpRequest = "HTTP Request"
|
||||
, hookCreated = "Webhook erstellt"
|
||||
, hookUpdated = "Webhook aktualisiert"
|
||||
, hookStarted = "Webhook ausgeführt"
|
||||
, hookDeleted = "Webhook gelöscht"
|
||||
, deleteThisHook = "Diesen Webhook löschen"
|
||||
, reallyDeleteHook = "Den webhook wirklich löschen?"
|
||||
, formInvalid = "Bitte alle erforderlichen Felder ausfüllen"
|
||||
, invalidJsonFilter = \m -> "Ereignisfilter ist falsch: " ++ m
|
||||
, integrate = "Integriere"
|
||||
, intoDocspell = "in Docspell"
|
||||
, postRequestInfo = "Docspell wird JSON POST requests senden."
|
||||
, updateWebhook = "Webhook aktualisieren"
|
||||
, addWebhook = "Neuen Webhook hinzufügen"
|
||||
, notifyEmailInfo = "Werde per E-Mail benachrichtigt."
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Messages.Comp.NotificationHookTable exposing
|
||||
( Texts
|
||||
, de
|
||||
, gb
|
||||
)
|
||||
|
||||
import Data.EventType exposing (EventType)
|
||||
import Messages.Basics
|
||||
import Messages.Data.EventType
|
||||
|
||||
|
||||
type alias Texts =
|
||||
{ basics : Messages.Basics.Texts
|
||||
, eventType : EventType -> Messages.Data.EventType.Texts
|
||||
, enabled : String
|
||||
, channel : String
|
||||
, events : String
|
||||
}
|
||||
|
||||
|
||||
gb : Texts
|
||||
gb =
|
||||
{ basics = Messages.Basics.gb
|
||||
, eventType = Messages.Data.EventType.gb
|
||||
, enabled = "Enabled"
|
||||
, channel = "Channel"
|
||||
, events = "Events"
|
||||
}
|
||||
|
||||
|
||||
de : Texts
|
||||
de =
|
||||
{ basics = Messages.Basics.de
|
||||
, eventType = Messages.Data.EventType.de
|
||||
, enabled = "Aktiv"
|
||||
, channel = "Kanal"
|
||||
, events = "Ereignisse"
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Messages.Comp.NotificationHttpForm exposing
|
||||
( Texts
|
||||
, de
|
||||
, gb
|
||||
)
|
||||
|
||||
import Messages.Basics
|
||||
|
||||
|
||||
type alias Texts =
|
||||
{ basics : Messages.Basics.Texts
|
||||
, httpUrl : String
|
||||
}
|
||||
|
||||
|
||||
gb : Texts
|
||||
gb =
|
||||
{ basics = Messages.Basics.gb
|
||||
, httpUrl = "Http URL"
|
||||
}
|
||||
|
||||
|
||||
de : Texts
|
||||
de =
|
||||
{ basics = Messages.Basics.de
|
||||
, httpUrl = "URL"
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Messages.Comp.NotificationMailForm exposing
|
||||
( Texts
|
||||
, de
|
||||
, gb
|
||||
)
|
||||
|
||||
import Messages.Basics
|
||||
|
||||
|
||||
type alias Texts =
|
||||
{ basics : Messages.Basics.Texts
|
||||
, selectConnection : String
|
||||
, sendVia : String
|
||||
, sendViaInfo : String
|
||||
, recipients : String
|
||||
, recipientsInfo : String
|
||||
, recipientsRequired : String
|
||||
}
|
||||
|
||||
|
||||
gb : Texts
|
||||
gb =
|
||||
{ basics = Messages.Basics.gb
|
||||
, selectConnection = "Select connection..."
|
||||
, sendVia = "Send via"
|
||||
, sendViaInfo = "The SMTP connection to use when sending notification mails."
|
||||
, recipients = "Recipient(s)"
|
||||
, recipientsInfo = "One or more mail addresses, confirm each by pressing 'Return'."
|
||||
, recipientsRequired = "At least one recipient is required."
|
||||
}
|
||||
|
||||
|
||||
de : Texts
|
||||
de =
|
||||
{ basics = Messages.Basics.de
|
||||
, selectConnection = "Verbindung auswählen…"
|
||||
, sendVia = "Senden via"
|
||||
, sendViaInfo = "Die SMTP-Verbindung, die zum Senden der Benachrichtigungs-E-Mails verwendet werden soll."
|
||||
, recipients = "Empfänger"
|
||||
, recipientsInfo = "Eine oder mehrere E-Mail-Adressen, jede mit 'Eingabe' bestätigen."
|
||||
, recipientsRequired = "Mindestens ein Empfänger muss angegeben werden."
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Messages.Comp.NotificationMatrixForm exposing
|
||||
( Texts
|
||||
, de
|
||||
, gb
|
||||
)
|
||||
|
||||
import Messages.Basics
|
||||
|
||||
|
||||
type alias Texts =
|
||||
{ basics : Messages.Basics.Texts
|
||||
, homeServer : String
|
||||
, roomId : String
|
||||
, accessKey : String
|
||||
}
|
||||
|
||||
|
||||
gb : Texts
|
||||
gb =
|
||||
{ basics = Messages.Basics.gb
|
||||
, homeServer = "Homeserver URL"
|
||||
, roomId = "Room ID"
|
||||
, accessKey = "Access Token"
|
||||
}
|
||||
|
||||
|
||||
de : Texts
|
||||
de =
|
||||
{ basics = Messages.Basics.de
|
||||
, homeServer = "Homeserver URL"
|
||||
, roomId = "Room ID"
|
||||
, accessKey = "Access Token"
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Messages.Comp.PeriodicQueryTaskForm exposing
|
||||
( Texts
|
||||
, de
|
||||
, gb
|
||||
)
|
||||
|
||||
import Data.ChannelType exposing (ChannelType)
|
||||
import Http
|
||||
import Messages.Basics
|
||||
import Messages.Comp.CalEventInput
|
||||
import Messages.Comp.ChannelForm
|
||||
import Messages.Comp.HttpError
|
||||
import Messages.Data.ChannelType
|
||||
|
||||
|
||||
type alias Texts =
|
||||
{ basics : Messages.Basics.Texts
|
||||
, calEventInput : Messages.Comp.CalEventInput.Texts
|
||||
, channelForm : Messages.Comp.ChannelForm.Texts
|
||||
, httpError : Http.Error -> String
|
||||
, reallyDeleteTask : String
|
||||
, startOnce : String
|
||||
, startTaskNow : String
|
||||
, deleteThisTask : String
|
||||
, enableDisable : String
|
||||
, summary : String
|
||||
, summaryInfo : String
|
||||
, schedule : String
|
||||
, scheduleClickForHelp : String
|
||||
, scheduleInfo : String
|
||||
, queryLabel : String
|
||||
, invalidCalEvent : String
|
||||
, channelRequired : String
|
||||
, queryStringRequired : String
|
||||
, channelHeader : ChannelType -> String
|
||||
}
|
||||
|
||||
|
||||
gb : Texts
|
||||
gb =
|
||||
{ basics = Messages.Basics.gb
|
||||
, calEventInput = Messages.Comp.CalEventInput.gb
|
||||
, channelForm = Messages.Comp.ChannelForm.gb
|
||||
, httpError = Messages.Comp.HttpError.gb
|
||||
, reallyDeleteTask = "Really delete this notification task?"
|
||||
, startOnce = "Start Once"
|
||||
, startTaskNow = "Start this task now"
|
||||
, deleteThisTask = "Delete this task"
|
||||
, enableDisable = "Enable or disable this task."
|
||||
, summary = "Summary"
|
||||
, summaryInfo = "Some human readable name, only for displaying"
|
||||
, schedule = "Schedule"
|
||||
, scheduleClickForHelp = "Click here for help"
|
||||
, scheduleInfo =
|
||||
"Specify how often and when this task should run. "
|
||||
++ "Use English 3-letter weekdays. Either a single value, "
|
||||
++ "a list (ex. 1,2,3), a range (ex. 1..3) or a '*' (meaning all) "
|
||||
++ "is allowed for each part."
|
||||
, invalidCalEvent = "The calendar event is not valid."
|
||||
, queryLabel = "Query"
|
||||
, channelRequired = "A valid channel must be given."
|
||||
, queryStringRequired = "A query string must be supplied"
|
||||
, channelHeader = \ct -> "Connection details for " ++ Messages.Data.ChannelType.gb ct
|
||||
}
|
||||
|
||||
|
||||
de : Texts
|
||||
de =
|
||||
{ basics = Messages.Basics.de
|
||||
, calEventInput = Messages.Comp.CalEventInput.de
|
||||
, channelForm = Messages.Comp.ChannelForm.de
|
||||
, httpError = Messages.Comp.HttpError.de
|
||||
, reallyDeleteTask = "Diesen Benachrichtigungsauftrag wirklich löschen?"
|
||||
, startOnce = "Jetzt starten"
|
||||
, startTaskNow = "Starte den Auftrag sofort"
|
||||
, deleteThisTask = "Den Auftrag löschen"
|
||||
, enableDisable = "Auftrag aktivieren oder deaktivieren"
|
||||
, summary = "Kurzbeschreibung"
|
||||
, summaryInfo = "Eine kurze lesbare Zusammenfassung, nur für die Anzeige"
|
||||
, schedule = "Zeitplan"
|
||||
, scheduleClickForHelp = "Klicke für Hilfe"
|
||||
, scheduleInfo =
|
||||
"Gib an, wie oft und wann der Auftrag laufen soll. "
|
||||
++ "Verwende englische 3-Buchstaben Wochentage. Entweder ein einzelner Wert, "
|
||||
++ "eine Liste (wie `1,2,3`), eine Bereich (wie `1..3`) oder ein '*' (für alle) "
|
||||
++ "ist mögich für jeden Teil."
|
||||
, invalidCalEvent = "Das Kalenderereignis ist nicht gültig."
|
||||
, queryLabel = "Abfrage"
|
||||
, channelRequired = "Ein Versandkanal muss angegeben werden."
|
||||
, queryStringRequired = "Eine Suchabfrage muss angegeben werden."
|
||||
, channelHeader = \ct -> "Details für " ++ Messages.Data.ChannelType.de ct
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Messages.Comp.PeriodicQueryTaskList exposing
|
||||
( Texts
|
||||
, de
|
||||
, gb
|
||||
)
|
||||
|
||||
import Messages.Basics
|
||||
|
||||
|
||||
type alias Texts =
|
||||
{ basics : Messages.Basics.Texts
|
||||
, summary : String
|
||||
, schedule : String
|
||||
, connection : String
|
||||
, recipients : String
|
||||
}
|
||||
|
||||
|
||||
gb : Texts
|
||||
gb =
|
||||
{ basics = Messages.Basics.gb
|
||||
, summary = "Summary"
|
||||
, schedule = "Schedule"
|
||||
, connection = "Connection"
|
||||
, recipients = "Recipients"
|
||||
}
|
||||
|
||||
|
||||
de : Texts
|
||||
de =
|
||||
{ basics = Messages.Basics.de
|
||||
, summary = "Kurzbeschreibung"
|
||||
, schedule = "Zeitplan"
|
||||
, connection = "Verbindung"
|
||||
, recipients = "Empfänger"
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Messages.Comp.PeriodicQueryTaskManage exposing
|
||||
( Texts
|
||||
, de
|
||||
, gb
|
||||
)
|
||||
|
||||
import Http
|
||||
import Messages.Basics
|
||||
import Messages.Comp.HttpError
|
||||
import Messages.Comp.PeriodicQueryTaskForm
|
||||
import Messages.Comp.PeriodicQueryTaskList
|
||||
import Messages.Data.ChannelType
|
||||
|
||||
|
||||
type alias Texts =
|
||||
{ basics : Messages.Basics.Texts
|
||||
, notificationForm : Messages.Comp.PeriodicQueryTaskForm.Texts
|
||||
, notificationTable : Messages.Comp.PeriodicQueryTaskList.Texts
|
||||
, httpError : Http.Error -> String
|
||||
, channelType : Messages.Data.ChannelType.Texts
|
||||
, newTask : String
|
||||
, createNewTask : String
|
||||
, taskCreated : String
|
||||
, taskUpdated : String
|
||||
, taskStarted : String
|
||||
, taskDeleted : String
|
||||
, matrix : String
|
||||
, gotify : String
|
||||
, email : String
|
||||
, httpRequest : String
|
||||
}
|
||||
|
||||
|
||||
gb : Texts
|
||||
gb =
|
||||
{ basics = Messages.Basics.gb
|
||||
, notificationForm = Messages.Comp.PeriodicQueryTaskForm.gb
|
||||
, notificationTable = Messages.Comp.PeriodicQueryTaskList.gb
|
||||
, httpError = Messages.Comp.HttpError.gb
|
||||
, channelType = Messages.Data.ChannelType.gb
|
||||
, newTask = "New Task"
|
||||
, createNewTask = "Create a new notification task"
|
||||
, taskCreated = "Task created."
|
||||
, taskUpdated = "Task updated."
|
||||
, taskStarted = "Task started."
|
||||
, taskDeleted = "Task deleted."
|
||||
, matrix = "Matrix"
|
||||
, gotify = "Gotify"
|
||||
, email = "E-Mail"
|
||||
, httpRequest = "HTTP Request"
|
||||
}
|
||||
|
||||
|
||||
de : Texts
|
||||
de =
|
||||
{ basics = Messages.Basics.de
|
||||
, notificationForm = Messages.Comp.PeriodicQueryTaskForm.de
|
||||
, notificationTable = Messages.Comp.PeriodicQueryTaskList.de
|
||||
, httpError = Messages.Comp.HttpError.de
|
||||
, channelType = Messages.Data.ChannelType.de
|
||||
, newTask = "Neuer Auftrag"
|
||||
, createNewTask = "Erstelle einen neuen Benachrichtigungsauftrag"
|
||||
, taskCreated = "Auftrag erstellt."
|
||||
, taskUpdated = "Auftrag aktualisiert."
|
||||
, taskStarted = "Auftrag gestartet."
|
||||
, taskDeleted = "Auftrag gelöscht."
|
||||
, matrix = "Matrix"
|
||||
, gotify = "Gotify"
|
||||
, email = "E-Mail"
|
||||
, httpRequest = "HTTP Request"
|
||||
}
|
46
modules/webapp/src/main/elm/Messages/Data/ChannelType.elm
Normal file
46
modules/webapp/src/main/elm/Messages/Data/ChannelType.elm
Normal file
@ -0,0 +1,46 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Messages.Data.ChannelType exposing (Texts, de, gb)
|
||||
|
||||
import Data.ChannelType exposing (ChannelType)
|
||||
|
||||
|
||||
type alias Texts =
|
||||
ChannelType -> String
|
||||
|
||||
|
||||
gb : Texts
|
||||
gb ct =
|
||||
case ct of
|
||||
Data.ChannelType.Matrix ->
|
||||
"Matrix"
|
||||
|
||||
Data.ChannelType.Gotify ->
|
||||
"Gotify"
|
||||
|
||||
Data.ChannelType.Mail ->
|
||||
"E-Mail"
|
||||
|
||||
Data.ChannelType.Http ->
|
||||
"HTTP request"
|
||||
|
||||
|
||||
de : Texts
|
||||
de ct =
|
||||
case ct of
|
||||
Data.ChannelType.Matrix ->
|
||||
"Matrix"
|
||||
|
||||
Data.ChannelType.Gotify ->
|
||||
"Gotify"
|
||||
|
||||
Data.ChannelType.Mail ->
|
||||
"E-Mail"
|
||||
|
||||
Data.ChannelType.Http ->
|
||||
"HTTP Request"
|
78
modules/webapp/src/main/elm/Messages/Data/EventType.elm
Normal file
78
modules/webapp/src/main/elm/Messages/Data/EventType.elm
Normal file
@ -0,0 +1,78 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Messages.Data.EventType exposing
|
||||
( Texts
|
||||
, de
|
||||
, gb
|
||||
)
|
||||
|
||||
import Data.EventType exposing (EventType(..))
|
||||
|
||||
|
||||
type alias Texts =
|
||||
{ name : String
|
||||
, info : String
|
||||
}
|
||||
|
||||
|
||||
gb : EventType -> Texts
|
||||
gb et =
|
||||
case et of
|
||||
TagsChanged ->
|
||||
{ name = "Tags changed"
|
||||
, info = "Whenever a tag on an item is added or removed"
|
||||
}
|
||||
|
||||
SetFieldValue ->
|
||||
{ name = "Set field value"
|
||||
, info = "Whenever a custom field is set to a value"
|
||||
}
|
||||
|
||||
DeleteFieldValue ->
|
||||
{ name = "Delete field value"
|
||||
, info = "Whenever a custom field is removed"
|
||||
}
|
||||
|
||||
JobSubmitted ->
|
||||
{ name = "Job submitted"
|
||||
, info = "Whenever a new job is submitted"
|
||||
}
|
||||
|
||||
JobDone ->
|
||||
{ name = "Job done"
|
||||
, info = "Whenever a new job finished"
|
||||
}
|
||||
|
||||
|
||||
de : EventType -> Texts
|
||||
de et =
|
||||
case et of
|
||||
TagsChanged ->
|
||||
{ name = "Tags geändert"
|
||||
, info = "Wenn ein tag hinzugefügt oder entfernt wird"
|
||||
}
|
||||
|
||||
SetFieldValue ->
|
||||
{ name = "Benutzerfeldwert ändert"
|
||||
, info = "Wenn für ein Benutzerfeld ein Wert gesetzt wird"
|
||||
}
|
||||
|
||||
DeleteFieldValue ->
|
||||
{ name = "Benutzerfeldwert entfernt"
|
||||
, info = "Wenn der Wert für ein Benuzterfeld entfernt wird"
|
||||
}
|
||||
|
||||
JobSubmitted ->
|
||||
{ name = "Auftrag gestartet"
|
||||
, info = "Wenn ein neuer Auftrag gestartet wird"
|
||||
}
|
||||
|
||||
JobDone ->
|
||||
{ name = "Auftrag beendet"
|
||||
, info = "Wenn ein Auftrag beendet wurde"
|
||||
}
|
@ -12,10 +12,12 @@ module Messages.Page.UserSettings exposing
|
||||
)
|
||||
|
||||
import Messages.Comp.ChangePasswordForm
|
||||
import Messages.Comp.DueItemsTaskManage
|
||||
import Messages.Comp.EmailSettingsManage
|
||||
import Messages.Comp.ImapSettingsManage
|
||||
import Messages.Comp.NotificationManage
|
||||
import Messages.Comp.NotificationHookManage
|
||||
import Messages.Comp.OtpSetup
|
||||
import Messages.Comp.PeriodicQueryTaskManage
|
||||
import Messages.Comp.ScanMailboxManage
|
||||
import Messages.Comp.UiSettingsManage
|
||||
|
||||
@ -25,8 +27,10 @@ type alias Texts =
|
||||
, uiSettingsManage : Messages.Comp.UiSettingsManage.Texts
|
||||
, emailSettingsManage : Messages.Comp.EmailSettingsManage.Texts
|
||||
, imapSettingsManage : Messages.Comp.ImapSettingsManage.Texts
|
||||
, notificationManage : Messages.Comp.NotificationManage.Texts
|
||||
, notificationManage : Messages.Comp.DueItemsTaskManage.Texts
|
||||
, scanMailboxManage : Messages.Comp.ScanMailboxManage.Texts
|
||||
, notificationHookManage : Messages.Comp.NotificationHookManage.Texts
|
||||
, periodicQueryTask : Messages.Comp.PeriodicQueryTaskManage.Texts
|
||||
, otpSetup : Messages.Comp.OtpSetup.Texts
|
||||
, userSettings : String
|
||||
, uiSettings : String
|
||||
@ -36,11 +40,16 @@ type alias Texts =
|
||||
, emailSettingImap : String
|
||||
, changePassword : String
|
||||
, uiSettingsInfo : String
|
||||
, notificationInfoText : String
|
||||
, notificationRemindDaysInfo : String
|
||||
, scanMailboxInfo1 : String
|
||||
, scanMailboxInfo2 : String
|
||||
, otpMenu : String
|
||||
, webhooks : String
|
||||
, genericQueries : String
|
||||
, dueItems : String
|
||||
, notificationInfoText : String
|
||||
, webhookInfoText : String
|
||||
, dueItemsInfoText : String
|
||||
, periodicQueryInfoText : String
|
||||
}
|
||||
|
||||
|
||||
@ -50,8 +59,10 @@ gb =
|
||||
, uiSettingsManage = Messages.Comp.UiSettingsManage.gb
|
||||
, emailSettingsManage = Messages.Comp.EmailSettingsManage.gb
|
||||
, imapSettingsManage = Messages.Comp.ImapSettingsManage.gb
|
||||
, notificationManage = Messages.Comp.NotificationManage.gb
|
||||
, notificationManage = Messages.Comp.DueItemsTaskManage.gb
|
||||
, scanMailboxManage = Messages.Comp.ScanMailboxManage.gb
|
||||
, notificationHookManage = Messages.Comp.NotificationHookManage.gb
|
||||
, periodicQueryTask = Messages.Comp.PeriodicQueryTaskManage.gb
|
||||
, otpSetup = Messages.Comp.OtpSetup.gb
|
||||
, userSettings = "User Settings"
|
||||
, uiSettings = "UI Settings"
|
||||
@ -63,13 +74,6 @@ gb =
|
||||
, uiSettingsInfo =
|
||||
"These settings only affect the web ui. They are stored in the browser, "
|
||||
++ "so they are separated between browsers and devices."
|
||||
, notificationInfoText =
|
||||
"""
|
||||
Docspell can notify you once the due dates of your items
|
||||
come closer. Notification is done via e-mail. You need to
|
||||
provide a connection in your e-mail settings."""
|
||||
, notificationRemindDaysInfo =
|
||||
"Docspell finds all items that are due in *Remind Days* days and sends this list via e-mail."
|
||||
, scanMailboxInfo1 =
|
||||
"Docspell can scan folders of your mailbox to import your mails. "
|
||||
++ "You need to provide a connection in "
|
||||
@ -85,6 +89,28 @@ gb =
|
||||
adjust the schedule to avoid reading over the same mails
|
||||
again."""
|
||||
, otpMenu = "Two Factor Authentication"
|
||||
, webhooks = "Webhooks"
|
||||
, genericQueries = "Generic Queries"
|
||||
, dueItems = "Due Items Query"
|
||||
, notificationInfoText = """
|
||||
|
||||
Docspell can send notification messages on various events. You can
|
||||
choose from these channels to send messages:
|
||||
[Matrix](https://matrix.org), [Gotify](https://gotify.net) or E-Mail.
|
||||
At last you can send a plain http request with the event details in
|
||||
its payload.
|
||||
|
||||
Additionally, you can setup queries that are executed periodically.
|
||||
The results are send as a notification message.
|
||||
|
||||
When creating a new notification task, choose first the communication
|
||||
channel.
|
||||
|
||||
"""
|
||||
, webhookInfoText = """Webhooks execute http request upon certain events in docspell.
|
||||
"""
|
||||
, dueItemsInfoText = """Docspell can notify you once the due dates of your items come closer. """
|
||||
, periodicQueryInfoText = "You can define a custom query that gets executed periodically."
|
||||
}
|
||||
|
||||
|
||||
@ -94,8 +120,10 @@ de =
|
||||
, uiSettingsManage = Messages.Comp.UiSettingsManage.de
|
||||
, emailSettingsManage = Messages.Comp.EmailSettingsManage.de
|
||||
, imapSettingsManage = Messages.Comp.ImapSettingsManage.de
|
||||
, notificationManage = Messages.Comp.NotificationManage.de
|
||||
, notificationManage = Messages.Comp.DueItemsTaskManage.de
|
||||
, scanMailboxManage = Messages.Comp.ScanMailboxManage.de
|
||||
, notificationHookManage = Messages.Comp.NotificationHookManage.de
|
||||
, periodicQueryTask = Messages.Comp.PeriodicQueryTaskManage.de
|
||||
, otpSetup = Messages.Comp.OtpSetup.de
|
||||
, userSettings = "Benutzereinstellung"
|
||||
, uiSettings = "Oberfläche"
|
||||
@ -106,13 +134,6 @@ de =
|
||||
, changePassword = "Passwort ändern"
|
||||
, uiSettingsInfo =
|
||||
"Diese Einstellungen sind für die Web-Oberfläche."
|
||||
, notificationInfoText =
|
||||
"""
|
||||
Docspell kann eine E-Mail versenden, sobald das
|
||||
Fälligkeitsdatum von Dokumenten näher kommt. Dafür muss eine
|
||||
E-Mail-SMTP-Verbindung konfiguriert werden.."""
|
||||
, notificationRemindDaysInfo =
|
||||
"Docspell sucht Dokumente die in X Tagen fällig sind und sendet diese Liste als E-Mail."
|
||||
, scanMailboxInfo1 =
|
||||
"""Docspell kann Postfächer durchsuchen und E-Mails importieren. Dafür sind
|
||||
E-Mail-Einstellungen (IMAP) notwendig."""
|
||||
@ -129,4 +150,26 @@ E-Mail-Einstellungen (IMAP) notwendig."""
|
||||
gleichen E-Mails möglichst nicht noch einmal eingelesen
|
||||
werden."""
|
||||
, otpMenu = "Zwei-Faktor-Authentifizierung"
|
||||
, webhooks = "Webhooks"
|
||||
, genericQueries = "Periodische Abfragen"
|
||||
, dueItems = "Fällige Dokumente"
|
||||
, notificationInfoText = """
|
||||
|
||||
Docspell kann Benachrichtigungen bei gewissen Ereignissen versenden.
|
||||
Es kann aus diesen Versandkanälen gewählt werden:
|
||||
[Matrix](https://matrix.org), [Gotify](https://gotify.net) oder
|
||||
E-Mail. Zusätzlich kann das HTTP request direkt empfangen werden, was
|
||||
alle Details zu einem Ereignis enthält.
|
||||
|
||||
|
||||
Ausserdem können periodische Suchabfragen erstellt werden, dessen
|
||||
Ergebnis dann als Benachrichtigung versendet wird.
|
||||
|
||||
Beim Erstellen eines neuen Auftrags muss zunächst der gewünschte
|
||||
Versandkanal gewählt werden.
|
||||
|
||||
"""
|
||||
, webhookInfoText = """Webhooks versenden HTTP Requests wenn bestimmte Ereignisse in Docspell auftreten."""
|
||||
, dueItemsInfoText = """Docspell kann dich benachrichtigen, sobald das Fälligkeitsdatum von Dokumenten näher kommt. """
|
||||
, periodicQueryInfoText = "Hier können beliebige Abfragen definiert werden, welche regelmäßig ausgeführt werden."
|
||||
}
|
||||
|
@ -13,10 +13,12 @@ module Page.UserSettings.Data exposing
|
||||
)
|
||||
|
||||
import Comp.ChangePasswordForm
|
||||
import Comp.DueItemsTaskManage
|
||||
import Comp.EmailSettingsManage
|
||||
import Comp.ImapSettingsManage
|
||||
import Comp.NotificationManage
|
||||
import Comp.NotificationHookManage
|
||||
import Comp.OtpSetup
|
||||
import Comp.PeriodicQueryTaskManage
|
||||
import Comp.ScanMailboxManage
|
||||
import Comp.UiSettingsManage
|
||||
import Data.Flags exposing (Flags)
|
||||
@ -28,10 +30,12 @@ type alias Model =
|
||||
, changePassModel : Comp.ChangePasswordForm.Model
|
||||
, emailSettingsModel : Comp.EmailSettingsManage.Model
|
||||
, imapSettingsModel : Comp.ImapSettingsManage.Model
|
||||
, notificationModel : Comp.NotificationManage.Model
|
||||
, notificationModel : Comp.DueItemsTaskManage.Model
|
||||
, scanMailboxModel : Comp.ScanMailboxManage.Model
|
||||
, uiSettingsModel : Comp.UiSettingsManage.Model
|
||||
, otpSetupModel : Comp.OtpSetup.Model
|
||||
, notificationHookModel : Comp.NotificationHookManage.Model
|
||||
, periodicQueryModel : Comp.PeriodicQueryTaskManage.Model
|
||||
}
|
||||
|
||||
|
||||
@ -43,19 +47,29 @@ init flags settings =
|
||||
|
||||
( otpm, otpc ) =
|
||||
Comp.OtpSetup.init flags
|
||||
|
||||
( nhm, nhc ) =
|
||||
Comp.NotificationHookManage.init flags
|
||||
|
||||
( pqm, pqc ) =
|
||||
Comp.PeriodicQueryTaskManage.init flags
|
||||
in
|
||||
( { currentTab = Just UiSettingsTab
|
||||
, changePassModel = Comp.ChangePasswordForm.emptyModel
|
||||
, emailSettingsModel = Comp.EmailSettingsManage.emptyModel
|
||||
, imapSettingsModel = Comp.ImapSettingsManage.emptyModel
|
||||
, notificationModel = Tuple.first (Comp.NotificationManage.init flags)
|
||||
, notificationModel = Tuple.first (Comp.DueItemsTaskManage.init flags)
|
||||
, scanMailboxModel = Tuple.first (Comp.ScanMailboxManage.init flags)
|
||||
, uiSettingsModel = um
|
||||
, otpSetupModel = otpm
|
||||
, notificationHookModel = nhm
|
||||
, periodicQueryModel = pqm
|
||||
}
|
||||
, Cmd.batch
|
||||
[ Cmd.map UiSettingsMsg uc
|
||||
, Cmd.map OtpSetupMsg otpc
|
||||
, Cmd.map NotificationHookMsg nhc
|
||||
, Cmd.map PeriodicQueryMsg pqc
|
||||
]
|
||||
)
|
||||
|
||||
@ -65,6 +79,9 @@ type Tab
|
||||
| EmailSettingsTab
|
||||
| ImapSettingsTab
|
||||
| NotificationTab
|
||||
| NotificationWebhookTab
|
||||
| NotificationQueriesTab
|
||||
| NotificationDueItemsTab
|
||||
| ScanMailboxTab
|
||||
| UiSettingsTab
|
||||
| OtpTab
|
||||
@ -74,10 +91,12 @@ type Msg
|
||||
= SetTab Tab
|
||||
| ChangePassMsg Comp.ChangePasswordForm.Msg
|
||||
| EmailSettingsMsg Comp.EmailSettingsManage.Msg
|
||||
| NotificationMsg Comp.NotificationManage.Msg
|
||||
| NotificationMsg Comp.DueItemsTaskManage.Msg
|
||||
| ImapSettingsMsg Comp.ImapSettingsManage.Msg
|
||||
| ScanMailboxMsg Comp.ScanMailboxManage.Msg
|
||||
| UiSettingsMsg Comp.UiSettingsManage.Msg
|
||||
| OtpSetupMsg Comp.OtpSetup.Msg
|
||||
| NotificationHookMsg Comp.NotificationHookManage.Msg
|
||||
| PeriodicQueryMsg Comp.PeriodicQueryTaskManage.Msg
|
||||
| UpdateSettings
|
||||
| ReceiveBrowserSettings StoredUiSettings
|
||||
|
@ -8,10 +8,12 @@
|
||||
module Page.UserSettings.Update exposing (UpdateResult, update)
|
||||
|
||||
import Comp.ChangePasswordForm
|
||||
import Comp.DueItemsTaskManage
|
||||
import Comp.EmailSettingsManage
|
||||
import Comp.ImapSettingsManage
|
||||
import Comp.NotificationManage
|
||||
import Comp.NotificationHookManage
|
||||
import Comp.OtpSetup
|
||||
import Comp.PeriodicQueryTaskManage
|
||||
import Comp.ScanMailboxManage
|
||||
import Comp.UiSettingsManage
|
||||
import Data.Flags exposing (Flags)
|
||||
@ -62,10 +64,32 @@ update flags settings msg model =
|
||||
UpdateResult m Cmd.none Sub.none Nothing
|
||||
|
||||
NotificationTab ->
|
||||
{ model = m
|
||||
, cmd = Cmd.none
|
||||
, sub = Sub.none
|
||||
, newSettings = Nothing
|
||||
}
|
||||
|
||||
NotificationWebhookTab ->
|
||||
{ model = m
|
||||
, cmd = Cmd.none
|
||||
, sub = Sub.none
|
||||
, newSettings = Nothing
|
||||
}
|
||||
|
||||
NotificationQueriesTab ->
|
||||
let
|
||||
initCmd =
|
||||
Cmd.map NotificationMsg
|
||||
(Tuple.second (Comp.NotificationManage.init flags))
|
||||
(Tuple.second (Comp.DueItemsTaskManage.init flags))
|
||||
in
|
||||
UpdateResult m initCmd Sub.none Nothing
|
||||
|
||||
NotificationDueItemsTab ->
|
||||
let
|
||||
initCmd =
|
||||
Cmd.map NotificationMsg
|
||||
(Tuple.second (Comp.DueItemsTaskManage.init flags))
|
||||
in
|
||||
UpdateResult m initCmd Sub.none Nothing
|
||||
|
||||
@ -119,7 +143,7 @@ update flags settings msg model =
|
||||
NotificationMsg lm ->
|
||||
let
|
||||
( m2, c2 ) =
|
||||
Comp.NotificationManage.update flags lm model.notificationModel
|
||||
Comp.DueItemsTaskManage.update flags lm model.notificationModel
|
||||
in
|
||||
{ model = { model | notificationModel = m2 }
|
||||
, cmd = Cmd.map NotificationMsg c2
|
||||
@ -160,6 +184,17 @@ update flags settings msg model =
|
||||
, newSettings = Nothing
|
||||
}
|
||||
|
||||
NotificationHookMsg lm ->
|
||||
let
|
||||
( hm, hc ) =
|
||||
Comp.NotificationHookManage.update flags lm model.notificationHookModel
|
||||
in
|
||||
{ model = { model | notificationHookModel = hm }
|
||||
, cmd = Cmd.map NotificationHookMsg hc
|
||||
, sub = Sub.none
|
||||
, newSettings = Nothing
|
||||
}
|
||||
|
||||
UpdateSettings ->
|
||||
update flags
|
||||
settings
|
||||
@ -172,3 +207,14 @@ update flags settings msg model =
|
||||
Comp.UiSettingsManage.ReceiveBrowserSettings sett
|
||||
in
|
||||
update flags settings (UiSettingsMsg lm) model
|
||||
|
||||
PeriodicQueryMsg lm ->
|
||||
let
|
||||
( pqm, pqc, pqs ) =
|
||||
Comp.PeriodicQueryTaskManage.update flags lm model.periodicQueryModel
|
||||
in
|
||||
{ model = { model | periodicQueryModel = pqm }
|
||||
, cmd = Cmd.map PeriodicQueryMsg pqc
|
||||
, sub = Sub.map PeriodicQueryMsg pqs
|
||||
, newSettings = Nothing
|
||||
}
|
||||
|
@ -8,10 +8,12 @@
|
||||
module Page.UserSettings.View2 exposing (viewContent, viewSidebar)
|
||||
|
||||
import Comp.ChangePasswordForm
|
||||
import Comp.DueItemsTaskManage
|
||||
import Comp.EmailSettingsManage
|
||||
import Comp.ImapSettingsManage
|
||||
import Comp.NotificationManage
|
||||
import Comp.NotificationHookManage
|
||||
import Comp.OtpSetup
|
||||
import Comp.PeriodicQueryTaskManage
|
||||
import Comp.ScanMailboxManage
|
||||
import Comp.UiSettingsManage
|
||||
import Data.Flags exposing (Flags)
|
||||
@ -27,6 +29,24 @@ import Styles as S
|
||||
|
||||
viewSidebar : Texts -> Bool -> Flags -> UiSettings -> Model -> Html Msg
|
||||
viewSidebar texts visible _ _ model =
|
||||
let
|
||||
isNotificationTab =
|
||||
case model.currentTab of
|
||||
Just NotificationTab ->
|
||||
True
|
||||
|
||||
Just NotificationQueriesTab ->
|
||||
True
|
||||
|
||||
Just NotificationWebhookTab ->
|
||||
True
|
||||
|
||||
Just NotificationDueItemsTab ->
|
||||
True
|
||||
|
||||
_ ->
|
||||
False
|
||||
in
|
||||
div
|
||||
[ id "sidebar"
|
||||
, class S.sidebar
|
||||
@ -50,16 +70,56 @@ viewSidebar texts visible _ _ model =
|
||||
[ class "ml-3" ]
|
||||
[ text texts.uiSettings ]
|
||||
]
|
||||
, a
|
||||
[ href "#"
|
||||
, onClick (SetTab NotificationTab)
|
||||
, menuEntryActive model NotificationTab
|
||||
, class S.sidebarLink
|
||||
]
|
||||
[ i [ class "fa fa-bullhorn" ] []
|
||||
, span
|
||||
[ class "ml-3" ]
|
||||
[ text texts.notifications ]
|
||||
, div []
|
||||
[ a
|
||||
[ href "#"
|
||||
, onClick (SetTab NotificationTab)
|
||||
, menuEntryActive model NotificationTab
|
||||
, class S.sidebarLink
|
||||
]
|
||||
[ i [ class "fa fa-bullhorn" ] []
|
||||
, span
|
||||
[ class "ml-3" ]
|
||||
[ text texts.notifications ]
|
||||
]
|
||||
, div
|
||||
[ class "ml-5 flex flex-col"
|
||||
, classList [ ( "hidden", not isNotificationTab ) ]
|
||||
]
|
||||
[ a
|
||||
[ href "#"
|
||||
, onClick (SetTab NotificationWebhookTab)
|
||||
, menuEntryActive model NotificationWebhookTab
|
||||
, class S.sidebarLink
|
||||
]
|
||||
[ i [ class "fa fa-bell" ] []
|
||||
, span
|
||||
[ class "ml-3" ]
|
||||
[ text texts.webhooks ]
|
||||
]
|
||||
, a
|
||||
[ href "#"
|
||||
, onClick (SetTab NotificationDueItemsTab)
|
||||
, menuEntryActive model NotificationDueItemsTab
|
||||
, class S.sidebarLink
|
||||
]
|
||||
[ i [ class "fa fa-history" ] []
|
||||
, span
|
||||
[ class "ml-3" ]
|
||||
[ text texts.dueItems ]
|
||||
]
|
||||
, a
|
||||
[ href "#"
|
||||
, onClick (SetTab NotificationQueriesTab)
|
||||
, menuEntryActive model NotificationQueriesTab
|
||||
, class S.sidebarLink
|
||||
]
|
||||
[ i [ class "fa fa-history" ] []
|
||||
, span
|
||||
[ class "ml-3" ]
|
||||
[ text texts.genericQueries ]
|
||||
]
|
||||
]
|
||||
]
|
||||
, a
|
||||
[ href "#"
|
||||
@ -134,7 +194,16 @@ viewContent texts flags settings model =
|
||||
viewEmailSettings texts settings model
|
||||
|
||||
Just NotificationTab ->
|
||||
viewNotificationManage texts settings model
|
||||
viewNotificationInfo texts settings model
|
||||
|
||||
Just NotificationWebhookTab ->
|
||||
viewNotificationHooks texts settings model
|
||||
|
||||
Just NotificationQueriesTab ->
|
||||
viewNotificationQueries texts settings model
|
||||
|
||||
Just NotificationDueItemsTab ->
|
||||
viewNotificationDueItems texts settings model
|
||||
|
||||
Just ImapSettingsTab ->
|
||||
viewImapSettings texts settings model
|
||||
@ -268,8 +337,8 @@ viewImapSettings texts settings model =
|
||||
]
|
||||
|
||||
|
||||
viewNotificationManage : Texts -> UiSettings -> Model -> List (Html Msg)
|
||||
viewNotificationManage texts settings model =
|
||||
viewNotificationInfo : Texts -> UiSettings -> Model -> List (Html Msg)
|
||||
viewNotificationInfo texts settings model =
|
||||
[ h2
|
||||
[ class S.header1
|
||||
, class "inline-flex items-center"
|
||||
@ -279,20 +348,119 @@ viewNotificationManage texts settings model =
|
||||
[ text texts.notifications
|
||||
]
|
||||
]
|
||||
, p [ class "opacity-80 text-lg mb-3" ]
|
||||
[ text texts.notificationInfoText
|
||||
, Markdown.toHtml [ class "opacity-80 text-lg max-w-prose mb-3 markdown-preview" ] texts.notificationInfoText
|
||||
, div [ class "mt-2" ]
|
||||
[ ul [ class "list-none ml-8" ]
|
||||
[ li [ class "py-2" ]
|
||||
[ a
|
||||
[ href "#"
|
||||
, onClick (SetTab NotificationWebhookTab)
|
||||
, class S.link
|
||||
]
|
||||
[ i [ class "fa fa-bell" ] []
|
||||
, span
|
||||
[ class "ml-3" ]
|
||||
[ text texts.webhooks ]
|
||||
]
|
||||
, div [ class "ml-3 text-sm opacity-50" ]
|
||||
[ text texts.webhookInfoText
|
||||
]
|
||||
]
|
||||
, li [ class "py-2" ]
|
||||
[ a
|
||||
[ href "#"
|
||||
, onClick (SetTab NotificationDueItemsTab)
|
||||
, class S.link
|
||||
]
|
||||
[ i [ class "fa fa-history" ] []
|
||||
, span
|
||||
[ class "ml-3" ]
|
||||
[ text texts.dueItems ]
|
||||
]
|
||||
, div [ class "ml-3 text-sm opacity-50" ]
|
||||
[ text texts.dueItemsInfoText
|
||||
]
|
||||
]
|
||||
, li [ class "py-2" ]
|
||||
[ a
|
||||
[ href "#"
|
||||
, onClick (SetTab NotificationQueriesTab)
|
||||
, class S.link
|
||||
]
|
||||
[ i [ class "fa fa-history" ] []
|
||||
, span
|
||||
[ class "ml-3" ]
|
||||
[ text texts.genericQueries ]
|
||||
]
|
||||
, div [ class "ml-3 text-sm opacity-50" ]
|
||||
[ text texts.periodicQueryInfoText
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
, p [ class "opacity-80 text-lg mb-3" ]
|
||||
[ Markdown.toHtml [] texts.notificationRemindDaysInfo
|
||||
]
|
||||
|
||||
|
||||
viewNotificationDueItems : Texts -> UiSettings -> Model -> List (Html Msg)
|
||||
viewNotificationDueItems texts settings model =
|
||||
[ h2
|
||||
[ class S.header1
|
||||
, class "inline-flex items-center"
|
||||
]
|
||||
[ i [ class "fa fa-history" ] []
|
||||
, div [ class "ml-3" ]
|
||||
[ text texts.dueItems
|
||||
]
|
||||
]
|
||||
, Markdown.toHtml [ class "opacity-80 text-lg mb-3 markdown-preview" ] texts.dueItemsInfoText
|
||||
, Html.map NotificationMsg
|
||||
(Comp.NotificationManage.view2 texts.notificationManage
|
||||
(Comp.DueItemsTaskManage.view2 texts.notificationManage
|
||||
settings
|
||||
model.notificationModel
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
viewNotificationQueries : Texts -> UiSettings -> Model -> List (Html Msg)
|
||||
viewNotificationQueries texts settings model =
|
||||
[ h2
|
||||
[ class S.header1
|
||||
, class "inline-flex items-center"
|
||||
]
|
||||
[ i [ class "fa fa-history" ] []
|
||||
, div [ class "ml-3" ]
|
||||
[ text texts.genericQueries
|
||||
]
|
||||
]
|
||||
, Markdown.toHtml [ class "opacity-80 text-lg mb-3 markdown-preview" ] texts.periodicQueryInfoText
|
||||
, Html.map PeriodicQueryMsg
|
||||
(Comp.PeriodicQueryTaskManage.view texts.periodicQueryTask
|
||||
settings
|
||||
model.periodicQueryModel
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
viewNotificationHooks : Texts -> UiSettings -> Model -> List (Html Msg)
|
||||
viewNotificationHooks texts settings model =
|
||||
[ h2
|
||||
[ class S.header1
|
||||
, class "inline-flex items-center"
|
||||
]
|
||||
[ i [ class "fa fa-bell" ] []
|
||||
, div [ class "ml-3" ]
|
||||
[ text texts.webhooks
|
||||
]
|
||||
]
|
||||
, Markdown.toHtml [ class "opacity-80 text-lg mb-3 markdown-preview" ] texts.webhookInfoText
|
||||
, Html.map NotificationHookMsg
|
||||
(Comp.NotificationHookManage.view texts.notificationHookManage
|
||||
settings
|
||||
model.notificationHookModel
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
viewScanMailboxManage : Texts -> Flags -> UiSettings -> Model -> List (Html Msg)
|
||||
viewScanMailboxManage texts flags settings model =
|
||||
[ h2
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
module Styles exposing (..)
|
||||
|
||||
import Svg exposing (Svg)
|
||||
|
||||
|
||||
sidebar : String
|
||||
sidebar =
|
||||
@ -348,6 +350,11 @@ header3 =
|
||||
" text-xl mb-3 font-medium tracking-wide "
|
||||
|
||||
|
||||
formHeader : String
|
||||
formHeader =
|
||||
header3 ++ " text-xl mb-4 font-medium tracking-wide border-b dark:border-bluegray-300 border-gray-800"
|
||||
|
||||
|
||||
editLinkTableCellStyle : String
|
||||
editLinkTableCellStyle =
|
||||
"w-px whitespace-nowrap pr-2 md:pr-4 py-4 md:py-2"
|
||||
|
Reference in New Issue
Block a user