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

@ -64,6 +64,7 @@ module Api exposing
, getChannels , getChannels
, getChannelsIgnoreError , getChannelsIgnoreError
, getClientSettings , getClientSettings
, getClientSettingsRaw
, getCollective , getCollective
, getCollectiveSettings , getCollectiveSettings
, getContacts , getContacts
@ -136,6 +137,7 @@ module Api exposing
, restoreItem , restoreItem
, sampleEvent , sampleEvent
, saveClientSettings , saveClientSettings
, saveUserClientSettingsBy
, searchShare , searchShare
, searchShareStats , searchShareStats
, sendMail , sendMail
@ -296,7 +298,7 @@ import Data.OrganizationOrder exposing (OrganizationOrder)
import Data.PersonOrder exposing (PersonOrder) import Data.PersonOrder exposing (PersonOrder)
import Data.Priority exposing (Priority) import Data.Priority exposing (Priority)
import Data.TagOrder exposing (TagOrder) import Data.TagOrder exposing (TagOrder)
import Data.UiSettings exposing (UiSettings) import Data.UiSettings exposing (StoredUiSettings, UiSettings)
import File exposing (File) import File exposing (File)
import Http import Http
import Json.Decode as JsonDecode import Json.Decode as JsonDecode
@ -2335,6 +2337,13 @@ getItemProposals flags item receive =
--- Client Settings --- Client Settings
uiSettingsPath : AccountScope -> String
uiSettingsPath scope =
Data.AccountScope.fold "/api/v1/sec/clientSettings/user/webClient"
"/api/v1/sec/clientSettings/collective/webClient"
scope
getClientSettings : Flags -> (Result Http.Error UiSettings -> msg) -> Cmd msg getClientSettings : Flags -> (Result Http.Error UiSettings -> msg) -> Cmd msg
getClientSettings flags receive = getClientSettings flags receive =
let let
@ -2346,29 +2355,91 @@ getClientSettings flags receive =
Data.UiSettings.storedUiSettingsDecoder Data.UiSettings.storedUiSettingsDecoder
in in
Http2.authGet Http2.authGet
{ url = flags.config.baseUrl ++ "/api/v1/sec/clientSettings/user/webClient" { url = flags.config.baseUrl ++ "/api/v1/sec/clientSettings/webClient"
, account = getAccount flags , account = getAccount flags
, expect = Http.expectJson receive decoder , expect = Http.expectJson receive decoder
} }
saveClientSettings : Flags -> UiSettings -> (Result Http.Error BasicResult -> msg) -> Cmd msg getClientSettingsTaskFor : Flags -> AccountScope -> Task.Task Http.Error StoredUiSettings
saveClientSettings flags settings receive = getClientSettingsTaskFor flags scope =
let let
storedSettings = path =
Data.UiSettings.toStoredUiSettings settings uiSettingsPath scope
encode =
Data.UiSettings.storedUiSettingsEncode storedSettings
in in
Http2.authPut Http2.authTask
{ url = flags.config.baseUrl ++ "/api/v1/sec/clientSettings/user/webClient" { method = "GET"
, url = flags.config.baseUrl ++ path
, account = getAccount flags , account = getAccount flags
, body = Http.jsonBody encode , body = Http.emptyBody
, expect = Http.expectJson receive Api.Model.BasicResult.decoder , resolver = Http2.jsonResolver Data.UiSettings.storedUiSettingsDecoder
, headers = []
, timeout = Nothing
} }
getClientSettingsRaw : Flags -> (Result Http.Error ( StoredUiSettings, StoredUiSettings ) -> msg) -> Cmd msg
getClientSettingsRaw flags receive =
let
coll =
getClientSettingsTaskFor flags Data.AccountScope.Collective
user =
getClientSettingsTaskFor flags Data.AccountScope.User
in
Task.map2 Tuple.pair coll user |> Task.attempt receive
saveClientSettingsTask :
Flags
-> StoredUiSettings
-> AccountScope
-> Task.Task Http.Error BasicResult
saveClientSettingsTask flags settings scope =
let
encoded =
Data.UiSettings.storedUiSettingsEncode settings
path =
uiSettingsPath scope
in
Http2.authTask
{ method = "PUT"
, url = flags.config.baseUrl ++ path
, account = getAccount flags
, body = Http.jsonBody encoded
, resolver = Http2.jsonResolver Api.Model.BasicResult.decoder
, headers = []
, timeout = Nothing
}
saveClientSettings :
Flags
-> StoredUiSettings
-> AccountScope
-> (Result Http.Error BasicResult -> msg)
-> Cmd msg
saveClientSettings flags settings scope receive =
saveClientSettingsTask flags settings scope |> Task.attempt receive
saveUserClientSettingsBy :
Flags
-> (StoredUiSettings -> StoredUiSettings)
-> (Result Http.Error BasicResult -> msg)
-> Cmd msg
saveUserClientSettingsBy flags modify receive =
let
readTask =
getClientSettingsTaskFor flags Data.AccountScope.User
save s =
saveClientSettingsTask flags s Data.AccountScope.User
in
Task.andThen (modify >> save) readTask |> Task.attempt receive
--- Dashboards --- Dashboards

View File

@ -204,8 +204,7 @@ type Msg
| ToggleDarkMode | ToggleDarkMode
| ToggleLangMenu | ToggleLangMenu
| SetLanguage UiLanguage | SetLanguage UiLanguage
| ClientSettingsSaveResp UiSettings (Result Http.Error BasicResult) | ClientSettingsSaveResp (Result Http.Error BasicResult)
| ReceiveBrowserSettings StoredUiSettings
| ReceiveWsMessage (Result String ServerEvent) | ReceiveWsMessage (Result String ServerEvent)
| ToggleShowNewItemsArrived | ToggleShowNewItemsArrived

View File

