web: stay in add form when there are errors
This commit is contained in:
		
							parent
							
								
									8bde2fd212
								
							
						
					
					
						commit
						e76cc6ee47
					
				| @ -25,6 +25,7 @@ import Settings (staticRoot, widgetFile, Extra (..)) | |||||||
| import Settings (staticDir) | import Settings (staticDir) | ||||||
| import Text.Jasmine (minifym) | import Text.Jasmine (minifym) | ||||||
| #endif | #endif | ||||||
|  | import Text.Blaze.Html.Renderer.String (renderHtml) | ||||||
| import Text.Hamlet (hamletFile) | import Text.Hamlet (hamletFile) | ||||||
| 
 | 
 | ||||||
| import Hledger.Web.Options | import Hledger.Web.Options | ||||||
| @ -104,7 +105,7 @@ instance Yesod App where | |||||||
| 
 | 
 | ||||||
|     defaultLayout widget = do |     defaultLayout widget = do | ||||||
|         master <- getYesod |         master <- getYesod | ||||||
|         mmsg <- getMessage |         vd@VD{..} <- getViewData | ||||||
| 
 | 
 | ||||||
|         -- We break up the default layout into two components: |         -- We break up the default layout into two components: | ||||||
|         -- default-layout is the contents of the body tag, and |         -- default-layout is the contents of the body tag, and | ||||||
| @ -140,7 +141,6 @@ instance Yesod App where | |||||||
|             $(widgetFile "default-layout") |             $(widgetFile "default-layout") | ||||||
| 
 | 
 | ||||||
|         staticRootUrl <- (staticRoot . settings) <$> getYesod |         staticRootUrl <- (staticRoot . settings) <$> getYesod | ||||||
|         vd@VD{..} <- getViewData |  | ||||||
|         withUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet") |         withUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet") | ||||||
| 
 | 
 | ||||||
|     -- This is done to provide an optimization for serving static files from |     -- This is done to provide an optimization for serving static files from | ||||||
| @ -232,8 +232,9 @@ getViewData :: Handler ViewData | |||||||
| getViewData = do | getViewData = do | ||||||
|   app        <- getYesod |   app        <- getYesod | ||||||
|   let opts@WebOpts{cliopts_=copts@CliOpts{reportopts_=ropts}} = appOpts app |   let opts@WebOpts{cliopts_=copts@CliOpts{reportopts_=ropts}} = appOpts app | ||||||
|   (j, err)   <- getCurrentJournal app copts{reportopts_=ropts{no_elide_=True}} |   (j, merr)  <- getCurrentJournal app copts{reportopts_=ropts{no_elide_=True}} | ||||||
|   msg        <- getMessageOr err |   lastmsg    <- getLastMessage | ||||||
|  |   let msg = maybe lastmsg (Just . toHtml) merr | ||||||
|   Just here  <- getCurrentRoute |   Just here  <- getCurrentRoute | ||||||
|   today      <- liftIO getCurrentDay |   today      <- liftIO getCurrentDay | ||||||
|   q          <- getParameterOrNull "q" |   q          <- getParameterOrNull "q" | ||||||
| @ -275,11 +276,10 @@ getViewData = do | |||||||
|       getParameterOrNull :: String -> Handler String |       getParameterOrNull :: String -> Handler String | ||||||
|       getParameterOrNull p = unpack `fmap` fromMaybe "" <$> lookupGetParam (pack p) |       getParameterOrNull p = unpack `fmap` fromMaybe "" <$> lookupGetParam (pack p) | ||||||
| 
 | 
 | ||||||
| -- | Get the message set by the last request, or the newer message provided, if any. | -- | Get the message that was set by the last request, in a | ||||||
| getMessageOr :: Maybe String -> Handler (Maybe Html) | -- referentially transparent manner (allowing multiple reads). | ||||||
| getMessageOr mnewmsg = do | getLastMessage :: Handler (Maybe Html) | ||||||
|   oldmsg <- getMessage | getLastMessage = cached getMessage | ||||||
|   return $ maybe oldmsg (Just . toHtml) mnewmsg |  | ||||||
| 
 | 
 | ||||||
