Allow to choose from existing tag categories

Also fixes a ui problem with a too long dropdown menu in the small
modal popup when adding tags or custom fields in item detail view.

Issue: #331
This commit is contained in:
Eike Kettner 2020-11-26 22:48:10 +01:00
parent 5a7d39add6
commit c87163052b
7 changed files with 103 additions and 24 deletions

View File

@ -165,11 +165,11 @@ initTag itemId tm =
init itemId (TM tm) init itemId (TM tm)
initTagByName : String -> String -> Model initTagByName : String -> String -> List String -> Model
initTagByName itemId name = initTagByName itemId name categories =
let let
tm = tm =
Comp.TagForm.emptyModel Comp.TagForm.emptyModel categories
tm_ = tm_ =
{ tm | name = name } { tm | name = name }

View File

@ -13,6 +13,7 @@ module Comp.Dropdown exposing
, setMkOption , setMkOption
, update , update
, view , view
, viewSingle
) )
{-| This needs to be rewritten from scratch! {-| This needs to be rewritten from scratch!
@ -252,7 +253,15 @@ filterOptions str list =
applyFilter : String -> Model a -> Model a applyFilter : String -> Model a -> Model a
applyFilter str model = applyFilter str model =
{ model | filterString = str, available = filterOptions str model.available } let
selected =
if str /= "" && not model.multiple then
[]
else
model.selected
in
{ model | filterString = str, available = filterOptions str model.available, selected = selected }
makeNextActive : (Int -> Int) -> Model a -> Model a makeNextActive : (Int -> Int) -> Model a -> Model a

View File

@ -98,6 +98,7 @@ type alias Model =
, customFieldsModel : Comp.CustomFieldMultiInput.Model , customFieldsModel : Comp.CustomFieldMultiInput.Model
, customFieldSavingIcon : Dict String String , customFieldSavingIcon : Dict String String
, customFieldThrottle : Throttle Msg , customFieldThrottle : Throttle Msg
, allTags : List Tag
} }
@ -202,6 +203,7 @@ emptyModel =
, customFieldsModel = Comp.CustomFieldMultiInput.initWith [] , customFieldsModel = Comp.CustomFieldMultiInput.initWith []
, customFieldSavingIcon = Dict.empty , customFieldSavingIcon = Dict.empty
, customFieldThrottle = Throttle.create 1 , customFieldThrottle = Throttle.create 1
, allTags = []
} }

View File

@ -65,6 +65,7 @@ import Util.Http
import Util.List import Util.List
import Util.Maybe import Util.Maybe
import Util.String import Util.String
import Util.Tag
update : Nav.Key -> Flags -> ItemNav -> UiSettings -> Msg -> Model -> UpdateResult update : Nav.Key -> Flags -> ItemNav -> UiSettings -> Msg -> Model -> UpdateResult
@ -588,7 +589,7 @@ update key flags inav settings msg model =
tagList = tagList =
Comp.Dropdown.SetOptions tags.items Comp.Dropdown.SetOptions tags.items
in in
update key flags inav settings (TagDropdownMsg tagList) model update key flags inav settings (TagDropdownMsg tagList) { model | allTags = tags.items }
GetTagsResp (Err _) -> GetTagsResp (Err _) ->
resultModel model resultModel model
@ -1039,9 +1040,13 @@ update key flags inav settings msg model =
resultModel model resultModel model
StartTagModal -> StartTagModal ->
let
cats =
Util.Tag.getCategories model.allTags
in
resultModel resultModel
{ model { model
| modalEdit = Just (Comp.DetailEdit.initTagByName model.item.id "") | modalEdit = Just (Comp.DetailEdit.initTagByName model.item.id "" cats)
} }
StartCorrOrgModal -> StartCorrOrgModal ->

View File

