Client settings per collective and user

Client settings can be stored at the user and and the collective. The
settings used in the application are merged from these two settings,
where any user setting takes precedence. The form can now manage both
variants.

Refs: #838
This commit is contained in:
eikek
2022-01-29 10:11:25 +01:00
parent ee927096a4
commit c29ce73dd0
19 changed files with 812 additions and 438 deletions

View File

@@ -16,26 +16,42 @@ module Comp.UiSettingsManage exposing
import Api
import Api.Model.BasicResult exposing (BasicResult)
import Comp.Basic
import Comp.MenuBar as MB
import Comp.UiSettingsForm
import Comp.UiSettingsMigrate
import Data.AccountScope exposing (AccountScope)
import Data.AppEvent exposing (AppEvent(..))
import Data.Flags exposing (Flags)
import Data.UiSettings exposing (StoredUiSettings, UiSettings)
import Html exposing (..)
import Html.Attributes exposing (..)
import Http
import Messages.Comp.UiSettingsManage exposing (Texts)
import Page.Search.Data exposing (Msg(..))
import Styles as S
type alias Model =
{ formModel : Comp.UiSettingsForm.Model
, settings : Maybe UiSettings
{ formModel : FormView
, formResult : FormResult
, settingsMigrate : Comp.UiSettingsMigrate.Model
, formData : Maybe FormData
}
type alias FormData =
{ userSettings : StoredUiSettings
, userModel : Comp.UiSettingsForm.Model
, collSettings : StoredUiSettings
, collModel : Comp.UiSettingsForm.Model
}
type FormView
= ViewLoading
| ViewUser
| ViewCollective
type FormResult
= FormInit
| FormUnchanged
@@ -45,35 +61,39 @@ type FormResult
type Msg
= UiSettingsFormMsg Comp.UiSettingsForm.Msg
| UiSettingsMigrateMsg Comp.UiSettingsMigrate.Msg
= UiFormMsg AccountScope Comp.UiSettingsForm.Msg
| Submit
| UpdateSettings
| SaveSettingsResp UiSettings (Result Http.Error BasicResult)
| ReceiveBrowserSettings StoredUiSettings
| SaveSettingsResp (Result Http.Error BasicResult)
| ReceiveServerSettings (Result Http.Error ( StoredUiSettings, StoredUiSettings ))
| ToggleExpandCollapse
| SwitchForm AccountScope
init : Flags -> UiSettings -> ( Model, Cmd Msg )
init flags settings =
let
( fm, fc ) =
Comp.UiSettingsForm.init flags settings
( mm, mc ) =
Comp.UiSettingsMigrate.init flags
in
( { formModel = fm
, settings = Nothing
init : Flags -> ( Model, Cmd Msg )
init flags =
( { formModel = ViewLoading
, formData = Nothing
, formResult = FormInit
, settingsMigrate = mm
}
, Cmd.batch
[ Cmd.map UiSettingsFormMsg fc
, Cmd.map UiSettingsMigrateMsg mc
[ Api.getClientSettingsRaw flags ReceiveServerSettings
]
)
getViewScope : Model -> AccountScope
getViewScope model =
case model.formModel of
ViewCollective ->
Data.AccountScope.Collective
ViewUser ->
Data.AccountScope.User
_ ->
Data.AccountScope.User
--- update
@@ -82,108 +102,165 @@ type alias UpdateResult =
{ model : Model
, cmd : Cmd Msg
, sub : Sub Msg
, newSettings : Maybe UiSettings
, appEvent : AppEvent
}
unit : Model -> UpdateResult
unit model =
UpdateResult model Cmd.none Sub.none AppNothing
update : Flags -> UiSettings -> Msg -> Model -> UpdateResult
update flags settings msg model =
case msg of
UiSettingsFormMsg lm ->
UiFormMsg scope lm ->
case model.formData of
Nothing ->
unit model
Just data ->
case scope of
Data.AccountScope.Collective ->
let
( m_, sett ) =
Comp.UiSettingsForm.update flags data.collSettings lm data.collModel
in
unit
{ model
| formData =
Just
{ data
| collSettings = Maybe.withDefault data.collSettings sett
, collModel = m_
}
, formResult =
if sett /= Nothing then
FormInit
else
model.formResult
}
Data.AccountScope.User ->
let
( m_, sett ) =
Comp.UiSettingsForm.update flags data.userSettings lm data.userModel
in
unit
{ model
| formData =
Just
{ data
| userSettings = Maybe.withDefault data.userSettings sett
, userModel = m_
}
, formResult =
if sett /= Nothing then
FormInit
else
model.formResult
}
Submit ->
case ( model.formModel, model.formData ) of
( ViewCollective, Just data ) ->
{ model = { model | formResult = FormInit }
, cmd =
Api.saveClientSettings flags
data.collSettings
Data.AccountScope.Collective
SaveSettingsResp
, sub = Sub.none
, appEvent = AppNothing
}
( ViewUser, Just data ) ->
{ model = { model | formResult = FormInit }
, cmd =
Api.saveClientSettings flags
data.userSettings
Data.AccountScope.User
SaveSettingsResp
, sub = Sub.none
, appEvent = AppNothing
}
_ ->
unit model
SaveSettingsResp (Ok res) ->
case ( res.success, model.formData ) of
( True, Just data ) ->
let
result =
update flags
settings
(ReceiveServerSettings (Ok ( data.collSettings, data.userSettings )))
model
in
{ result | appEvent = AppReloadUiSettings }
_ ->
unit { model | formResult = FormUnknownError }
SaveSettingsResp (Err err) ->
UpdateResult { model | formResult = FormHttpError err } Cmd.none Sub.none AppNothing
ReceiveServerSettings (Ok ( coll, user )) ->
let
inSettings =
Maybe.withDefault settings model.settings
collDefaults =
Data.UiSettings.defaults
( m_, sett ) =
Comp.UiSettingsForm.update inSettings lm model.formModel
userDefaults =
Data.UiSettings.merge coll collDefaults
( um, uc ) =
Comp.UiSettingsForm.init flags user userDefaults
( cm, cc ) =
Comp.UiSettingsForm.init flags coll collDefaults
model_ =
{ model
| formData =
Just
{ userSettings = user
, userModel = um
, collSettings = coll
, collModel = cm
}
, formModel = ViewUser
}
cmds =
Cmd.batch
[ Cmd.map (UiFormMsg Data.AccountScope.User) uc
, Cmd.map (UiFormMsg Data.AccountScope.Collective) cc
]
in
{ model =
{ model
| formModel = m_
, settings =
if sett == Nothing then
model.settings
UpdateResult model_ cmds Sub.none AppNothing
else
sett
, formResult =
if sett /= Nothing then
FormInit
ReceiveServerSettings (Err err) ->
unit { model | formResult = FormHttpError err }
else
model.formResult
}
, cmd = Cmd.none
, sub = Sub.none
, newSettings = Nothing
}
UiSettingsMigrateMsg lm ->
let
result =
Comp.UiSettingsMigrate.update flags lm model.settingsMigrate
in
{ model = { model | settingsMigrate = result.model }
, cmd = Cmd.map UiSettingsMigrateMsg result.cmd
, sub = Sub.map UiSettingsMigrateMsg result.sub
, newSettings = result.newSettings
}
ReceiveBrowserSettings sett ->
ToggleExpandCollapse ->
let
lm =
UiSettingsMigrateMsg (Comp.UiSettingsMigrate.receiveBrowserSettings sett)
UiFormMsg (getViewScope model) Comp.UiSettingsForm.toggleAllTabs
in
update flags settings lm model
Submit ->
case model.settings of
Just s ->
{ model = { model | formResult = FormInit }
, cmd = Api.saveClientSettings flags s (SaveSettingsResp s)
, sub = Sub.none
, newSettings = Nothing
}
Nothing ->
{ model = { model | formResult = FormUnchanged }
, cmd = Cmd.none
, sub = Sub.none
, newSettings = Nothing
}
SaveSettingsResp newSettings (Ok res) ->
if res.success then
{ model = { model | formResult = FormSaved }
, cmd = Cmd.none
, sub = Sub.none
, newSettings = Just newSettings
}
else
{ model = { model | formResult = FormUnknownError }
, cmd = Cmd.none
, sub = Sub.none
, newSettings = Nothing
}
SaveSettingsResp _ (Err err) ->
UpdateResult { model | formResult = FormHttpError err } Cmd.none Sub.none Nothing
UpdateSettings ->
SwitchForm scope ->
let
( fm, fc ) =
Comp.UiSettingsForm.init flags settings
forUser =
unit { model | formModel = ViewUser }
forColl =
unit { model | formModel = ViewCollective }
in
{ model = { model | formModel = fm }
, cmd = Cmd.map UiSettingsFormMsg fc
, sub = Sub.none
, newSettings = Nothing
}
--- View2
Data.AccountScope.fold forUser forColl scope
isError : Model -> Bool
@@ -211,7 +288,11 @@ isSuccess model =
view2 : Texts -> Flags -> UiSettings -> String -> Model -> Html Msg
view2 texts flags settings classes model =
view2 texts flags _ classes model =
let
scope =
getViewScope model
in
div [ class classes ]
[ MB.view
{ start =
@@ -221,14 +302,29 @@ view2 texts flags settings classes model =
, title = texts.saveSettings
, icon = Just "fa fa-save"
}
, MB.SecondaryButton
{ tagger = ToggleExpandCollapse
, label = ""
, title = texts.expandCollapse
, icon = Just "fa fa-compress"
}
]
, end =
[ MB.RadioButton
{ tagger = \_ -> SwitchForm Data.AccountScope.User
, label = texts.accountScope Data.AccountScope.User
, value = Data.AccountScope.fold True False scope
, id = "ui-settings-chooser-user"
}
, MB.RadioButton
{ tagger = \_ -> SwitchForm Data.AccountScope.Collective
, label = texts.accountScope Data.AccountScope.Collective
, value = Data.AccountScope.fold False True scope
, id = "ui-settings-chooser-collective"
}
]
, end = []
, rootClasses = "mb-4"
}
, div []
[ Html.map UiSettingsMigrateMsg
(Comp.UiSettingsMigrate.view model.settingsMigrate)
]
, div
[ classList
[ ( S.successMessage, isSuccess model )
@@ -252,11 +348,52 @@ view2 texts flags settings classes model =
FormUnknownError ->
text texts.unknownSaveError
]
, Html.map UiSettingsFormMsg
(Comp.UiSettingsForm.view2
texts.uiSettingsForm
flags
settings
model.formModel
)
, case model.formModel of
ViewLoading ->
div [ class "h-24 md:relative" ]
[ Comp.Basic.loadingDimmer
{ label = ""
, active = True
}
]
ViewCollective ->
case model.formData of
Just data ->
div []
[ h2 [ class S.header2 ]
[ text texts.collectiveHeader
]
, Html.map (UiFormMsg scope)
(Comp.UiSettingsForm.view2
texts.uiSettingsForm
flags
data.collSettings
data.collModel
)
]
Nothing ->
span [ class "hidden" ] []
ViewUser ->
case model.formData of
Just data ->
div []
[ h2 [ class S.header2 ]
[ text texts.userHeader
]
, div [ class "py-1 opacity-80" ]
[ text texts.userInfo
]
, Html.map (UiFormMsg scope)
(Comp.UiSettingsForm.view2 texts.uiSettingsForm
flags
data.userSettings
data.userModel
)
]
Nothing ->
span [ class "hidden" ] []
]