docspell/modules/webapp/src/main/elm/App/Update.elm
eikek 9009ebcb39 Prefill share mail form
To have access to the translated content, the messages must be given
to the update function. There is no way to set the values in the view.
2021-10-23 14:33:24 +02:00

650 lines
18 KiB
Elm

{-
Copyright 2020 Eike K. & Contributors
SPDX-License-Identifier: AGPL-3.0-or-later
-}
module App.Update exposing
( initPage
, update
)
import Api
import App.Data exposing (..)
import Browser exposing (UrlRequest(..))
import Browser.Navigation as Nav
import Data.Flags
import Data.UiSettings exposing (UiSettings)
import Data.UiTheme
import Messages exposing (Messages)
import Page exposing (Page(..))
import Page.CollectiveSettings.Data
import Page.CollectiveSettings.Update
import Page.Home.Data
import Page.Home.Update
import Page.ItemDetail.Data
import Page.ItemDetail.Update
import Page.Login.Data
import Page.Login.Update
import Page.ManageData.Data
import Page.ManageData.Update
import Page.NewInvite.Data
import Page.NewInvite.Update
import Page.Queue.Data
import Page.Queue.Update
import Page.Register.Data
import Page.Register.Update
import Page.Share.Data
import Page.Share.Update
import Page.ShareDetail.Data
import Page.ShareDetail.Update
import Page.Upload.Data
import Page.Upload.Update
import Page.UserSettings.Data
import Page.UserSettings.Update
import Ports
import Url
import Util.Maybe
import Util.Update
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
let
( m, c, s ) =
updateWithSub msg model
in
( { m | subs = s }, c )
updateWithSub : Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
updateWithSub msg model =
let
texts =
Messages.get <| App.Data.getUiLanguage model
in
case msg of
ToggleSidebar ->
( { model | sidebarVisible = not model.sidebarVisible }, Cmd.none, Sub.none )
ToggleDarkMode ->
case model.flags.account of
Just _ ->
let
settings =
model.uiSettings
next =
Data.UiTheme.cycle settings.uiTheme
newSettings =
{ settings | uiTheme = next }
in
-- when authenticated, store it in settings only
-- once new settings are successfully saved (the
-- response is arrived), the ui is updated. so it
-- is also updated on page refresh
( { model | userMenuOpen = False }
, Api.saveClientSettings model.flags newSettings (ClientSettingsSaveResp newSettings)
, Sub.none
)
Nothing ->
let
next =
Data.UiTheme.cycle model.anonymousTheme
in
-- when not logged in, simply set the theme
( { model | userMenuOpen = False, anonymousTheme = next }
, Ports.setUiTheme next
, Sub.none
)
ClientSettingsSaveResp settings (Ok res) ->
if res.success then
applyClientSettings texts model settings
else
( model, Cmd.none, Sub.none )
ClientSettingsSaveResp _ (Err _) ->
( model, Cmd.none, Sub.none )
ToggleLangMenu ->
( { model | langMenuOpen = not model.langMenuOpen }
, Cmd.none
, Sub.none
)
SetLanguage lang ->
( { model | anonymousUiLang = lang, langMenuOpen = False }, Cmd.none, Sub.none )
HomeMsg lm ->
updateHome texts lm model
ShareMsg lm ->
updateShare lm model
ShareDetailMsg lm ->
updateShareDetail lm model
LoginMsg lm ->
updateLogin lm model
ManageDataMsg lm ->
updateManageData lm model
CollSettingsMsg m ->
updateCollSettings texts m model
UserSettingsMsg m ->
updateUserSettings texts m model
QueueMsg m ->
updateQueue m model
RegisterMsg m ->
updateRegister m model
UploadMsg m ->
updateUpload m model
NewInviteMsg m ->
updateNewInvite m model
ItemDetailMsg m ->
updateItemDetail texts m model
VersionResp (Ok info) ->
( { model | version = info }, Cmd.none, Sub.none )
VersionResp (Err _) ->
( model, Cmd.none, Sub.none )
Logout ->
( model
, Cmd.batch
[ Api.logout model.flags LogoutResp
, Ports.removeAccount ()
]
, Sub.none
)
LogoutResp _ ->
( { model | loginModel = Page.Login.Data.emptyModel }
, Page.goto (LoginPage Page.emptyLoginData)
, Sub.none
)
SessionCheckResp res ->
case res of
Ok lr ->
let
newFlags =
if lr.success then
Data.Flags.withAccount model.flags lr
else
Data.Flags.withoutAccount model.flags
command =
if lr.success then
Cmd.batch
[ Api.refreshSession newFlags SessionCheckResp
, Ports.setAccount lr
, case model.flags.account of
Just _ ->
Cmd.none
Nothing ->
Page.goto model.page
]
else
Cmd.batch
[ Ports.removeAccount ()
, case model.page of
LoginPage _ ->
Cmd.none
_ ->
Page.goto (Page.loginPage model.page)
]
in
( { model | flags = newFlags }, command, Sub.none )
Err _ ->
( model
, Cmd.batch
[ Ports.removeAccount ()
, case model.page of
LoginPage _ ->
Cmd.none
_ ->
Page.goto (Page.loginPage model.page)
]
, Sub.none
)
NavRequest req ->
case req of
Internal url ->
if String.startsWith "/app" url.path then
let
isCurrent =
Page.fromUrl url
|> Maybe.map (\p -> p == model.page)
|> Maybe.withDefault True
in
( model
, if isCurrent then
Cmd.none
else
Nav.pushUrl model.key (Url.toString url)
, Sub.none
)
else
( model, Nav.load <| Url.toString url, Sub.none )
External url ->
( model
, Nav.load url
, Sub.none
)
NavChange url ->
let
page =
Page.fromUrl url
|> Maybe.withDefault (defaultPage model.flags)
( m, c, s ) =
initPage model page
in
( { m | page = page }, c, s )
ToggleNavMenu ->
( { model
| navMenuOpen = not model.navMenuOpen
, userMenuOpen =
if not model.navMenuOpen then
False
else
model.userMenuOpen
}
, Cmd.none
, Sub.none
)
ToggleUserMenu ->
( { model
| userMenuOpen = not model.userMenuOpen
, navMenuOpen =
if not model.userMenuOpen then
False
else
model.navMenuOpen
}
, Cmd.none
, Sub.none
)
GetUiSettings (Ok settings) ->
applyClientSettings texts model settings
GetUiSettings (Err _) ->
( model, Cmd.none, Sub.none )
ReceiveBrowserSettings sett ->
let
lm =
Page.UserSettings.Data.ReceiveBrowserSettings sett
in
updateUserSettings texts lm model
applyClientSettings : Messages -> Model -> UiSettings -> ( Model, Cmd Msg, Sub Msg )
applyClientSettings texts model settings =
let
setTheme =
Ports.setUiTheme settings.uiTheme
in
Util.Update.andThen2
[ \m ->
( { m | sidebarVisible = settings.sideMenuVisible }
, setTheme
, Sub.none
)
, updateUserSettings texts Page.UserSettings.Data.UpdateSettings
, updateHome texts Page.Home.Data.UiSettingsUpdated
, updateItemDetail texts Page.ItemDetail.Data.UiSettingsUpdated
]
{ model | uiSettings = settings }
updateShareDetail : Page.ShareDetail.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
updateShareDetail lmsg model =
case Page.pageShareDetail model.page of
Just ( shareId, itemId ) ->
let
( m, c ) =
Page.ShareDetail.Update.update shareId itemId model.flags lmsg model.shareDetailModel
in
( { model | shareDetailModel = m }
, Cmd.map ShareDetailMsg c
, Sub.none
)
Nothing ->
( model, Cmd.none, Sub.none )
updateShare : Page.Share.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
updateShare lmsg model =
case Page.pageShareId model.page of
Just id ->
let
result =
Page.Share.Update.update model.flags model.uiSettings id lmsg model.shareModel
in
( { model | shareModel = result.model }
, Cmd.map ShareMsg result.cmd
, Sub.map ShareMsg result.sub
)
Nothing ->
( model, Cmd.none, Sub.none )
updateItemDetail : Messages -> Page.ItemDetail.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
updateItemDetail texts lmsg model =
let
inav =
Page.Home.Data.itemNav model.itemDetailModel.detail.item.id model.homeModel
result =
Page.ItemDetail.Update.update
model.key
model.flags
inav
model.uiSettings
lmsg
model.itemDetailModel
model_ =
{ model
| itemDetailModel = result.model
}
( hm, hc, hs ) =
updateHome texts (Page.Home.Data.SetLinkTarget result.linkTarget) model_
( hm1, hc1, hs1 ) =
case result.removedItem of
Just removedId ->
updateHome texts (Page.Home.Data.RemoveItem removedId) hm
Nothing ->
( hm, hc, hs )
in
( hm1
, Cmd.batch [ Cmd.map ItemDetailMsg result.cmd, hc, hc1 ]
, Sub.batch [ Sub.map ItemDetailMsg result.sub, hs, hs1 ]
)
updateNewInvite : Page.NewInvite.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
updateNewInvite lmsg model =
let
( lm, lc ) =
Page.NewInvite.Update.update model.flags lmsg model.newInviteModel
in
( { model | newInviteModel = lm }
, Cmd.map NewInviteMsg lc
, Sub.none
)
updateUpload : Page.Upload.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
updateUpload lmsg model =
let
( lm, lc, ls ) =
Page.Upload.Update.update
(Page.uploadId model.page)
model.flags
lmsg
model.uploadModel
in
( { model | uploadModel = lm }
, Cmd.map UploadMsg lc
, Sub.map UploadMsg ls
)
updateRegister : Page.Register.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
updateRegister lmsg model =
let
( lm, lc ) =
Page.Register.Update.update model.flags lmsg model.registerModel
in
( { model | registerModel = lm }
, Cmd.map RegisterMsg lc
, Sub.none
)
updateQueue : Page.Queue.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
updateQueue lmsg model =
let
( lm, lc ) =
Page.Queue.Update.update model.flags lmsg model.queueModel
in
( { model | queueModel = lm }
, Cmd.map QueueMsg lc
, Sub.none
)
updateUserSettings : Messages -> Page.UserSettings.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
updateUserSettings texts lmsg model =
let
result =
Page.UserSettings.Update.update model.flags model.uiSettings lmsg model.userSettingsModel
model_ =
{ model | userSettingsModel = result.model }
( lm2, lc2, s2 ) =
case result.newSettings of
Just sett ->
applyClientSettings texts model_ sett
Nothing ->
( model_, Cmd.none, Sub.none )
in
( lm2
, Cmd.batch
[ Cmd.map UserSettingsMsg result.cmd
, lc2
]
, Sub.batch
[ Sub.map UserSettingsMsg result.sub
, s2
]
)
updateCollSettings : Messages -> Page.CollectiveSettings.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
updateCollSettings texts lmsg model =
let
( lm, lc, ls ) =
Page.CollectiveSettings.Update.update texts.collectiveSettings
model.flags
lmsg
model.collSettingsModel
in
( { model | collSettingsModel = lm }
, Cmd.map CollSettingsMsg lc
, Sub.map CollSettingsMsg ls
)
updateLogin : Page.Login.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
updateLogin lmsg model =
let
( lm, lc, ar ) =
Page.Login.Update.update (Page.loginPageReferrer model.page)
model.flags
lmsg
model.loginModel
newFlags =
Maybe.map (Data.Flags.withAccount model.flags) ar
|> Maybe.withDefault model.flags
in
( { model | loginModel = lm, flags = newFlags }
, Cmd.map LoginMsg lc
, Sub.none
)
updateHome : Messages -> Page.Home.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
updateHome texts lmsg model =
let
mid =
case model.page of
HomePage ->
Util.Maybe.fromString model.itemDetailModel.detail.item.id
_ ->
Nothing
result =
Page.Home.Update.update mid model.key model.flags texts.home model.uiSettings lmsg model.homeModel
model_ =
{ model | homeModel = result.model }
( lm, lc, ls ) =
case result.newSettings of
Just sett ->
applyClientSettings texts model_ sett
Nothing ->
( model_, Cmd.none, Sub.none )
in
( lm
, Cmd.batch
[ Cmd.map HomeMsg result.cmd
, lc
]
, Sub.batch
[ Sub.map HomeMsg result.sub
, ls
]
)
updateManageData : Page.ManageData.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
updateManageData lmsg model =
let
( lm, lc ) =
Page.ManageData.Update.update model.flags lmsg model.manageDataModel
in
( { model | manageDataModel = lm }
, Cmd.map ManageDataMsg lc
, Sub.none
)
initPage : Model -> Page -> ( Model, Cmd Msg, Sub Msg )
initPage model_ page =
let
model =
{ model_ | page = page }
texts =
Messages.get <| App.Data.getUiLanguage model
in
case page of
HomePage ->
Util.Update.andThen2
[ updateHome texts Page.Home.Data.Init
, updateQueue Page.Queue.Data.StopRefresh
]
model
LoginPage _ ->
updateQueue Page.Queue.Data.StopRefresh model
ManageDataPage ->
updateQueue Page.Queue.Data.StopRefresh model
CollectiveSettingPage ->
Util.Update.andThen2
[ updateQueue Page.Queue.Data.StopRefresh
, updateCollSettings texts Page.CollectiveSettings.Data.Init
]
model
UserSettingPage ->
Util.Update.andThen2
[ updateQueue Page.Queue.Data.StopRefresh
]
model
QueuePage ->
updateQueue Page.Queue.Data.Init model
RegisterPage ->
updateQueue Page.Queue.Data.StopRefresh model
UploadPage _ ->
Util.Update.andThen2
[ updateQueue Page.Queue.Data.StopRefresh
, updateUpload Page.Upload.Data.Clear
]
model
NewInvitePage ->
updateQueue Page.Queue.Data.StopRefresh model
ItemDetailPage id ->
Util.Update.andThen2
[ updateItemDetail texts (Page.ItemDetail.Data.Init id)
, updateQueue Page.Queue.Data.StopRefresh
]
model
SharePage id ->
let
cmd =
Cmd.map ShareMsg (Page.Share.Data.initCmd id model.flags)
shareModel =
model.shareModel
in
if shareModel.initialized then
( model, Cmd.none, Sub.none )
else
( { model | shareModel = { shareModel | initialized = True } }, cmd, Sub.none )
ShareDetailPage _ _ ->
case model_.page of
SharePage _ ->
let
verifyResult =
model.shareModel.verifyResult
in
updateShareDetail (Page.ShareDetail.Data.VerifyResp (Ok verifyResult)) model
_ ->
( model, Cmd.none, Sub.none )