web: show all add form errors as form errors
Don't allow internal server errors during form validation.
This commit is contained in:
parent
d3453c66c1
commit
9351f10b81
@ -10,12 +10,10 @@ import Control.Applicative
|
|||||||
import Data.Either (lefts,rights)
|
import Data.Either (lefts,rights)
|
||||||
import Data.List (sort)
|
import Data.List (sort)
|
||||||
import qualified Data.List as L (head) -- qualified keeps dev & prod builds warning-free
|
import qualified Data.List as L (head) -- qualified keeps dev & prod builds warning-free
|
||||||
-- import Data.Maybe
|
import Data.Text (append, pack, unpack)
|
||||||
import Data.Text (unpack)
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
-- import Data.Time.Calendar
|
import Data.Time.Calendar
|
||||||
import Text.Parsec (digit, eof, many1, string, runParser)
|
import Text.Parsec (digit, eof, many1, string, runParser)
|
||||||
-- import Yesod.Form.Jquery
|
|
||||||
|
|
||||||
import Hledger.Utils
|
import Hledger.Utils
|
||||||
import Hledger.Data hiding (num)
|
import Hledger.Data hiding (num)
|
||||||
@ -26,50 +24,57 @@ import Hledger.Cli hiding (num)
|
|||||||
-- Part of the data required from the add form.
|
-- Part of the data required from the add form.
|
||||||
-- Don't know how to handle the variable posting fields with yesod-form yet.
|
-- Don't know how to handle the variable posting fields with yesod-form yet.
|
||||||
data AddForm = AddForm
|
data AddForm = AddForm
|
||||||
{ addFormJournalFile :: Maybe Text -- FilePath
|
{ addFormDate :: Day
|
||||||
, addFormDate :: Maybe Text -- Day
|
|
||||||
, addFormDescription :: Maybe Text -- String
|
, addFormDescription :: Maybe Text -- String
|
||||||
-- , addFormPostings :: [(AccountName, String)]
|
-- , addFormPostings :: [(AccountName, String)]
|
||||||
|
, addFormJournalFile :: Maybe Text -- FilePath
|
||||||
}
|
}
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
postAddForm :: Handler Html
|
postAddForm :: Handler Html
|
||||||
postAddForm = do
|
postAddForm = do
|
||||||
VD{..} <- getViewData
|
|
||||||
let showErrors errs = do
|
let showErrors errs = do
|
||||||
-- error $ show errs -- XXX uncomment to prevent redirect, for debugging
|
-- error $ show errs -- XXX uncomment to prevent redirect for debugging
|
||||||
setMessage [shamlet|
|
setMessage [shamlet|
|
||||||
Error:<br>
|
Errors:<br>
|
||||||
$forall e<-errs
|
$forall e<-errs
|
||||||
\#{e}<br>
|
\#{e}<br>
|
||||||
|]
|
|]
|
||||||
|
|
||||||
|
-- 1. process the fixed fields with yesod-form
|
||||||
|
|
||||||
|
VD{..} <- getViewData
|
||||||
|
let
|
||||||
|
validateJournalFile :: Text -> Either FormMessage Text
|
||||||
|
validateJournalFile f
|
||||||
|
| unpack f `elem` journalFilePaths j = Right f
|
||||||
|
| otherwise = Left $ MsgInvalidEntry $ pack "the selected journal file \"" `append` f `append` "\"is unknown"
|
||||||
|
|
||||||
|
validateDate :: Text -> Handler (Either FormMessage Day)
|
||||||
|
validateDate s = return $
|
||||||
|
case fixSmartDateStrEither' today $ strip $ unpack s of
|
||||||
|
Right d -> Right d
|
||||||
|
Left _ -> Left $ MsgInvalidEntry $ pack "could not parse date \"" `append` s `append` pack "\":" -- ++ show e)
|
||||||
|
|
||||||
formresult <- runInputPostResult $ AddForm
|
formresult <- runInputPostResult $ AddForm
|
||||||
<$> iopt textField "journal"
|
<$> ireq (checkMMap validateDate (pack . show) textField) "date"
|
||||||
<*> iopt textField "date"
|
|
||||||
-- (jqueryDayField def
|
|
||||||
-- {
|
|
||||||
-- jdsChangeYear = True -- give a year dropdown
|
|
||||||
-- , jdsYearRange = "1900:-5" -- 1900 till five years ago
|
|
||||||
-- }) "date"
|
|
||||||
<*> iopt textField "description"
|
<*> iopt textField "description"
|
||||||
|
<*> iopt (check validateJournalFile textField) "journal"
|
||||||
|
|
||||||
case formresult of
|
case formresult of
|
||||||
FormMissing -> showErrors ["there is no form data"::String]
|
FormMissing -> showErrors ["there is no form data"::String]
|
||||||
FormFailure errs -> showErrors errs
|
FormFailure errs -> showErrors errs
|
||||||
FormSuccess formdata -> do
|
FormSuccess dat -> do
|
||||||
let AddForm{
|
let AddForm{
|
||||||
addFormJournalFile=mjournalfile
|
addFormDate =date
|
||||||
,addFormDate =mdate
|
|
||||||
,addFormDescription=mdesc
|
,addFormDescription=mdesc
|
||||||
} = formdata
|
,addFormJournalFile=mjournalfile
|
||||||
date = parsedate $ fixSmartDateStr today $ maybe "today" (strip . unpack) mdate
|
} = dat
|
||||||
desc = maybe "" unpack mdesc
|
desc = maybe "" unpack mdesc
|
||||||
journalfile = maybe
|
journalfile = maybe (journalFilePath j) unpack mjournalfile
|
||||||
(journalFilePath j)
|
|
||||||
(\f' -> let f = unpack f' in
|
-- 2. the fixed fields look good; now process the posting fields adhocly,
|
||||||
if f `elem` journalFilePaths j
|
-- getting either errors or a balanced transaction
|
||||||
then f
|
|
||||||
else error $ "the selected journal file is unknown: " ++ f)
|
|
||||||
mjournalfile
|
|
||||||
|
|
||||||
(params,_) <- runRequestBody
|
(params,_) <- runRequestBody
|
||||||
let numberedParams s =
|
let numberedParams s =
|
||||||
@ -93,22 +98,23 @@ postAddForm = do
|
|||||||
(amts', amtErrs) = (rights eamts, map show $ lefts eamts)
|
(amts', amtErrs) = (rights eamts, map show $ lefts eamts)
|
||||||
amts | length amts' == num = amts'
|
amts | length amts' == num = amts'
|
||||||
| otherwise = amts' ++ [missingamt]
|
| otherwise = amts' ++ [missingamt]
|
||||||
-- if no errors so far, generate a transaction and balance it or get the error.
|
|
||||||
errs = if not (null paramErrs) then paramErrs else (acctErrs ++ amtErrs)
|
errs = if not (null paramErrs) then paramErrs else (acctErrs ++ amtErrs)
|
||||||
et | not $ null errs = Left errs
|
etxn | not $ null errs = Left errs
|
||||||
| otherwise = either (\e -> Left [L.head $ lines e]) Right
|
| otherwise = either (\e -> Left [L.head $ lines e]) Right
|
||||||
(balanceTransaction Nothing $ nulltransaction {
|
(balanceTransaction Nothing $ nulltransaction {
|
||||||
tdate=date
|
tdate=date
|
||||||
,tdescription=desc
|
,tdescription=desc
|
||||||
,tpostings=[nullposting{paccount=acct, pamount=Mixed [amt]} | (acct,amt) <- zip accts amts]
|
,tpostings=[nullposting{paccount=acct, pamount=Mixed [amt]} | (acct,amt) <- zip accts amts]
|
||||||
})
|
})
|
||||||
-- display errors or add transaction
|
case etxn of
|
||||||
case et of
|
|
||||||
Left errs -> showErrors errs
|
Left errs -> showErrors errs
|
||||||
Right t -> do
|
Right t -> do
|
||||||
let t' = txnTieKnot t -- XXX move into balanceTransaction
|
-- 3. all fields look good and form a balanced transaction; append it to the file
|
||||||
liftIO $ do ensureJournalFileExists journalfile
|
liftIO $ do ensureJournalFileExists journalfile
|
||||||
appendToJournalFileOrStdout journalfile $ showTransaction t'
|
appendToJournalFileOrStdout journalfile $
|
||||||
|
showTransaction $
|
||||||
|
txnTieKnot -- XXX move into balanceTransaction
|
||||||
|
t
|
||||||
setMessage [shamlet|<span>Transaction added.|]
|
setMessage [shamlet|<span>Transaction added.|]
|
||||||
|
|
||||||
redirect (JournalR) -- , [("add","1")])
|
redirect (JournalR) -- , [("add","1")])
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user