web: Resurrect ImportForm and EditForm
This commit is contained in:
		
							parent
							
								
									c24c8f1c99
								
							
						
					
					
						commit
						4faf0d8b4a
					
				| @ -17,9 +17,9 @@ import Yesod.Default.Config | |||||||
| import Yesod.Default.Main (defaultDevelApp) | import Yesod.Default.Main (defaultDevelApp) | ||||||
| import Yesod.Default.Handlers (getFaviconR, getRobotsR) | import Yesod.Default.Handlers (getFaviconR, getRobotsR) | ||||||
| 
 | 
 | ||||||
| -- Import all relevant handler modules here. |  | ||||||
| -- Don't forget to add new modules to your cabal file! |  | ||||||
| import Handler.AddR (postAddR) | import Handler.AddR (postAddR) | ||||||
|  | import Handler.EditR (postEditR) | ||||||
|  | import Handler.ImportR (postImportR) | ||||||
| import Handler.JournalR (getJournalR) | import Handler.JournalR (getJournalR) | ||||||
| import Handler.RegisterR (getRegisterR) | import Handler.RegisterR (getRegisterR) | ||||||
| import Handler.RootR (getRootR) | import Handler.RootR (getRootR) | ||||||
| @ -41,30 +41,29 @@ mkYesodDispatch "App" resourcesApp | |||||||
| -- place to put your migrate statements to have automatic database | -- place to put your migrate statements to have automatic database | ||||||
| -- migrations handled by Yesod. | -- migrations handled by Yesod. | ||||||
| makeApplication :: WebOpts -> Journal -> AppConfig DefaultEnv Extra -> IO Application | makeApplication :: WebOpts -> Journal -> AppConfig DefaultEnv Extra -> IO Application | ||||||
| makeApplication opts j conf = do | makeApplication opts' j' conf' = do | ||||||
|     foundation <- makeFoundation conf opts |     foundation <- makeFoundation conf' opts' | ||||||
|     writeIORef (appJournal foundation) j |     writeIORef (appJournal foundation) j' | ||||||
|     app <- toWaiAppPlain foundation |     logWare <$> toWaiAppPlain foundation | ||||||
|     return $ logWare app |  | ||||||
|   where |   where | ||||||
|     logWare | development  = logStdoutDev |     logWare | development  = logStdoutDev | ||||||
|             | serve_ opts  = logStdout |             | serve_ opts'  = logStdout | ||||||
|             | otherwise    = id |             | otherwise    = id | ||||||
| 
 | 
 | ||||||
| makeFoundation :: AppConfig DefaultEnv Extra -> WebOpts -> IO App | makeFoundation :: AppConfig DefaultEnv Extra -> WebOpts -> IO App | ||||||
| makeFoundation conf opts = do | makeFoundation conf opts' = do | ||||||
|     manager <- newManager defaultManagerSettings |     manager <- newManager defaultManagerSettings | ||||||
|     s <- staticSite |     s <- staticSite | ||||||
|     jref <- newIORef nulljournal |     jref <- newIORef nulljournal | ||||||
|     return $ App conf s manager opts jref |     return $ App conf s manager opts' jref | ||||||
| 
 | 
 | ||||||
