Change webapp to support multiple scan-mailbox tasks

This commit is contained in:
Eike Kettner 2020-05-21 20:50:40 +02:00
parent 9f9dd6c0fb
commit 920fcf28dd
8 changed files with 535 additions and 88 deletions

View File

@ -4,6 +4,7 @@ module Api exposing
, checkCalEvent
, createImapSettings
, createMailSettings
, createScanMailbox
, deleteAttachment
, deleteEquip
, deleteImapSettings
@ -11,6 +12,7 @@ module Api exposing
, deleteMailSettings
, deleteOrg
, deletePerson
, deleteScanMailbox
, deleteSource
, deleteTag
, deleteUser
@ -67,7 +69,7 @@ module Api exposing
, startOnceNotifyDueItems
, startOnceScanMailbox
, submitNotifyDueItems
, submitScanMailbox
, updateScanMailbox
, upload
, uploadSingle
, versionInfo
@ -109,6 +111,7 @@ import Api.Model.PersonList exposing (PersonList)
import Api.Model.ReferenceList exposing (ReferenceList)
import Api.Model.Registration exposing (Registration)
import Api.Model.ScanMailboxSettings exposing (ScanMailboxSettings)
import Api.Model.ScanMailboxSettingsList exposing (ScanMailboxSettingsList)
import Api.Model.SentMails exposing (SentMails)
import Api.Model.SimpleMail exposing (SimpleMail)
import Api.Model.Source exposing (Source)
@ -134,6 +137,19 @@ import Util.Http as Http2
--- Scan Mailboxes
deleteScanMailbox :
Flags
-> String
-> (Result Http.Error BasicResult -> msg)
-> Cmd msg
deleteScanMailbox flags id receive =
Http2.authDelete
{ url = flags.config.baseUrl ++ "/api/v1/sec/usertask/scanmailbox/" ++ id
, account = getAccount flags
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
}
startOnceScanMailbox :
Flags
-> ScanMailboxSettings
@ -148,12 +164,26 @@ startOnceScanMailbox flags settings receive =
}
submitScanMailbox :
updateScanMailbox :
Flags
-> ScanMailboxSettings
-> (Result Http.Error BasicResult -> msg)
-> Cmd msg
submitScanMailbox flags settings receive =
updateScanMailbox flags settings receive =
Http2.authPut
{ url = flags.config.baseUrl ++ "/api/v1/sec/usertask/scanmailbox"
, account = getAccount flags
, body = Http.jsonBody (Api.Model.ScanMailboxSettings.encode settings)
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
}
createScanMailbox :
Flags
-> ScanMailboxSettings
-> (Result Http.Error BasicResult -> msg)
-> Cmd msg
createScanMailbox flags settings receive =
Http2.authPost
{ url = flags.config.baseUrl ++ "/api/v1/sec/usertask/scanmailbox"
, account = getAccount flags
@ -164,13 +194,13 @@ submitScanMailbox flags settings receive =
getScanMailbox :
Flags
-> (Result Http.Error ScanMailboxSettings -> msg)
-> (Result Http.Error ScanMailboxSettingsList -> msg)
-> Cmd msg
getScanMailbox flags receive =
Http2.authGet
{ url = flags.config.baseUrl ++ "/api/v1/sec/usertask/scanmailbox"
, account = getAccount flags
, expect = Http.expectJson receive Api.Model.ScanMailboxSettings.decoder
, expect = Http.expectJson receive Api.Model.ScanMailboxSettingsList.decoder
}

View File

@ -1,7 +1,9 @@
module Comp.ScanMailboxForm exposing
( Model
( Action(..)
, Model
, Msg
, init
, initWith
, update
, view
)
@ -14,6 +16,7 @@ import Comp.CalEventInput
import Comp.Dropdown
import Comp.IntField
import Comp.StringListInput
import Comp.YesNoDimmer
import Data.CalEvent exposing (CalEvent)
import Data.Direction exposing (Direction(..))
import Data.Flags exposing (Flags)
@ -43,31 +46,75 @@ type alias Model =
, scheduleModel : Comp.CalEventInput.Model
, formMsg : Maybe BasicResult
, loading : Int
, yesNoDelete : Comp.YesNoDimmer.Model
}
type Action
= SubmitAction ScanMailboxSettings
| StartOnceAction ScanMailboxSettings
| CancelAction
| DeleteAction String
| NoAction
type Msg
= Submit
| Cancel
| RequestDelete
| ConnMsg (Comp.Dropdown.Msg String)
| ConnResp (Result Http.Error ImapSettingsList)
| ToggleEnabled
| ToggleDeleteMail
| CalEventMsg Comp.CalEventInput.Msg
| SetScanMailboxSettings (Result Http.Error ScanMailboxSettings)
| SubmitResp (Result Http.Error BasicResult)
| StartOnce
| ReceivedHoursMsg Comp.IntField.Msg
| SetTargetFolder String
| FoldersMsg Comp.StringListInput.Msg
| DirectionMsg (Maybe Direction)
| YesNoDeleteMsg Comp.YesNoDimmer.Msg
initCmd : Flags -> Cmd Msg
initCmd flags =
Cmd.batch
initWith : Flags -> ScanMailboxSettings -> ( Model, Cmd Msg )
initWith flags s =
let
( im, _ ) =
init flags
imap =
Util.Maybe.fromString s.imapConnection
|> Maybe.map List.singleton
|> Maybe.withDefault []
( nm, _, nc ) =
update flags (ConnMsg (Comp.Dropdown.SetSelection imap)) im
newSchedule =
Data.CalEvent.fromEvent s.schedule
|> Maybe.withDefault Data.CalEvent.everyMonth
( sm, sc ) =
Comp.CalEventInput.init flags newSchedule
in
( { nm
| settings = s
, enabled = s.enabled
, deleteMail = s.deleteMail
, receivedHours = s.receivedSinceHours
, targetFolder = s.targetFolder
, folders = s.folders
, schedule = Data.Validated.Unknown newSchedule
, direction = Maybe.andThen Data.Direction.fromString s.direction
, scheduleModel = sm
, formMsg = Nothing
, yesNoDelete = Comp.YesNoDimmer.emptyModel
}
, Cmd.batch
[ Api.getImapSettings flags "" ConnResp
, Api.getScanMailbox flags SetScanMailboxSettings
, nc
, Cmd.map CalEventMsg sc
]
)
init : Flags -> ( Model, Cmd Msg )
@ -96,10 +143,11 @@ init flags =
, schedule = initialSchedule
, scheduleModel = sm
, formMsg = Nothing
, loading = 2
, loading = 1
, yesNoDelete = Comp.YesNoDimmer.emptyModel
}
, Cmd.batch
[ initCmd flags
[ Api.getImapSettings flags "" ConnResp
, Cmd.map CalEventMsg sc
]
)
@ -146,12 +194,13 @@ makeSettings model =
infolders
withValidSettings : (ScanMailboxSettings -> Cmd Msg) -> Model -> ( Model, Cmd Msg )
withValidSettings mkcmd model =
withValidSettings : (ScanMailboxSettings -> Action) -> Model -> ( Model, Action, Cmd Msg )
withValidSettings mkAction model =
case makeSettings model of
Valid set ->
( { model | formMsg = Nothing }
, mkcmd set
, mkAction set
, Cmd.none
)
Invalid errs _ ->
@ -159,15 +208,19 @@ withValidSettings mkcmd model =
errMsg =
String.join ", " errs
in
( { model | formMsg = Just (BasicResult False errMsg) }, Cmd.none )
( { model | formMsg = Just (BasicResult False errMsg) }
, NoAction
, Cmd.none
)
Unknown _ ->
( { model | formMsg = Just (BasicResult False "An unknown error occured") }
, NoAction
, Cmd.none
)
update : Flags -> Msg -> Model -> ( Model, Cmd Msg )
update : Flags -> Msg -> Model -> ( Model, Action, Cmd Msg )
update flags msg model =
case msg of
CalEventMsg lmsg ->
@ -183,6 +236,7 @@ update flags msg model =
, scheduleModel = cm
, formMsg = Nothing
}
, NoAction
, Cmd.map CalEventMsg cc
)
@ -195,6 +249,7 @@ update flags msg model =
| connectionModel = cm
, formMsg = Nothing
}
, NoAction
, Cmd.map ConnMsg cc
)
@ -224,6 +279,7 @@ update flags msg model =
else
Nothing
}
, NoAction
, Cmd.none
)
@ -232,6 +288,7 @@ update flags msg model =
| formMsg = Just (BasicResult False (Util.Http.errorToString err))
, loading = model.loading - 1
}
, NoAction
, Cmd.none
)
@ -240,6 +297,7 @@ update flags msg model =
| enabled = not model.enabled
, formMsg = Nothing
}
, NoAction
, Cmd.none
)
@ -248,6 +306,7 @@ update flags msg model =
| deleteMail = not model.deleteMail
, formMsg = Nothing
}
, NoAction
, Cmd.none
)
@ -261,11 +320,13 @@ update flags msg model =
, receivedHours = val
, formMsg = Nothing
}
, NoAction
, Cmd.none
)
SetTargetFolder str ->
( { model | targetFolder = Util.Maybe.fromString str }
, NoAction
, Cmd.none
)
@ -289,80 +350,55 @@ update flags msg model =
| foldersModel = fm
, folders = newList
}
, NoAction
, Cmd.none
)
DirectionMsg md ->
( { model | direction = md }
, Cmd.none
)
SetScanMailboxSettings (Ok s) ->
let
imap =
Util.Maybe.fromString s.imapConnection
|> Maybe.map List.singleton
|> Maybe.withDefault []
( nm, nc ) =
Util.Update.andThen1
[ update flags (ConnMsg (Comp.Dropdown.SetSelection imap))
]
model
newSchedule =
Data.CalEvent.fromEvent s.schedule
|> Maybe.withDefault Data.CalEvent.everyMonth
( sm, sc ) =
Comp.CalEventInput.init flags newSchedule
in
( { nm
| settings = s
, enabled = s.enabled
, deleteMail = s.deleteMail
, receivedHours = s.receivedSinceHours
, targetFolder = s.targetFolder
, folders = s.folders
, schedule = Data.Validated.Unknown newSchedule
, direction = Maybe.andThen Data.Direction.fromString s.direction
, scheduleModel = sm
, formMsg = Nothing
, loading = model.loading - 1
}
, Cmd.batch
[ nc
, Cmd.map CalEventMsg sc
]
)
SetScanMailboxSettings (Err err) ->
( { model
| formMsg = Just (BasicResult False (Util.Http.errorToString err))
, loading = model.loading - 1
}
, NoAction
, Cmd.none
)
Submit ->
withValidSettings
(\set -> Api.submitScanMailbox flags set SubmitResp)
SubmitAction
model
StartOnce ->
withValidSettings
(\set -> Api.startOnceScanMailbox flags set SubmitResp)
StartOnceAction
model
SubmitResp (Ok res) ->
( { model | formMsg = Just res }
Cancel ->
( model, CancelAction, Cmd.none )
RequestDelete ->
let
( ym, _ ) =
Comp.YesNoDimmer.update
Comp.YesNoDimmer.activate
model.yesNoDelete
in
( { model | yesNoDelete = ym }
, NoAction
, Cmd.none
)
SubmitResp (Err err) ->
( { model
| formMsg = Just (BasicResult False (Util.Http.errorToString err))
}
YesNoDeleteMsg lm ->
let
( ym, flag ) =
Comp.YesNoDimmer.update lm model.yesNoDelete
act =
if flag then
DeleteAction model.settings.id
else
NoAction
in
( { model | yesNoDelete = ym }
, act
, Cmd.none
)
@ -394,7 +430,8 @@ view extraClasses model =
, ( "success", isFormSuccess model )
]
]
[ div
[ Html.map YesNoDeleteMsg (Comp.YesNoDimmer.view model.yesNoDelete)
, div
[ classList
[ ( "ui dimmer", True )
, ( "active", model.loading > 0 )
@ -553,6 +590,18 @@ view extraClasses model =
]
[ text "Submit"
]
, button
[ class "ui secondary button"
, onClick Cancel
]
[ text "Cancel"
]
, button
[ class "ui red button"
, onClick RequestDelete
]
[ text "Delete"
]
, button
[ class "ui right floated button"
, onClick StartOnce

View File

@ -0,0 +1,104 @@
module Comp.ScanMailboxList exposing
( Action(..)
, Model
, Msg
, init
, update
, view
)
import Api.Model.ScanMailboxSettings exposing (ScanMailboxSettings)
import Api.Model.ScanMailboxSettingsList exposing (ScanMailboxSettingsList)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick)
import Util.Html
type alias Model =
{}
type Msg
= EditSettings ScanMailboxSettings
type Action
= NoAction
| EditAction ScanMailboxSettings
init : Model
init =
{}
update : Msg -> Model -> ( Model, Action )
update msg model =
case msg of
EditSettings settings ->
( model, EditAction settings )
view : Model -> List ScanMailboxSettings -> Html Msg
view model items =
div []
[ table [ class "ui very basic table" ]
[ thead []
[ th [ class "collapsing" ] []
, th [ class "collapsing" ]
[ i [ class "check icon" ] []
]
, th [] [ text "Connection" ]
, th [] [ text "Folders" ]
, th [] [ text "Schedule" ]
, th [] [ text "Received Since" ]
, th [] [ text "Target" ]
, th [] [ text "Delete" ]
]
, tbody []
(List.map viewItem items)
]
]
viewItem : ScanMailboxSettings -> Html Msg
viewItem item =
tr []
[ td [ class "collapsing" ]
[ a
[ href "#"
, class "ui basic small blue label"
, onClick (EditSettings item)
]
[ i [ class "edit icon" ] []
, text "Edit"
]
]
, td [ class "collapsing" ]
[ Util.Html.checkbox item.enabled
]
, td []
[ text item.imapConnection
]
, td []
[ String.join ", " item.folders |> text
]
, td []
[ code []
[ text item.schedule
]
]
, td []
[ Maybe.map String.fromInt item.receivedSinceHours
|> Maybe.withDefault "-"
|> text
]
, td []
[ Maybe.withDefault "-" item.targetFolder
|> text
]
, td []
[ Util.Html.checkbox item.deleteMail
]
]

View File

@ -0,0 +1,242 @@
module Comp.ScanMailboxManage exposing
( Model
, Msg
, init
, update
, view
)
import Api
import Api.Model.BasicResult exposing (BasicResult)
import Api.Model.ScanMailboxSettings exposing (ScanMailboxSettings)
import Api.Model.ScanMailboxSettingsList exposing (ScanMailboxSettingsList)
import Comp.ScanMailboxForm
import Comp.ScanMailboxList
import Data.Flags exposing (Flags)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick)
import Http
import Util.Http
type alias Model =
{ listModel : Comp.ScanMailboxList.Model
, detailModel : Maybe Comp.ScanMailboxForm.Model
, items : List ScanMailboxSettings
, result : Maybe BasicResult
}
type Msg
= ListMsg Comp.ScanMailboxList.Msg
| DetailMsg Comp.ScanMailboxForm.Msg
| GetDataResp (Result Http.Error ScanMailboxSettingsList)
| NewTask
| SubmitResp (Result Http.Error BasicResult)
| DeleteResp (Result Http.Error BasicResult)
initModel : Model
initModel =
{ listModel = Comp.ScanMailboxList.init
, detailModel = Nothing
, items = []
, result = Nothing
}
initCmd : Flags -> Cmd Msg
initCmd flags =
Api.getScanMailbox 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
GetDataResp (Ok res) ->
( { model
| items = res.items
, result = Nothing
}
, Cmd.none
)
GetDataResp (Err err) ->
( { model | result = Just (BasicResult False (Util.Http.errorToString err)) }
, Cmd.none
)
ListMsg lm ->
let
( mm, action ) =
Comp.ScanMailboxList.update lm model.listModel
( detail, cmd ) =
case action of
Comp.ScanMailboxList.NoAction ->
( Nothing, Cmd.none )
Comp.ScanMailboxList.EditAction settings ->
let
( dm, dc ) =
Comp.ScanMailboxForm.initWith flags settings
in
( Just dm, Cmd.map DetailMsg dc )
in
( { model
| listModel = mm
, detailModel = detail
}
, cmd
)
DetailMsg lm ->
case model.detailModel of
Just dm ->
let
( mm, action, mc ) =
Comp.ScanMailboxForm.update flags lm dm
( model_, cmd_ ) =
case action of
Comp.ScanMailboxForm.NoAction ->
( { model | detailModel = Just mm }
, Cmd.none
)
Comp.ScanMailboxForm.SubmitAction settings ->
( { model
| detailModel = Just mm
, result = Nothing
}
, if settings.id == "" then
Api.createScanMailbox flags settings SubmitResp
else
Api.updateScanMailbox flags settings SubmitResp
)
Comp.ScanMailboxForm.CancelAction ->
( { model
| detailModel = Nothing
, result = Nothing
}
, initCmd flags
)
Comp.ScanMailboxForm.StartOnceAction settings ->
( { model
| detailModel = Just mm
, result = Nothing
}
, Api.startOnceScanMailbox flags settings SubmitResp
)
Comp.ScanMailboxForm.DeleteAction id ->
( { model
| detailModel = Just mm
, result = Nothing
}
, Api.deleteScanMailbox flags id DeleteResp
)
in
( model_
, Cmd.batch
[ Cmd.map DetailMsg mc
, cmd_
]
)
Nothing ->
( model, Cmd.none )
NewTask ->
let
( mm, mc ) =
Comp.ScanMailboxForm.init flags
in
( { model | detailModel = Just mm }, Cmd.map DetailMsg mc )
SubmitResp (Ok res) ->
( { model | result = Just res }
, Cmd.none
)
SubmitResp (Err err) ->
( { model | result = Just (BasicResult False (Util.Http.errorToString err)) }
, Cmd.none
)
DeleteResp (Ok res) ->
if res.success then
( { model | result = Nothing, detailModel = Nothing }
, initCmd flags
)
else
( { model | result = Just res }
, Cmd.none
)
DeleteResp (Err err) ->
( { model | result = Just (BasicResult False (Util.Http.errorToString err)) }
, Cmd.none
)
--- View
view : Model -> Html Msg
view model =
div []
[ div [ class "ui menu" ]
[ a
[ class "link item"
, href "#"
, onClick NewTask
]
[ i [ class "add icon" ] []
, text "New Task"
]
]
, div
[ classList
[ ( "ui message", True )
, ( "error", Maybe.map .success model.result == Just False )
, ( "success", Maybe.map .success model.result == Just True )
, ( "invisible hidden", model.result == Nothing )
]
]
[ Maybe.map .message model.result
|> Maybe.withDefault ""
|> text
]
, case model.detailModel of
Just settings ->
viewForm settings
Nothing ->
viewList model
]
viewForm : Comp.ScanMailboxForm.Model -> Html Msg
viewForm model =
Html.map DetailMsg (Comp.ScanMailboxForm.view "segment" model)
viewList : Model -> Html Msg
viewList model =
Html.map ListMsg (Comp.ScanMailboxList.view model.listModel model.items)

View File

@ -9,7 +9,7 @@ import Comp.ChangePasswordForm
import Comp.EmailSettingsManage
import Comp.ImapSettingsManage
import Comp.NotificationForm
import Comp.ScanMailboxForm
import Comp.ScanMailboxManage
import Data.Flags exposing (Flags)
@ -19,7 +19,7 @@ type alias Model =
, emailSettingsModel : Comp.EmailSettingsManage.Model
, imapSettingsModel : Comp.ImapSettingsManage.Model
, notificationModel : Comp.NotificationForm.Model
, scanMailboxModel : Comp.ScanMailboxForm.Model
, scanMailboxModel : Comp.ScanMailboxManage.Model
}
@ -30,7 +30,7 @@ emptyModel flags =
, emailSettingsModel = Comp.EmailSettingsManage.emptyModel
, imapSettingsModel = Comp.ImapSettingsManage.emptyModel
, notificationModel = Tuple.first (Comp.NotificationForm.init flags)
, scanMailboxModel = Tuple.first (Comp.ScanMailboxForm.init flags)
, scanMailboxModel = Tuple.first (Comp.ScanMailboxManage.init flags)
}
@ -48,4 +48,4 @@ type Msg
| EmailSettingsMsg Comp.EmailSettingsManage.Msg
| NotificationMsg Comp.NotificationForm.Msg
| ImapSettingsMsg Comp.ImapSettingsManage.Msg
| ScanMailboxMsg Comp.ScanMailboxForm.Msg
| ScanMailboxMsg Comp.ScanMailboxManage.Msg

