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

@ -23,6 +23,11 @@ fold user coll scope =
coll
all : List AccountScope
all =
[ Collective, User ]
isUser : AccountScope -> Bool
isUser scope =
fold True False scope

View File

@ -0,0 +1,13 @@
{-
Copyright 2020 Eike K. & Contributors
SPDX-License-Identifier: AGPL-3.0-or-later
-}
module Data.AppEvent exposing (AppEvent(..))
type AppEvent
= AppNothing
| AppReloadUiSettings

View File

@ -15,8 +15,10 @@ module Data.UiSettings exposing
, catColor
, catColorFg2
, catColorString2
, convert
, defaults
, documentationSite
, emptyStoredSettings
, fieldHidden
, fieldVisible
, getUiLanguage
@ -30,7 +32,6 @@ module Data.UiSettings exposing
, tagColor
, tagColorFg2
, tagColorString2
, toStoredUiSettings
)
import Api.Model.Tag exposing (Tag)
@ -62,7 +63,7 @@ force default settings.
-}
type alias StoredUiSettings =
{ itemSearchPageSize : Maybe Int
, tagCategoryColors : List ( String, String )
, tagCategoryColors : Maybe (List ( String, String ))
, pdfMode : Maybe String
, itemSearchNoteLength : Maybe Int
, itemDetailNotesPosition : Maybe String
@ -70,23 +71,51 @@ type alias StoredUiSettings =
, searchMenuTagCount : Maybe Int
, searchMenuTagCatCount : Maybe Int
, formFields : Maybe (List String)
, itemDetailShortcuts : Bool
, searchMenuVisible : Bool
, editMenuVisible : Bool
, itemDetailShortcuts : Maybe Bool
, searchMenuVisible : Maybe Bool
, editMenuVisible : Maybe Bool
, cardPreviewSize : Maybe String
, cardTitleTemplate : Maybe String
, cardSubtitleTemplate : Maybe String
, searchStatsVisible : Bool
, cardPreviewFullWidth : Bool
, searchStatsVisible : Maybe Bool
, cardPreviewFullWidth : Maybe Bool
, uiTheme : Maybe String
, sideMenuVisible : Bool
, powerSearchEnabled : Bool
, sideMenuVisible : Maybe Bool
, powerSearchEnabled : Maybe Bool
, uiLang : Maybe String
, itemSearchShowGroups : Bool
, itemSearchShowGroups : Maybe Bool
, itemSearchArrange : Maybe String
}
emptyStoredSettings : StoredUiSettings
emptyStoredSettings =
{ itemSearchPageSize = Nothing
, tagCategoryColors = Nothing
, pdfMode = Nothing
, itemSearchNoteLength = Nothing
, itemDetailNotesPosition = Nothing
, searchMenuFolderCount = Nothing
, searchMenuTagCount = Nothing
, searchMenuTagCatCount = Nothing
, formFields = Nothing
, itemDetailShortcuts = Nothing
, searchMenuVisible = Nothing
, editMenuVisible = Nothing
, cardPreviewSize = Nothing
, cardTitleTemplate = Nothing
, cardSubtitleTemplate = Nothing
, searchStatsVisible = Nothing
, cardPreviewFullWidth = Nothing
, uiTheme = Nothing
, sideMenuVisible = Nothing
, powerSearchEnabled = Nothing
, uiLang = Nothing
, itemSearchShowGroups = Nothing
, itemSearchArrange = Nothing
}
storedUiSettingsDecoder : Decode.Decoder StoredUiSettings
storedUiSettingsDecoder =
let
@ -96,12 +125,12 @@ storedUiSettingsDecoder =
maybeString =
Decode.maybe Decode.string
def =
defaults
maybeBool =
Decode.maybe Decode.bool
in
Decode.succeed StoredUiSettings
|> P.optional "itemSearchPageSize" maybeInt Nothing
|> P.optional "tagCategoryColors" (Decode.keyValuePairs Decode.string) []
|> P.optional "tagCategoryColors" (Decode.maybe <| Decode.keyValuePairs Decode.string) Nothing
|> P.optional "pdfMode" maybeString Nothing
|> P.optional "itemSearchNoteLength" maybeInt Nothing
|> P.optional "itemDetailNotesPosition" maybeString Nothing
@ -109,53 +138,56 @@ storedUiSettingsDecoder =
|> P.optional "searchMenuTagCount" maybeInt Nothing
|> P.optional "searchMenuTagCatCount" maybeInt Nothing
|> P.optional "formFields" (Decode.maybe <| Decode.list Decode.string) Nothing
|> P.optional "itemDetailShortcuts" Decode.bool def.itemDetailShortcuts
|> P.optional "searchMenuVisible" Decode.bool def.searchMenuVisible
|> P.optional "editMenuVisible" Decode.bool def.editMenuVisible
|> P.optional "itemDetailShortcuts" maybeBool Nothing
|> P.optional "searchMenuVisible" maybeBool Nothing
|> P.optional "editMenuVisible" maybeBool Nothing
|> P.optional "cardPreviewSize" maybeString Nothing
|> P.optional "cardTitleTemplate" maybeString Nothing
|> P.optional "cardSubtitleTemplate" maybeString Nothing
|> P.optional "searchStatsVisible" Decode.bool def.searchStatsVisible
|> P.optional "cardPreviewFullWidth" Decode.bool def.cardPreviewFullWidth
|> P.optional "searchStatsVisible" maybeBool Nothing
|> P.optional "cardPreviewFullWidth" maybeBool Nothing
|> P.optional "uiTheme" maybeString Nothing
|> P.optional "sideMenuVisible" Decode.bool def.sideMenuVisible
|> P.optional "powerSearchEnabled" Decode.bool def.powerSearchEnabled
|> P.optional "sideMenuVisible" maybeBool Nothing
|> P.optional "powerSearchEnabled" maybeBool Nothing
|> P.optional "uiLang" maybeString Nothing
|> P.optional "itemSearchShowGroups" Decode.bool def.itemSearchShowGroups
|> P.optional "itemSearchShowGroups" maybeBool Nothing
|> P.optional "itemSearchArrange" maybeString Nothing
storedUiSettingsEncode : StoredUiSettings -> Encode.Value
storedUiSettingsEncode value =
let
maybeEnc enca ma =
Maybe.map enca ma |> Maybe.withDefault Encode.null
maybeEnc field enca ma =
Maybe.map (\a -> ( field, enca a )) ma
in
Encode.object
[ ( "itemSearchPageSize", maybeEnc Encode.int value.itemSearchPageSize )
, ( "tagCategoryColors", Encode.dict identity Encode.string (Dict.fromList value.tagCategoryColors) )
, ( "pdfMode", maybeEnc Encode.string value.pdfMode )
, ( "itemSearchNoteLength", maybeEnc Encode.int value.itemSearchNoteLength )
, ( "itemDetailNotesPosition", maybeEnc Encode.string value.itemDetailNotesPosition )
, ( "searchMenuFolderCount", maybeEnc Encode.int value.searchMenuFolderCount )
, ( "searchMenuTagCount", maybeEnc Encode.int value.searchMenuTagCount )
, ( "searchMenuTagCatCount", maybeEnc Encode.int value.searchMenuTagCatCount )
, ( "formFields", maybeEnc (Encode.list Encode.string) value.formFields )
, ( "itemDetailShortcuts", Encode.bool value.itemDetailShortcuts )
, ( "searchMenuVisible", Encode.bool value.searchMenuVisible )
, ( "editMenuVisible", Encode.bool value.editMenuVisible )
, ( "cardPreviewSize", maybeEnc Encode.string value.cardPreviewSize )
, ( "cardTitleTemplate", maybeEnc Encode.string value.cardTitleTemplate )
, ( "cardSubtitleTemplate", maybeEnc Encode.string value.cardSubtitleTemplate )
, ( "searchStatsVisible", Encode.bool value.searchStatsVisible )
, ( "cardPreviewFullWidth", Encode.bool value.cardPreviewFullWidth )
, ( "uiTheme", maybeEnc Encode.string value.uiTheme )
, ( "sideMenuVisible", Encode.bool value.sideMenuVisible )
, ( "powerSearchEnabled", Encode.bool value.powerSearchEnabled )
, ( "uiLang", maybeEnc Encode.string value.uiLang )
, ( "itemSearchShowGroups", Encode.bool value.itemSearchShowGroups )
, ( "itemSearchArrange", maybeEnc Encode.string value.itemSearchArrange )
]
Encode.object <|
List.filterMap identity
[ maybeEnc "itemSearchPageSize" Encode.int value.itemSearchPageSize
, maybeEnc "tagCategoryColors"
(Encode.dict identity Encode.string)
(Maybe.map Dict.fromList value.tagCategoryColors)
, maybeEnc "pdfMode" Encode.string value.pdfMode
, maybeEnc "itemSearchNoteLength" Encode.int value.itemSearchNoteLength
, maybeEnc "itemDetailNotesPosition" Encode.string value.itemDetailNotesPosition
, maybeEnc "searchMenuFolderCount" Encode.int value.searchMenuFolderCount
, maybeEnc "searchMenuTagCount" Encode.int value.searchMenuTagCount
, maybeEnc "searchMenuTagCatCount" Encode.int value.searchMenuTagCatCount
, maybeEnc "formFields" (Encode.list Encode.string) value.formFields
, maybeEnc "itemDetailShortcuts" Encode.bool value.itemDetailShortcuts
, maybeEnc "searchMenuVisible" Encode.bool value.searchMenuVisible
, maybeEnc "editMenuVisible" Encode.bool value.editMenuVisible
, maybeEnc "cardPreviewSize" Encode.string value.cardPreviewSize
, maybeEnc "cardTitleTemplate" Encode.string value.cardTitleTemplate
, maybeEnc "cardSubtitleTemplate" Encode.string value.cardSubtitleTemplate
, maybeEnc "searchStatsVisible" Encode.bool value.searchStatsVisible
, maybeEnc "cardPreviewFullWidth" Encode.bool value.cardPreviewFullWidth
, maybeEnc "uiTheme" Encode.string value.uiTheme
, maybeEnc "sideMenuVisible" Encode.bool value.sideMenuVisible
, maybeEnc "powerSearchEnabled" Encode.bool value.powerSearchEnabled
, maybeEnc "uiLang" Encode.string value.uiLang
, maybeEnc "itemSearchShowGroups" Encode.bool value.itemSearchShowGroups
, maybeEnc "itemSearchArrange" Encode.string value.itemSearchArrange
]
{-| Settings for the web ui. These fields are all mandatory, since
@ -273,7 +305,8 @@ merge given fallback =
choose given.itemSearchPageSize fallback.itemSearchPageSize
, tagCategoryColors =
Dict.union
(Dict.fromList given.tagCategoryColors
(Maybe.map Dict.fromList given.tagCategoryColors
|> Maybe.withDefault Dict.empty
|> Dict.map (\_ -> Data.Color.fromString)
|> Dict.filter (\_ -> \mc -> mc /= Nothing)
|> Dict.map (\_ -> Maybe.withDefault Data.Color.Grey)
@ -299,9 +332,9 @@ merge given fallback =
choose
(Maybe.map Data.Fields.fromList given.formFields)
fallback.formFields
, itemDetailShortcuts = given.itemDetailShortcuts
, searchMenuVisible = given.searchMenuVisible
, editMenuVisible = given.editMenuVisible
, itemDetailShortcuts = choose given.itemDetailShortcuts fallback.itemDetailShortcuts
, searchMenuVisible = choose given.searchMenuVisible fallback.searchMenuVisible
, editMenuVisible = choose given.editMenuVisible fallback.editMenuVisible
, cardPreviewSize =
given.cardPreviewSize
|> Maybe.andThen Data.BasicSize.fromString
@ -312,17 +345,17 @@ merge given fallback =
, cardSubtitleTemplate =
Maybe.andThen readPattern given.cardSubtitleTemplate
|> Maybe.withDefault fallback.cardSubtitleTemplate
, searchStatsVisible = given.searchStatsVisible
, cardPreviewFullWidth = given.cardPreviewFullWidth
, searchStatsVisible = choose given.searchStatsVisible fallback.searchStatsVisible
, cardPreviewFullWidth = choose given.cardPreviewFullWidth fallback.cardPreviewFullWidth
, uiTheme =
Maybe.andThen Data.UiTheme.fromString given.uiTheme
|> Maybe.withDefault fallback.uiTheme
, sideMenuVisible = given.sideMenuVisible
, powerSearchEnabled = given.powerSearchEnabled
, sideMenuVisible = choose given.sideMenuVisible fallback.sideMenuVisible
, powerSearchEnabled = choose given.powerSearchEnabled fallback.powerSearchEnabled
, uiLang =
Maybe.map Messages.fromIso2 given.uiLang
|> Maybe.withDefault Messages.UiLanguage.English
, itemSearchShowGroups = given.itemSearchShowGroups
|> Maybe.withDefault fallback.uiLang
, itemSearchShowGroups = choose given.itemSearchShowGroups fallback.itemSearchShowGroups
, itemSearchArrange =
Maybe.andThen Data.ItemArrange.fromString given.itemSearchArrange
|> Maybe.withDefault fallback.itemSearchArrange
@ -334,12 +367,13 @@ mergeDefaults given =
merge given defaults
toStoredUiSettings : UiSettings -> StoredUiSettings
toStoredUiSettings settings =
convert : UiSettings -> StoredUiSettings
convert settings =
{ itemSearchPageSize = Just settings.itemSearchPageSize
, tagCategoryColors =
Dict.map (\_ -> Data.Color.toString) settings.tagCategoryColors
|> Dict.toList
|> Just
, pdfMode = Just (Data.Pdf.asString settings.pdfMode)
, itemSearchNoteLength = Just settings.itemSearchNoteLength
, itemDetailNotesPosition = Just (posToString settings.itemDetailNotesPosition)
@ -349,22 +383,22 @@ toStoredUiSettings settings =
, formFields =
List.map Data.Fields.toString settings.formFields
|> Just
, itemDetailShortcuts = settings.itemDetailShortcuts
, searchMenuVisible = settings.searchMenuVisible
, editMenuVisible = settings.editMenuVisible
, itemDetailShortcuts = Just settings.itemDetailShortcuts
, searchMenuVisible = Just settings.searchMenuVisible
, editMenuVisible = Just settings.editMenuVisible
, cardPreviewSize =
settings.cardPreviewSize
|> Data.BasicSize.asString
|> Just
, cardTitleTemplate = settings.cardTitleTemplate.pattern |> Just
, cardSubtitleTemplate = settings.cardSubtitleTemplate.pattern |> Just
, searchStatsVisible = settings.searchStatsVisible
, cardPreviewFullWidth = settings.cardPreviewFullWidth
, searchStatsVisible = Just settings.searchStatsVisible
, cardPreviewFullWidth = Just settings.cardPreviewFullWidth
, uiTheme = Just (Data.UiTheme.toString settings.uiTheme)
, sideMenuVisible = settings.sideMenuVisible
, powerSearchEnabled = settings.powerSearchEnabled
, sideMenuVisible = Just settings.sideMenuVisible
, powerSearchEnabled = Just settings.powerSearchEnabled
, uiLang = Just <| Messages.toIso2 settings.uiLang
, itemSearchShowGroups = settings.itemSearchShowGroups
, itemSearchShowGroups = Just settings.itemSearchShowGroups
, itemSearchArrange = Data.ItemArrange.asString settings.itemSearchArrange |> Just
}