| -- for yesod devel | -- for yesod devel | ||||||
| -- uses the journal specified by the LEDGER_FILE env var, or ~/.hledger.journal | -- uses the journal specified by the LEDGER_FILE env var, or ~/.hledger.journal | ||||||
| getApplicationDev :: IO (Int, Application) | getApplicationDev :: IO (Int, Application) | ||||||
| getApplicationDev = do | getApplicationDev = do | ||||||
|   f <- head `fmap` journalFilePathFromOpts defcliopts -- XXX head should be safe for now |   f <- head `fmap` journalFilePathFromOpts defcliopts -- XXX head should be safe for now | ||||||
|   j <- either error' id `fmap` readJournalFile def f |   j' <- either error' id <$> readJournalFile def f | ||||||
|   defaultDevelApp loader (makeApplication defwebopts j) |   defaultDevelApp loader (makeApplication defwebopts j') | ||||||
|   where |   where | ||||||
|     loader = Yesod.Default.Config.loadConfig (configSettings Development) |     loader = Yesod.Default.Config.loadConfig (configSettings Development) | ||||||
|         { csParseExtra = parseExtra |         { csParseExtra = parseExtra | ||||||
|  | |||||||
| @ -114,52 +114,6 @@ searchform VD{q, here} = [hamlet| | |||||||
|       <button .btn .btn-default type=button data-toggle="modal" data-target="#helpmodal" title="Show search and general help">? |       <button .btn .btn-default type=button data-toggle="modal" data-target="#helpmodal" title="Show search and general help">? | ||||||
| |] | |] | ||||||
| 
 | 
 | ||||||
| -- -- | Edit journal form. |  | ||||||
| -- editform :: ViewData -> HtmlUrl AppRoute |  | ||||||
| -- editform VD{..} = [hamlet| |  | ||||||
| -- <form#editform method=POST style=display:none;> |  | ||||||
| --  <h2#contenttitle>#{title}> |  | ||||||
| --  <table.form> |  | ||||||
| --   $if manyfiles |  | ||||||
| --    <tr> |  | ||||||
| --     <td colspan=2> |  | ||||||
| --      Editing ^{journalselect $ files j} |  | ||||||
| --   <tr> |  | ||||||
| --    <td colspan=2> |  | ||||||
| --     <!-- XXX textarea ids are unquoted journal file paths here, not valid html --> |  | ||||||
| --     $forall f <- files j |  | ||||||
| --      <textarea id=#{fst f}_textarea name=text rows=25 cols=80 style=display:none; disabled=disabled> |  | ||||||
| --       \#{snd f} |  | ||||||
| --   <tr#addbuttonrow> |  | ||||||
| --    <td> |  | ||||||
| --     <span.help>^{formathelp} |  | ||||||
| --    <td> |  | ||||||
| --     <span.help> |  | ||||||
| --      Are you sure ? This will overwrite the journal. # |  | ||||||
| --     <input type=hidden name=action value=edit> |  | ||||||
| --     <input type=submit name=submit value="save journal"> |  | ||||||
| --     \ or # |  | ||||||
| --     <a href="#" onclick="return editformToggle(event)">cancel |  | ||||||
| -- |] |  | ||||||
| --   where |  | ||||||
| --     title = "Edit journal" :: String |  | ||||||
| --     manyfiles = length (files j) > 1 |  | ||||||
| --     formathelp = helplink "file-format" "file format help" |  | ||||||
| 
 |  | ||||||
| -- -- | Import journal form. |  | ||||||
| -- importform :: HtmlUrl AppRoute |  | ||||||
| -- importform = [hamlet| |  | ||||||
| -- <form#importform method=POST style=display:none;> |  | ||||||
| --  <table.form> |  | ||||||
| --   <tr> |  | ||||||
| --    <td> |  | ||||||
| --     <input type=file name=file> |  | ||||||
| --     <input type=hidden name=action value=import> |  | ||||||
| --     <input type=submit name=submit value="import from file"> |  | ||||||
| --     \ or # |  | ||||||
| --     <a href="#" onclick="return importformToggle(event)">cancel |  | ||||||
| -- |] |  | ||||||
| 
 |  | ||||||
| -- | Link to a topic in the manual. | -- | Link to a topic in the manual. | ||||||
| helplink :: Text -> Text -> HtmlUrl AppRoute | helplink :: Text -> Text -> HtmlUrl AppRoute | ||||||
| helplink topic label = [hamlet| | helplink topic label = [hamlet| | ||||||
|  | |||||||
| @ -1,75 +0,0 @@ | |||||||
| -- -- | Handle a post from the journal edit form. |  | ||||||
| -- handleEdit :: Handler Html |  | ||||||
| -- handleEdit = do |  | ||||||
| --   VD{..} <- getViewData |  | ||||||
| --   -- get form input values, or validation errors. |  | ||||||
| --   -- getRequest >>= liftIO (reqRequestBody req) >>= mtrace |  | ||||||
| --   mtext <- lookupPostParam "text" |  | ||||||
| --   mtrace "--------------------------" |  | ||||||
| --   mtrace (journalFilePaths j) |  | ||||||
| --   mjournalpath <- lookupPostParam "journal" |  | ||||||
| --   let etext = maybe (Left "No value provided") (Right . unpack) mtext |  | ||||||
| --       ejournalpath = maybe |  | ||||||
| --                        (Right $ journalFilePath j) |  | ||||||
| --                        (\f -> let f' = unpack f in |  | ||||||
| --                               if f' `elem` dbg0 "paths2" (journalFilePaths j) |  | ||||||
| --                               then Right f' |  | ||||||
| --                               else Left ("unrecognised journal file path"::String)) |  | ||||||
| --                        mjournalpath |  | ||||||
| --       estrs = [etext, ejournalpath] |  | ||||||
| --       errs = lefts estrs |  | ||||||
| --       [text,journalpath] = rights estrs |  | ||||||
| --   -- display errors or perform edit |  | ||||||
| --   if not $ null errs |  | ||||||
| --    then do |  | ||||||
| --     setMessage $ toHtml (intercalate "; " errs :: String) |  | ||||||
| --     redirect JournalR |  | ||||||
| 
 |  | ||||||
| -- -- | Handle a post from the journal edit form. |  | ||||||
| -- handleEdit :: Handler Html |  | ||||||
| -- handleEdit = do |  | ||||||
| --   VD{..} <- getViewData |  | ||||||
| --   -- get form input values, or validation errors. |  | ||||||
| --   -- getRequest >>= liftIO (reqRequestBody req) >>= mtrace |  | ||||||
| --   mtext <- lookupPostParam "text" |  | ||||||
| --   mjournalpath <- lookupPostParam "journal" |  | ||||||
| --   let etext = maybe (Left "No value provided") (Right . unpack) mtext |  | ||||||
| --       ejournalpath = maybe |  | ||||||
| --                        (Right $ journalFilePath j) |  | ||||||
| --                        (\f -> let f' = unpack f in |  | ||||||
| --                               if f' `elem` journalFilePaths j |  | ||||||
| --                               then Right f' |  | ||||||
| --                               else Left ("unrecognised journal file path"::String)) |  | ||||||
| --                        mjournalpath |  | ||||||
| --       estrs = [etext, ejournalpath] |  | ||||||
| --       errs = lefts estrs |  | ||||||
| --       [text,journalpath] = rights estrs |  | ||||||
| --   -- display errors or perform edit |  | ||||||
| --   if not $ null errs |  | ||||||
| --    then do |  | ||||||
| --     setMessage $ toHtml (intercalate "; " errs :: String) |  | ||||||
| --     redirect JournalR |  | ||||||
| 
 |  | ||||||
| --    else do |  | ||||||
| --     -- try to avoid unnecessary backups or saving invalid data |  | ||||||
| --     filechanged' <- liftIO $ journalSpecifiedFileIsNewer j journalpath |  | ||||||
| --     told <- liftIO $ readFileStrictly journalpath |  | ||||||
| --     let tnew = filter (/= '\r') text |  | ||||||
| --         changed = tnew /= told || filechanged' |  | ||||||
| --     if not changed |  | ||||||
| --      then do |  | ||||||
| --        setMessage "No change" |  | ||||||
| --        redirect JournalR |  | ||||||
| --      else do |  | ||||||
| --       jE <- liftIO $ readJournal def (Just journalpath) tnew |  | ||||||
| --       either |  | ||||||
| --        (\e -> do |  | ||||||
| --           setMessage $ toHtml e |  | ||||||
| --           redirect JournalR) |  | ||||||
| --        (const $ do |  | ||||||
| --           liftIO $ writeFileWithBackup journalpath tnew |  | ||||||
| --           setMessage $ toHtml (printf "Saved journal %s\n" (show journalpath) :: String) |  | ||||||
| --           redirect JournalR) |  | ||||||
| --        jE |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
							
								
								
									
										46
									
								
								hledger-web/Handler/EditR.hs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								hledger-web/Handler/EditR.hs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | |||||||
|  | {-# LANGUAGE LambdaCase #-} | ||||||
|  | {-# LANGUAGE NamedFieldPuns #-} | ||||||
|  | {-# LANGUAGE OverloadedStrings #-} | ||||||
|  | 
 | ||||||
|  | module Handler.EditR | ||||||
|  |   ( postEditR | ||||||
|  |   ) where | ||||||
|  | 
 | ||||||
|  | import Import | ||||||
|  | 
 | ||||||
|  | import Control.Monad.Trans (lift) | ||||||
|  | import Control.Monad.Trans.Except | ||||||
|  | import qualified Data.Text as T | ||||||
|  | import Text.Printf (printf) | ||||||
|  | 
 | ||||||
|  | import Handler.Common (showErrors) | ||||||
|  | 
 | ||||||
|  | import Hledger | ||||||
|  | import Hledger.Cli.Utils | ||||||
|  | 
 | ||||||
|  | -- | Handle a post from the journal edit form. | ||||||
|  | postEditR :: Handler () | ||||||
|  | postEditR = runE $ do | ||||||
|  |   VD {j} <- lift getViewData | ||||||
|  |   -- get form input values, or validation errors. | ||||||
|  |   text <- ExceptT $ maybe (Left "No value provided") Right <$> lookupPostParam "text" | ||||||
|  |   journalpath <- ExceptT $ maybe | ||||||
|  |     (Right . T.pack $ journalFilePath j) | ||||||
|  |     (\f -> | ||||||
|  |        if T.unpack f `elem` journalFilePaths j | ||||||
|  |          then Right f | ||||||
|  |          else Left "unrecognised journal file path") <$> | ||||||
|  |     lookupPostParam "journal" | ||||||
|  |   -- try to avoid unnecessary backups or saving invalid data | ||||||
|  |   let tnew = T.filter (/= '\r') text | ||||||
|  | 
 | ||||||
|  |   jE <- liftIO $ readJournal def (Just $ T.unpack journalpath) tnew | ||||||
|  |   _ <- ExceptT . pure $ first T.pack jE | ||||||
|  |   _ <- liftIO $ writeFileWithBackupIfChanged (T.unpack journalpath) tnew | ||||||
|  |   setMessage $ toHtml (printf "Saved journal %s\n" (show journalpath) :: String) | ||||||
|  |   redirect JournalR | ||||||
|  |   where | ||||||
|  |     runE :: ExceptT Text Handler () -> Handler () | ||||||
|  |     runE f = runExceptT f >>= \case | ||||||
|  |       Left e -> showErrors [e] >> redirect JournalR | ||||||
|  |       Right x -> pure x | ||||||
| @ -1,18 +0,0 @@ | |||||||
| -- -- | Handle a post from the journal import form. |  | ||||||
| -- handleImport :: Handler Html |  | ||||||
| -- handleImport = do |  | ||||||
| --   setMessage "can't handle file upload yet" |  | ||||||
| --   redirect JournalR |  | ||||||
| --   -- -- get form input values, or basic validation errors. E means an Either value. |  | ||||||
| --   -- fileM <- runFormPost $ maybeFileInput "file" |  | ||||||
| --   -- let fileE = maybe (Left "No file provided") Right fileM |  | ||||||
| --   -- -- display errors or import transactions |  | ||||||
| --   -- case fileE of |  | ||||||
| --   --  Left errs -> do |  | ||||||
| --   --   setMessage errs |  | ||||||
| --   --   redirect JournalR |  | ||||||
| 
 |  | ||||||
| --   --  Right s -> do |  | ||||||
| --   --    setMessage s |  | ||||||
| --   --    redirect JournalR |  | ||||||
| 
 |  | ||||||
							
								
								
									
										29
									
								
								hledger-web/Handler/ImportR.hs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								hledger-web/Handler/ImportR.hs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | |||||||
|  | {-# LANGUAGE LambdaCase #-} | ||||||
|  | {-# LANGUAGE OverloadedStrings #-} | ||||||
|  | 
 | ||||||
|  | module Handler.ImportR | ||||||
|  |   ( postImportR | ||||||
|  |   ) where | ||||||
|  | 
 | ||||||
|  | import Import | ||||||
|  | 
 | ||||||
|  | import Control.Monad.Trans (lift) | ||||||
|  | import Control.Monad.Trans.Except | ||||||
|  | 
 | ||||||
|  | import Handler.Common (showErrors) | ||||||
|  | 
 | ||||||
|  | -- | Handle a post from the journal import form. | ||||||
|  | postImportR :: Handler () | ||||||
|  | postImportR = runE $ do | ||||||
|  |   ((res, _), _) <- lift . runFormPost . renderDivs $ areq fileField "file" Nothing | ||||||
|  |   case res of | ||||||
|  |     FormMissing -> throwE ["No file provided"] | ||||||
|  |     FormFailure es -> throwE es | ||||||
|  |     FormSuccess _ -> do | ||||||
|  |      setMessage "File uploaded successfully" | ||||||
|  |      redirect JournalR | ||||||
|  |   where | ||||||
|  |     runE :: ExceptT [Text] Handler () -> Handler () | ||||||
|  |     runE f = runExceptT f >>= \case | ||||||
|  |       Left e -> showErrors e >> redirect JournalR | ||||||
|  |       Right x -> pure x | ||||||
| @ -9,6 +9,7 @@ import           Yesod                as Import hiding (Route (..)) | |||||||
| 
 | 
 | ||||||
| import           Control.Monad        as Import (when, unless, void) | import           Control.Monad        as Import (when, unless, void) | ||||||
| import           Data.Bifunctor       as Import (first, second, bimap) | import           Data.Bifunctor       as Import (first, second, bimap) | ||||||
|  | import           Data.Default         as Import (Default(def)) | ||||||
| import           Data.Either          as Import (lefts, rights, partitionEithers) | import           Data.Either          as Import (lefts, rights, partitionEithers) | ||||||
| import           Data.Maybe           as Import (fromMaybe, maybeToList, mapMaybe, isJust) | import           Data.Maybe           as Import (fromMaybe, maybeToList, mapMaybe, isJust) | ||||||
| import           Data.Text            as Import (Text) | import           Data.Text            as Import (Text) | ||||||
|  | |||||||
| @ -6,6 +6,8 @@ | |||||||
| /register        RegisterR       GET | /register        RegisterR       GET | ||||||
| /sidebar         SidebarR        GET | /sidebar         SidebarR        GET | ||||||
| /add             AddR            POST | /add             AddR            POST | ||||||
|  | /edit            EditR           POST | ||||||
|  | /import          ImportR         POST | ||||||
| 
 | 
 | ||||||
| -- /accounts        AccountsR       GET | -- /accounts        AccountsR       GET | ||||||
| -- /api/accounts    AccountsJsonR   GET | -- /api/accounts    AccountsJsonR   GET | ||||||
|  | |||||||
| @ -125,6 +125,8 @@ library | |||||||
|       Handler.AddForm |       Handler.AddForm | ||||||
|       Handler.AddR |       Handler.AddR | ||||||
|       Handler.Common |       Handler.Common | ||||||
|  |       Handler.EditR | ||||||
|  |       Handler.ImportR | ||||||
|       Handler.JournalR |       Handler.JournalR | ||||||
|       Handler.RegisterR |       Handler.RegisterR | ||||||
|       Handler.RootR |       Handler.RootR | ||||||
|  | |||||||
| @ -118,8 +118,10 @@ library: | |||||||
|   - Application |   - Application | ||||||
|   - Foundation |   - Foundation | ||||||
|   - Handler.AddForm |   - Handler.AddForm | ||||||
|   - Handler.Common |  | ||||||
|   - Handler.AddR |   - Handler.AddR | ||||||
|  |   - Handler.Common | ||||||
|  |   - Handler.EditR | ||||||
|  |   - Handler.ImportR | ||||||
|   - Handler.JournalR |   - Handler.JournalR | ||||||
|   - Handler.RegisterR |   - Handler.RegisterR | ||||||
|   - Handler.RootR |   - Handler.RootR | ||||||
|  | |||||||
							
								
								
									
										24
									
								
								hledger-web/templates/edit-form.hamlet
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								hledger-web/templates/edit-form.hamlet
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | |||||||
|  | <form#editform method=POST style=display:none;> | ||||||
|  |   <h2#contenttitle>Edit journal | ||||||
|  |   <table.form> | ||||||
|  |     $if length (jfiles j) > 1 | ||||||
|  |      <tr> | ||||||
|  |        <td colspan=2> | ||||||
|  |          Editing ^{journalselect (fmap (T.unpack . snd) (jfiles j))} | ||||||
|  |     <tr> | ||||||
|  |       <td colspan=2> | ||||||
|  |         <!-- XXX textarea ids are unquoted journal file paths here, not valid html --> | ||||||
|  |          $forall f <- jfiles j | ||||||
|  |           <textarea id=#{fst f}_textarea name=text rows=25 cols=80 style=display:none; disabled=disabled> | ||||||
|  |             \#{snd f} | ||||||
|  |     <tr#addbuttonrow> | ||||||
|  |       <td> | ||||||
|  |         <span.help> | ||||||
|  |           ^{helplink "file-format" "file format help"} | ||||||
|  |       <td> | ||||||
|  |         <span.help> | ||||||
|  |           Are you sure ? This will overwrite the journal. # | ||||||
|  |         <input type=hidden name=action value=edit> | ||||||
|  |         <input type=submit name=submit value="save journal"> | ||||||
|  |         \ or # | ||||||
|  |         <a href="#" onclick="return editformToggle(event)">cancel | ||||||
							
								
								
									
										9
									
								
								hledger-web/templates/import-form.hamlet
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								hledger-web/templates/import-form.hamlet
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | <form#importform method=POST style=display:none;> | ||||||
|  |  <table.form> | ||||||
|  |   <tr> | ||||||
|  |    <td> | ||||||
|  |     <input type=file name=file> | ||||||
|  |     <input type=hidden name=action value=import> | ||||||
|  |     <input type=submit name=submit value="import from file"> | ||||||
|  |     \ or # | ||||||
|  |     <a href="#" onclick="return importformToggle(event)">cancel | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user