2021-06-06 13:59:50 +02:00

507 lines
14 KiB
Elm

module Comp.SourceForm exposing
( Model
, Msg(..)
, getSource
, init
, isValid
, update
, view2
)
import Api
import Api.Model.FolderItem exposing (FolderItem)
import Api.Model.FolderList exposing (FolderList)
import Api.Model.IdName exposing (IdName)
import Api.Model.SourceAndTags exposing (SourceAndTags)
import Api.Model.Tag exposing (Tag)
import Api.Model.TagList exposing (TagList)
import Comp.Basic as B
import Comp.Dropdown exposing (isDropdownChangeMsg)
import Comp.FixedDropdown
import Data.DropdownStyle as DS
import Data.Flags exposing (Flags)
import Data.Language exposing (Language)
import Data.Priority exposing (Priority)
import Data.UiSettings exposing (UiSettings)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onCheck, onInput)
import Http
import Markdown
import Messages.Comp.SourceForm exposing (Texts)
import Styles as S
import Util.Folder exposing (mkFolderOption)
import Util.Maybe
import Util.Tag
import Util.Update
type alias Model =
{ source : SourceAndTags
, abbrev : String
, description : Maybe String
, priorityModel : Comp.FixedDropdown.Model Priority
, priority : Priority
, enabled : Bool
, folderModel : Comp.Dropdown.Model IdName
, allFolders : List FolderItem
, folderId : Maybe String
, tagModel : Comp.Dropdown.Model Tag
, fileFilter : Maybe String
, languageModel : Comp.Dropdown.Model Language
, language : Maybe String
}
emptyModel : Model
emptyModel =
{ source = Api.Model.SourceAndTags.empty
, abbrev = ""
, description = Nothing
, priorityModel =
Comp.FixedDropdown.init Data.Priority.all
, priority = Data.Priority.Low
, enabled = False
, folderModel = Comp.Dropdown.makeSingle
, allFolders = []
, folderId = Nothing
, tagModel = Util.Tag.makeDropdownModel
, fileFilter = Nothing
, languageModel =
Comp.Dropdown.makeSingleList
{ options = Data.Language.all
, selected = Nothing
}
, language = Nothing
}
init : Flags -> ( Model, Cmd Msg )
init flags =
( emptyModel
, Cmd.batch
[ Api.getFolders flags "" False GetFolderResp
, Api.getTags flags "" GetTagResp
]
)
isValid : Model -> Bool
isValid model =
model.abbrev /= ""
getSource : Model -> SourceAndTags
getSource model =
let
st =
model.source
s =
st.source
tags =
Comp.Dropdown.getSelected model.tagModel
n =
{ s
| abbrev = model.abbrev
, description = model.description
, enabled = model.enabled
, priority = Data.Priority.toName model.priority
, folder = model.folderId
, fileFilter = model.fileFilter
, language = model.language
}
in
{ st | source = n, tags = TagList (List.length tags) tags }
type Msg
= SetAbbrev String
| SetSource SourceAndTags
| SetDescr String
| ToggleEnabled
| PrioDropdownMsg (Comp.FixedDropdown.Msg Priority)
| GetFolderResp (Result Http.Error FolderList)
| FolderDropdownMsg (Comp.Dropdown.Msg IdName)
| GetTagResp (Result Http.Error TagList)
| TagDropdownMsg (Comp.Dropdown.Msg Tag)
| SetFileFilter String
| LanguageMsg (Comp.Dropdown.Msg Language)
--- Update
update : Flags -> Msg -> Model -> ( Model, Cmd Msg )
update flags msg model =
case msg of
SetSource t ->
let
stpost =
model.source
post =
stpost.source
np =
{ post
| id = t.source.id
, abbrev = t.source.abbrev
, description = t.source.description
, priority = t.source.priority
, enabled = t.source.enabled
, folder = t.source.folder
, fileFilter = t.source.fileFilter
}
newModel =
{ model
| source = { stpost | source = np }
, abbrev = t.source.abbrev
, description = t.source.description
, priority =
Data.Priority.fromString t.source.priority
|> Maybe.withDefault Data.Priority.Low
, enabled = t.source.enabled
, folderId = t.source.folder
, fileFilter = t.source.fileFilter
}
mkIdName id =
List.filterMap
(\f ->
if f.id == id then
Just (IdName id f.name)
else
Nothing
)
model.allFolders
sel =
case Maybe.map mkIdName t.source.folder of
Just idref ->
idref
Nothing ->
[]
tags =
Comp.Dropdown.SetSelection t.tags.items
in
Util.Update.andThen1
[ update flags (FolderDropdownMsg (Comp.Dropdown.SetSelection sel))
, update flags (TagDropdownMsg tags)
]
newModel
ToggleEnabled ->
( { model | enabled = not model.enabled }, Cmd.none )
SetAbbrev n ->
( { model | abbrev = n }, Cmd.none )
SetDescr d ->
( { model | description = Util.Maybe.fromString d }
, Cmd.none
)
PrioDropdownMsg m ->
let
( m2, p2 ) =
Comp.FixedDropdown.update m model.priorityModel
in
( { model
| priorityModel = m2
, priority = Maybe.withDefault model.priority p2
}
, Cmd.none
)
GetFolderResp (Ok fs) ->
let
model_ =
{ model | allFolders = fs.items }
mkIdName fitem =
IdName fitem.id fitem.name
opts =
fs.items
|> List.map mkIdName
|> Comp.Dropdown.SetOptions
in
update flags (FolderDropdownMsg opts) model_
GetFolderResp (Err _) ->
( model, Cmd.none )
FolderDropdownMsg m ->
let
( m2, c2 ) =
Comp.Dropdown.update m model.folderModel
newModel =
{ model | folderModel = m2 }
idref =
Comp.Dropdown.getSelected m2 |> List.head
model_ =
if isDropdownChangeMsg m then
{ newModel | folderId = Maybe.map .id idref }
else
newModel
in
( model_, Cmd.map FolderDropdownMsg c2 )
GetTagResp (Ok list) ->
let
opts =
Comp.Dropdown.SetOptions list.items
in
update flags (TagDropdownMsg opts) model
GetTagResp (Err _) ->
( model, Cmd.none )
TagDropdownMsg lm ->
let
( m2, c2 ) =
Comp.Dropdown.update lm model.tagModel
newModel =
{ model | tagModel = m2 }
in
( newModel, Cmd.map TagDropdownMsg c2 )
SetFileFilter d ->
( { model | fileFilter = Util.Maybe.fromString d }
, Cmd.none
)
LanguageMsg lm ->
let
( dm, dc ) =
Comp.Dropdown.update lm model.languageModel
newModel =
{ model | languageModel = dm }
lang =
Comp.Dropdown.getSelected dm |> List.head
model_ =
if isDropdownChangeMsg lm then
{ newModel | language = Maybe.map Data.Language.toIso3 lang }
else
newModel
in
( model_
, Cmd.map LanguageMsg dc
)
--- View2
view2 : Flags -> Texts -> UiSettings -> Model -> Html Msg
view2 flags texts settings model =
let
folderCfg =
{ makeOption = mkFolderOption flags model.allFolders
, placeholder = texts.basics.selectPlaceholder
, labelColor = \_ -> \_ -> ""
, style = DS.mainStyle
}
tagCfg =
Util.Tag.tagSettings texts.basics.chooseTag DS.mainStyle
languageCfg =
{ makeOption =
\a ->
{ text = texts.languageLabel a
, additional = ""
}
, placeholder = texts.basics.selectPlaceholder
, labelColor = \_ -> \_ -> ""
, style = DS.mainStyle
}
priorityCfg =
{ display = Data.Priority.toName
, icon = \_ -> Nothing
, style = DS.mainStyle
, selectPlaceholder = texts.basics.selectPlaceholder
}
in
div [ class "flex flex-col" ]
[ div [ class "mb-4" ]
[ label
[ for "source-abbrev"
, class S.inputLabel
]
[ text texts.basics.name
, B.inputRequired
]
, input
[ type_ "text"
, id "source-abbrev"
, onInput SetAbbrev
, placeholder texts.basics.name
, value model.abbrev
, class S.textInput
, classList [ ( S.inputErrorBorder, not (isValid model) ) ]
]
[]
]
, div [ class "mb-4" ]
[ label
[ for "source-descr"
, class S.inputLabel
]
[ text texts.description
]
, textarea
[ onInput SetDescr
, model.description |> Maybe.withDefault "" |> value
, rows 3
, class S.textAreaInput
, id "source-descr"
]
[]
]
, div [ class "mb-4" ]
[ label
[ class "inline-flex items-center"
, for "source-enabled"
]
[ input
[ type_ "checkbox"
, onCheck (\_ -> ToggleEnabled)
, checked model.enabled
, class S.checkboxInput
, id "source-enabled"
]
[]
, span [ class "ml-2" ]
[ text texts.enabled
]
]
]
, div [ class "mb-4" ]
[ label [ class S.inputLabel ]
[ text texts.priority
]
, Html.map PrioDropdownMsg
(Comp.FixedDropdown.viewStyled2
priorityCfg
False
(Just model.priority)
model.priorityModel
)
, div [ class "opacity-50 text-sm" ]
[ text texts.priorityInfo
]
]
, div
[ class S.header2
, class "mt-6"
]
[ text texts.metadata
]
, div
[ class S.message
, class "mb-4"
]
[ text texts.metadataInfoText
]
, div [ class "mb-4" ]
[ label [ class S.inputLabel ]
[ text texts.basics.folder
]
, Html.map FolderDropdownMsg
(Comp.Dropdown.view2
folderCfg
settings
model.folderModel
)
, div [ class "opacity-50 text-sm" ]
[ text texts.folderInfo
]
, div
[ classList
[ ( "hidden", isFolderMember2 model )
]
, class S.message
]
[ Markdown.toHtml [] texts.basics.folderNotOwnerWarning
]
]
, div [ class "mb-4" ]
[ label [ class S.inputLabel ]
[ text texts.basics.tags
]
, Html.map TagDropdownMsg
(Comp.Dropdown.view2
tagCfg
settings
model.tagModel
)
, div [ class "opacity-50 text-sm" ]
[ text texts.tagsInfo
]
]
, div
[ class "mb-4"
]
[ label [ class S.inputLabel ]
[ text texts.fileFilter ]
, input
[ type_ "text"
, onInput SetFileFilter
, placeholder texts.fileFilter
, model.fileFilter
|> Maybe.withDefault ""
|> value
, class S.textInput
]
[]
, div [ class "opacity-50 text-sm" ]
[ Markdown.toHtml [] texts.fileFilterInfo
]
]
, div [ class "mb-4" ]
[ label [ class S.inputLabel ]
[ text (texts.language ++ ":")
]
, Html.map LanguageMsg
(Comp.Dropdown.view2
languageCfg
settings
model.languageModel
)
, div [ class "opacity-50 text-sm" ]
[ text texts.languageInfo
]
]
]
isFolderMember2 : Model -> Bool
isFolderMember2 model =
let
selected =
Comp.Dropdown.getSelected model.folderModel
|> List.head
|> Maybe.map .id
in
Util.Folder.isFolderMember model.allFolders selected