@ -9,24 +9,38 @@ module Comp.TagForm exposing
) )
import Api.Model.Tag exposing (Tag) import Api.Model.Tag exposing (Tag)
import Comp.Dropdown
import Data.Flags exposing (Flags) import Data.Flags exposing (Flags)
import Html exposing (..) import Html exposing (..)
import Html.Attributes exposing (..) import Html.Attributes exposing (..)
import Html.Events exposing (onInput) import Html.Events exposing (onInput)
import Util.Maybe
type alias Model = type alias Model =
{ tag : Tag { tag : Tag
, name : String , name : String
, category : Maybe String , allCategories : List String
, catDropdown : Comp.Dropdown.Model String
} }
emptyModel : Model emptyModel : List String -> Model
emptyModel = emptyModel categories =
{ tag = Api.Model.Tag.empty { tag = Api.Model.Tag.empty
, name = "" , name = ""
, category = Nothing , allCategories = categories
, catDropdown =
let
cm =
Comp.Dropdown.makeSingleList
{ makeOption = \s -> Comp.Dropdown.mkOption s s
, placeholder = "Select or define category..."
, options = categories
, selected = Nothing
}
in
{ cm | searchable = \_ -> True }
} }
@ -37,26 +51,66 @@ isValid model =
getTag : Model -> Tag getTag : Model -> Tag
getTag model = getTag model =
Tag model.tag.id model.name model.category 0 let
cat =
Comp.Dropdown.getSelected model.catDropdown
|> List.head
|> Maybe.withDefault model.catDropdown.filterString
in
Tag model.tag.id model.name (Util.Maybe.fromString cat) 0
type Msg type Msg
= SetName String = SetName String
| SetCategory String | SetCategory String
| SetCategoryOptions (List String)
| SetTag Tag | SetTag Tag
| CatMsg (Comp.Dropdown.Msg String)
update : Flags -> Msg -> Model -> ( Model, Cmd Msg ) update : Flags -> Msg -> Model -> ( Model, Cmd Msg )
update _ msg model = update _ msg model =
case msg of case msg of
SetTag t -> SetTag t ->
( { model | tag = t, name = t.name, category = t.category }, Cmd.none ) let
( dm_, cmd_ ) =
Comp.Dropdown.update
(Comp.Dropdown.SetSelection
(List.filterMap identity [ t.category ])
)
model.catDropdown
in
( { model | tag = t, name = t.name, catDropdown = dm_ }
, Cmd.map CatMsg cmd_
)
SetName n -> SetName n ->
( { model | name = n }, Cmd.none ) ( { model | name = n }, Cmd.none )
SetCategory n -> SetCategory n ->
( { model | category = Just n }, Cmd.none ) let
( dm_, cmd_ ) =
Comp.Dropdown.update (Comp.Dropdown.SetSelection [ n ]) model.catDropdown
in
( { model | catDropdown = dm_ }, Cmd.map CatMsg cmd_ )
SetCategoryOptions list ->
let
( dm_, cmd_ ) =
Comp.Dropdown.update
(Comp.Dropdown.SetOptions list)
model.catDropdown
in
( { model | catDropdown = dm_ }
, Cmd.map CatMsg cmd_
)
CatMsg lm ->
let
( dm_, cmd_ ) =
Comp.Dropdown.update lm model.catDropdown
in
( { model | catDropdown = dm_ }, Cmd.map CatMsg cmd_ )
view : Model -> Html Msg view : Model -> Html Msg
@ -78,13 +132,8 @@ view model =
[] []
] ]
, div [ class "field" ] , div [ class "field" ]
[ label [] [ text "Category" ] [ label []
, input [ text "Category" ]
[ type_ "text" , Html.map CatMsg (Comp.Dropdown.viewSingle model.catDropdown)
, onInput SetCategory
, placeholder "Category (optional)"
, value (Maybe.withDefault "" model.category)
]
[]
] ]
] ]

View File

@ -20,6 +20,8 @@ import Html.Events exposing (onClick, onInput, onSubmit)
import Http import Http
import Util.Http import Util.Http
import Util.Maybe import Util.Maybe
import Util.Tag
import Util.Update
type alias Model = type alias Model =
@ -41,7 +43,7 @@ type ViewMode
emptyModel : Model emptyModel : Model
emptyModel = emptyModel =
{ tagTableModel = Comp.TagTable.emptyModel { tagTableModel = Comp.TagTable.emptyModel
, tagFormModel = Comp.TagForm.emptyModel , tagFormModel = Comp.TagForm.emptyModel []
, viewMode = Table , viewMode = Table
, formError = Nothing , formError = Nothing
, loading = False , loading = False
@ -110,8 +112,15 @@ update flags msg model =
let let
m2 = m2 =
{ model | viewMode = Table, loading = False } { model | viewMode = Table, loading = False }
cats =
Util.Tag.getCategories tags.items
in in
update flags (TableMsg (Comp.TagTable.SetTags tags.items)) m2 Util.Update.andThen1
[ update flags (TableMsg (Comp.TagTable.SetTags tags.items))
, update flags (FormMsg (Comp.TagForm.SetCategoryOptions cats))
]
m2
TagResp (Err _) -> TagResp (Err _) ->
( { model | loading = False }, Cmd.none ) ( { model | loading = False }, Cmd.none )

View File

@ -252,7 +252,12 @@ textarea.markdown-editor {
.ui.modal.keep-small { .ui.modal.keep-small {
width: 95%; width: 95%;
} }
.ui.modal.keep-small .scrolling.content {
min-height: 23rem;
}
.ui.modal.keep-small .scrolling.content .menu.transition.visible {
max-height: 11rem;
}
label span.muted { label span.muted {
font-size: smaller; font-size: smaller;