From d9df5c3fcffe12aac239b58ccf2fd82c19c3be62 Mon Sep 17 00:00:00 2001 From: Joris Date: Sun, 3 Jan 2016 23:37:14 +0100 Subject: Validate add payment server side --- src/client/elm/Model/Action/AddPaymentAction.elm | 3 ++- src/client/elm/Model/Action/LoggedInAction.elm | 2 +- src/client/elm/Model/View/LoggedIn/Account.elm | 12 ++++++---- src/client/elm/Model/View/LoggedIn/AddPayment.elm | 16 +------------ src/client/elm/Native/Reads.js | 22 ------------------ src/client/elm/Reads.elm | 10 -------- src/client/elm/Server.elm | 17 ++++++++++---- src/client/elm/SimpleHTTP.elm | 8 ++++++- src/client/elm/Update/LoggedIn.elm | 18 +++++++++++---- src/client/elm/Update/LoggedIn/AddPayment.elm | 28 +++++++++++++++++++++++ src/client/elm/Utils/Validation.elm | 23 ------------------- src/client/elm/View/LoggedIn/AddPayment.elm | 10 +++----- src/client/elm/View/LoggedIn/Paging.elm | 4 ++-- 13 files changed, 79 insertions(+), 94 deletions(-) delete mode 100644 src/client/elm/Native/Reads.js delete mode 100644 src/client/elm/Reads.elm delete mode 100644 src/client/elm/Utils/Validation.elm (limited to 'src/client/elm') diff --git a/src/client/elm/Model/Action/AddPaymentAction.elm b/src/client/elm/Model/Action/AddPaymentAction.elm index a109a49..2d4f92a 100644 --- a/src/client/elm/Model/Action/AddPaymentAction.elm +++ b/src/client/elm/Model/Action/AddPaymentAction.elm @@ -3,7 +3,8 @@ module Model.Action.AddPaymentAction ) where type AddPaymentAction = - UpdateName String + NoOp + | UpdateName String | UpdateCost String | AddError (Maybe String) (Maybe String) | ToggleFrequency diff --git a/src/client/elm/Model/Action/LoggedInAction.elm b/src/client/elm/Model/Action/LoggedInAction.elm index ef81b09..4538ec7 100644 --- a/src/client/elm/Model/Action/LoggedInAction.elm +++ b/src/client/elm/Model/Action/LoggedInAction.elm @@ -11,7 +11,7 @@ type LoggedInAction = NoOp | UpdateAdd AddPaymentAction | UpdatePayments Payments - | AddPayment String Int PaymentFrequency + | AddPayment String String PaymentFrequency | ValidateAddPayment PaymentId String Int PaymentFrequency | DeletePayment Payment PaymentFrequency | ValidateDeletePayment Payment PaymentFrequency diff --git a/src/client/elm/Model/View/LoggedIn/Account.elm b/src/client/elm/Model/View/LoggedIn/Account.elm index 4638c8d..d03d84f 100644 --- a/src/client/elm/Model/View/LoggedIn/Account.elm +++ b/src/client/elm/Model/View/LoggedIn/Account.elm @@ -9,8 +9,8 @@ module Model.View.LoggedIn.Account import Result as Result exposing (Result(..)) import Dict +import String -import Utils.Validation exposing (..) import Utils.Dict exposing (mapValues) import Model.Translations exposing (..) @@ -62,6 +62,10 @@ initIncomeEdition income = validateIncome : String -> Translations -> Result String Int validateIncome amount translations = - amount - |> validateNonEmpty (getMessage "IncomeRequired" translations) - |> flip Result.andThen (validateNumber (getMessage "IncomeMustBePositiveNumber" translations) (\number -> number > 0)) + case String.toInt amount of + Ok number -> + if number > 0 + then Ok number + else Err <| getMessage "IncomeMustBePositiveNumber" translations + Err _ -> + Err <| getMessage "IncomeRequired" translations diff --git a/src/client/elm/Model/View/LoggedIn/AddPayment.elm b/src/client/elm/Model/View/LoggedIn/AddPayment.elm index 3a14b00..c7680bb 100644 --- a/src/client/elm/Model/View/LoggedIn/AddPayment.elm +++ b/src/client/elm/Model/View/LoggedIn/AddPayment.elm @@ -1,13 +1,10 @@ module Model.View.LoggedIn.AddPayment ( AddPayment , initAddPayment - , validateName - , validateCost ) where import Result as Result exposing (Result(..)) - -import Utils.Validation exposing (..) +import Json.Decode exposing ((:=)) import Model.Translations exposing (..) import Model.Payment exposing (PaymentFrequency(..)) @@ -30,14 +27,3 @@ initAddPayment frequency = , frequency = frequency , waitingServer = False } - -validateName : String -> Translations -> Result String String -validateName name translations = - name - |> validateNonEmpty (getMessage "CategoryRequired" translations) - -validateCost : String -> Translations -> Result String Int -validateCost cost translations = - cost - |> validateNonEmpty (getMessage "CostRequired" translations) - |> flip Result.andThen (validateNumber (getMessage "CostRequired" translations) ((/=) 0)) diff --git a/src/client/elm/Native/Reads.js b/src/client/elm/Native/Reads.js deleted file mode 100644 index 5785aed..0000000 --- a/src/client/elm/Native/Reads.js +++ /dev/null @@ -1,22 +0,0 @@ -Elm.Native.Reads = {}; -Elm.Native.Reads.make = function(localRuntime) { - - localRuntime.Native = localRuntime.Native || {}; - localRuntime.Native.Reads = localRuntime.Native.Reads || {}; - if(localRuntime.Native.Reads.values) { - return localRuntime.Native.Reads.values; - } - - var Maybe = Elm.Maybe.make(localRuntime); - - function readInt(str) { - var number = Number(str); - return isNaN(number) || str === '' - ? Maybe.Nothing - : Maybe.Just(number); - } - - return localRuntime.Native.Reads.values = { - readInt: readInt - }; -}; diff --git a/src/client/elm/Reads.elm b/src/client/elm/Reads.elm deleted file mode 100644 index f855802..0000000 --- a/src/client/elm/Reads.elm +++ /dev/null @@ -1,10 +0,0 @@ -module Reads - ( readInt - ) where - - -import Native.Reads -import Result exposing (Result) - -readInt : String -> Maybe Int -readInt = Native.Reads.readInt diff --git a/src/client/elm/Server.elm b/src/client/elm/Server.elm index 3a6c86a..e50de7e 100644 --- a/src/client/elm/Server.elm +++ b/src/client/elm/Server.elm @@ -14,16 +14,19 @@ import Json.Decode as Json exposing ((:=)) import Date import Time exposing (Time) import Debug +import String import SimpleHTTP exposing (..) import Model.Action as U exposing (Action) +import Model.Action.AddPaymentAction as AddPayment import Model.Action.LoggedInAction as UL exposing (LoggedInAction) import Model.Action.MonthlyAction as UM exposing (MonthlyAction) import Model.Action.AccountAction as UA exposing (AccountAction) import Model.Payment exposing (..) import Model.Payer exposing (Payers, payersDecoder) import Model.User exposing (Users, usersDecoder, UserId, userIdDecoder) +import Model.Translations exposing (Translations, getMessage) import Update.SignIn exposing (updateSignIn) @@ -32,11 +35,17 @@ signIn assertion = post ("/signIn?assertion=" ++ assertion) |> flip Task.andThen (always initViewAction) -addPayment : String -> Int -> PaymentFrequency -> Task Http.Error LoggedInAction -addPayment name cost frequency = - post ("/payment/add?name=" ++ name ++ "&cost=" ++ (toString cost) ++ "&frequency=" ++ (toString frequency)) +addPayment : Translations -> String -> String -> PaymentFrequency -> Task Http.Error LoggedInAction +addPayment translations name cost frequency = + post ("/payment/add?name=" ++ name ++ "&cost=" ++ cost ++ "&frequency=" ++ (toString frequency)) |> flip Task.andThen (decodeHttpValue <| "id" := paymentIdDecoder) - |> Task.map (\paymentId -> (UL.ValidateAddPayment paymentId name cost frequency)) + |> Task.map (\paymentId -> + case String.toInt cost of + Err _ -> + UL.UpdateAdd (AddPayment.AddError Nothing (Just (getMessage "CostRequired" translations))) + Ok costNumber -> + UL.ValidateAddPayment paymentId name costNumber frequency + ) deletePayment : Payment -> PaymentFrequency -> Task Http.Error LoggedInAction deletePayment payment frequency = diff --git a/src/client/elm/SimpleHTTP.elm b/src/client/elm/SimpleHTTP.elm index 99a7056..3e01178 100644 --- a/src/client/elm/SimpleHTTP.elm +++ b/src/client/elm/SimpleHTTP.elm @@ -22,7 +22,13 @@ handleResponse : Response -> Task Error Value handleResponse response = if 200 <= response.status && response.status < 300 then Task.succeed response.value - else fail (BadResponse response.status response.statusText) + else fail (BadResponse response.status (responseString response.value)) + +responseString : Value -> String +responseString value = + case value of + Text str -> str + _ -> "" promoteError : RawError -> Error promoteError rawError = diff --git a/src/client/elm/Update/LoggedIn.elm b/src/client/elm/Update/LoggedIn.elm index 74e213a..134aec2 100644 --- a/src/client/elm/Update/LoggedIn.elm +++ b/src/client/elm/Update/LoggedIn.elm @@ -4,9 +4,11 @@ module Update.LoggedIn import Date import Dict +import Debug +import Task import Effects exposing (Effects) -import Task +import Http exposing (Error(..)) import Server @@ -20,7 +22,7 @@ import Model.Action.AddPaymentAction as AddPayment import Model.View.LoggedInView exposing (..) import Model.View.LoggedIn.AddPayment exposing (..) -import Update.LoggedIn.AddPayment exposing (updateAddPayment) +import Update.LoggedIn.AddPayment exposing (updateAddPayment, addPaymentError) import Update.LoggedIn.Monthly exposing (updateMonthly) import Update.LoggedIn.Account exposing (updateAccount) @@ -42,8 +44,16 @@ updateLoggedIn model action loggedInView = AddPayment name cost frequency -> ( { loggedInView | add = updateAddPayment AddPayment.WaitingServer loggedInView.add } - , Server.addPayment name cost frequency - |> flip Task.onError (always <| Task.succeed NoOp) + , Server.addPayment model.translations name cost frequency + |> flip Task.onError (\err -> + case err of + BadResponse 400 jsonErr -> + case addPaymentError model.translations jsonErr of + Just addPaymentAction -> Task.succeed (UpdateAdd addPaymentAction) + Nothing -> Task.succeed NoOp + _ -> + Task.succeed NoOp + ) |> Effects.task ) diff --git a/src/client/elm/Update/LoggedIn/AddPayment.elm b/src/client/elm/Update/LoggedIn/AddPayment.elm index 3eb2ea4..4c9c484 100644 --- a/src/client/elm/Update/LoggedIn/AddPayment.elm +++ b/src/client/elm/Update/LoggedIn/AddPayment.elm @@ -1,26 +1,54 @@ module Update.LoggedIn.AddPayment ( updateAddPayment + , addPaymentError ) where +import Maybe +import Json.Decode as Json exposing ((:=)) + import Model.Action.AddPaymentAction exposing (..) import Model.View.LoggedIn.AddPayment exposing (..) +import Model.Translations exposing (Translations, getMessage) import Model.Payment exposing (PaymentFrequency(..)) updateAddPayment : AddPaymentAction -> AddPayment -> AddPayment updateAddPayment action addPayment = case action of + + NoOp -> + addPayment + UpdateName name -> { addPayment | name = name } + UpdateCost cost -> { addPayment | cost = cost } + AddError nameError costError -> { addPayment | nameError = nameError , costError = costError + , waitingServer = False } + ToggleFrequency -> { addPayment | frequency = if addPayment.frequency == Punctual then Monthly else Punctual } + WaitingServer -> { addPayment | waitingServer = True } + +addPaymentError : Translations -> String -> Maybe AddPaymentAction +addPaymentError translations jsonErr = + let decoder = + Json.object2 (,) + (Json.maybe <| "name" := Json.string) + (Json.maybe <| "cost" := Json.string) + in case Json.decodeString decoder jsonErr of + Err _ -> + Nothing + Ok (mbNameKey, mbCostKey) -> + Just <| AddError + (Maybe.map (flip getMessage translations) mbNameKey) + (Maybe.map (flip getMessage translations) mbCostKey) diff --git a/src/client/elm/Utils/Validation.elm b/src/client/elm/Utils/Validation.elm deleted file mode 100644 index b9bccb3..0000000 --- a/src/client/elm/Utils/Validation.elm +++ /dev/null @@ -1,23 +0,0 @@ -module Utils.Validation - ( validateNonEmpty - , validateNumber - ) where - -import String -import Reads exposing (readInt) - -validateNonEmpty : String -> String -> Result String String -validateNonEmpty message str = - if String.isEmpty str - then Err message - else Ok str - -validateNumber : String -> (Int -> Bool) -> String -> Result String Int -validateNumber message numberForm str = - case readInt str of - Just number -> - if numberForm number - then Ok number - else Err message - Nothing -> - Err message diff --git a/src/client/elm/View/LoggedIn/AddPayment.elm b/src/client/elm/View/LoggedIn/AddPayment.elm index 0b39591..0149432 100644 --- a/src/client/elm/View/LoggedIn/AddPayment.elm +++ b/src/client/elm/View/LoggedIn/AddPayment.elm @@ -2,7 +2,6 @@ module View.LoggedIn.AddPayment ( addPayment ) where -import Reads exposing (readInt) import Result exposing (..) import Signal exposing (Address) @@ -31,13 +30,10 @@ addPayment address model loggedInView = H.form [ let update = if loggedInView.add.waitingServer - then Action.NoOp + then + Action.NoOp else - case (validateName loggedInView.add.name model.translations, validateCost loggedInView.add.cost model.translations) of - (Ok name, Ok cost) -> - UpdateLoggedIn <| LoggedInAction.AddPayment name cost loggedInView.add.frequency - (resName, resCost) -> - UpdateLoggedIn <| UpdateAdd <| AddError (toMaybeError resName) (toMaybeError resCost) + UpdateLoggedIn <| LoggedInAction.AddPayment loggedInView.add.name loggedInView.add.cost loggedInView.add.frequency in onSubmitPrevDefault address update , class "addPayment" ] diff --git a/src/client/elm/View/LoggedIn/Paging.elm b/src/client/elm/View/LoggedIn/Paging.elm index 154686a..b722ee7 100644 --- a/src/client/elm/View/LoggedIn/Paging.elm +++ b/src/client/elm/View/LoggedIn/Paging.elm @@ -8,7 +8,7 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (..) -import Model.Action exposing (..) +import Model.Action as Action exposing (..) import Model.Action.LoggedInAction exposing (..) import Model.View.LoggedInView exposing (..) import Model.Payment exposing (perPage) @@ -94,6 +94,6 @@ paymentsPage address loggedInView page = , ("current", onCurrentPage) ] , onClick address <| - if onCurrentPage then NoOp else UpdateLoggedIn (UpdatePage page) + if onCurrentPage then Action.NoOp else UpdateLoggedIn (UpdatePage page) ] [ text (toString page) ] -- cgit v1.2.3