@ -14,6 +14,7 @@ import Api
import App.Data exposing (..) import App.Data exposing (..)
import Browser exposing (UrlRequest(..)) import Browser exposing (UrlRequest(..))
import Browser.Navigation as Nav import Browser.Navigation as Nav
import Data.AppEvent exposing (AppEvent(..))
import Data.Flags import Data.Flags
import Data.ServerEvent exposing (ServerEvent(..)) import Data.ServerEvent exposing (ServerEvent(..))
import Data.UiSettings exposing (UiSettings) import Data.UiSettings exposing (UiSettings)
@ -81,15 +82,15 @@ updateWithSub msg model =
next = next =
Data.UiTheme.cycle settings.uiTheme Data.UiTheme.cycle settings.uiTheme
newSettings = newSettings s =
{ settings | uiTheme = next } { s | uiTheme = Just (Data.UiTheme.toString next) }
in in
-- when authenticated, store it in settings only -- when authenticated, store it in settings only
-- once new settings are successfully saved (the -- once new settings are successfully saved (the
-- response is arrived), the ui is updated. so it -- response is arrived), the ui is updated. so it
-- is also updated on page refresh -- is also updated on page refresh
( { model | userMenuOpen = False } ( { model | userMenuOpen = False }
, Api.saveClientSettings model.flags newSettings (ClientSettingsSaveResp newSettings) , Api.saveUserClientSettingsBy model.flags newSettings ClientSettingsSaveResp
, Sub.none , Sub.none
) )
@ -104,14 +105,14 @@ updateWithSub msg model =
, Sub.none , Sub.none
) )
ClientSettingsSaveResp settings (Ok res) -> ClientSettingsSaveResp (Ok res) ->
if res.success then if res.success then
applyClientSettings texts model settings ( model, Api.getClientSettings model.flags GetUiSettings, Sub.none )
else else
( model, Cmd.none, Sub.none ) ( model, Cmd.none, Sub.none )
ClientSettingsSaveResp _ (Err _) -> ClientSettingsSaveResp (Err _) ->
( model, Cmd.none, Sub.none ) ( model, Cmd.none, Sub.none )
ToggleLangMenu -> ToggleLangMenu ->
@ -307,13 +308,6 @@ updateWithSub msg model =
GetUiSettings (Err _) -> GetUiSettings (Err _) ->
( model, Cmd.none, Sub.none ) ( model, Cmd.none, Sub.none )
ReceiveBrowserSettings sett ->
let
lm =
Page.UserSettings.Data.ReceiveBrowserSettings sett
in
updateUserSettings texts lm model
ReceiveWsMessage data -> ReceiveWsMessage data ->
case data of case data of
Ok (JobDone task) -> Ok (JobDone task) ->
@ -342,7 +336,7 @@ updateWithSub msg model =
Ok (JobsWaiting n) -> Ok (JobsWaiting n) ->
( { model | jobsWaiting = max 0 n }, Cmd.none, Sub.none ) ( { model | jobsWaiting = max 0 n }, Cmd.none, Sub.none )
Err err -> Err _ ->
( model, Cmd.none, Sub.none ) ( model, Cmd.none, Sub.none )
ToggleShowNewItemsArrived -> ToggleShowNewItemsArrived ->
@ -368,7 +362,6 @@ applyClientSettings texts model settings =
, Sub.none , Sub.none
) )
, updateDashboard texts Page.Dashboard.Data.reloadUiSettings , updateDashboard texts Page.Dashboard.Data.reloadUiSettings
, updateUserSettings texts Page.UserSettings.Data.UpdateSettings
, updateSearch texts Page.Search.Data.UiSettingsUpdated , updateSearch texts Page.Search.Data.UiSettingsUpdated
, updateItemDetail texts Page.ItemDetail.Data.UiSettingsUpdated , updateItemDetail texts Page.ItemDetail.Data.UiSettingsUpdated
] ]
@ -524,22 +517,21 @@ updateUserSettings texts lmsg model =
model_ = model_ =
{ model | userSettingsModel = result.model } { model | userSettingsModel = result.model }
( lm2, lc2, s2 ) = lc =
case result.newSettings of case result.appEvent of
Just sett -> AppReloadUiSettings ->
applyClientSettings texts model_ sett Api.getClientSettings model.flags GetUiSettings
Nothing -> AppNothing ->
( model_, Cmd.none, Sub.none ) Cmd.none
in in
( lm2 ( model_
, Cmd.batch , Cmd.batch
[ Cmd.map UserSettingsMsg result.cmd [ Cmd.map UserSettingsMsg result.cmd
, lc2 , lc
] ]
, Sub.batch , Sub.batch
[ Sub.map UserSettingsMsg result.sub [ Sub.map UserSettingsMsg result.sub
, s2
] ]
) )
@ -595,22 +587,21 @@ updateSearch texts lmsg model =
model_ = model_ =
{ model | searchModel = result.model } { model | searchModel = result.model }
( lm, lc, ls ) = lc =
case result.newSettings of case result.appEvent of
Just sett -> AppReloadUiSettings ->
applyClientSettings texts model_ sett Api.getClientSettings model.flags GetUiSettings
Nothing -> AppNothing ->
( model_, Cmd.none, Sub.none ) Cmd.none
in in
( lm ( model_
, Cmd.batch , Cmd.batch
[ Cmd.map SearchMsg result.cmd [ Cmd.map SearchMsg result.cmd
, lc , lc
] ]
, Sub.batch , Sub.batch
[ Sub.map SearchMsg result.sub [ Sub.map SearchMsg result.sub
, ls
] ]
) )

View File

