mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-04-05 19:09:32 +00:00
The problem was that the field executes a request to validate its state. This was initiated at the same time for two values. Then it was undetermined which value comes back first.
268 lines
7.3 KiB
Elm
268 lines
7.3 KiB
Elm
module Comp.CalEventInput exposing
|
||
( Model
|
||
, Msg
|
||
, init
|
||
, initDefault
|
||
, update
|
||
, view
|
||
)
|
||
|
||
import Api
|
||
import Api.Model.CalEventCheck exposing (CalEventCheck)
|
||
import Api.Model.CalEventCheckResult exposing (CalEventCheckResult)
|
||
import Data.CalEvent exposing (CalEvent)
|
||
import Data.Flags exposing (Flags)
|
||
import Data.Validated exposing (Validated(..))
|
||
import Html exposing (..)
|
||
import Html.Attributes exposing (..)
|
||
import Html.Events exposing (onInput)
|
||
import Http
|
||
import Util.Http
|
||
import Util.Maybe
|
||
import Util.Time
|
||
|
||
|
||
type alias Model =
|
||
{ checkResult : Maybe CalEventCheckResult
|
||
}
|
||
|
||
|
||
type Msg
|
||
= SetYear String
|
||
| SetMonth String
|
||
| SetDay String
|
||
| SetHour String
|
||
| SetMinute String
|
||
| SetWeekday String
|
||
| CheckInputMsg CalEvent (Result Http.Error CalEventCheckResult)
|
||
|
||
|
||
initDefault : Model
|
||
initDefault =
|
||
Model Nothing
|
||
|
||
|
||
init : Flags -> CalEvent -> ( Model, Cmd Msg )
|
||
init flags ev =
|
||
( Model Nothing, checkInput flags ev )
|
||
|
||
|
||
checkInput : Flags -> CalEvent -> Cmd Msg
|
||
checkInput flags ev =
|
||
let
|
||
eventStr =
|
||
Data.CalEvent.makeEvent ev
|
||
|
||
input =
|
||
CalEventCheck eventStr
|
||
in
|
||
Api.checkCalEvent flags input (CheckInputMsg ev)
|
||
|
||
|
||
withCheckInput : Flags -> CalEvent -> Model -> ( Model, Cmd Msg, Validated CalEvent )
|
||
withCheckInput flags ev model =
|
||
( model, checkInput flags ev, Unknown ev )
|
||
|
||
|
||
isCheckError : Model -> Bool
|
||
isCheckError model =
|
||
Maybe.map .success model.checkResult
|
||
|> Maybe.withDefault True
|
||
|> not
|
||
|
||
|
||
update : Flags -> CalEvent -> Msg -> Model -> ( Model, Cmd Msg, Validated CalEvent )
|
||
update flags ev msg model =
|
||
case msg of
|
||
SetYear str ->
|
||
withCheckInput flags { ev | year = str } model
|
||
|
||
SetMonth str ->
|
||
withCheckInput flags { ev | month = str } model
|
||
|
||
SetDay str ->
|
||
withCheckInput flags { ev | day = str } model
|
||
|
||
SetHour str ->
|
||
withCheckInput flags { ev | hour = str } model
|
||
|
||
SetMinute str ->
|
||
withCheckInput flags { ev | minute = str } model
|
||
|
||
SetWeekday str ->
|
||
withCheckInput flags { ev | weekday = Util.Maybe.fromString str } model
|
||
|
||
CheckInputMsg event (Ok res) ->
|
||
let
|
||
m =
|
||
{ model | checkResult = Just res }
|
||
in
|
||
( m
|
||
, Cmd.none
|
||
, if res.success then
|
||
Valid event
|
||
|
||
else
|
||
Invalid [ res.message ] event
|
||
)
|
||
|
||
CheckInputMsg event (Err err) ->
|
||
let
|
||
emptyResult =
|
||
Api.Model.CalEventCheckResult.empty
|
||
|
||
m =
|
||
{ model
|
||
| checkResult =
|
||
Just
|
||
{ emptyResult
|
||
| success = False
|
||
, message = Util.Http.errorToString err
|
||
}
|
||
}
|
||
in
|
||
( m, Cmd.none, Unknown event )
|
||
|
||
|
||
view : String -> CalEvent -> Model -> Html Msg
|
||
view extraClasses ev model =
|
||
let
|
||
yearLen =
|
||
Basics.max 4 (String.length ev.year)
|
||
|
||
otherLen str =
|
||
Basics.max 2 (String.length str)
|
||
in
|
||
div
|
||
[ classList
|
||
[ ( extraClasses, True )
|
||
]
|
||
]
|
||
[ div [ class "calevent-input" ]
|
||
[ div []
|
||
[ label [] [ text "Weekday" ]
|
||
, input
|
||
[ type_ "text"
|
||
, class "time-input"
|
||
, size
|
||
(Maybe.map otherLen ev.weekday
|
||
|> Maybe.withDefault 4
|
||
)
|
||
, Maybe.withDefault "" ev.weekday
|
||
|> value
|
||
, onInput SetWeekday
|
||
]
|
||
[]
|
||
]
|
||
, div []
|
||
[ label [] [ text "Year" ]
|
||
, input
|
||
[ type_ "text"
|
||
, class "time-input"
|
||
, size yearLen
|
||
, value ev.year
|
||
, onInput SetYear
|
||
]
|
||
[]
|
||
]
|
||
, div [ class "date separator" ]
|
||
[ text "–"
|
||
]
|
||
, div []
|
||
[ label [] [ text "Month" ]
|
||
, input
|
||
[ type_ "text"
|
||
, class "time-input"
|
||
, size (otherLen ev.month)
|
||
, value ev.month
|
||
, onInput SetMonth
|
||
]
|
||
[]
|
||
]
|
||
, div [ class "date separator" ]
|
||
[ text "–"
|
||
]
|
||
, div []
|
||
[ label [] [ text "Day" ]
|
||
, input
|
||
[ type_ "text"
|
||
, class "time-input"
|
||
, size (otherLen ev.day)
|
||
, value ev.day
|
||
, onInput SetDay
|
||
]
|
||
[]
|
||
]
|
||
, div [ class "datetime separator" ]
|
||
[ text " "
|
||
]
|
||
, div []
|
||
[ label [] [ text "Hour" ]
|
||
, input
|
||
[ type_ "text"
|
||
, class "time-input"
|
||
, size (otherLen ev.hour)
|
||
, value ev.hour
|
||
, onInput SetHour
|
||
]
|
||
[]
|
||
]
|
||
, div [ class "time separator" ]
|
||
[ text ":"
|
||
]
|
||
, div []
|
||
[ label [] [ text "Minute" ]
|
||
, input
|
||
[ type_ "text"
|
||
, class "time-input"
|
||
, size (otherLen ev.minute)
|
||
, value ev.minute
|
||
, onInput SetMinute
|
||
]
|
||
[]
|
||
]
|
||
]
|
||
, div
|
||
[ classList
|
||
[ ( "ui basic red pointing label", True )
|
||
, ( "hidden invisible", not (isCheckError model) )
|
||
]
|
||
]
|
||
[ text "Error: "
|
||
, Maybe.map .message model.checkResult
|
||
|> Maybe.withDefault ""
|
||
|> text
|
||
]
|
||
, div
|
||
[ classList
|
||
[ ( "ui message", True )
|
||
, ( "hidden invisible"
|
||
, model.checkResult == Nothing || isCheckError model
|
||
)
|
||
]
|
||
]
|
||
[ dl []
|
||
[ dt []
|
||
[ text "Schedule: "
|
||
]
|
||
, dd []
|
||
[ code []
|
||
[ Maybe.andThen .event model.checkResult
|
||
|> Maybe.withDefault ""
|
||
|> text
|
||
]
|
||
]
|
||
, dt []
|
||
[ text "Next: "
|
||
]
|
||
, dd []
|
||
(Maybe.map .next model.checkResult
|
||
|> Maybe.withDefault []
|
||
|> List.map Util.Time.formatDateTime
|
||
|> List.map text
|
||
|> List.intersperse (br [] [])
|
||
)
|
||
]
|
||
]
|
||
]
|