Skip to content

Support stdin journal (web), create journal file if not exists (ui, web) #978

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions hledger-lib/Hledger/Read.hs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ requireJournalFileExists f = do

-- | Ensure there is a journal file at the given path, creating an empty one if needed.
ensureJournalFileExists :: FilePath -> IO ()
ensureJournalFileExists "-" = return ()
ensureJournalFileExists f = do
exists <- doesFileExist f
when (not exists) $ do
Expand Down
21 changes: 11 additions & 10 deletions hledger-ui/Hledger/UI/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ Copyright (c) 2007-2015 Simon Michael <simon@joyful.com>
Released under GPL version 3 or later.
-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE OverloadedStrings #-}

module Hledger.UI.Main where

Expand All @@ -30,6 +31,7 @@ import System.Exit
import System.Directory
import System.FilePath
import System.FSNotify
import Text.Printf (printf)
import Brick

#if MIN_VERSION_brick(0,16,0)
Expand Down Expand Up @@ -66,15 +68,14 @@ main = do
{ inputopts_ = (inputopts_ copts) { auto_ = True }
, reportopts_ = (reportopts_ copts) { forecast_ = True }
}

-- when (debug_ $ cliopts_ opts) $ printf "%s\n" prognameandversion >> printf "opts: %s\n" (show opts)
run $ opts { cliopts_ = copts' }
where
run opts
| "help" `inRawOpts` (rawopts_ $ cliopts_ opts) = putStr (showModeUsage uimode) >> exitSuccess
| "version" `inRawOpts` (rawopts_ $ cliopts_ opts) = putStrLn prognameandversion >> exitSuccess
| "binary-filename" `inRawOpts` (rawopts_ $ cliopts_ opts) = putStrLn (binaryfilename progname)
| otherwise = withJournalDo (cliopts_ opts) (runBrickUi opts)
when (debug_ copts' > 0) $ printf "%s\n" prognameandversion >> printf "opts: %s\n" (show opts)
if
| "help" `inRawOpts` rawopts_ copts' -> putStr (showModeUsage uimode) >> exitSuccess
| "version" `inRawOpts` rawopts_ copts' -> putStrLn prognameandversion >> exitSuccess
| "binary-filename" `inRawOpts` rawopts_ copts' -> putStrLn (binaryfilename progname)
| otherwise -> do
mapM_ ensureJournalFileExists =<< journalFilePathFromOpts copts'
withJournalDo copts' (runBrickUi $ opts { cliopts_ = copts' })

runBrickUi :: UIOpts -> Journal -> IO ()
runBrickUi uopts@UIOpts{cliopts_=copts@CliOpts{inputopts_=_iopts,reportopts_=ropts}} j = do
Expand Down
23 changes: 15 additions & 8 deletions hledger-web/Hledger/Web/Handler/AddR.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ module Hledger.Web.Handler.AddR
) where

import Data.Aeson.Types (Result(..))
import Data.IORef (writeIORef)
import qualified Data.Text as T
import Network.HTTP.Types.Status (status400)
import Text.Blaze.Html (preEscapedToHtml)
import Yesod

import Hledger
import Hledger.Cli.Commands.Add (appendToJournalFileOrStdout, journalAddTransaction)
import Hledger.Cli.Commands.Add (journalAddTransaction)
import Hledger.Web.Import
import Hledger.Web.Json ()
import Hledger.Web.WebOptions (WebOpts(..))
Expand All @@ -28,17 +29,20 @@ getAddR = postAddR

postAddR :: Handler ()
postAddR = do
VD{caps, j, today} <- getViewData
VD { opts, caps, j, today } <- getViewData
App { appJournal } <- getYesod
when (CapAdd `notElem` caps) (permissionDenied "Missing the 'add' capability")

((res, view), enctype) <- runFormPost $ addForm j today
case res of
FormSuccess res' -> do
let t = txnTieKnot res'
-- XXX(?) move into balanceTransaction
liftIO $ ensureJournalFileExists (journalFilePath j)
-- XXX why not journalAddTransaction ?
liftIO $ appendToJournalFileOrStdout (journalFilePath j) (showTransaction t)
let t = txnTieKnot res'
liftIO $ do
ensureJournalFileExists (journalFilePath j)
j' <- journalAddTransaction j (cliopts_ opts) t
-- explicitly write to IORef for journals read from stdin
writeIORef appJournal j'
setMessage "Transaction added."
redirect JournalR
FormMissing -> showForm view enctype
Expand All @@ -59,11 +63,14 @@ postAddR = do
putAddR :: Handler RepJson
putAddR = do
VD{caps, j, opts} <- getViewData
App { appJournal } <- getYesod
when (CapAdd `notElem` caps) (permissionDenied "Missing the 'add' capability")

(r :: Result Transaction) <- parseCheckJsonBody
case r of
Error err -> sendStatusJSON status400 ("could not parse json: " ++ err ::String)
Success t -> do
void $ liftIO $ journalAddTransaction j (cliopts_ opts) t
sendResponseCreated TransactionsR
j' <- liftIO $ journalAddTransaction j (cliopts_ opts) t
-- explicitly write to IORef for journals read from stdin
liftIO $ writeIORef appJournal j'
sendResponseCreated TransactionsR
7 changes: 6 additions & 1 deletion hledger-web/Hledger/Web/Handler/EditR.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ module Hledger.Web.Handler.EditR
, postEditR
) where

