mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-21 01:48:26 +00:00
412 lines
13 KiB
Elm
412 lines
13 KiB
Elm
module Comp.UiSettingsForm exposing
|
|
( Model
|
|
, Msg
|
|
, init
|
|
, update
|
|
, view
|
|
)
|
|
|
|
import Api
|
|
import Api.Model.TagList exposing (TagList)
|
|
import Comp.ColorTagger
|
|
import Comp.FieldListSelect
|
|
import Comp.IntField
|
|
import Data.Color exposing (Color)
|
|
import Data.Fields exposing (Field)
|
|
import Data.Flags exposing (Flags)
|
|
import Data.UiSettings exposing (Pos(..), UiSettings)
|
|
import Dict exposing (Dict)
|
|
import Html exposing (..)
|
|
import Html.Attributes exposing (..)
|
|
import Html.Events exposing (onCheck)
|
|
import Http
|
|
import Util.Tag
|
|
|
|
|
|
type alias Model =
|
|
{ itemSearchPageSize : Maybe Int
|
|
, searchPageSizeModel : Comp.IntField.Model
|
|
, tagColors : Dict String Color
|
|
, tagColorModel : Comp.ColorTagger.Model
|
|
, nativePdfPreview : Bool
|
|
, itemSearchNoteLength : Maybe Int
|
|
, searchNoteLengthModel : Comp.IntField.Model
|
|
, itemDetailNotesPosition : Pos
|
|
, searchMenuFolderCount : Maybe Int
|
|
, searchMenuFolderCountModel : Comp.IntField.Model
|
|
, searchMenuTagCount : Maybe Int
|
|
, searchMenuTagCountModel : Comp.IntField.Model
|
|
, searchMenuTagCatCount : Maybe Int
|
|
, searchMenuTagCatCountModel : Comp.IntField.Model
|
|
, formFields : List Field
|
|
, itemDetailShortcuts : Bool
|
|
}
|
|
|
|
|
|
init : Flags -> UiSettings -> ( Model, Cmd Msg )
|
|
init flags settings =
|
|
( { itemSearchPageSize = Just settings.itemSearchPageSize
|
|
, searchPageSizeModel =
|
|
Comp.IntField.init
|
|
(Just 10)
|
|
(Just flags.config.maxPageSize)
|
|
False
|
|
"Page size"
|
|
, tagColors = settings.tagCategoryColors
|
|
, tagColorModel =
|
|
Comp.ColorTagger.init
|
|
[]
|
|
Data.Color.all
|
|
, nativePdfPreview = settings.nativePdfPreview
|
|
, itemSearchNoteLength = Just settings.itemSearchNoteLength
|
|
, searchNoteLengthModel =
|
|
Comp.IntField.init
|
|
(Just 0)
|
|
(Just flags.config.maxNoteLength)
|
|
False
|
|
"Max. Note Length"
|
|
, itemDetailNotesPosition = settings.itemDetailNotesPosition
|
|
, searchMenuFolderCount = Just settings.searchMenuFolderCount
|
|
, searchMenuFolderCountModel =
|
|
Comp.IntField.init
|
|
(Just 0)
|
|
(Just 2000)
|
|
False
|
|
"Number of folders in search menu"
|
|
, searchMenuTagCount = Just settings.searchMenuTagCount
|
|
, searchMenuTagCountModel =
|
|
Comp.IntField.init
|
|
(Just 0)
|
|
(Just 2000)
|
|
False
|
|
"Number of tags in search menu"
|
|
, searchMenuTagCatCount = Just settings.searchMenuTagCatCount
|
|
, searchMenuTagCatCountModel =
|
|
Comp.IntField.init
|
|
(Just 0)
|
|
(Just 2000)
|
|
False
|
|
"Number of categories in search menu"
|
|
, formFields = settings.formFields
|
|
, itemDetailShortcuts = settings.itemDetailShortcuts
|
|
}
|
|
, Api.getTags flags "" GetTagsResp
|
|
)
|
|
|
|
|
|
type Msg
|
|
= SearchPageSizeMsg Comp.IntField.Msg
|
|
| TagColorMsg Comp.ColorTagger.Msg
|
|
| GetTagsResp (Result Http.Error TagList)
|
|
| TogglePdfPreview
|
|
| NoteLengthMsg Comp.IntField.Msg
|
|
| SetNotesPosition Pos
|
|
| SearchMenuFolderMsg Comp.IntField.Msg
|
|
| SearchMenuTagMsg Comp.IntField.Msg
|
|
| SearchMenuTagCatMsg Comp.IntField.Msg
|
|
| FieldListMsg Comp.FieldListSelect.Msg
|
|
| ToggleItemDetailShortcuts
|
|
|
|
|
|
|
|
--- Update
|
|
|
|
|
|
update : UiSettings -> Msg -> Model -> ( Model, Maybe UiSettings )
|
|
update sett msg model =
|
|
case msg of
|
|
SearchPageSizeMsg lm ->
|
|
let
|
|
( m, n ) =
|
|
Comp.IntField.update lm model.searchPageSizeModel
|
|
|
|
nextSettings =
|
|
Maybe.map (\sz -> { sett | itemSearchPageSize = sz }) n
|
|
|
|
model_ =
|
|
{ model
|
|
| searchPageSizeModel = m
|
|
, itemSearchPageSize = n
|
|
}
|
|
in
|
|
( model_, nextSettings )
|
|
|
|
NoteLengthMsg lm ->
|
|
let
|
|
( m, n ) =
|
|
Comp.IntField.update lm model.searchNoteLengthModel
|
|
|
|
nextSettings =
|
|
Maybe.map (\len -> { sett | itemSearchNoteLength = len }) n
|
|
|
|
model_ =
|
|
{ model
|
|
| searchNoteLengthModel = m
|
|
, itemSearchNoteLength = n
|
|
}
|
|
in
|
|
( model_, nextSettings )
|
|
|
|
SearchMenuFolderMsg lm ->
|
|
let
|
|
( m, n ) =
|
|
Comp.IntField.update lm model.searchMenuFolderCountModel
|
|
|
|
nextSettings =
|
|
Maybe.map (\len -> { sett | searchMenuFolderCount = len }) n
|
|
|
|
model_ =
|
|
{ model
|
|
| searchMenuFolderCountModel = m
|
|
, searchMenuFolderCount = n
|
|
}
|
|
in
|
|
( model_, nextSettings )
|
|
|
|
SearchMenuTagMsg lm ->
|
|
let
|
|
( m, n ) =
|
|
Comp.IntField.update lm model.searchMenuTagCountModel
|
|
|
|
nextSettings =
|
|
Maybe.map (\len -> { sett | searchMenuTagCount = len }) n
|
|
|
|
model_ =
|
|
{ model
|
|
| searchMenuTagCountModel = m
|
|
, searchMenuTagCount = n
|
|
}
|
|
in
|
|
( model_, nextSettings )
|
|
|
|
SearchMenuTagCatMsg lm ->
|
|
let
|
|
( m, n ) =
|
|
Comp.IntField.update lm model.searchMenuTagCatCountModel
|
|
|
|
nextSettings =
|
|
Maybe.map (\len -> { sett | searchMenuTagCatCount = len }) n
|
|
|
|
model_ =
|
|
{ model
|
|
| searchMenuTagCatCountModel = m
|
|
, searchMenuTagCatCount = n
|
|
}
|
|
in
|
|
( model_, nextSettings )
|
|
|
|
SetNotesPosition pos ->
|
|
let
|
|
model_ =
|
|
{ model | itemDetailNotesPosition = pos }
|
|
in
|
|
if model_.itemDetailNotesPosition == sett.itemDetailNotesPosition then
|
|
( model_, Nothing )
|
|
|
|
else
|
|
( model_, Just { sett | itemDetailNotesPosition = model_.itemDetailNotesPosition } )
|
|
|
|
TagColorMsg lm ->
|
|
let
|
|
( m_, d_ ) =
|
|
Comp.ColorTagger.update lm model.tagColorModel
|
|
|
|
nextSettings =
|
|
Maybe.map (\tc -> { sett | tagCategoryColors = tc }) d_
|
|
|
|
model_ =
|
|
{ model
|
|
| tagColorModel = m_
|
|
, tagColors = Maybe.withDefault model.tagColors d_
|
|
}
|
|
in
|
|
( model_, nextSettings )
|
|
|
|
TogglePdfPreview ->
|
|
let
|
|
flag =
|
|
not model.nativePdfPreview
|
|
in
|
|
( { model | nativePdfPreview = flag }
|
|
, Just { sett | nativePdfPreview = flag }
|
|
)
|
|
|
|
GetTagsResp (Ok tl) ->
|
|
let
|
|
categories =
|
|
Util.Tag.getCategories tl.items
|
|
in
|
|
( { model
|
|
| tagColorModel =
|
|
Comp.ColorTagger.init
|
|
categories
|
|
Data.Color.all
|
|
}
|
|
, Nothing
|
|
)
|
|
|
|
GetTagsResp (Err _) ->
|
|
( model, Nothing )
|
|
|
|
FieldListMsg lm ->
|
|
let
|
|
selected =
|
|
Comp.FieldListSelect.update lm model.formFields
|
|
|
|
newSettings =
|
|
{ sett | formFields = selected }
|
|
in
|
|
( { model | formFields = selected }
|
|
, if selected /= model.formFields then
|
|
Just newSettings
|
|
|
|
else
|
|
Nothing
|
|
)
|
|
|
|
ToggleItemDetailShortcuts ->
|
|
let
|
|
flag =
|
|
not model.itemDetailShortcuts
|
|
in
|
|
( { model | itemDetailShortcuts = flag }
|
|
, Just { sett | itemDetailShortcuts = flag }
|
|
)
|
|
|
|
|
|
|
|
--- View
|
|
|
|
|
|
tagColorViewOpts : Comp.ColorTagger.ViewOpts
|
|
tagColorViewOpts =
|
|
{ renderItem =
|
|
\( k, v ) ->
|
|
span [ class ("ui label " ++ Data.Color.toString v) ]
|
|
[ text k ]
|
|
, label = "Choose color for tag categories"
|
|
, description = Just "Tags can be represented differently based on their category."
|
|
}
|
|
|
|
|
|
view : Flags -> UiSettings -> Model -> Html Msg
|
|
view flags _ model =
|
|
div [ class "ui form" ]
|
|
[ div [ class "ui dividing header" ]
|
|
[ text "Item Search"
|
|
]
|
|
, Html.map SearchPageSizeMsg
|
|
(Comp.IntField.viewWithInfo
|
|
("Maximum results in one page when searching items. At most "
|
|
++ String.fromInt flags.config.maxPageSize
|
|
++ "."
|
|
)
|
|
model.itemSearchPageSize
|
|
"field"
|
|
model.searchPageSizeModel
|
|
)
|
|
, Html.map NoteLengthMsg
|
|
(Comp.IntField.viewWithInfo
|
|
("Maximum size of the item notes to display in card view. Between 0 - "
|
|
++ String.fromInt flags.config.maxNoteLength
|
|
++ "."
|
|
)
|
|
model.itemSearchNoteLength
|
|
"field"
|
|
model.searchNoteLengthModel
|
|
)
|
|
, div [ class "ui dividing header" ]
|
|
[ text "Search Menu" ]
|
|
, Html.map SearchMenuTagMsg
|
|
(Comp.IntField.viewWithInfo
|
|
"How many tags to display in search menu at once. Others can be expanded. Use 0 to always show all."
|
|
model.searchMenuTagCount
|
|
"field"
|
|
model.searchMenuTagCountModel
|
|
)
|
|
, Html.map SearchMenuTagCatMsg
|
|
(Comp.IntField.viewWithInfo
|
|
"How many categories to display in search menu at once. Others can be expanded. Use 0 to always show all."
|
|
model.searchMenuTagCatCount
|
|
"field"
|
|
model.searchMenuTagCatCountModel
|
|
)
|
|
, Html.map SearchMenuFolderMsg
|
|
(Comp.IntField.viewWithInfo
|
|
"How many folders to display in search menu at once. Other folders can be expanded. Use 0 to always show all."
|
|
model.searchMenuFolderCount
|
|
"field"
|
|
model.searchMenuFolderCountModel
|
|
)
|
|
, div [ class "ui dividing header" ]
|
|
[ text "Item Detail"
|
|
]
|
|
, div [ class "field" ]
|
|
[ div [ class "ui checkbox" ]
|
|
[ input
|
|
[ type_ "checkbox"
|
|
, onCheck (\_ -> TogglePdfPreview)
|
|
, checked model.nativePdfPreview
|
|
]
|
|
[]
|
|
, label []
|
|
[ text "Browser-native PDF preview"
|
|
]
|
|
]
|
|
]
|
|
, div [ class "field" ]
|
|
[ div [ class "ui checkbox" ]
|
|
[ input
|
|
[ type_ "checkbox"
|
|
, onCheck (\_ -> ToggleItemDetailShortcuts)
|
|
, checked model.itemDetailShortcuts
|
|
]
|
|
[]
|
|
, label []
|
|
[ text "Use keyboard shortcuts for navigation and confirm/unconfirm with open edit menu."
|
|
]
|
|
]
|
|
]
|
|
, div [ class "grouped fields" ]
|
|
[ label [] [ text "Position of item notes" ]
|
|
, div [ class "field" ]
|
|
[ div [ class "ui radio checkbox" ]
|
|
[ input
|
|
[ type_ "radio"
|
|
, checked (model.itemDetailNotesPosition == Top)
|
|
, onCheck (\_ -> SetNotesPosition Top)
|
|
]
|
|
[]
|
|
, label [] [ text "Top" ]
|
|
]
|
|
]
|
|
, div [ class "field" ]
|
|
[ div [ class "ui radio checkbox" ]
|
|
[ input
|
|
[ type_ "radio"
|
|
, checked (model.itemDetailNotesPosition == Bottom)
|
|
, onCheck (\_ -> SetNotesPosition Bottom)
|
|
]
|
|
[]
|
|
, label [] [ text "Bottom" ]
|
|
]
|
|
]
|
|
]
|
|
, div [ class "ui dividing header" ]
|
|
[ text "Tag Category Colors"
|
|
]
|
|
, Html.map TagColorMsg
|
|
(Comp.ColorTagger.view
|
|
model.tagColors
|
|
tagColorViewOpts
|
|
model.tagColorModel
|
|
)
|
|
, div [ class "ui dividing header" ]
|
|
[ text "Fields"
|
|
]
|
|
, span [ class "small-info" ]
|
|
[ text "Choose which fields to display in search and edit menus."
|
|
]
|
|
, Html.map FieldListMsg (Comp.FieldListSelect.view model.formFields)
|
|
]
|