Ui improvements

- don't show custom fields in edit menu if there are none. This
reduces load of ui elements. The first custom field must be created in
manage-data page.

- Add more validation to the money type
This commit is contained in:
Eike Kettner 2020-11-22 13:25:24 +01:00
parent ff30ed5558
commit bb19e02c66
4 changed files with 85 additions and 26 deletions

View File

@ -13,6 +13,7 @@ import Api.Model.CustomField exposing (CustomField)
import Api.Model.ItemFieldValue exposing (ItemFieldValue) import Api.Model.ItemFieldValue exposing (ItemFieldValue)
import Comp.DatePicker import Comp.DatePicker
import Data.CustomFieldType exposing (CustomFieldType) import Data.CustomFieldType exposing (CustomFieldType)
import Data.Money
import Date exposing (Date) import Date exposing (Date)
import DatePicker exposing (DatePicker) import DatePicker exposing (DatePicker)
import Html exposing (..) import Html exposing (..)
@ -130,14 +131,14 @@ initWith value =
Data.CustomFieldType.Numeric -> Data.CustomFieldType.Numeric ->
let let
( fm, _ ) = ( fm, _ ) =
updateFloatModel value.value identity updateFloatModel value.value string2Float
in in
NumberField fm NumberField fm
Data.CustomFieldType.Money -> Data.CustomFieldType.Money ->
let let
( fm, _ ) = ( fm, _ ) =
updateFloatModel value.value identity updateFloatModel value.value Data.Money.fromString
in in
MoneyField fm MoneyField fm
@ -174,35 +175,32 @@ type alias UpdateResult =
} }
updateFloatModel : String -> (Float -> Float) -> ( FloatModel, FieldResult ) updateFloatModel : String -> (String -> Result String Float) -> ( FloatModel, FieldResult )
updateFloatModel msg rounding = updateFloatModel msg parse =
case String.toFloat msg of case parse msg of
Just n -> Ok n ->
let ( { input = msg
fieldVal = , result = Ok n
if String.endsWith "." msg || String.endsWith ".0" msg then
msg
else
String.fromFloat (rounding n)
in
( { input = fieldVal
, result = Ok (rounding n)
} }
, Value (String.fromFloat (rounding n)) , Value msg
) )
Nothing -> Err err ->
( { input = msg ( { input = msg
, result = Err ("Not a number: " ++ msg) , result = Err err
} }
, NoResult , NoResult
) )
roundScale2 : Float -> Float string2Float : String -> Result String Float
roundScale2 input = string2Float str =
(round (input * 100) |> toFloat) / 100 case String.toFloat str of
Just n ->
Ok n
Nothing ->
Err ("Not a number: " ++ str)
update : Msg -> Model -> UpdateResult update : Msg -> Model -> UpdateResult
@ -218,7 +216,7 @@ update msg model =
( NumberMsg str, NumberField _ ) -> ( NumberMsg str, NumberField _ ) ->
let let
( fm, res ) = ( fm, res ) =
updateFloatModel str identity updateFloatModel str string2Float
model_ = model_ =
{ model | fieldModel = NumberField fm } { model | fieldModel = NumberField fm }
@ -228,7 +226,9 @@ update msg model =
( MoneyMsg str, MoneyField _ ) -> ( MoneyMsg str, MoneyField _ ) ->
let let
( fm, res ) = ( fm, res ) =
updateFloatModel str roundScale2 updateFloatModel
str
Data.Money.fromString
model_ = model_ =
{ model | fieldModel = MoneyField fm } { model | fieldModel = MoneyField fm }

View File

@ -7,6 +7,7 @@ module Comp.CustomFieldMultiInput exposing
, init , init
, initCmd , initCmd
, initWith , initWith
, nonEmpty
, setValues , setValues
, update , update
, view , view
@ -59,6 +60,11 @@ type alias FieldSelect =
} }
nonEmpty : Model -> Bool
nonEmpty model =
not (List.isEmpty model.availableFields && List.isEmpty model.visibleFields)
initWith : List CustomField -> Model initWith : List CustomField -> Model
initWith fields = initWith fields =
{ fieldModels = Dict.empty { fieldModels = Dict.empty

View File

@ -729,6 +729,10 @@ renderEditForm settings model =
else else
span [ class "invisible hidden" ] [] span [ class "invisible hidden" ] []
showCustomFields =
fieldVisible Data.Fields.CustomFields
&& Comp.CustomFieldMultiInput.nonEmpty model.customFieldsModel
customFieldSettings = customFieldSettings =
Comp.CustomFieldMultiInput.ViewSettings True "field" Comp.CustomFieldMultiInput.ViewSettings True "field"
in in
@ -777,14 +781,20 @@ item visible. This message will disappear then.
""" """
] ]
] ]
, optional [ Data.Fields.CustomFields ] <| , if showCustomFields then
h4 [ class "ui dividing header" ] h4 [ class "ui dividing header" ]
[ Icons.customFieldIcon "" [ Icons.customFieldIcon ""
, text "Custom Fields" , text "Custom Fields"
] ]
, optional [ Data.Fields.CustomFields ] <|
else
span [ class "hidden invisible" ] []
, if showCustomFields then
Html.map CustomFieldMsg Html.map CustomFieldMsg
(Comp.CustomFieldMultiInput.view customFieldSettings model.customFieldsModel) (Comp.CustomFieldMultiInput.view customFieldSettings model.customFieldsModel)
else
span [ class "hidden invisible" ] []
, optional [ Data.Fields.DueDate, Data.Fields.Date ] <| , optional [ Data.Fields.DueDate, Data.Fields.Date ] <|
h4 [ class "ui dividing header" ] h4 [ class "ui dividing header" ]
[ Icons.itemDatesIcon "" [ Icons.itemDatesIcon ""

View File

@ -0,0 +1,43 @@
module Data.Money exposing
( Money
, format
, fromString
, roundMoney
)
type alias Money =
Float
fromString : String -> Result String Money
fromString str =
let
points =
String.indexes "." str
len =
String.length str
in
case points of
index :: [] ->
if index == (len - 3) then
String.toFloat str
|> Maybe.map Ok
|> Maybe.withDefault (Err "Two digits required after the dot.")
else
Err ("Two digits required after the dot: " ++ str)
_ ->
Err "One single dot + digits required for money."
format : Float -> String
format money =
String.fromFloat (roundMoney money)
roundMoney : Float -> Float
roundMoney input =
(round (input * 100) |> toFloat) / 100