import Data.IORef (writeIORef)

import Hledger.Web.Import
import Hledger.Web.Widget.Common
(fromFormSuccess, helplink, journalFile404, writeValidJournal)
Expand All @@ -28,6 +30,7 @@ getEditR = postEditR
postEditR :: FilePath -> Handler ()
postEditR f = do
VD {caps, j} <- getViewData
App { appJournal } <- getYesod
when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability")

(f', txt) <- journalFile404 f j
Expand All @@ -37,7 +40,9 @@ postEditR f = do
Left e -> do
setMessage $ "Failed to load journal: " <> toHtml e
showForm view enctype
Right () -> do
Right j' -> do
-- explicitly write to IORef for journals read from stdin
liftIO $ writeIORef appJournal j'
setMessage $ "Saved journal " <> toHtml f <> "\n"
redirect JournalR
where
Expand Down
6 changes: 5 additions & 1 deletion hledger-web/Hledger/Web/Handler/UploadR.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module Hledger.Web.Handler.UploadR
import qualified Data.ByteString.Lazy as BL
import Data.Conduit (connect)
import Data.Conduit.Binary (sinkLbs)
import Data.IORef (writeIORef)
import qualified Data.Text.Encoding as TE

import Hledger.Web.Import
Expand All @@ -32,6 +33,7 @@ getUploadR = postUploadR
postUploadR :: FilePath -> Handler ()
postUploadR f = do
VD {caps, j} <- getViewData
App { appJournal } <- getYesod
when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability")

(f', _) <- journalFile404 f j
Expand All @@ -53,7 +55,9 @@ postUploadR f = do
Left e -> do
setMessage $ "Failed to load journal: " <> toHtml e
showForm view enctype
Right () -> do
Right j' -> do
-- explicitly write to IORef for journals read from stdin
liftIO $ writeIORef appJournal j'
setMessage $ "File " <> toHtml f <> " uploaded successfully"
redirect JournalR
where
Expand Down
19 changes: 10 additions & 9 deletions hledger-web/Hledger/Web/Main.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE OverloadedStrings #-}
{-|

Expand Down Expand Up @@ -33,8 +34,15 @@ import Hledger.Web.WebOptions
hledgerWebMain :: IO ()
hledgerWebMain = do
opts <- getHledgerWebOpts
when (debug_ (cliopts_ opts) > 0) $ printf "%s\n" prognameandversion >> printf "opts: %s\n" (show opts)
runWith opts
let copts = cliopts_ opts
when (debug_ copts > 0) $ printf "%s\n" prognameandversion >> printf "opts: %s\n" (show opts)
if
| "help" `inRawOpts` rawopts_ copts -> putStr (showModeUsage webmode) >> exitSuccess
| "version" `inRawOpts` rawopts_ copts -> putStrLn prognameandversion >> exitSuccess
| "binary-filename" `inRawOpts` rawopts_ copts -> putStrLn (binaryfilename progname)
| otherwise -> do
mapM_ ensureJournalFileExists =<< journalFilePathFromOpts copts
withJournalDo copts (web opts)

hledgerWebDev :: IO (Int, Application)
hledgerWebDev =
Expand All @@ -44,13 +52,6 @@ hledgerWebDev =
Yesod.Default.Config.loadConfig
(configSettings Development) {csParseExtra = parseExtra}

runWith :: WebOpts -> IO ()
runWith opts
| "help" `inRawOpts` rawopts_ (cliopts_ opts) = putStr (showModeUsage webmode) >> exitSuccess
| "version" `inRawOpts` rawopts_ (cliopts_ opts) = putStrLn prognameandversion >> exitSuccess
| "binary-filename" `inRawOpts` rawopts_ (cliopts_ opts) = putStrLn (binaryfilename progname)
| otherwise = withJournalDo (cliopts_ opts) (web opts)

-- | The web command.
web :: WebOpts -> Journal -> IO ()
web opts j = do
Expand Down
7 changes: 4 additions & 3 deletions hledger-web/Hledger/Web/Widget/Common.hs
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,14 @@ fromFormSuccess h FormMissing = h
fromFormSuccess h (FormFailure _) = h
fromFormSuccess _ (FormSuccess a) = pure a

writeValidJournal :: MonadHandler m => FilePath -> Text -> m (Either String ())
writeValidJournal :: MonadHandler m => FilePath -> Text -> m (Either String Journal)
writeValidJournal "-" txt = liftIO (readJournal def Nothing txt)
writeValidJournal f txt =
liftIO (readJournal def (Just f) txt) >>= \case
Left e -> return (Left e)
Right _ -> do
Right j -> do
_ <- liftIO (writeFileWithBackupIfChanged f txt)
return (Right ())
return (Right j)


-- | Link to a topic in the manual.
Expand Down
1 change: 1 addition & 0 deletions hledger/Hledger/Cli/Utils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ journalFileIsNewer j@Journal{jlastreadtime=tread} = do
-- | Has the specified file (presumably one of journal's data files)
-- changed since journal was last read ?
journalSpecifiedFileIsNewer :: Journal -> FilePath -> IO Bool
journalSpecifiedFileIsNewer _ "-" = return False
journalSpecifiedFileIsNewer Journal{jlastreadtime=tread} f = do
tmod <- fileModificationTime f
return $ diffClockTimes tmod tread > (TimeDiff 0 0 0 0 0 0 0)
Expand Down