| -- add form dialog, part of the default template | -- add form dialog, part of the default template | ||||||
| 
 | 
 | ||||||
| @ -334,7 +334,7 @@ addform _ vd@VD{..} = [hamlet| | |||||||
|      <table style="width:100%;"> |      <table style="width:100%;"> | ||||||
|       <tr#descriptionrow> |       <tr#descriptionrow> | ||||||
|        <td> |        <td> | ||||||
|         <input #date        .typeahead .form-control .input-lg type=text size=15 name=date placeholder="Date" value=#{date}> |         <input #date        .typeahead .form-control .input-lg type=text size=15 name=date placeholder="Date" value=#{defdate}> | ||||||
|        <td> |        <td> | ||||||
|         <input #description .typeahead .form-control .input-lg type=text size=40 name=description placeholder="Description"> |         <input #description .typeahead .form-control .input-lg type=text size=40 name=description placeholder="Description"> | ||||||
|    $forall n <- postingnums |    $forall n <- postingnums | ||||||
| @ -344,7 +344,7 @@ addform _ vd@VD{..} = [hamlet| | |||||||
|      Tab in last field for <a .small href="#" onclick="addformAddPosting(); return false;">more</a> (or ctrl +, ctrl -) |      Tab in last field for <a .small href="#" onclick="addformAddPosting(); return false;">more</a> (or ctrl +, ctrl -) | ||||||
| |] | |] | ||||||
|  where |  where | ||||||
|   date = "today" :: String |   defdate = "today" :: String | ||||||
|   dates = ["today","yesterday","tomorrow"] :: [String] |   dates = ["today","yesterday","tomorrow"] :: [String] | ||||||
|   descriptions = sort $ nub $ map tdescription $ jtxns j |   descriptions = sort $ nub $ map tdescription $ jtxns j | ||||||
|   accts = sort $ journalAccountNamesUsed j |   accts = sort $ journalAccountNamesUsed j | ||||||
|  | |||||||
| @ -61,9 +61,9 @@ postAddForm = do | |||||||
|     <*> iopt textField "description" |     <*> iopt textField "description" | ||||||
|     <*> iopt (check validateJournalFile textField) "journal" |     <*> iopt (check validateJournalFile textField) "journal" | ||||||
|    |    | ||||||
|   case formresult of |   ok <- case formresult of | ||||||
|     FormMissing      -> showErrors ["there is no form data"::String] |     FormMissing      -> showErrors ["there is no form data"::String] >> return False | ||||||
|     FormFailure errs -> showErrors errs |     FormFailure errs -> showErrors errs >> return False | ||||||
|     FormSuccess dat  -> do |     FormSuccess dat  -> do | ||||||
|       let AddForm{ |       let AddForm{ | ||||||
|              addFormDate       =date |              addFormDate       =date | ||||||
| @ -107,7 +107,7 @@ postAddForm = do | |||||||
|                                  ,tpostings=[nullposting{paccount=acct, pamount=Mixed [amt]} | (acct,amt) <- zip accts amts] |                                  ,tpostings=[nullposting{paccount=acct, pamount=Mixed [amt]} | (acct,amt) <- zip accts amts] | ||||||
|                                  }) |                                  }) | ||||||
|       case etxn of |       case etxn of | ||||||
|        Left errs -> showErrors errs |        Left errs -> showErrors errs >> return False | ||||||
|        Right t -> do |        Right t -> do | ||||||
|         -- 3. all fields look good and form a balanced transaction; append it to the file |         -- 3. all fields look good and form a balanced transaction; append it to the file | ||||||
|         liftIO $ do ensureJournalFileExists journalfile |         liftIO $ do ensureJournalFileExists journalfile | ||||||
| @ -116,5 +116,6 @@ postAddForm = do | |||||||
|                       txnTieKnot -- XXX move into balanceTransaction |                       txnTieKnot -- XXX move into balanceTransaction | ||||||
|                       t |                       t | ||||||
|         setMessage [shamlet|<span>Transaction added.|] |         setMessage [shamlet|<span>Transaction added.|] | ||||||
|  |         return True | ||||||
| 
 | 
 | ||||||