@ -26,6 +26,7 @@ import Styles as S
type Item msg type Item msg
= TextInput (TextInputData msg) = TextInput (TextInputData msg)
| Checkbox (CheckboxData msg) | Checkbox (CheckboxData msg)
| RadioButton (CheckboxData msg)
| PrimaryButton (ButtonData msg) | PrimaryButton (ButtonData msg)
| SecondaryButton (ButtonData msg) | SecondaryButton (ButtonData msg)
| DeleteButton (ButtonData msg) | DeleteButton (ButtonData msg)
@ -119,7 +120,7 @@ view1 classes mb =
(List.map viewItem mb.start) (List.map viewItem mb.start)
right = right =
div [ class "flex-grow flex-row flex justify-end space-x-2 w-full" ] div [ class "flex-grow flex-row items-center flex justify-end space-x-2 w-full" ]
(List.map viewItem mb.end) (List.map viewItem mb.end)
in in
div div
@ -139,7 +140,10 @@ viewItem item =
makeInput model makeInput model
Checkbox model -> Checkbox model ->
makeCheckbox model makeCheckbox False model
RadioButton model ->
makeCheckbox True model
PrimaryButton model -> PrimaryButton model ->
makeButton [ ( S.primaryButton, True ) ] model makeButton [ ( S.primaryButton, True ) ] model
@ -306,8 +310,8 @@ makeButton btnType model =
(icon ++ label) (icon ++ label)
makeCheckbox : CheckboxData msg -> Html msg makeCheckbox : Bool -> CheckboxData msg -> Html msg
makeCheckbox model = makeCheckbox radio model =
let let
withId list = withId list =
if model.id == "" then if model.id == "" then
@ -315,6 +319,13 @@ makeCheckbox model =
else else
id model.id :: list id model.id :: list
fold rd ck =
if radio then
rd
else
ck
in in
div [ class "" ] div [ class "" ]
[ label [ label
@ -323,10 +334,10 @@ makeCheckbox model =
] ]
[ input [ input
(withId (withId
[ type_ "checkbox" [ type_ (fold "radio" "checkbox")
, onCheck model.tagger , onCheck model.tagger
, checked model.value , checked model.value
, class S.checkboxInput , class (fold S.radioInput S.checkboxInput)
] ]
) )
[] []

View File

@ -9,6 +9,7 @@ module Comp.UiSettingsForm exposing
( Model ( Model
, Msg , Msg
, init , init
, toggleAllTabs
, update , update
, view2 , view2
) )
@ -30,7 +31,7 @@ import Data.Flags exposing (Flags)
import Data.ItemTemplate as IT exposing (ItemTemplate) import Data.ItemTemplate as IT exposing (ItemTemplate)
import Data.Pdf exposing (PdfMode) import Data.Pdf exposing (PdfMode)
import Data.TagOrder import Data.TagOrder
import Data.UiSettings exposing (ItemPattern, Pos(..), UiSettings) import Data.UiSettings exposing (ItemPattern, Pos(..), StoredUiSettings, UiSettings)
import Dict exposing (Dict) import Dict exposing (Dict)
import Html exposing (..) import Html exposing (..)
import Html.Attributes exposing (..) import Html.Attributes exposing (..)
@ -73,6 +74,7 @@ type alias Model =
, uiLangModel : Comp.FixedDropdown.Model UiLanguage , uiLangModel : Comp.FixedDropdown.Model UiLanguage
, uiLang : UiLanguage , uiLang : UiLanguage
, openTabs : Set String , openTabs : Set String
, defaults : UiSettings
} }
@ -111,9 +113,13 @@ updatePatternModel pm str =
} }
init : Flags -> UiSettings -> ( Model, Cmd Msg ) initModel : Flags -> StoredUiSettings -> UiSettings -> Model
init flags settings = initModel flags storedSettings defaults =
( { itemSearchPageSize = Just settings.itemSearchPageSize let
settings =
Data.UiSettings.merge storedSettings defaults
in
{ itemSearchPageSize = Just settings.itemSearchPageSize
, searchPageSizeModel = , searchPageSizeModel =
Comp.IntField.init Comp.IntField.init
(Just 10) (Just 10)
@ -163,9 +169,13 @@ init flags settings =
, uiLangModel = , uiLangModel =
Comp.FixedDropdown.init Messages.UiLanguage.all Comp.FixedDropdown.init Messages.UiLanguage.all
, openTabs = Set.empty , openTabs = Set.empty
, defaults = defaults
} }
, Api.getTags flags "" Data.TagOrder.NameAsc GetTagsResp
)
init : Flags -> StoredUiSettings -> UiSettings -> ( Model, Cmd Msg )
init flags storedSettings defaults =
( initModel flags storedSettings defaults, Api.getTags flags "" Data.TagOrder.NameAsc GetTagsResp )
type Msg type Msg
@ -188,14 +198,61 @@ type Msg
| TogglePowerSearch | TogglePowerSearch
| UiLangMsg (Comp.FixedDropdown.Msg UiLanguage) | UiLangMsg (Comp.FixedDropdown.Msg UiLanguage)
| PdfModeMsg (Comp.FixedDropdown.Msg PdfMode) | PdfModeMsg (Comp.FixedDropdown.Msg PdfMode)
| ToggleAllTabs
| ResetTab AkkordionTab
toggleAllTabs : Msg
toggleAllTabs =
ToggleAllTabs
type AkkordionTab
= GeneralTab
| SearchTab
| CardsTab
| SearchMenuTab
| DetailTab
| TagsTab
| FieldsTab
allTabs : List AkkordionTab
allTabs =
[ GeneralTab, SearchTab, CardsTab, SearchMenuTab, DetailTab, TagsTab, FieldsTab ]
akkordionTabName : AkkordionTab -> String
akkordionTabName tab =
case tab of
GeneralTab ->
"general"
SearchTab ->
"search"
CardsTab ->
"item-cards"
SearchMenuTab ->
"search-menu"
DetailTab ->
"item-detail"
TagsTab ->
"tags"
FieldsTab ->
"fields"
--- Update --- Update
update : UiSettings -> Msg -> Model -> ( Model, Maybe UiSettings ) update : Flags -> StoredUiSettings -> Msg -> Model -> ( Model, Maybe StoredUiSettings )
update sett msg model = update flags sett msg model =
case msg of case msg of
SearchPageSizeMsg lm -> SearchPageSizeMsg lm ->
let let
@ -203,7 +260,7 @@ update sett msg model =
Comp.IntField.update lm model.searchPageSizeModel Comp.IntField.update lm model.searchPageSizeModel
nextSettings = nextSettings =
Maybe.map (\sz -> { sett | itemSearchPageSize = sz }) n Maybe.map (\sz -> { sett | itemSearchPageSize = Just sz }) n
model_ = model_ =
{ model { model
@ -219,7 +276,7 @@ update sett msg model =
Comp.IntField.update lm model.searchNoteLengthModel Comp.IntField.update lm model.searchNoteLengthModel
nextSettings = nextSettings =
Maybe.map (\len -> { sett | itemSearchNoteLength = len }) n Maybe.map (\len -> { sett | itemSearchNoteLength = Just len }) n
model_ = model_ =
{ model { model
@ -235,7 +292,7 @@ update sett msg model =
Comp.IntField.update lm model.searchMenuFolderCountModel Comp.IntField.update lm model.searchMenuFolderCountModel
nextSettings = nextSettings =
Maybe.map (\len -> { sett | searchMenuFolderCount = len }) n Maybe.map (\len -> { sett | searchMenuFolderCount = Just len }) n
model_ = model_ =
{ model { model
@ -251,7 +308,7 @@ update sett msg model =
Comp.IntField.update lm model.searchMenuTagCountModel Comp.IntField.update lm model.searchMenuTagCountModel
nextSettings = nextSettings =
Maybe.map (\len -> { sett | searchMenuTagCount = len }) n Maybe.map (\len -> { sett | searchMenuTagCount = Just len }) n
model_ = model_ =
{ model { model
@ -267,7 +324,7 @@ update sett msg model =
Comp.IntField.update lm model.searchMenuTagCatCountModel Comp.IntField.update lm model.searchMenuTagCatCountModel
nextSettings = nextSettings =
Maybe.map (\len -> { sett | searchMenuTagCatCount = len }) n Maybe.map (\len -> { sett | searchMenuTagCatCount = Just len }) n
model_ = model_ =
{ model { model
@ -282,8 +339,13 @@ update sett msg model =
( m_, d_ ) = ( m_, d_ ) =
Comp.ColorTagger.update lm model.tagColorModel Comp.ColorTagger.update lm model.tagColorModel
colors dict =
Dict.map (\_ -> Data.Color.toString) dict
|> Dict.toList
|> Just
nextSettings = nextSettings =
Maybe.map (\tc -> { sett | tagCategoryColors = tc }) d_ Maybe.map (\tc -> { sett | tagCategoryColors = colors tc }) d_
model_ = model_ =
{ model { model
@ -316,7 +378,11 @@ update sett msg model =
Comp.FieldListSelect.update lm model.formFields Comp.FieldListSelect.update lm model.formFields
newSettings = newSettings =
{ sett | formFields = selected } { sett
| formFields =
List.map Data.Fields.toString selected
|> Just
}
in in
( { model | formFields = selected } ( { model | formFields = selected }
, if selected /= model.formFields then , if selected /= model.formFields then
@ -332,7 +398,7 @@ update sett msg model =
not model.itemDetailShortcuts not model.itemDetailShortcuts
in in
( { model | itemDetailShortcuts = flag } ( { model | itemDetailShortcuts = flag }
, Just { sett | itemDetailShortcuts = flag } , Just { sett | itemDetailShortcuts = Just flag }
) )
CardPreviewSizeMsg lm -> CardPreviewSizeMsg lm ->
@ -343,7 +409,13 @@ update sett msg model =
newSettings = newSettings =
if next /= model.cardPreviewSize then if next /= model.cardPreviewSize then
Just { sett | cardPreviewSize = next } Just
{ sett
| cardPreviewSize =
next
|> Data.BasicSize.asString
|> Just
}
else else
Nothing Nothing
@ -361,14 +433,8 @@ update sett msg model =
updatePatternModel pm str updatePatternModel pm str
newSettings = newSettings =
if pm_.pattern /= Just sett.cardTitleTemplate.pattern then if pm_.pattern /= sett.cardTitleTemplate then
Just Just { sett | cardTitleTemplate = pm_.pattern }
{ sett
| cardTitleTemplate =
ItemPattern
(Maybe.withDefault "" pm_.pattern)
pm_.current
}
else else
Nothing Nothing
@ -384,14 +450,8 @@ update sett msg model =
updatePatternModel pm str updatePatternModel pm str
newSettings = newSettings =
if pm_.pattern /= Just sett.cardSubtitleTemplate.pattern then if pm_.pattern /= sett.cardSubtitleTemplate then
Just Just { sett | cardSubtitleTemplate = pm_.pattern }
{ sett
| cardSubtitleTemplate =
ItemPattern
(Maybe.withDefault "" pm_.pattern)
pm_.current
}
else else
Nothing Nothing
@ -407,9 +467,21 @@ update sett msg model =
not model.searchStatsVisible not model.searchStatsVisible
in in
( { model | searchStatsVisible = flag } ( { model | searchStatsVisible = flag }
, Just { sett | searchStatsVisible = flag } , Just { sett | searchStatsVisible = Just flag }
) )
ToggleAllTabs ->
let
tabs =
if Set.isEmpty model.openTabs then
List.map akkordionTabName allTabs
|> Set.fromList
else
Set.empty
in
( { model | openTabs = tabs }, Nothing )
ToggleAkkordionTab name -> ToggleAkkordionTab name ->
let let
tabs = tabs =
@ -429,7 +501,7 @@ update sett msg model =
not model.sideMenuVisible not model.sideMenuVisible
in in
( { model | sideMenuVisible = next } ( { model | sideMenuVisible = next }
, Just { sett | sideMenuVisible = next } , Just { sett | sideMenuVisible = Just next }
) )
TogglePowerSearch -> TogglePowerSearch ->
@ -438,7 +510,7 @@ update sett msg model =
not model.powerSearchEnabled not model.powerSearchEnabled
in in
( { model | powerSearchEnabled = next } ( { model | powerSearchEnabled = next }
, Just { sett | powerSearchEnabled = next } , Just { sett | powerSearchEnabled = Just next }
) )
UiLangMsg lm -> UiLangMsg lm ->
@ -454,7 +526,7 @@ update sett msg model =
Nothing Nothing
else else
Just { sett | uiLang = newLang } Just { sett | uiLang = Just (Messages.toIso2 newLang) }
) )
PdfModeMsg lm -> PdfModeMsg lm ->
@ -470,9 +542,53 @@ update sett msg model =
Nothing Nothing
else else
Just { sett | pdfMode = newMode } Just { sett | pdfMode = Just (Data.Pdf.asString newMode) }
) )
ResetTab tab ->
let
newSettings =
case tab of
GeneralTab ->
{ sett | uiLang = Nothing, sideMenuVisible = Nothing }
SearchTab ->
{ sett
| itemSearchPageSize = Nothing
, searchStatsVisible = Nothing
, powerSearchEnabled = Nothing
}
CardsTab ->
{ sett
| itemSearchNoteLength = Nothing
, cardPreviewSize = Nothing
, cardTitleTemplate = Nothing
, cardSubtitleTemplate = Nothing
}
SearchMenuTab ->
{ sett
| searchMenuTagCount = Nothing
, searchMenuTagCatCount = Nothing
, searchMenuFolderCount = Nothing
}
DetailTab ->
{ sett | pdfMode = Nothing, itemDetailShortcuts = Nothing }
TagsTab ->
{ sett | tagCategoryColors = Nothing }
-- no reset here
FieldsTab ->
{ sett | formFields = Nothing }
nm =
initModel flags newSettings model.defaults
in
( { nm | openTabs = model.openTabs }, Just newSettings )
--- View2 --- View2
@ -495,7 +611,7 @@ tagColorViewOpts2 texts =
} }
view2 : Texts -> Flags -> UiSettings -> Model -> Html Msg view2 : Texts -> Flags -> StoredUiSettings -> Model -> Html Msg
view2 texts flags settings model = view2 texts flags settings model =
let let
state tab = state tab =
@ -517,7 +633,7 @@ view2 texts flags settings model =
] ]
settingFormTabs : Texts -> Flags -> UiSettings -> Model -> List (Comp.Tabs.Tab Msg) settingFormTabs : Texts -> Flags -> StoredUiSettings -> Model -> List (Comp.Tabs.Tab Msg)
settingFormTabs texts flags _ model = settingFormTabs texts flags _ model =
let let
langCfg = langCfg =
@ -533,10 +649,21 @@ settingFormTabs texts flags _ model =
, style = DS.mainStyle , style = DS.mainStyle
, selectPlaceholder = texts.basics.selectPlaceholder , selectPlaceholder = texts.basics.selectPlaceholder
} }
resetLink tab =
a
[ href "#"
, class S.link
, class "text-sm"
, onClick (ResetTab tab)
]
[ i [ class "fa fa-eraser mr-1" ] []
, text "Reset"
]
in in
[ { name = "general" [ { name = akkordionTabName GeneralTab
, title = texts.general , title = texts.general
, titleRight = [] , titleRight = [ resetLink GeneralTab ]
, info = Nothing , info = Nothing
, body = , body =
[ div [ class "mb-4 " ] [ div [ class "mb-4 " ]
@ -560,9 +687,9 @@ settingFormTabs texts flags _ model =
] ]
] ]
} }
, { name = "item-search" , { name = akkordionTabName SearchTab
, title = texts.itemSearch , title = texts.itemSearch
, titleRight = [] , titleRight = [ resetLink SearchTab ]
, info = Nothing , info = Nothing
, body = , body =
[ Html.map SearchPageSizeMsg [ Html.map SearchPageSizeMsg
@ -594,9 +721,9 @@ settingFormTabs texts flags _ model =
] ]
] ]
} }
, { name = "item-cards" , { name = akkordionTabName CardsTab
, title = texts.itemCards , title = texts.itemCards
, titleRight = [] , titleRight = [ resetLink CardsTab ]
, info = Nothing , info = Nothing
, body = , body =
[ Html.map NoteLengthMsg [ Html.map NoteLengthMsg
@ -666,9 +793,9 @@ settingFormTabs texts flags _ model =
texts.templateHelpMessage texts.templateHelpMessage
] ]
} }
, { name = "search-menu" , { name = akkordionTabName SearchMenuTab
, title = texts.searchMenu , title = texts.searchMenu
, titleRight = [] , titleRight = [ resetLink SearchMenuTab ]
, info = Nothing , info = Nothing
, body = , body =
[ Html.map SearchMenuTagMsg [ Html.map SearchMenuTagMsg
@ -700,9 +827,9 @@ settingFormTabs texts flags _ model =
) )
] ]
} }
, { name = "item-detail" , { name = akkordionTabName DetailTab
, title = texts.itemDetail , title = texts.itemDetail
, titleRight = [] , titleRight = [ resetLink DetailTab ]
, info = Nothing , info = Nothing
, body = , body =
[ div [ class "mb-4" ] [ div [ class "mb-4" ]
@ -726,9 +853,9 @@ settingFormTabs texts flags _ model =
] ]
] ]
} }
, { name = "tag-category-colors" , { name = akkordionTabName TagsTab
, title = texts.tagCategoryColors , title = texts.tagCategoryColors
, titleRight = [] , titleRight = [ resetLink TagsTab ]
, info = Nothing , info = Nothing
, body = , body =
[ Html.map TagColorMsg [ Html.map TagColorMsg
@ -739,9 +866,9 @@ settingFormTabs texts flags _ model =
) )
] ]
} }
, { name = "fields" , { name = akkordionTabName FieldsTab
, title = texts.fields , title = texts.fields
, titleRight = [] , titleRight = [ resetLink FieldsTab ]
, info = Nothing , info = Nothing
, body = , body =
[ span [ class "opacity-50 text-sm" ] [ span [ class "opacity-50 text-sm" ]

View File

@ -16,26 +16,42 @@ module Comp.UiSettingsManage exposing
import Api import Api
import Api.Model.BasicResult exposing (BasicResult) import Api.Model.BasicResult exposing (BasicResult)
import Comp.Basic
import Comp.MenuBar as MB import Comp.MenuBar as MB
import Comp.UiSettingsForm import Comp.UiSettingsForm
import Comp.UiSettingsMigrate import Data.AccountScope exposing (AccountScope)
import Data.AppEvent exposing (AppEvent(..))
import Data.Flags exposing (Flags) import Data.Flags exposing (Flags)
import Data.UiSettings exposing (StoredUiSettings, UiSettings) import Data.UiSettings exposing (StoredUiSettings, UiSettings)
import Html exposing (..) import Html exposing (..)
import Html.Attributes exposing (..) import Html.Attributes exposing (..)
import Http import Http
import Messages.Comp.UiSettingsManage exposing (Texts) import Messages.Comp.UiSettingsManage exposing (Texts)
import Page.Search.Data exposing (Msg(..))
import Styles as S import Styles as S
type alias Model = type alias Model =
{ formModel : Comp.UiSettingsForm.Model { formModel : FormView
, settings : Maybe UiSettings
, formResult : FormResult , 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 type FormResult
= FormInit = FormInit
| FormUnchanged | FormUnchanged
@ -45,35 +61,39 @@ type FormResult
type Msg type Msg
= UiSettingsFormMsg Comp.UiSettingsForm.Msg = UiFormMsg AccountScope Comp.UiSettingsForm.Msg
| UiSettingsMigrateMsg Comp.UiSettingsMigrate.Msg
| Submit | Submit
| UpdateSettings | SaveSettingsResp (Result Http.Error BasicResult)
| SaveSettingsResp UiSettings (Result Http.Error BasicResult) | ReceiveServerSettings (Result Http.Error ( StoredUiSettings, StoredUiSettings ))
| ReceiveBrowserSettings StoredUiSettings | ToggleExpandCollapse
| SwitchForm AccountScope
init : Flags -> UiSettings -> ( Model, Cmd Msg ) init : Flags -> ( Model, Cmd Msg )
init flags settings = init flags =
let ( { formModel = ViewLoading
( fm, fc ) = , formData = Nothing
Comp.UiSettingsForm.init flags settings
( mm, mc ) =
Comp.UiSettingsMigrate.init flags
in
( { formModel = fm
, settings = Nothing
, formResult = FormInit , formResult = FormInit
, settingsMigrate = mm
} }
, Cmd.batch , Cmd.batch
[ Cmd.map UiSettingsFormMsg fc [ Api.getClientSettingsRaw flags ReceiveServerSettings
, Cmd.map UiSettingsMigrateMsg mc
] ]
) )
getViewScope : Model -> AccountScope
getViewScope model =
case model.formModel of
ViewCollective ->
Data.AccountScope.Collective
ViewUser ->
Data.AccountScope.User
_ ->
Data.AccountScope.User
--- update --- update
@ -82,30 +102,38 @@ type alias UpdateResult =
{ model : Model { model : Model
, cmd : Cmd Msg , cmd : Cmd Msg
, sub : Sub 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 -> UiSettings -> Msg -> Model -> UpdateResult
update flags settings msg model = update flags settings msg model =
case msg of case msg of
UiSettingsFormMsg lm -> UiFormMsg scope lm ->
case model.formData of
Nothing ->
unit model
Just data ->
case scope of
Data.AccountScope.Collective ->
let let
inSettings =
Maybe.withDefault settings model.settings
( m_, sett ) = ( m_, sett ) =
Comp.UiSettingsForm.update inSettings lm model.formModel Comp.UiSettingsForm.update flags data.collSettings lm data.collModel
in in
{ model = unit
{ model { model
| formModel = m_ | formData =
, settings = Just
if sett == Nothing then { data
model.settings | collSettings = Maybe.withDefault data.collSettings sett
, collModel = m_
else }
sett
, formResult = , formResult =
if sett /= Nothing then if sett /= Nothing then
FormInit FormInit
@ -113,77 +141,126 @@ update flags settings msg model =
else else
model.formResult model.formResult
} }
, cmd = Cmd.none
, sub = Sub.none Data.AccountScope.User ->
, newSettings = Nothing 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
} }
UiSettingsMigrateMsg lm -> 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 let
result = result =
Comp.UiSettingsMigrate.update flags lm model.settingsMigrate update flags
settings
(ReceiveServerSettings (Ok ( data.collSettings, data.userSettings )))
model
in in
{ model = { model | settingsMigrate = result.model } { result | appEvent = AppReloadUiSettings }
, cmd = Cmd.map UiSettingsMigrateMsg result.cmd
, sub = Sub.map UiSettingsMigrateMsg result.sub _ ->
, newSettings = result.newSettings unit { model | formResult = FormUnknownError }
SaveSettingsResp (Err err) ->
UpdateResult { model | formResult = FormHttpError err } Cmd.none Sub.none AppNothing
ReceiveServerSettings (Ok ( coll, user )) ->
let
collDefaults =
Data.UiSettings.defaults
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
} }
ReceiveBrowserSettings sett -> cmds =
Cmd.batch
[ Cmd.map (UiFormMsg Data.AccountScope.User) uc
, Cmd.map (UiFormMsg Data.AccountScope.Collective) cc
]
in
UpdateResult model_ cmds Sub.none AppNothing
ReceiveServerSettings (Err err) ->
unit { model | formResult = FormHttpError err }
ToggleExpandCollapse ->
let let
lm = lm =
UiSettingsMigrateMsg (Comp.UiSettingsMigrate.receiveBrowserSettings sett) UiFormMsg (getViewScope model) Comp.UiSettingsForm.toggleAllTabs
in in
update flags settings lm model update flags settings lm model
Submit -> SwitchForm scope ->
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 ->
let let
( fm, fc ) = forUser =
Comp.UiSettingsForm.init flags settings unit { model | formModel = ViewUser }
forColl =
unit { model | formModel = ViewCollective }
in in
{ model = { model | formModel = fm } Data.AccountScope.fold forUser forColl scope
, cmd = Cmd.map UiSettingsFormMsg fc
, sub = Sub.none
, newSettings = Nothing
}
--- View2
isError : Model -> Bool isError : Model -> Bool
@ -211,7 +288,11 @@ isSuccess model =
view2 : Texts -> Flags -> UiSettings -> String -> Model -> Html Msg 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 ] div [ class classes ]
[ MB.view [ MB.view
{ start = { start =
@ -221,14 +302,29 @@ view2 texts flags settings classes model =
, title = texts.saveSettings , title = texts.saveSettings
, icon = Just "fa fa-save" , 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" , rootClasses = "mb-4"
} }
, div []
[ Html.map UiSettingsMigrateMsg
(Comp.UiSettingsMigrate.view model.settingsMigrate)
]
, div , div
[ classList [ classList
[ ( S.successMessage, isSuccess model ) [ ( S.successMessage, isSuccess model )
@ -252,11 +348,52 @@ view2 texts flags settings classes model =
FormUnknownError -> FormUnknownError ->
text texts.unknownSaveError text texts.unknownSaveError
] ]
, Html.map UiSettingsFormMsg , 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 (Comp.UiSettingsForm.view2
texts.uiSettingsForm texts.uiSettingsForm
flags flags
settings data.collSettings
model.formModel 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" ] []
]

View File

@ -17,6 +17,7 @@ module Comp.UiSettingsMigrate exposing
import Api import Api
import Api.Model.BasicResult exposing (BasicResult) import Api.Model.BasicResult exposing (BasicResult)
import Data.AccountScope
import Data.Flags exposing (Flags) import Data.Flags exposing (Flags)
import Data.UiSettings exposing (StoredUiSettings, UiSettings) import Data.UiSettings exposing (StoredUiSettings, UiSettings)
import Html exposing (..) import Html exposing (..)
@ -132,7 +133,10 @@ update flags msg model =
Data.UiSettings.merge settings Data.UiSettings.defaults Data.UiSettings.merge settings Data.UiSettings.defaults
cmd = cmd =
Api.saveClientSettings flags uiSettings (SaveSettingsResp uiSettings) Api.saveClientSettings flags
(Data.UiSettings.convert uiSettings)
Data.AccountScope.Collective
(SaveSettingsResp uiSettings)
in in
{ empty | model = MigrateRequestRunning, cmd = cmd } { empty | model = MigrateRequestRunning, cmd = cmd }

View File

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

View File

@ -14,7 +14,6 @@ import App.View2
import Browser exposing (Document) import Browser exposing (Document)
import Browser.Navigation exposing (Key) import Browser.Navigation exposing (Key)
import Data.Flags exposing (Flags) import Data.Flags exposing (Flags)
import Data.NotificationChannel
import Data.UiSettings import Data.UiSettings
import Html exposing (..) import Html exposing (..)
import Html.Attributes exposing (..) import Html.Attributes exposing (..)
@ -93,6 +92,5 @@ subscriptions : Model -> Sub Msg
subscriptions model = subscriptions model =
Sub.batch Sub.batch
[ model.subs [ model.subs
, Ports.receiveUiSettings ReceiveBrowserSettings
, Ports.receiveServerEvent ReceiveWsMessage , Ports.receiveServerEvent ReceiveWsMessage
] ]

View File

@ -15,16 +15,22 @@ import Http
import Messages.Basics import Messages.Basics
import Messages.Comp.HttpError import Messages.Comp.HttpError
import Messages.Comp.UiSettingsForm import Messages.Comp.UiSettingsForm
import Messages.Data.AccountScope
type alias Texts = type alias Texts =
{ basics : Messages.Basics.Texts { basics : Messages.Basics.Texts
, uiSettingsForm : Messages.Comp.UiSettingsForm.Texts , uiSettingsForm : Messages.Comp.UiSettingsForm.Texts
, accountScope : Messages.Data.AccountScope.Texts
, saveSettings : String , saveSettings : String
, settingsUnchanged : String , settingsUnchanged : String
, settingsSaved : String , settingsSaved : String
, unknownSaveError : String , unknownSaveError : String
, httpError : Http.Error -> String , httpError : Http.Error -> String
, userHeader : String
, userInfo : String
, collectiveHeader : String
, expandCollapse : String
} }
@ -32,11 +38,16 @@ gb : Texts
gb = gb =
{ basics = Messages.Basics.gb { basics = Messages.Basics.gb
, uiSettingsForm = Messages.Comp.UiSettingsForm.gb , uiSettingsForm = Messages.Comp.UiSettingsForm.gb
, accountScope = Messages.Data.AccountScope.gb
, saveSettings = "Save settings" , saveSettings = "Save settings"
, settingsUnchanged = "Settings unchanged or invalid." , settingsUnchanged = "Settings unchanged or invalid."
, settingsSaved = "Settings saved." , settingsSaved = "Settings saved."
, unknownSaveError = "Unknown error while trying to save settings." , unknownSaveError = "Unknown error while trying to save settings."
, httpError = Messages.Comp.HttpError.gb , httpError = Messages.Comp.HttpError.gb
, userHeader = "Personal settings"
, userInfo = "Your personal settings override those of the collective. On reset, settings are set back to those of the collective."
, collectiveHeader = "Collective settings"
, expandCollapse = "Expand/collapse all"
} }
@ -44,9 +55,14 @@ de : Texts
de = de =
{ basics = Messages.Basics.de { basics = Messages.Basics.de
, uiSettingsForm = Messages.Comp.UiSettingsForm.de , uiSettingsForm = Messages.Comp.UiSettingsForm.de
, accountScope = Messages.Data.AccountScope.de
, saveSettings = "Einstellungen speichern" , saveSettings = "Einstellungen speichern"
, settingsUnchanged = "Einstellungen nicht verändert oder ungültig." , settingsUnchanged = "Einstellungen nicht verändert oder ungültig."
, settingsSaved = "Einstellungen gespeichert" , settingsSaved = "Einstellungen gespeichert"
, unknownSaveError = "Unbekannter Fehler beim Speichern der Einstellungen." , unknownSaveError = "Unbekannter Fehler beim Speichern der Einstellungen."
, httpError = Messages.Comp.HttpError.de , httpError = Messages.Comp.HttpError.de
, userHeader = "Persönliche Einstellungen"
, userInfo = "Die persönlichen Einstellungen überschreiben die des Kollektivs. Wenn Einstellungen zurückgesetzt werden, werden sie auf die Werte des Kollektivs gesetzt."
, collectiveHeader = "Kollektiv Einstellungen"
, expandCollapse = "Alle ein-/ausklappen"
} }

View File

@ -80,8 +80,7 @@ gb =
, changePassword = "Change Password" , changePassword = "Change Password"
, channelSettings = "Notification Channels" , channelSettings = "Notification Channels"
, uiSettingsInfo = , uiSettingsInfo =
"These settings only affect the web ui. They are stored in the browser, " "These settings only affect the web ui. Settings can be stored to the collective or to your personal user. Personal settings are prefered when both values exist."
++ "so they are separated between browsers and devices."
, scanMailboxInfo1 = , scanMailboxInfo1 =
"Docspell can scan folders of your mailbox to import your mails. " "Docspell can scan folders of your mailbox to import your mails. "
++ "You need to provide a connection in " ++ "You need to provide a connection in "
@ -144,7 +143,7 @@ de =
, channelSettings = "Benachrichtigungskanäle" , channelSettings = "Benachrichtigungskanäle"
, changePassword = "Passwort ändern" , changePassword = "Passwort ändern"
, uiSettingsInfo = , uiSettingsInfo =
"Diese Einstellungen sind für die Web-Oberfläche." "Diese Einstellungen sind für die Web-Oberfläche. Es kann entweder für das ganze Kollektiv Einstellungen gemacht werden oder persönliche. Die persönlichen Einstellungen werden bevorzugt, falls beide gesetzt sind."
, scanMailboxInfo1 = , scanMailboxInfo1 =
"""Docspell kann Postfächer durchsuchen und E-Mails importieren. Dafür sind """Docspell kann Postfächer durchsuchen und E-Mails importieren. Dafür sind
E-Mail-Einstellungen (IMAP) notwendig.""" E-Mail-Einstellungen (IMAP) notwendig."""

View File

@ -231,7 +231,7 @@ type Msg
| KeyUpPowerSearchbarMsg (Maybe KeyCode) | KeyUpPowerSearchbarMsg (Maybe KeyCode)
| RequestReprocessSelected | RequestReprocessSelected
| ReprocessSelectedConfirmed | ReprocessSelectedConfirmed
| ClientSettingsSaveResp UiSettings (Result Http.Error BasicResult) | ClientSettingsSaveResp (Result Http.Error BasicResult)
| RemoveItem String | RemoveItem String
| MergeSelectedItems | MergeSelectedItems
| MergeItemsMsg Comp.ItemMerge.Msg | MergeItemsMsg Comp.ItemMerge.Msg

View File

@ -22,7 +22,9 @@ import Comp.LinkTarget exposing (LinkTarget)
import Comp.PowerSearchInput import Comp.PowerSearchInput
import Comp.PublishItems import Comp.PublishItems
import Comp.SearchMenu import Comp.SearchMenu
import Data.AppEvent exposing (AppEvent(..))
import Data.Flags exposing (Flags) import Data.Flags exposing (Flags)
import Data.ItemArrange
import Data.ItemQuery as Q import Data.ItemQuery as Q
import Data.ItemSelection import Data.ItemSelection
import Data.Items import Data.Items
@ -44,7 +46,7 @@ type alias UpdateResult =
{ model : Model { model : Model
, cmd : Cmd Msg , cmd : Cmd Msg
, sub : Sub Msg , sub : Sub Msg
, newSettings : Maybe UiSettings , appEvent : AppEvent
} }
@ -74,7 +76,7 @@ update bookmarkId mId key flags texts settings msg model =
model model
DoNothing -> DoNothing ->
UpdateResult model Cmd.none Sub.none Nothing UpdateResult model Cmd.none Sub.none AppNothing
ResetSearch -> ResetSearch ->
let let
@ -868,26 +870,26 @@ update bookmarkId mId key flags texts settings msg model =
TogglePreviewFullWidth -> TogglePreviewFullWidth ->
let let
newSettings = newSettings s =
{ settings | cardPreviewFullWidth = not settings.cardPreviewFullWidth } { s | cardPreviewFullWidth = Just (not settings.cardPreviewFullWidth) }
cmd = cmd =
Api.saveClientSettings flags newSettings (ClientSettingsSaveResp newSettings) Api.saveUserClientSettingsBy flags newSettings ClientSettingsSaveResp
in in
noSub ( { model | viewMenuOpen = False }, cmd ) noSub ( { model | viewMenuOpen = False }, cmd )
ClientSettingsSaveResp newSettings (Ok res) -> ClientSettingsSaveResp (Ok res) ->
if res.success then if res.success then
{ model = model { model = model
, cmd = Cmd.none , cmd = Cmd.none
, sub = Sub.none , sub = Sub.none
, newSettings = Just newSettings , appEvent = AppReloadUiSettings
} }
else else
noSub ( model, Cmd.none ) noSub ( model, Cmd.none )
ClientSettingsSaveResp _ (Err _) -> ClientSettingsSaveResp (Err _) ->
noSub ( model, Cmd.none ) noSub ( model, Cmd.none )
PowerSearchMsg lm -> PowerSearchMsg lm ->
@ -1015,21 +1017,21 @@ update bookmarkId mId key flags texts settings msg model =
ToggleShowGroups -> ToggleShowGroups ->
let let
newSettings = newSettings s =
{ settings | itemSearchShowGroups = not settings.itemSearchShowGroups } { s | itemSearchShowGroups = Just (not settings.itemSearchShowGroups) }
cmd = cmd =
Api.saveClientSettings flags newSettings (ClientSettingsSaveResp newSettings) Api.saveUserClientSettingsBy flags newSettings ClientSettingsSaveResp
in in
noSub ( { model | viewMenuOpen = False }, cmd ) noSub ( { model | viewMenuOpen = False }, cmd )
ToggleArrange am -> ToggleArrange am ->
let let
newSettings = newSettings s =
{ settings | itemSearchArrange = am } { s | itemSearchArrange = Data.ItemArrange.asString am |> Just }
cmd = cmd =
Api.saveClientSettings flags newSettings (ClientSettingsSaveResp newSettings) Api.saveUserClientSettingsBy flags newSettings ClientSettingsSaveResp
in in
noSub ( { model | viewMenuOpen = False }, cmd ) noSub ( { model | viewMenuOpen = False }, cmd )
@ -1201,5 +1203,5 @@ makeResult ( m, c, s ) =
{ model = m { model = m
, cmd = c , cmd = c
, sub = s , sub = s
, newSettings = Nothing , appEvent = AppNothing
} }

View File

@ -42,10 +42,10 @@ type alias Model =
init : Flags -> UiSettings -> ( Model, Cmd Msg ) init : Flags -> UiSettings -> ( Model, Cmd Msg )
init flags settings = init flags _ =
let let
( um, uc ) = ( um, uc ) =
Comp.UiSettingsManage.init flags settings Comp.UiSettingsManage.init flags
( otpm, otpc ) = ( otpm, otpc ) =
Comp.OtpSetup.init flags Comp.OtpSetup.init flags
@ -107,5 +107,3 @@ type Msg
| NotificationHookMsg Comp.NotificationHookManage.Msg | NotificationHookMsg Comp.NotificationHookManage.Msg
| PeriodicQueryMsg Comp.PeriodicQueryTaskManage.Msg | PeriodicQueryMsg Comp.PeriodicQueryTaskManage.Msg
| ChannelMsg Comp.NotificationChannelManage.Msg | ChannelMsg Comp.NotificationChannelManage.Msg
| UpdateSettings
| ReceiveBrowserSettings StoredUiSettings

View File

@ -17,6 +17,7 @@ import Comp.OtpSetup
import Comp.PeriodicQueryTaskManage import Comp.PeriodicQueryTaskManage
import Comp.ScanMailboxManage import Comp.ScanMailboxManage
import Comp.UiSettingsManage import Comp.UiSettingsManage
import Data.AppEvent exposing (AppEvent(..))
import Data.Flags exposing (Flags) import Data.Flags exposing (Flags)
import Data.UiSettings exposing (UiSettings) import Data.UiSettings exposing (UiSettings)
import Page.UserSettings.Data exposing (..) import Page.UserSettings.Data exposing (..)
@ -26,10 +27,15 @@ type alias UpdateResult =
{ model : Model { model : Model
, cmd : Cmd Msg , cmd : Cmd Msg
, sub : Sub 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 -> UiSettings -> Msg -> Model -> UpdateResult
update flags settings msg model = update flags settings msg model =
case msg of case msg of
@ -47,7 +53,7 @@ update flags settings msg model =
{ model = { m | emailSettingsModel = em } { model = { m | emailSettingsModel = em }
, cmd = Cmd.map EmailSettingsMsg c , cmd = Cmd.map EmailSettingsMsg c
, sub = Sub.none , sub = Sub.none
, newSettings = Nothing , appEvent = AppNothing
} }
ImapSettingsTab -> ImapSettingsTab ->
@ -58,18 +64,14 @@ update flags settings msg model =
{ model = { m | imapSettingsModel = em } { model = { m | imapSettingsModel = em }
, cmd = Cmd.map ImapSettingsMsg c , cmd = Cmd.map ImapSettingsMsg c
, sub = Sub.none , sub = Sub.none
, newSettings = Nothing , appEvent = AppNothing
} }
ChangePassTab -> ChangePassTab ->
UpdateResult m Cmd.none Sub.none Nothing unit m
NotificationTab -> NotificationTab ->
{ model = m unit m
, cmd = Cmd.none
, sub = Sub.none
, newSettings = Nothing
}
NotificationWebhookTab -> NotificationWebhookTab ->
let let
@ -79,7 +81,7 @@ update flags settings msg model =
{ model = m { model = m
, cmd = Cmd.map NotificationHookMsg nc , cmd = Cmd.map NotificationHookMsg nc
, sub = Sub.none , sub = Sub.none
, newSettings = Nothing , appEvent = AppNothing
} }
NotificationQueriesTab -> NotificationQueriesTab ->
@ -88,7 +90,7 @@ update flags settings msg model =
Cmd.map NotificationMsg Cmd.map NotificationMsg
(Tuple.second (Comp.DueItemsTaskManage.init flags)) (Tuple.second (Comp.DueItemsTaskManage.init flags))
in in
UpdateResult m initCmd Sub.none Nothing UpdateResult m initCmd Sub.none AppNothing
NotificationDueItemsTab -> NotificationDueItemsTab ->
let let
@ -96,7 +98,7 @@ update flags settings msg model =
Cmd.map NotificationMsg Cmd.map NotificationMsg
(Tuple.second (Comp.DueItemsTaskManage.init flags)) (Tuple.second (Comp.DueItemsTaskManage.init flags))
in in
UpdateResult m initCmd Sub.none Nothing UpdateResult m initCmd Sub.none AppNothing
ScanMailboxTab -> ScanMailboxTab ->
let let
@ -104,16 +106,24 @@ update flags settings msg model =
Cmd.map ScanMailboxMsg Cmd.map ScanMailboxMsg
(Tuple.second (Comp.ScanMailboxManage.init flags)) (Tuple.second (Comp.ScanMailboxManage.init flags))
in in
UpdateResult m initCmd Sub.none Nothing UpdateResult m initCmd Sub.none AppNothing
UiSettingsTab -> UiSettingsTab ->
UpdateResult m Cmd.none Sub.none Nothing let
( um, uc ) =
Comp.UiSettingsManage.init flags
in
{ model = { m | uiSettingsModel = um }
, cmd = Cmd.map UiSettingsMsg uc
, sub = Sub.none
, appEvent = AppNothing
}
OtpTab -> OtpTab ->
UpdateResult m Cmd.none Sub.none Nothing unit m
ChannelTab -> ChannelTab ->
UpdateResult m Cmd.none Sub.none Nothing unit m
ChangePassMsg m -> ChangePassMsg m ->
let let
@ -123,7 +133,7 @@ update flags settings msg model =
{ model = { model | changePassModel = m2 } { model = { model | changePassModel = m2 }
, cmd = Cmd.map ChangePassMsg c2 , cmd = Cmd.map ChangePassMsg c2
, sub = Sub.none , sub = Sub.none
, newSettings = Nothing , appEvent = AppNothing
} }
EmailSettingsMsg m -> EmailSettingsMsg m ->
@ -134,7 +144,7 @@ update flags settings msg model =
{ model = { model | emailSettingsModel = m2 } { model = { model | emailSettingsModel = m2 }
, cmd = Cmd.map EmailSettingsMsg c2 , cmd = Cmd.map EmailSettingsMsg c2
, sub = Sub.none , sub = Sub.none
, newSettings = Nothing , appEvent = AppNothing
} }
ImapSettingsMsg m -> ImapSettingsMsg m ->
@ -145,7 +155,7 @@ update flags settings msg model =
{ model = { model | imapSettingsModel = m2 } { model = { model | imapSettingsModel = m2 }
, cmd = Cmd.map ImapSettingsMsg c2 , cmd = Cmd.map ImapSettingsMsg c2
, sub = Sub.none , sub = Sub.none
, newSettings = Nothing , appEvent = AppNothing
} }
NotificationMsg lm -> NotificationMsg lm ->
@ -156,7 +166,7 @@ update flags settings msg model =
{ model = { model | notificationModel = m2 } { model = { model | notificationModel = m2 }
, cmd = Cmd.map NotificationMsg c2 , cmd = Cmd.map NotificationMsg c2
, sub = Sub.none , sub = Sub.none
, newSettings = Nothing , appEvent = AppNothing
} }
ScanMailboxMsg lm -> ScanMailboxMsg lm ->
@ -167,7 +177,7 @@ update flags settings msg model =
{ model = { model | scanMailboxModel = m2 } { model = { model | scanMailboxModel = m2 }
, cmd = Cmd.map ScanMailboxMsg c2 , cmd = Cmd.map ScanMailboxMsg c2
, sub = Sub.none , sub = Sub.none
, newSettings = Nothing , appEvent = AppNothing
} }
UiSettingsMsg lm -> UiSettingsMsg lm ->
@ -178,7 +188,7 @@ update flags settings msg model =
{ model = { model | uiSettingsModel = res.model } { model = { model | uiSettingsModel = res.model }
, cmd = Cmd.map UiSettingsMsg res.cmd , cmd = Cmd.map UiSettingsMsg res.cmd
, sub = Sub.map UiSettingsMsg res.sub , sub = Sub.map UiSettingsMsg res.sub
, newSettings = res.newSettings , appEvent = res.appEvent
} }
OtpSetupMsg lm -> OtpSetupMsg lm ->
@ -189,7 +199,7 @@ update flags settings msg model =
{ model = { model | otpSetupModel = otpm } { model = { model | otpSetupModel = otpm }
, cmd = Cmd.map OtpSetupMsg otpc , cmd = Cmd.map OtpSetupMsg otpc
, sub = Sub.none , sub = Sub.none
, newSettings = Nothing , appEvent = AppNothing
} }
NotificationHookMsg lm -> NotificationHookMsg lm ->
@ -200,7 +210,7 @@ update flags settings msg model =
{ model = { model | notificationHookModel = hm } { model = { model | notificationHookModel = hm }
, cmd = Cmd.map NotificationHookMsg hc , cmd = Cmd.map NotificationHookMsg hc
, sub = Sub.none , sub = Sub.none
, newSettings = Nothing , appEvent = AppNothing
} }
ChannelMsg lm -> ChannelMsg lm ->
@ -211,22 +221,9 @@ update flags settings msg model =
{ model = { model | channelModel = cm } { model = { model | channelModel = cm }
, cmd = Cmd.map ChannelMsg cc , cmd = Cmd.map ChannelMsg cc
, sub = Sub.none , sub = Sub.none
, newSettings = Nothing , appEvent = AppNothing
} }
UpdateSettings ->
update flags
settings
(UiSettingsMsg Comp.UiSettingsManage.UpdateSettings)
model
ReceiveBrowserSettings sett ->
let
lm =
Comp.UiSettingsManage.ReceiveBrowserSettings sett
in
update flags settings (UiSettingsMsg lm) model
PeriodicQueryMsg lm -> PeriodicQueryMsg lm ->
let let
( pqm, pqc, pqs ) = ( pqm, pqc, pqs ) =
@ -235,5 +232,5 @@ update flags settings msg model =
{ model = { model | periodicQueryModel = pqm } { model = { model | periodicQueryModel = pqm }
, cmd = Cmd.map PeriodicQueryMsg pqc , cmd = Cmd.map PeriodicQueryMsg pqc
, sub = Sub.map PeriodicQueryMsg pqs , sub = Sub.map PeriodicQueryMsg pqs
, newSettings = Nothing , appEvent = AppNothing
} }

View File

@ -11,9 +11,7 @@ port module Ports exposing
, printElement , printElement
, receiveCheckQueryResult , receiveCheckQueryResult
, receiveServerEvent , receiveServerEvent
, receiveUiSettings
, removeAccount , removeAccount
, requestUiSettings
, setAccount , setAccount
, setUiTheme , setUiTheme
) )
@ -21,7 +19,6 @@ port module Ports exposing
import Api.Model.AuthResult exposing (AuthResult) import Api.Model.AuthResult exposing (AuthResult)
import Data.QueryParseResult exposing (QueryParseResult) import Data.QueryParseResult exposing (QueryParseResult)
import Data.ServerEvent exposing (ServerEvent) import Data.ServerEvent exposing (ServerEvent)
import Data.UiSettings exposing (StoredUiSettings)
import Data.UiTheme exposing (UiTheme) import Data.UiTheme exposing (UiTheme)
import Json.Decode as D import Json.Decode as D
@ -46,12 +43,6 @@ port receiveCheckQueryResult : (QueryParseResult -> msg) -> Sub msg
port initClipboard : ( String, String ) -> Cmd msg port initClipboard : ( String, String ) -> Cmd msg
port receiveUiSettings : (StoredUiSettings -> msg) -> Sub msg
port requestUiSettings : AuthResult -> Cmd msg
{-| Creates a new window/tab, writes the contents of the given element {-| Creates a new window/tab, writes the contents of the given element
and calls the print dialog. and calls the print dialog.
-} -}

View File

@ -55,25 +55,6 @@ elmApp.ports.removeAccount.subscribe(function() {
closeWS(); closeWS();
}); });
elmApp.ports.requestUiSettings.subscribe(function(args) {
console.log("Requesting ui settings");
var account = args;
var collective = account ? account.collective : null;
var user = account ? account.user : null;
if (collective && user) {
var key = collective + "/" + user + "/uiSettings";
var settings = localStorage.getItem(key);
try {
var data = settings ? JSON.parse(settings) : null;
if (data) {
console.log("Sending browser ui settings");
elmApp.ports.receiveUiSettings.send(data);
}
} catch (error) {
console.log(error);
}
}
});
var docspell_clipboards = {}; var docspell_clipboards = {};