mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-05 22:55:58 +00:00
Add input field to provide colors for tag categories
This commit is contained in:
parent
c595f3b737
commit
f4e37b512f
@ -47,30 +47,35 @@ type alias Model =
|
||||
}
|
||||
|
||||
|
||||
init : Key -> Url -> Flags -> Model
|
||||
init : Key -> Url -> Flags -> ( Model, Cmd Msg )
|
||||
init key url flags =
|
||||
let
|
||||
page =
|
||||
Page.fromUrl url
|
||||
|> Maybe.withDefault (defaultPage flags)
|
||||
|
||||
( um, uc ) =
|
||||
Page.UserSettings.Data.emptyModel flags
|
||||
in
|
||||
{ flags = flags
|
||||
, key = key
|
||||
, page = page
|
||||
, version = Api.Model.VersionInfo.empty
|
||||
, homeModel = Page.Home.Data.init flags
|
||||
, loginModel = Page.Login.Data.emptyModel
|
||||
, manageDataModel = Page.ManageData.Data.emptyModel
|
||||
, collSettingsModel = Page.CollectiveSettings.Data.emptyModel
|
||||
, userSettingsModel = Page.UserSettings.Data.emptyModel flags
|
||||
, queueModel = Page.Queue.Data.emptyModel
|
||||
, registerModel = Page.Register.Data.emptyModel
|
||||
, uploadModel = Page.Upload.Data.emptyModel
|
||||
, newInviteModel = Page.NewInvite.Data.emptyModel
|
||||
, itemDetailModel = Page.ItemDetail.Data.emptyModel
|
||||
, navMenuOpen = False
|
||||
, subs = Sub.none
|
||||
}
|
||||
( { flags = flags
|
||||
, key = key
|
||||
, page = page
|
||||
, version = Api.Model.VersionInfo.empty
|
||||
, homeModel = Page.Home.Data.init flags
|
||||
, loginModel = Page.Login.Data.emptyModel
|
||||
, manageDataModel = Page.ManageData.Data.emptyModel
|
||||
, collSettingsModel = Page.CollectiveSettings.Data.emptyModel
|
||||
, userSettingsModel = um
|
||||
, queueModel = Page.Queue.Data.emptyModel
|
||||
, registerModel = Page.Register.Data.emptyModel
|
||||
, uploadModel = Page.Upload.Data.emptyModel
|
||||
, newInviteModel = Page.NewInvite.Data.emptyModel
|
||||
, itemDetailModel = Page.ItemDetail.Data.emptyModel
|
||||
, navMenuOpen = False
|
||||
, subs = Sub.none
|
||||
}
|
||||
, Cmd.map UserSettingsMsg uc
|
||||
)
|
||||
|
||||
|
||||
type Msg
|
||||
|
@ -8,6 +8,7 @@ module Comp.FixedDropdown exposing
|
||||
, initTuple
|
||||
, update
|
||||
, view
|
||||
, viewString
|
||||
)
|
||||
|
||||
import Html exposing (..)
|
||||
@ -101,6 +102,11 @@ view selected model =
|
||||
]
|
||||
|
||||
|
||||
viewString : Maybe String -> Model String -> Html (Msg String)
|
||||
viewString selected model =
|
||||
view (Maybe.map (\s -> Item s s) selected) model
|
||||
|
||||
|
||||
renderItems : Item a -> Html (Msg a)
|
||||
renderItems item =
|
||||
div [ class "item", onClick (SelectItem item) ]
|
||||
|
181
modules/webapp/src/main/elm/Comp/MappingForm.elm
Normal file
181
modules/webapp/src/main/elm/Comp/MappingForm.elm
Normal file
@ -0,0 +1,181 @@
|
||||
module Comp.MappingForm exposing
|
||||
( FormData
|
||||
, Model
|
||||
, Msg
|
||||
, ViewOpts
|
||||
, init
|
||||
, update
|
||||
, view
|
||||
)
|
||||
|
||||
import Comp.FixedDropdown
|
||||
import Dict exposing (Dict)
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onClick)
|
||||
import Util.Maybe
|
||||
|
||||
|
||||
type alias FormData =
|
||||
Dict String String
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ leftDropdown : Comp.FixedDropdown.Model String
|
||||
, rightDropdown : Comp.FixedDropdown.Model String
|
||||
, leftSelect : Maybe String
|
||||
, rightSelect : Maybe String
|
||||
}
|
||||
|
||||
|
||||
type Msg
|
||||
= AddPair FormData
|
||||
| DeleteItem FormData String
|
||||
| EditItem String String
|
||||
| LeftMsg (Comp.FixedDropdown.Msg String)
|
||||
| RightMsg (Comp.FixedDropdown.Msg String)
|
||||
|
||||
|
||||
init : List String -> List String -> Model
|
||||
init leftSel rightSel =
|
||||
{ leftDropdown = Comp.FixedDropdown.initString leftSel
|
||||
, rightDropdown = Comp.FixedDropdown.initString rightSel
|
||||
, leftSelect = Nothing
|
||||
, rightSelect = Nothing
|
||||
}
|
||||
|
||||
|
||||
|
||||
--- Update
|
||||
|
||||
|
||||
update : Msg -> Model -> ( Model, Maybe FormData )
|
||||
update msg model =
|
||||
case msg of
|
||||
AddPair data ->
|
||||
case ( model.leftSelect, model.rightSelect ) of
|
||||
( Just l, Just r ) ->
|
||||
( { model
|
||||
| leftSelect = Nothing
|
||||
, rightSelect = Nothing
|
||||
}
|
||||
, Just (Dict.insert l r data)
|
||||
)
|
||||
|
||||
_ ->
|
||||
( model, Nothing )
|
||||
|
||||
DeleteItem data k ->
|
||||
( model, Just (Dict.remove k data) )
|
||||
|
||||
EditItem k v ->
|
||||
( { model
|
||||
| leftSelect = Just k
|
||||
, rightSelect = Just v
|
||||
}
|
||||
, Nothing
|
||||
)
|
||||
|
||||
LeftMsg lm ->
|
||||
let
|
||||
( m_, la ) =
|
||||
Comp.FixedDropdown.update lm model.leftDropdown
|
||||
in
|
||||
( { model
|
||||
| leftDropdown = m_
|
||||
, leftSelect = Util.Maybe.withDefault model.leftSelect la
|
||||
}
|
||||
, Nothing
|
||||
)
|
||||
|
||||
RightMsg lm ->
|
||||
let
|
||||
( m_, la ) =
|
||||
Comp.FixedDropdown.update lm model.rightDropdown
|
||||
in
|
||||
( { model
|
||||
| rightDropdown = m_
|
||||
, rightSelect = Util.Maybe.withDefault model.rightSelect la
|
||||
}
|
||||
, Nothing
|
||||
)
|
||||
|
||||
|
||||
|
||||
--- View
|
||||
|
||||
|
||||
type alias ViewOpts =
|
||||
{ renderItem : ( String, String ) -> Html Msg
|
||||
, label : String
|
||||
, description : Maybe String
|
||||
}
|
||||
|
||||
|
||||
view : FormData -> ViewOpts -> Model -> Html Msg
|
||||
view data opts model =
|
||||
div [ class "field" ]
|
||||
[ label [] [ text opts.label ]
|
||||
, div [ class "fields" ]
|
||||
[ div [ class "inline field" ]
|
||||
[ Html.map LeftMsg
|
||||
(Comp.FixedDropdown.viewString
|
||||
model.leftSelect
|
||||
model.leftDropdown
|
||||
)
|
||||
]
|
||||
, div [ class "inline field" ]
|
||||
[ Html.map RightMsg
|
||||
(Comp.FixedDropdown.viewString
|
||||
model.rightSelect
|
||||
model.rightDropdown
|
||||
)
|
||||
]
|
||||
, button
|
||||
[ class "ui icon button"
|
||||
, onClick (AddPair data)
|
||||
, href "#"
|
||||
]
|
||||
[ i [ class "add icon" ] []
|
||||
]
|
||||
]
|
||||
, span
|
||||
[ classList
|
||||
[ ( "small-info", True )
|
||||
, ( "invisible hidden", opts.description == Nothing )
|
||||
]
|
||||
]
|
||||
[ Maybe.withDefault "" opts.description
|
||||
|> text
|
||||
]
|
||||
, renderFormData opts data
|
||||
]
|
||||
|
||||
|
||||
renderFormData : ViewOpts -> FormData -> Html Msg
|
||||
renderFormData opts data =
|
||||
let
|
||||
values =
|
||||
Dict.toList data
|
||||
|
||||
renderItem ( k, v ) =
|
||||
div [ class "item" ]
|
||||
[ a
|
||||
[ class "link icon"
|
||||
, href "#"
|
||||
, onClick (DeleteItem data k)
|
||||
]
|
||||
[ i [ class "trash icon" ] []
|
||||
]
|
||||
, a
|
||||
[ class "link icon"
|
||||
, href "#"
|
||||
, onClick (EditItem k v)
|
||||
]
|
||||
[ i [ class "edit icon" ] []
|
||||
]
|
||||
, opts.renderItem ( k, v )
|
||||
]
|
||||
in
|
||||
div [ class "ui list" ]
|
||||
(List.map renderItem values)
|
@ -2,40 +2,51 @@ module Comp.UiSettingsForm exposing
|
||||
( Model
|
||||
, Msg
|
||||
, init
|
||||
, initWith
|
||||
, update
|
||||
, view
|
||||
)
|
||||
|
||||
import Api
|
||||
import Api.Model.TagList exposing (TagList)
|
||||
import Comp.IntField
|
||||
import Comp.MappingForm
|
||||
import Data.Color
|
||||
import Data.Flags exposing (Flags)
|
||||
import Data.UiSettings exposing (StoredUiSettings, UiSettings)
|
||||
import Dict exposing (Dict)
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Http
|
||||
import Util.List
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ defaults : UiSettings
|
||||
, input : StoredUiSettings
|
||||
, searchPageSizeModel : Comp.IntField.Model
|
||||
, tagColorModel : Comp.MappingForm.Model
|
||||
, tagColors : Dict String String
|
||||
}
|
||||
|
||||
|
||||
initWith : UiSettings -> Model
|
||||
initWith defaults =
|
||||
{ defaults = defaults
|
||||
, input = Data.UiSettings.toStoredUiSettings defaults
|
||||
, searchPageSizeModel =
|
||||
Comp.IntField.init
|
||||
(Just 10)
|
||||
(Just 500)
|
||||
False
|
||||
"Item search page"
|
||||
}
|
||||
|
||||
|
||||
init : Model
|
||||
init =
|
||||
initWith Data.UiSettings.defaults
|
||||
init : Flags -> UiSettings -> ( Model, Cmd Msg )
|
||||
init flags defaults =
|
||||
( { defaults = defaults
|
||||
, input = Data.UiSettings.toStoredUiSettings defaults
|
||||
, searchPageSizeModel =
|
||||
Comp.IntField.init
|
||||
(Just 10)
|
||||
(Just 500)
|
||||
False
|
||||
"Item search page"
|
||||
, tagColorModel =
|
||||
Comp.MappingForm.init
|
||||
[]
|
||||
Data.Color.allString
|
||||
, tagColors = Dict.empty
|
||||
}
|
||||
, Api.getTags flags "" GetTagsResp
|
||||
)
|
||||
|
||||
|
||||
changeInput : (StoredUiSettings -> StoredUiSettings) -> Model -> StoredUiSettings
|
||||
@ -45,6 +56,8 @@ changeInput change model =
|
||||
|
||||
type Msg
|
||||
= SearchPageSizeMsg Comp.IntField.Msg
|
||||
| TagColorMsg Comp.MappingForm.Msg
|
||||
| GetTagsResp (Result Http.Error TagList)
|
||||
|
||||
|
||||
getSettings : Model -> UiSettings
|
||||
@ -75,11 +88,53 @@ update msg model =
|
||||
in
|
||||
( model_, nextSettings )
|
||||
|
||||
TagColorMsg lm ->
|
||||
let
|
||||
( m_, d_ ) =
|
||||
Comp.MappingForm.update lm model.tagColorModel
|
||||
in
|
||||
( { model
|
||||
| tagColorModel = m_
|
||||
, tagColors = Maybe.withDefault model.tagColors d_
|
||||
}
|
||||
, Nothing
|
||||
)
|
||||
|
||||
GetTagsResp (Ok tl) ->
|
||||
let
|
||||
categories =
|
||||
List.filterMap .category tl.items
|
||||
|> Util.List.distinct
|
||||
in
|
||||
( { model
|
||||
| tagColorModel =
|
||||
Comp.MappingForm.init
|
||||
categories
|
||||
Data.Color.allString
|
||||
, tagColors = Dict.empty
|
||||
}
|
||||
, Nothing
|
||||
)
|
||||
|
||||
GetTagsResp (Err _) ->
|
||||
( model, Nothing )
|
||||
|
||||
|
||||
|
||||
--- View
|
||||
|
||||
|
||||
tagColorViewOpts : Comp.MappingForm.ViewOpts
|
||||
tagColorViewOpts =
|
||||
{ renderItem =
|
||||
\( k, v ) ->
|
||||
span [ class ("ui label " ++ v) ]
|
||||
[ text k ]
|
||||
, label = "Choose color for tag categories"
|
||||
, description = Just "Tags can be represented differently based on their category."
|
||||
}
|
||||
|
||||
|
||||
view : Model -> Html Msg
|
||||
view model =
|
||||
div [ class "ui form" ]
|
||||
@ -87,7 +142,13 @@ view model =
|
||||
(Comp.IntField.viewWithInfo
|
||||
"Maximum results in one page when searching items."
|
||||
model.input.itemSearchPageSize
|
||||
""
|
||||
"field"
|
||||
model.searchPageSizeModel
|
||||
)
|
||||
, Html.map TagColorMsg
|
||||
(Comp.MappingForm.view
|
||||
model.tagColors
|
||||
tagColorViewOpts
|
||||
model.tagColorModel
|
||||
)
|
||||
]
|
||||
|
@ -29,12 +29,18 @@ type Msg
|
||||
| SettingsSaved
|
||||
|
||||
|
||||
init : UiSettings -> Model
|
||||
init defaults =
|
||||
{ formModel = Comp.UiSettingsForm.initWith defaults
|
||||
, settings = Nothing
|
||||
, message = Nothing
|
||||
}
|
||||
init : Flags -> UiSettings -> ( Model, Cmd Msg )
|
||||
init flags defaults =
|
||||
let
|
||||
( fm, fc ) =
|
||||
Comp.UiSettingsForm.init flags defaults
|
||||
in
|
||||
( { formModel = fm
|
||||
, settings = Nothing
|
||||
, message = Nothing
|
||||
}
|
||||
, Cmd.map UiSettingsFormMsg fc
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
134
modules/webapp/src/main/elm/Data/Color.elm
Normal file
134
modules/webapp/src/main/elm/Data/Color.elm
Normal file
@ -0,0 +1,134 @@
|
||||
module Data.Color exposing
|
||||
( Color
|
||||
, all
|
||||
, allString
|
||||
, fromString
|
||||
, toString
|
||||
)
|
||||
|
||||
|
||||
type Color
|
||||
= Red
|
||||
| Orange
|
||||
| Yellow
|
||||
| Olive
|
||||
| Green
|
||||
| Teal
|
||||
| Blue
|
||||
| Violet
|
||||
| Purple
|
||||
| Pink
|
||||
| Brown
|
||||
| Grey
|
||||
| Black
|
||||
|
||||
|
||||
all : List Color
|
||||
all =
|
||||
[ Red
|
||||
, Orange
|
||||
, Yellow
|
||||
, Olive
|
||||
, Green
|
||||
, Teal
|
||||
, Blue
|
||||
, Violet
|
||||
, Purple
|
||||
, Pink
|
||||
, Brown
|
||||
, Grey
|
||||
]
|
||||
|
||||
|
||||
allString : List String
|
||||
allString =
|
||||
List.map toString all
|
||||
|
||||
|
||||
fromString : String -> Maybe Color
|
||||
fromString str =
|
||||
case String.toLower str of
|
||||
"red" ->
|
||||
Just Red
|
||||
|
||||
"orange" ->
|
||||
Just Orange
|
||||
|
||||
"yellow" ->
|
||||
Just Yellow
|
||||
|
||||
"olive" ->
|
||||
Just Olive
|
||||
|
||||
"green" ->
|
||||
Just Green
|
||||
|
||||
"teal" ->
|
||||
Just Teal
|
||||
|
||||
"blue" ->
|
||||
Just Blue
|
||||
|
||||
"violet" ->
|
||||
Just Violet
|
||||
|
||||
"purple" ->
|
||||
Just Purple
|
||||
|
||||
"pink" ->
|
||||
Just Pink
|
||||
|
||||
"brown" ->
|
||||
Just Brown
|
||||
|
||||
"grey" ->
|
||||
Just Grey
|
||||
|
||||
"black" ->
|
||||
Just Black
|
||||
|
||||
_ ->
|
||||
Nothing
|
||||
|
||||
|
||||
toString : Color -> String
|
||||
toString color =
|
||||
case color of
|
||||
Red ->
|
||||
"red"
|
||||
|
||||
Orange ->
|
||||
"orange"
|
||||
|
||||
Yellow ->
|
||||
"yellow"
|
||||
|
||||
Olive ->
|
||||
"olive"
|
||||
|
||||
Green ->
|
||||
"green"
|
||||
|
||||
Teal ->
|
||||
"teal"
|
||||
|
||||
Blue ->
|
||||
"blue"
|
||||
|
||||
Violet ->
|
||||
"violet"
|
||||
|
||||
Purple ->
|
||||
"purple"
|
||||
|
||||
Pink ->
|
||||
"pink"
|
||||
|
||||
Brown ->
|
||||
"brown"
|
||||
|
||||
Grey ->
|
||||
"grey"
|
||||
|
||||
Black ->
|
||||
"black"
|
@ -38,7 +38,7 @@ main =
|
||||
init : Flags -> Url -> Key -> ( Model, Cmd Msg )
|
||||
init flags url key =
|
||||
let
|
||||
im =
|
||||
( im, ic ) =
|
||||
App.Data.init key url flags
|
||||
|
||||
page =
|
||||
@ -62,6 +62,7 @@ init flags url key =
|
||||
( m
|
||||
, Cmd.batch
|
||||
[ cmd
|
||||
, ic
|
||||
, Api.versionInfo flags VersionResp
|
||||
, sessionCheck
|
||||
, Ports.getUiSettings flags
|
||||
|
@ -26,16 +26,22 @@ type alias Model =
|
||||
}
|
||||
|
||||
|
||||
emptyModel : Flags -> Model
|
||||
emptyModel : Flags -> ( Model, Cmd Msg )
|
||||
emptyModel flags =
|
||||
{ currentTab = Nothing
|
||||
, changePassModel = Comp.ChangePasswordForm.emptyModel
|
||||
, emailSettingsModel = Comp.EmailSettingsManage.emptyModel
|
||||
, imapSettingsModel = Comp.ImapSettingsManage.emptyModel
|
||||
, notificationModel = Tuple.first (Comp.NotificationForm.init flags)
|
||||
, scanMailboxModel = Tuple.first (Comp.ScanMailboxManage.init flags)
|
||||
, uiSettingsModel = Comp.UiSettingsManage.init Data.UiSettings.defaults
|
||||
}
|
||||
let
|
||||
( um, uc ) =
|
||||
Comp.UiSettingsManage.init flags Data.UiSettings.defaults
|
||||
in
|
||||
( { currentTab = Nothing
|
||||
, changePassModel = Comp.ChangePasswordForm.emptyModel
|
||||
, emailSettingsModel = Comp.EmailSettingsManage.emptyModel
|
||||
, imapSettingsModel = Comp.ImapSettingsManage.emptyModel
|
||||
, notificationModel = Tuple.first (Comp.NotificationForm.init flags)
|
||||
, scanMailboxModel = Tuple.first (Comp.ScanMailboxManage.init flags)
|
||||
, uiSettingsModel = um
|
||||
}
|
||||
, Cmd.map UiSettingsMsg uc
|
||||
)
|
||||
|
||||
|
||||
type Tab
|
||||
|
@ -97,8 +97,12 @@ update flags msg model =
|
||||
)
|
||||
|
||||
GetUiSettings settings ->
|
||||
( { model | uiSettingsModel = Comp.UiSettingsManage.init settings }
|
||||
, Cmd.none
|
||||
let
|
||||
( um, uc ) =
|
||||
Comp.UiSettingsManage.init flags settings
|
||||
in
|
||||
( { model | uiSettingsModel = um }
|
||||
, Cmd.map UiSettingsMsg uc
|
||||
, Sub.none
|
||||
)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user