View File

@ -4,7 +4,7 @@ import Comp.ChangePasswordForm
import Comp.EmailSettingsManage
import Comp.ImapSettingsManage
import Comp.NotificationForm
import Comp.ScanMailboxForm
import Comp.ScanMailboxManage
import Data.Flags exposing (Flags)
import Page.UserSettings.Data exposing (..)
@ -48,7 +48,7 @@ update flags msg model =
let
initCmd =
Cmd.map ScanMailboxMsg
(Tuple.second (Comp.ScanMailboxForm.init flags))
(Tuple.second (Comp.ScanMailboxManage.init flags))
in
( m, initCmd )
in
@ -87,7 +87,7 @@ update flags msg model =
ScanMailboxMsg lm ->
let
( m2, c2 ) =
Comp.ScanMailboxForm.update flags lm model.scanMailboxModel
Comp.ScanMailboxManage.update flags lm model.scanMailboxModel
in
( { model | scanMailboxModel = m2 }
, Cmd.map ScanMailboxMsg c2

View File

@ -4,7 +4,7 @@ import Comp.ChangePasswordForm
import Comp.EmailSettingsManage
import Comp.ImapSettingsManage
import Comp.NotificationForm
import Comp.ScanMailboxForm
import Comp.ScanMailboxManage
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick)
@ -45,7 +45,7 @@ view model =
viewImapSettings model
Just ScanMailboxTab ->
viewScanMailboxForm model
viewScanMailboxManage model
Nothing ->
[]
@ -126,8 +126,8 @@ viewNotificationForm model =
]
viewScanMailboxForm : Model -> List (Html Msg)
viewScanMailboxForm model =
viewScanMailboxManage : Model -> List (Html Msg)
viewScanMailboxManage model =
[ h2 [ class "ui header" ]
[ i [ class "ui envelope open outline icon" ] []
, div [ class "content" ]
@ -151,5 +151,7 @@ viewScanMailboxForm model =
again."""
]
, Html.map ScanMailboxMsg
(Comp.ScanMailboxForm.view "segment" model.scanMailboxModel)
(Comp.ScanMailboxManage.view
model.scanMailboxModel
)
]

View File

@ -1,17 +1,37 @@
module Util.Html exposing
( KeyCode(..)
, checkbox
, classActive
, intToKeyCode
, onClickk
, onKeyUp
)
import Html exposing (Attribute)
import Html exposing (Attribute, Html, i)
import Html.Attributes exposing (class)
import Html.Events exposing (keyCode, on)
import Json.Decode as Decode
checkboxChecked : Html msg
checkboxChecked =
i [ class "ui check square outline icon" ] []
checkboxUnchecked : Html msg
checkboxUnchecked =
i [ class "ui square outline icon" ] []
checkbox : Bool -> Html msg
checkbox flag =
if flag then
checkboxChecked
else
checkboxUnchecked
type KeyCode
= Up
| Down