Using elm-format for all files

This commit is contained in:
Eike Kettner
2019-12-29 21:55:12 +01:00
parent 546f1a6ee3
commit 2001cca88b
84 changed files with 7668 additions and 5079 deletions

View File

@ -1,39 +1,41 @@
module Comp.Dropdown exposing ( Model
, Option
, makeModel
, makeSingle
, makeSingleList
, makeMultiple
, update
, isDropdownChangeMsg
, view
, getSelected
, Msg(..))
module Comp.Dropdown exposing
( Model
, Msg(..)
, Option
, getSelected
, isDropdownChangeMsg
, makeModel
, makeMultiple
, makeSingle
, makeSingleList
, update
, view
)
import Http
import Task
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onInput, onClick, onFocus, onBlur)
import Json.Decode as Decode
import Html.Events exposing (onClick, onInput)
import Simple.Fuzzy
import Util.Html exposing (onKeyUp)
import Util.List
type alias Option =
{ value: String
, text: String
{ value : String
, text : String
}
type alias Item a =
{ value: a
, option: Option
, visible: Bool
, selected: Bool
, active: Bool
{ value : a
, option : Option
, visible : Bool
, selected : Bool
, active : Bool
}
makeItem: Model a -> a -> Item a
makeItem : Model a -> a -> Item a
makeItem model val =
{ value = val
, option = model.makeOption val
@ -42,25 +44,28 @@ makeItem model val =
, active = False
}
type alias Model a =
{ multiple: Bool
, selected: List (Item a)
, available: List (Item a)
, makeOption: a -> Option
, menuOpen: Bool
, filterString: String
, labelColor: a -> String
, searchable: Int -> Bool
, placeholder: String
{ multiple : Bool
, selected : List (Item a)
, available : List (Item a)
, makeOption : a -> Option
, menuOpen : Bool
, filterString : String
, labelColor : a -> String
, searchable : Int -> Bool
, placeholder : String
}
makeModel:
{ multiple: Bool
, searchable: Int -> Bool
, makeOption: a -> Option
, labelColor: a -> String
, placeholder: String
} -> Model a
makeModel :
{ multiple : Bool
, searchable : Int -> Bool
, makeOption : a -> Option
, labelColor : a -> String
, placeholder : String
}
-> Model a
makeModel input =
{ multiple = input.multiple
, searchable = input.searchable
@ -73,10 +78,12 @@ makeModel input =
, placeholder = input.placeholder
}
makeSingle:
{ makeOption: a -> Option
, placeholder: String
} -> Model a
makeSingle :
{ makeOption : a -> Option
, placeholder : String
}
-> Model a
makeSingle opts =
makeModel
{ multiple = False
@ -86,26 +93,35 @@ makeSingle opts =
, placeholder = opts.placeholder
}
makeSingleList:
{ makeOption: a -> Option
, placeholder: String
, options: List a
, selected: Maybe a
} -> Model a
makeSingleList :
{ makeOption : a -> Option
, placeholder : String
, options : List a
, selected : Maybe a
}
-> Model a
makeSingleList opts =
let
m = makeSingle {makeOption = opts.makeOption, placeholder = opts.placeholder}
m2 = {m | available = List.map (makeItem m) opts.options}
m3 = Maybe.map (makeItem m2) opts.selected
|> Maybe.map (selectItem m2)
|> Maybe.withDefault m2
in
m3
m =
makeSingle { makeOption = opts.makeOption, placeholder = opts.placeholder }
makeMultiple:
{ makeOption: a -> Option
, labelColor: a -> String
} -> Model a
m2 =
{ m | available = List.map (makeItem m) opts.options }
m3 =
Maybe.map (makeItem m2) opts.selected
|> Maybe.map (selectItem m2)
|> Maybe.withDefault m2
in
m3
makeMultiple :
{ makeOption : a -> Option
, labelColor : a -> String
}
-> Model a
makeMultiple opts =
makeModel
{ multiple = True
@ -115,10 +131,12 @@ makeMultiple opts =
, placeholder = ""
}
getSelected: Model a -> List a
getSelected : Model a -> List a
getSelected model =
List.map .value model.selected
type Msg a
= SetOptions (List a)
| SetSelection (List a)
@ -129,265 +147,367 @@ type Msg a
| ShowMenu Bool
| KeyPress Int
getOptions: Model a -> List (Item a)
getOptions model =
if not model.multiple && isSearchable model && model.menuOpen
then List.filter .visible model.available
else List.filter (\e -> e.visible && (not e.selected)) model.available
isSearchable: Model a -> Bool
getOptions : Model a -> List (Item a)
getOptions model =
if not model.multiple && isSearchable model && model.menuOpen then
List.filter .visible model.available
else
List.filter (\e -> e.visible && not e.selected) model.available
isSearchable : Model a -> Bool
isSearchable model =
List.length model.available |> model.searchable
-- Update
deselectItem: Model a -> Item a -> Model a
deselectItem : Model a -> Item a -> Model a
deselectItem model item =
let
value = item.option.value
sel = if model.multiple then List.filter (\e -> e.option.value /= value) model.selected
else []
value =
item.option.value
show e = if e.option.value == value then {e | selected = False } else e
avail = List.map show model.available
sel =
if model.multiple then
List.filter (\e -> e.option.value /= value) model.selected
else
[]
show e =
if e.option.value == value then
{ e | selected = False }
else
e
avail =
List.map show model.available
in
{ model | selected = sel, available = avail }
{ model | selected = sel, available = avail }
selectItem: Model a -> Item a -> Model a
selectItem : Model a -> Item a -> Model a
selectItem model item =
let
value = item.option.value
sel = if model.multiple
then List.concat [ model.selected, [ item ] ]
else [ item ]
value =
item.option.value
hide e = if e.option.value == value
then {e | selected = True }
else if model.multiple then e else {e | selected = False}
avail = List.map hide model.available
sel =
if model.multiple then
List.concat [ model.selected, [ item ] ]
else
[ item ]
hide e =
if e.option.value == value then
{ e | selected = True }
else if model.multiple then
e
else
{ e | selected = False }
avail =
List.map hide model.available
in
{ model | selected = sel, available = avail }
{ model | selected = sel, available = avail }
filterOptions: String -> List (Item a) -> List (Item a)
filterOptions : String -> List (Item a) -> List (Item a)
filterOptions str list =
List.map (\e -> {e | visible = Simple.Fuzzy.match str e.option.text, active = False}) list
List.map (\e -> { e | visible = Simple.Fuzzy.match str e.option.text, active = False }) list
applyFilter: String -> Model a -> Model a
applyFilter : String -> Model a -> Model a
applyFilter str model =
{ model | filterString = str, available = filterOptions str model.available }
makeNextActive: (Int -> Int) -> Model a -> Model a
makeNextActive : (Int -> Int) -> Model a -> Model a
makeNextActive nextEl model =
let
opts = getOptions model
current = Util.List.findIndexed .active opts
next = Maybe.map Tuple.second current
|> Maybe.map nextEl
|> Maybe.andThen (Util.List.get opts)
merge item1 item2 = { item2 | active = item1.option.value == item2.option.value }
updateModel item = { model | available = List.map (merge item) model.available, menuOpen = True }
in
case next of
Just item -> updateModel item
Nothing ->
case List.head opts of
Just item -> updateModel item
Nothing -> model
opts =
getOptions model
selectActive: Model a -> Model a
current =
Util.List.findIndexed .active opts
next =
Maybe.map Tuple.second current
|> Maybe.map nextEl
|> Maybe.andThen (Util.List.get opts)
merge item1 item2 =
{ item2 | active = item1.option.value == item2.option.value }
updateModel item =
{ model | available = List.map (merge item) model.available, menuOpen = True }
in
case next of
Just item ->
updateModel item
Nothing ->
case List.head opts of
Just item ->
updateModel item
Nothing ->
model
selectActive : Model a -> Model a
selectActive model =
let
current = getOptions model |> Util.List.find .active
current =
getOptions model |> Util.List.find .active
in
case current of
Just item ->
selectItem model item |> applyFilter ""
Nothing ->
model
case current of
Just item ->
selectItem model item |> applyFilter ""
clearActive: Model a -> Model a
Nothing ->
model
clearActive : Model a -> Model a
clearActive model =
{ model | available = List.map (\e -> {e | active = False}) model.available }
{ model | available = List.map (\e -> { e | active = False }) model.available }
-- TODO enhance update function to return this info
isDropdownChangeMsg: Msg a -> Bool
isDropdownChangeMsg : Msg a -> Bool
isDropdownChangeMsg cm =
case cm of
AddItem _ -> True
RemoveItem _ -> True
AddItem _ ->
True
RemoveItem _ ->
True
KeyPress code ->
Util.Html.intToKeyCode code
|> Maybe.map (\c -> c == Util.Html.Enter)
|> Maybe.withDefault False
_ -> False
Util.Html.intToKeyCode code
|> Maybe.map (\c -> c == Util.Html.Enter)
|> Maybe.withDefault False
_ ->
False
update: Msg a -> Model a -> (Model a, Cmd (Msg a))
update : Msg a -> Model a -> ( Model a, Cmd (Msg a) )
update msg model =
case msg of
SetOptions list ->
({model | available = List.map (makeItem model) list}, Cmd.none)
( { model | available = List.map (makeItem model) list }, Cmd.none )
SetSelection list ->
let
m0 = List.foldl (\item -> \m -> deselectItem m item) model model.selected
m1 = List.map (makeItem model) list
|> List.foldl (\item -> \m -> selectItem m item) m0
m0 =
List.foldl (\item -> \m -> deselectItem m item) model model.selected
m1 =
List.map (makeItem model) list
|> List.foldl (\item -> \m -> selectItem m item) m0
in
(m1, Cmd.none)
( m1, Cmd.none )
ToggleMenu ->
({model | menuOpen = not model.menuOpen}, Cmd.none)
( { model | menuOpen = not model.menuOpen }, Cmd.none )
AddItem e ->
let
m = selectItem model e |> applyFilter ""
m =
selectItem model e |> applyFilter ""
in
({ m | menuOpen = False }, Cmd.none)
( { m | menuOpen = False }, Cmd.none )
RemoveItem e ->
let
m = deselectItem model e |> applyFilter ""
m =
deselectItem model e |> applyFilter ""
in
({ m | menuOpen = False }, Cmd.none)
( { m | menuOpen = False }, Cmd.none )
Filter str ->
let
m = applyFilter str model
m =
applyFilter str model
in
({ m | menuOpen = True}, Cmd.none)
( { m | menuOpen = True }, Cmd.none )
ShowMenu flag ->
({ model | menuOpen = flag }, Cmd.none)
( { model | menuOpen = flag }, Cmd.none )
KeyPress code ->
case Util.Html.intToKeyCode code of
Just Util.Html.Up ->
(makeNextActive (\n -> n - 1) model, Cmd.none)
( makeNextActive (\n -> n - 1) model, Cmd.none )
Just Util.Html.Down ->
(makeNextActive ((+) 1) model, Cmd.none)
( makeNextActive ((+) 1) model, Cmd.none )
Just Util.Html.Enter ->
let
m = selectActive model
m =
selectActive model
in
({m | menuOpen = False }, Cmd.none)
( { m | menuOpen = False }, Cmd.none )
_ ->
(model, Cmd.none)
( model, Cmd.none )
-- View
view: Model a -> Html (Msg a)
view : Model a -> Html (Msg a)
view model =
if model.multiple then viewMultiple model else viewSingle model
if model.multiple then
viewMultiple model
else
viewSingle model
viewSingle: Model a -> Html (Msg a)
viewSingle : Model a -> Html (Msg a)
viewSingle model =
let
renderClosed item =
div [class "message"
,style "display" "inline-block !important"
,onClick ToggleMenu
div
[ class "message"
, style "display" "inline-block !important"
, onClick ToggleMenu
]
[i [class "delete icon", onClick (RemoveItem item)][]
,text item.option.text
[ i [ class "delete icon", onClick (RemoveItem item) ] []
, text item.option.text
]
renderDefault =
[ List.head model.selected |> Maybe.map renderClosed |> Maybe.withDefault (renderPlaceholder model)
, renderMenu model
]
openSearch =
[ input [ class "search"
[ input
[ class "search"
, placeholder "Search"
, onInput Filter
, onKeyUp KeyPress
, value model.filterString
]
[]
, renderMenu model
]
in
div
[ classList
[ ( "ui search dropdown selection", True )
, ( "open", model.menuOpen )
]
]
(List.append
[ i [ class "dropdown icon", onClick ToggleMenu ] []
]
<|
if model.menuOpen && isSearchable model then
openSearch
else
renderDefault
)
viewMultiple : Model a -> Html (Msg a)
viewMultiple model =
let
renderSelectMultiple : Item a -> Html (Msg a)
renderSelectMultiple item =
div
[ classList
[ ( "ui label", True )
, ( model.labelColor item.value, True )
]
, style "display" "inline-block !important"
, onClick (RemoveItem item)
]
[ text item.option.text
, i [ class "delete icon" ] []
]
in
div
[ classList
[ ( "ui search dropdown multiple selection", True )
, ( "open", model.menuOpen )
]
]
(List.concat
[ [ i [ class "dropdown icon", onClick ToggleMenu ] []
]
, List.map renderSelectMultiple model.selected
, if isSearchable model then
[ input
[ class "search"
, placeholder "Search"
, onInput Filter
, onKeyUp KeyPress
, value model.filterString
][]
, renderMenu model
]
in
div [classList [ ("ui search dropdown selection", True)
, ("open", model.menuOpen)
]
]
(List.append [ i [class "dropdown icon", onClick ToggleMenu][]
] <|
if model.menuOpen && isSearchable model
then openSearch
else renderDefault
)
viewMultiple: Model a -> Html (Msg a)
viewMultiple model =
let
renderSelectMultiple: Item a -> Html (Msg a)
renderSelectMultiple item =
div [classList [ ("ui label", True)
, (model.labelColor item.value, True)
]
,style "display" "inline-block !important"
,onClick (RemoveItem item)
]
[]
]
[text item.option.text
,i [class "delete icon"][]
]
in
div [classList [ ("ui search dropdown multiple selection", True)
, ("open", model.menuOpen)
]
]
(List.concat
[ [i [class "dropdown icon", onClick ToggleMenu][]
]
, List.map renderSelectMultiple model.selected
, if isSearchable model then
[ input [ class "search"
, placeholder "Search"
, onInput Filter
, onKeyUp KeyPress
, value model.filterString
][]
]
else []
, [ renderMenu model
]
])
renderMenu: Model a -> Html (Msg a)
else
[]
, [ renderMenu model
]
]
)
renderMenu : Model a -> Html (Msg a)
renderMenu model =
div [classList [( "menu", True )
,( "transition visible", model.menuOpen )
]
] (getOptions model |> List.map renderOption)
div
[ classList
[ ( "menu", True )
, ( "transition visible", model.menuOpen )
]
]
(getOptions model |> List.map renderOption)
renderPlaceholder: Model a -> Html (Msg a)
renderPlaceholder : Model a -> Html (Msg a)
renderPlaceholder model =
div [classList [ ("placeholder-message", True)
, ("text", model.multiple)
]
,style "display" "inline-block !important"
,onClick ToggleMenu
div
[ classList
[ ( "placeholder-message", True )
, ( "text", model.multiple )
]
, style "display" "inline-block !important"
, onClick ToggleMenu
]
[ text model.placeholder
]
[text model.placeholder
]
renderOption: Item a -> Html (Msg a)
renderOption : Item a -> Html (Msg a)
renderOption item =
div [classList [ ("item", True)
, ("active", item.active || item.selected)
]
,onClick (AddItem item)
div
[ classList
[ ( "item", True )
, ( "active", item.active || item.selected )
]
, onClick (AddItem item)
]
[text item.option.text
[ text item.option.text
]