|   redirect (JournalR) -- , [("add","1")]) |   if ok then redirect JournalR else redirect (JournalR, [("add","1")]) | ||||||
|  | |||||||
| @ -55,8 +55,6 @@ topbar VD{..} = [hamlet| | |||||||
| <nav class="navbar" role="navigation"> | <nav class="navbar" role="navigation"> | ||||||
|  <div#topbar> |  <div#topbar> | ||||||
|   <h1>#{title} |   <h1>#{title} | ||||||
|  $maybe m' <- msg |  | ||||||
|   <div#message>#{m'} |  | ||||||
| |] | |] | ||||||
|   where |   where | ||||||
|     title = takeFileName $ journalFilePath j |     title = takeFileName $ journalFilePath j | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ | |||||||
| $(document).ready(function() { | $(document).ready(function() { | ||||||
| 
 | 
 | ||||||
|   // show add form if ?add=1
 |   // show add form if ?add=1
 | ||||||
|   if ($.url.param('add')) { addformShow(); } |   if ($.url.param('add')) { addformShow(showmsg=true); } | ||||||
| 
 | 
 | ||||||
|   // sidebar account hover handlers
 |   // sidebar account hover handlers
 | ||||||
|   $('#sidebar td a').mouseenter(function(){ $(this).parent().addClass('mouseover'); }); |   $('#sidebar td a').mouseenter(function(){ $(this).parent().addClass('mouseover'); }); | ||||||
| @ -126,8 +126,8 @@ function registerChartClick(ev, pos, item) { | |||||||
| //----------------------------------------------------------------------
 | //----------------------------------------------------------------------
 | ||||||
| // ADD FORM
 | // ADD FORM
 | ||||||
| 
 | 
 | ||||||
| function addformShow() { | function addformShow(showmsg=false) { | ||||||
|   addformReset(); |   addformReset(showmsg); | ||||||
|   $('#addmodal') |   $('#addmodal') | ||||||
|     .on('shown.bs.modal', function (e) { |     .on('shown.bs.modal', function (e) { | ||||||
|       addformFocus(); |       addformFocus(); | ||||||
| @ -136,13 +136,14 @@ function addformShow() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Make sure the add form is empty and clean for display.
 | // Make sure the add form is empty and clean for display.
 | ||||||
| function addformReset() { | function addformReset(showmsg=false) { | ||||||
|   if ($('form#addform').length > 0) { |   if ($('form#addform').length > 0) { | ||||||
|  |     if (!showmsg) $('div#message').html(''); | ||||||
|     $('form#addform')[0].reset(); |     $('form#addform')[0].reset(); | ||||||
|     $('input#date').val('today'); |  | ||||||
|     // reset typehead state (though not fetched completions)
 |     // reset typehead state (though not fetched completions)
 | ||||||
|     $('.typeahead').typeahead('val', ''); |     $('.typeahead').typeahead('val', ''); | ||||||
|     $('.tt-dropdown-menu').hide(); |     $('.tt-dropdown-menu').hide(); | ||||||
|  |     $('input#date').val('today'); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -100,4 +100,7 @@ $newline never | |||||||
|                 <button type="button" .close data-dismiss="modal" aria-hidden="true">× |                 <button type="button" .close data-dismiss="modal" aria-hidden="true">× | ||||||
|                 <h3 .modal-title #addLabel>Add a transaction |                 <h3 .modal-title #addLabel>Add a transaction | ||||||
|               <div .modal-body> |               <div .modal-body> | ||||||
|  |                 $maybe m <- msg | ||||||
|  |                   $if isPrefixOf "Errors" (renderHtml m) | ||||||
|  |                     <div #message>#{m} | ||||||
|                 ^{addform staticRootUrl vd} |                 ^{addform staticRootUrl vd} | ||||||
|  | |||||||
| @ -1,3 +1,4 @@ | |||||||
| $maybe msg <- mmsg | $maybe m <- msg | ||||||
|     <div #message>#{msg} |   $if not $ isPrefixOf "Errors" (renderHtml m) | ||||||
|  |     <div #message>#{m} | ||||||
| ^{widget} | ^{widget} | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user