hledger-web 1.14.1 → 1.15
raw patch · 17 files changed
+472/−297 lines, 17 filesdep ~hledgerdep ~hledger-libPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: hledger, hledger-lib
API changes (from Hackage documentation)
- Hledger.Web.Import: packPTH :: String -> Text
- Hledger.Web.Import: sqlOnlySettings :: MkPersistSettings
- Hledger.Web.Json: instance Data.Aeson.Types.FromJSON.FromJSON Hledger.Data.Types.Price
- Hledger.Web.Json: instance Data.Aeson.Types.ToJSON.ToJSON Hledger.Data.Types.Price
+ Hledger.Web.Foundation: checkServerSideUiEnabled :: Handler ()
+ Hledger.Web.Handler.RegisterR: decorateLinks :: [(acct, ([char], [char]))] -> [(Maybe acct, char)]
+ Hledger.Web.Handler.RegisterR: elideRightDecorated :: Int -> [(Maybe d, Char)] -> [(Maybe d, Char)]
+ Hledger.Web.Handler.RegisterR: otherTransactionAccounts :: Query -> Query -> Transaction -> [Posting]
+ Hledger.Web.Handler.RegisterR: preferReal :: [Posting] -> [Posting]
+ Hledger.Web.Handler.RegisterR: undecorateLinks :: [(Maybe acct, char)] -> [(acct, ([char], [char]))]
+ Hledger.Web.Import: PersistArray :: [PersistValue] -> PersistValue
+ Hledger.Web.Import: [FilterValue] :: forall typ. () => typ -> FilterValue typ
+ Hledger.Web.Import: [FilterValues] :: forall typ. () => [typ] -> FilterValue typ
+ Hledger.Web.Import: [UnsafeValue] :: forall typ a. PersistField a => a -> FilterValue typ
+ Hledger.Web.Import: [entityComments] :: EntityDef -> !Maybe Text
+ Hledger.Web.Import: [fieldComments] :: FieldDef -> !Maybe Text
+ Hledger.Web.Import: checkServerSideUiEnabled :: Handler ()
+ Hledger.Web.Import: class PersistEntity record => AtLeastOneUniqueKey record
+ Hledger.Web.Import: class PersistEntity record => OnlyOneUniqueKey record
+ Hledger.Web.Import: data FilterValue typ
+ Hledger.Web.Import: embedEntityDefs :: [EntityDef] -> [EntityDef]
+ Hledger.Web.Import: jsAttributesHandler :: Yesod site => HandlerFor site [(Text, Text)]
+ Hledger.Web.Import: mkEntityDefList :: String -> [EntityDef] -> Q [Dec]
+ Hledger.Web.Import: mreqMsg :: (RenderMessage site msg, HandlerSite m ~ site, MonadHandler m) => Field m a -> FieldSettings site -> msg -> Maybe a -> MForm m (FormResult a, FieldView site)
+ Hledger.Web.Import: onlyUniqueP :: OnlyOneUniqueKey record => record -> Unique record
+ Hledger.Web.Import: requireUniquesP :: AtLeastOneUniqueKey record => record -> NonEmpty (Unique record)
+ Hledger.Web.Import: type MultipleUniqueKeysError ty = Text "The entity " :<>: ShowType ty :<>: Text " has multiple unique keys." :$$: Text "The function you are trying to call requires only a single " :<>: Text "unique key." :$$: Text "There is probably a variant of the function with 'By' " :<>: Text "appended that will allow you to select a unique key " :<>: Text "for the operation."
+ Hledger.Web.Import: type NoUniqueKeysError ty = Text "The entity " :<>: ShowType ty :<>: Text " does not have any unique keys." :$$: Text "The function you are trying to call requires a unique key " :<>: Text "to be defined on the entity."
+ Hledger.Web.Json: instance Data.Aeson.Types.FromJSON.FromJSON Hledger.Data.Types.AmountPrice
+ Hledger.Web.Json: instance Data.Aeson.Types.ToJSON.ToJSON Hledger.Data.Types.AmountPrice
+ Hledger.Web.WebOptions: [serve_api_] :: WebOpts -> Bool
- Hledger.Web.Import: EntityDef :: !HaskellName -> !DBName -> !FieldDef -> ![Attr] -> ![FieldDef] -> ![UniqueDef] -> ![ForeignDef] -> ![Text] -> !Map Text [ExtraLine] -> !Bool -> EntityDef
+ Hledger.Web.Import: EntityDef :: !HaskellName -> !DBName -> !FieldDef -> ![Attr] -> ![FieldDef] -> ![UniqueDef] -> ![ForeignDef] -> ![Text] -> !Map Text [ExtraLine] -> !Bool -> !Maybe Text -> EntityDef
- Hledger.Web.Import: FieldDef :: !HaskellName -> !DBName -> !FieldType -> !SqlType -> ![Attr] -> !Bool -> !ReferenceDef -> FieldDef
+ Hledger.Web.Import: FieldDef :: !HaskellName -> !DBName -> !FieldType -> !SqlType -> ![Attr] -> !Bool -> !ReferenceDef -> !Maybe Text -> FieldDef
- Hledger.Web.Import: [Filter] :: forall record typ. PersistField typ => {filterField :: EntityField record typ, filterValue :: Either typ [typ], filterFilter :: PersistFilter} -> Filter record
+ Hledger.Web.Import: [Filter] :: forall record typ. PersistField typ => {filterField :: EntityField record typ, filterValue :: FilterValue typ, filterFilter :: PersistFilter} -> Filter record
- Hledger.Web.Import: entityIdFromJSON :: (PersistEntity record, FromJSON record, FromJSON (Key record)) => Value -> Parser (Entity record)
+ Hledger.Web.Import: entityIdFromJSON :: (PersistEntity record, FromJSON record) => Value -> Parser (Entity record)
- Hledger.Web.Import: entityIdToJSON :: (PersistEntity record, ToJSON record, ToJSON (Key record)) => Entity record -> Value
+ Hledger.Web.Import: entityIdToJSON :: (PersistEntity record, ToJSON record) => Entity record -> Value
- Hledger.Web.Import: getByValue :: (MonadIO m, PersistUniqueRead backend, PersistRecordBackend record backend) => record -> ReaderT backend m (Maybe (Entity record))
+ Hledger.Web.Import: getByValue :: (MonadIO m, PersistUniqueRead backend, PersistRecordBackend record backend, AtLeastOneUniqueKey record) => record -> ReaderT backend m (Maybe (Entity record))
- Hledger.Web.Import: getJust :: (PersistStoreRead backend, Show (Key record), PersistRecordBackend record backend, MonadIO m) => Key record -> ReaderT backend m record
+ Hledger.Web.Import: getJust :: (PersistStoreRead backend, PersistRecordBackend record backend, MonadIO m) => Key record -> ReaderT backend m record
- Hledger.Web.Import: insertBy :: (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend) => record -> ReaderT backend m (Either (Entity record) (Key record))
+ Hledger.Web.Import: insertBy :: (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend, AtLeastOneUniqueKey record) => record -> ReaderT backend m (Either (Entity record) (Key record))
- Hledger.Web.Import: keyValueEntityFromJSON :: (PersistEntity record, FromJSON record, FromJSON (Key record)) => Value -> Parser (Entity record)
+ Hledger.Web.Import: keyValueEntityFromJSON :: (PersistEntity record, FromJSON record) => Value -> Parser (Entity record)
- Hledger.Web.Import: keyValueEntityToJSON :: (PersistEntity record, ToJSON record, ToJSON (Key record)) => Entity record -> Value
+ Hledger.Web.Import: keyValueEntityToJSON :: (PersistEntity record, ToJSON record) => Entity record -> Value
- Hledger.Web.Import: liftPersist :: (MonadIO m, MonadReader backend m, HasPersistBackend backend) => ReaderT (BaseBackend backend) IO b -> m b
+ Hledger.Web.Import: liftPersist :: (MonadIO m, MonadReader backend m) => ReaderT backend IO b -> m b
- Hledger.Web.Import: onlyUnique :: (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend) => record -> ReaderT backend m (Unique record)
+ Hledger.Web.Import: onlyUnique :: (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend, OnlyOneUniqueKey record) => record -> ReaderT backend m (Unique record)
- Hledger.Web.Import: replaceUnique :: (MonadIO m, Eq record, Eq (Unique record), PersistRecordBackend record backend, PersistUniqueWrite backend) => Key record -> record -> ReaderT backend m (Maybe (Unique record))
+ Hledger.Web.Import: replaceUnique :: (MonadIO m, Eq (Unique record), PersistRecordBackend record backend, PersistUniqueWrite backend) => Key record -> record -> ReaderT backend m (Maybe (Unique record))
- Hledger.Web.Import: selectKeys :: (PersistQueryRead (BaseBackend backend), MonadResource m, PersistEntity record, BaseBackend (BaseBackend backend) ~ PersistEntityBackend record, MonadReader backend m, HasPersistBackend backend) => [Filter record] -> [SelectOpt record] -> ConduitM () (Key record) m ()
+ Hledger.Web.Import: selectKeys :: (PersistQueryRead backend, MonadResource m, PersistRecordBackend record backend, MonadReader backend m) => [Filter record] -> [SelectOpt record] -> ConduitM () (Key record) m ()
- Hledger.Web.Import: selectSource :: (PersistQueryRead (BaseBackend backend), MonadResource m, PersistEntity record, PersistEntityBackend record ~ BaseBackend (BaseBackend backend), MonadReader backend m, HasPersistBackend backend) => [Filter record] -> [SelectOpt record] -> ConduitM () (Entity record) m ()
+ Hledger.Web.Import: selectSource :: (PersistQueryRead backend, MonadResource m, PersistRecordBackend record backend, MonadReader backend m) => [Filter record] -> [SelectOpt record] -> ConduitM () (Entity record) m ()
- Hledger.Web.Import: upsert :: (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> [Update record] -> ReaderT backend m (Entity record)
+ Hledger.Web.Import: upsert :: (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend, OnlyOneUniqueKey record) => record -> [Update record] -> ReaderT backend m (Entity record)
- Hledger.Web.WebOptions: WebOpts :: Bool -> String -> Int -> String -> Maybe String -> [Capability] -> Maybe (CI ByteString) -> CliOpts -> WebOpts
+ Hledger.Web.WebOptions: WebOpts :: Bool -> Bool -> String -> Int -> String -> Maybe String -> [Capability] -> Maybe (CI ByteString) -> CliOpts -> WebOpts
Files
- CHANGES.md +17/−0
- Hledger/Web/Application.hs +3/−3
- Hledger/Web/Foundation.hs +26/−3
- Hledger/Web/Handler/AddR.hs +6/−3
- Hledger/Web/Handler/EditR.hs +4/−1
- Hledger/Web/Handler/JournalR.hs +2/−1
- Hledger/Web/Handler/MiscR.hs +11/−7
- Hledger/Web/Handler/RegisterR.hs +55/−2
- Hledger/Web/Handler/UploadR.hs +4/−1
- Hledger/Web/Json.hs +9/−9
- Hledger/Web/Main.hs +6/−4
- Hledger/Web/WebOptions.hs +8/−1
- hledger-web.1 +165/−187
- hledger-web.cabal +8/−8
- hledger-web.info +56/−16
- hledger-web.txt +88/−49
- templates/register.hamlet +4/−2
CHANGES.md view
@@ -1,6 +1,23 @@ User-visible changes in hledger-web. See also the hledger changelog. +# 1.15 2019-09-01++- web: ?sidebar= hides the sidebar, like ?sidebar=0++- web: --serve-api disables server-side UI++- register page: clip linked accounts to 40 characters (Henning Thielemann)+ This was the behaviour before adding the links.++- avoid spaces before commas in register account links (Henning Thielemann)++- add links to accounts in register transactions (Henning Thielemann)++- fix "_create_locale could not be located" error on windows 7 (#1039)++- use hledger 1.15+ # 1.14.1 2019-03-20 - /accounts JSON: return all accounts, not just top-level ones (#985)
Hledger/Web/Application.hs view
@@ -17,13 +17,13 @@ import Hledger.Data (Journal, nulljournal) import Hledger.Web.Handler.AddR-import Hledger.Web.Handler.MiscR +import Hledger.Web.Handler.MiscR import Hledger.Web.Handler.EditR import Hledger.Web.Handler.UploadR import Hledger.Web.Handler.JournalR import Hledger.Web.Handler.RegisterR import Hledger.Web.Import-import Hledger.Web.WebOptions (WebOpts(serve_))+import Hledger.Web.WebOptions (WebOpts(serve_,serve_api_)) -- This line actually creates our YesodDispatch instance. It is the second half -- of the call to mkYesodData which occurs in Foundation.hs. Please see the@@ -41,7 +41,7 @@ logWare <$> toWaiApp foundation where logWare | development = logStdoutDev- | serve_ opts' = logStdout+ | serve_ opts' || serve_api_ opts' = logStdout | otherwise = id makeFoundation :: AppConfig DefaultEnv Extra -> WebOpts -> IO App
Hledger/Web/Foundation.hs view
@@ -16,7 +16,7 @@ module Hledger.Web.Foundation where -import Control.Monad (join)+import Control.Monad (join, when) import qualified Data.ByteString.Char8 as BC import Data.Traversable (for) import Data.IORef (IORef, readIORef, writeIORef)@@ -26,6 +26,7 @@ import qualified Data.Text as T import Data.Time.Calendar (Day) import Network.HTTP.Conduit (Manager)+import Network.HTTP.Types (status403) import Network.Wai (requestHeaders) import System.FilePath (takeFileName) import Text.Blaze (Markup)@@ -96,9 +97,18 @@ instance Yesod App where approot = ApprootMaster $ appRoot . settings - makeSessionBackend _ = Just <$> defaultClientSessionBackend 120 ".hledger-web_client_session_key.aes"+ makeSessionBackend _ =+ let sessionexpirysecs = 120+ in Just <$> defaultClientSessionBackend sessionexpirysecs ".hledger-web_client_session_key.aes" + -- defaultLayout :: WidgetFor site () -> HandlerFor site Html defaultLayout widget = do++ -- Don't run if server-side UI is disabled.+ -- This single check probably covers all the HTML-returning handlers,+ -- but for now they do the check as well.+ checkServerSideUiEnabled+ master <- getYesod here <- fromMaybe RootR <$> getCurrentRoute VD {caps, j, m, opts, q, qopts} <- getViewData@@ -204,13 +214,26 @@ Right c -> pure [c] return VD {opts, today, j, q, m, qopts, caps} +checkServerSideUiEnabled :: Handler ()+checkServerSideUiEnabled = do+ VD{opts=WebOpts{serve_api_}} <- getViewData+ when serve_api_ $+ -- this one gives 500 internal server error when called from defaultLayout:+ -- permissionDenied "server-side UI is disabled due to --serve-api"+ sendResponseStatus status403 ("server-side UI is disabled due to --serve-api" :: Text)+ -- | Find out if the sidebar should be visible. Show it, unless there is a -- showsidebar cookie set to "0", or a ?sidebar=0 query parameter. shouldShowSidebar :: Handler Bool shouldShowSidebar = do msidebarparam <- lookupGetParam "sidebar" msidebarcookie <- lookup "showsidebar" . reqCookies <$> getRequest- return $ maybe (msidebarcookie /= Just "0") (/="0") msidebarparam+ return $+ let disablevalues = ["","0"]+ in maybe+ (not $ msidebarcookie `elem` map Just disablevalues)+ (not . (`elem` disablevalues))+ msidebarparam -- | Update our copy of the journal if the file changed. If there is an -- error while reloading, keep the old one and return the error, and set a
Hledger/Web/Handler/AddR.hs view
@@ -24,10 +24,13 @@ import Hledger.Web.Widget.AddForm (addForm) getAddR :: Handler ()-getAddR = postAddR+getAddR = do+ checkServerSideUiEnabled+ postAddR postAddR :: Handler () postAddR = do+ checkServerSideUiEnabled VD{caps, j, today} <- getViewData when (CapAdd `notElem` caps) (permissionDenied "Missing the 'add' capability") @@ -55,7 +58,7 @@ |] -- Add a single new transaction, send as JSON via PUT, to the journal.--- The web form handler above should probably use PUT as well. +-- The web form handler above should probably use PUT as well. putAddR :: Handler RepJson putAddR = do VD{caps, j, opts} <- getViewData@@ -66,4 +69,4 @@ Error err -> sendStatusJSON status400 ("could not parse json: " ++ err ::String) Success t -> do void $ liftIO $ journalAddTransaction j (cliopts_ opts) t- sendResponseCreated TransactionsR + sendResponseCreated TransactionsR
Hledger/Web/Handler/EditR.hs view
@@ -23,10 +23,13 @@ fs = FieldSettings "text" mzero mzero mzero [("class", "form-control"), ("rows", "25")] getEditR :: FilePath -> Handler ()-getEditR = postEditR+getEditR f = do+ checkServerSideUiEnabled+ postEditR f postEditR :: FilePath -> Handler () postEditR f = do+ checkServerSideUiEnabled VD {caps, j} <- getViewData when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability")
Hledger/Web/Handler/JournalR.hs view
@@ -17,6 +17,7 @@ -- | The formatted journal view, with sidebar. getJournalR :: Handler Html getJournalR = do+ checkServerSideUiEnabled VD{caps, j, m, opts, qopts, today} <- getViewData when (CapView `notElem` caps) (permissionDenied "Missing the 'view' capability") let title = case inAccount qopts of@@ -24,7 +25,7 @@ Just (a, inclsubs) -> "Transactions in " <> a <> if inclsubs then "" else " (excluding subaccounts)" title' = title <> if m /= Any then ", filtered" else "" acctlink a = (RegisterR, [("q", accountQuery a)])- (_, items) = journalTransactionsReport (reportopts_ $ cliopts_ opts) j m+ (_, items) = transactionsReport (reportopts_ $ cliopts_ opts) j m defaultLayout $ do setTitle "journal - hledger-web"
Hledger/Web/Handler/MiscR.hs view
@@ -7,11 +7,11 @@ {-# LANGUAGE TemplateHaskell #-} module Hledger.Web.Handler.MiscR- ( getAccountnamesR - , getTransactionsR - , getPricesR - , getCommoditiesR - , getAccountsR + ( getAccountnamesR+ , getTransactionsR+ , getPricesR+ , getCommoditiesR+ , getAccountsR , getAccounttransactionsR , getDownloadR , getFaviconR@@ -30,10 +30,13 @@ import Hledger.Web.Widget.Common (journalFile404) getRootR :: Handler Html-getRootR = redirect JournalR+getRootR = do+ checkServerSideUiEnabled+ redirect JournalR getManageR :: Handler Html getManageR = do+ checkServerSideUiEnabled VD{caps, j} <- getViewData when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability") defaultLayout $ do@@ -42,6 +45,7 @@ getDownloadR :: FilePath -> Handler TypedContent getDownloadR f = do+ checkServerSideUiEnabled VD{caps, j} <- getViewData when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability") (f', txt) <- journalFile404 f j@@ -69,7 +73,7 @@ VD{caps, j} <- getViewData when (CapView `notElem` caps) (permissionDenied "Missing the 'view' capability") selectRep $ do- provideJson $ jmarketprices j+ provideJson $ map priceDirectiveToMarketPrice $ jpricedirectives j getCommoditiesR :: Handler TypedContent getCommoditiesR = do
Hledger/Web/Handler/RegisterR.hs view
@@ -8,7 +8,7 @@ module Hledger.Web.Handler.RegisterR where -import Data.List (intersperse)+import Data.List (intersperse, nub, partition) import qualified Data.Text as T import Text.Hamlet (hamletFile) @@ -17,11 +17,12 @@ import Hledger.Web.Import import Hledger.Web.WebOptions import Hledger.Web.Widget.AddForm (addModal)-import Hledger.Web.Widget.Common (mixedAmountAsHtml)+import Hledger.Web.Widget.Common (accountQuery, mixedAmountAsHtml) -- | The main journal/account register view, with accounts sidebar. getRegisterR :: Handler Html getRegisterR = do+ checkServerSideUiEnabled VD{caps, j, m, opts, qopts, today} <- getViewData when (CapView `notElem` caps) (permissionDenied "Missing the 'view' capability") @@ -32,11 +33,63 @@ let ropts = reportopts_ (cliopts_ opts) acctQuery = fromMaybe Any (inAccountQuery qopts)+ acctlink acc = (RegisterR, [("q", accountQuery acc)])+ otherTransAccounts =+ map (\(acct,(name,comma)) -> (acct, (T.pack name, T.pack comma))) .+ undecorateLinks . elideRightDecorated 40 . decorateLinks .+ addCommas . preferReal . otherTransactionAccounts m acctQuery+ addCommas xs =+ zip xs $+ zip (map (T.unpack . accountSummarisedName . paccount) xs) $+ tail $ (", "<$xs) ++ [""] r@(balancelabel,items) = accountTransactionsReport ropts j m acctQuery balancelabel' = if isJust (inAccount qopts) then balancelabel else "Total" defaultLayout $ do setTitle "register - hledger-web" $(widgetFile "register")++-- cf. Hledger.Reports.AccountTransactionsReport.accountTransactionsReportItems+otherTransactionAccounts :: Query -> Query -> Transaction -> [Posting]+otherTransactionAccounts reportq thisacctq torig+ -- no current account ? summarise all matched postings+ | thisacctq == None = reportps+ -- only postings to current account ? summarise those+ | null otheraccts = thisacctps+ -- summarise matched postings to other account(s)+ | otherwise = otheracctps+ where+ reportps = tpostings $ filterTransactionPostings reportq torig+ (thisacctps, otheracctps) = partition (matchesPosting thisacctq) reportps+ otheraccts = nub $ map paccount otheracctps++-- cf. Hledger.Reports.AccountTransactionsReport.summarisePostingAccounts+preferReal :: [Posting] -> [Posting]+preferReal ps+ | null realps = ps+ | otherwise = realps+ where realps = filter isReal ps++elideRightDecorated :: Int -> [(Maybe d, Char)] -> [(Maybe d, Char)]+elideRightDecorated width s =+ if length s > width+ then take (width - 2) s ++ map ((,) Nothing) ".."+ else s++undecorateLinks :: [(Maybe acct, char)] -> [(acct, ([char], [char]))]+undecorateLinks [] = []+undecorateLinks xs0@(x:_) =+ case x of+ (Just acct, _) ->+ let (link, xs1) = span (isJust . fst) xs0+ (comma, xs2) = span (isNothing . fst) xs1+ in (acct, (map snd link, map snd comma)) : undecorateLinks xs2+ _ -> error "link name not decorated with account"++decorateLinks :: [(acct, ([char], [char]))] -> [(Maybe acct, char)]+decorateLinks =+ concatMap+ (\(acct, (name, comma)) ->+ map ((,) (Just acct)) name ++ map ((,) Nothing) comma) -- | Generate javascript/html for a register balance line chart based on -- the provided "TransactionsReportItem"s.
Hledger/Web/Handler/UploadR.hs view
@@ -27,10 +27,13 @@ fs = FieldSettings "file" Nothing (Just "file") (Just "file") [] getUploadR :: FilePath -> Handler ()-getUploadR = postUploadR+getUploadR f = do+ checkServerSideUiEnabled+ postUploadR f postUploadR :: FilePath -> Handler () postUploadR f = do+ checkServerSideUiEnabled VD {caps, j} <- getViewData when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability")
Hledger/Web/Json.hs view
@@ -21,7 +21,7 @@ --{-# LANGUAGE TypeFamilies #-} --{-# LANGUAGE TypeOperators #-} -module Hledger.Web.Json ( +module Hledger.Web.Json ( -- * Instances -- * Utilities readJsonFile@@ -51,7 +51,7 @@ instance ToJSON DigitGroupStyle instance ToJSON MixedAmount instance ToJSON BalanceAssertion-instance ToJSON Price+instance ToJSON AmountPrice instance ToJSON MarketPrice instance ToJSON PostingType @@ -66,11 +66,11 @@ ,"ptype" .= toJSON ptype ,"ptags" .= toJSON ptags ,"pbalanceassertion" .= toJSON pbalanceassertion- -- To avoid a cycle, show just the parent transaction's index number + -- To avoid a cycle, show just the parent transaction's index number -- in a dummy field. When re-parsed, there will be no parent. ,"ptransaction_" .= toJSON (maybe "" (show.tindex) ptransaction) -- This is probably not wanted in json, we discard it.- ,"poriginal" .= toJSON (Nothing :: Maybe Posting) + ,"poriginal" .= toJSON (Nothing :: Maybe Posting) ] instance ToJSON Transaction@@ -82,7 +82,7 @@ ,"aibalance" .= toJSON (aibalance a) ,"anumpostings" .= toJSON (anumpostings a) ,"aboring" .= toJSON (aboring a)- -- To avoid a cycle, show just the parent account's name + -- To avoid a cycle, show just the parent account's name -- in a dummy field. When re-parsed, there will be no parent. ,"aparent_" .= toJSON (maybe "" aname $ aparent a) -- Just the names of subaccounts, as a dummy field, ignored when parsed.@@ -103,21 +103,21 @@ instance FromJSON DigitGroupStyle instance FromJSON MixedAmount instance FromJSON BalanceAssertion-instance FromJSON Price+instance FromJSON AmountPrice instance FromJSON MarketPrice instance FromJSON PostingType instance FromJSON Posting instance FromJSON Transaction instance FromJSON AccountDeclarationInfo -- XXX The ToJSON instance replaces subaccounts with just names.--- Here we should try to make use of those to reconstruct the +-- Here we should try to make use of those to reconstruct the -- parent-child relationships. instance FromJSON Account -- Decimal, various attempts -- -- https://stackoverflow.com/questions/40331851/haskell-data-decimal-as-aeson-type-----instance FromJSON Decimal where parseJSON = +----instance FromJSON Decimal where parseJSON = ---- A.withScientific "Decimal" (return . right . eitherFromRational . toRational) -- -- https://github.com/bos/aeson/issues/474@@ -156,7 +156,7 @@ readJsonFile :: FromJSON a => FilePath -> IO a readJsonFile f = do bs <- BL.readFile f- let v = fromMaybe (error "could not decode bytestring as json value") (decode bs :: Maybe Value) + let v = fromMaybe (error "could not decode bytestring as json value") (decode bs :: Maybe Value) case fromJSON v :: FromJSON a => Result a of Error e -> error e Success t -> return t
Hledger/Web/Main.hs view
@@ -69,16 +69,18 @@ } app <- makeApplication opts j' appconfig -- XXX would like to allow a host name not just an IP address here- _ <- printf "Starting web app on IP address %s port %d with base url %s\n" h p u- if serve_ opts+ _ <- printf "Serving web %s on %s:%d with base url %s\n"+ (if serve_api_ opts then "API" else "UI and API" :: String) h p u+ if serve_ opts || serve_api_ opts then do putStrLn "Press ctrl-c to quit" hFlush stdout let warpsettings = setHost (fromString h) (setPort p defaultSettings) Network.Wai.Handler.Warp.runSettings warpsettings app else do- putStrLn "Starting web browser..."- putStrLn "Web app will auto-exit after a few minutes with no browsers (or press ctrl-c)"+ putStrLn "This server will exit after 2m with no browser windows open (or press ctrl-c)"+ putStrLn "Opening web browser..." hFlush stdout+ -- exits after 2m of inactivity (hardcoded) Network.Wai.Handler.Launch.runHostPortUrl h p "" app
Hledger/Web/WebOptions.hs view
@@ -31,6 +31,10 @@ ["serve", "server"] (setboolopt "serve") "serve and log requests, don't browse or auto-exit"+ , flagNone+ ["serve-api"]+ (setboolopt "serve-api")+ "like --serve, but serve only the JSON web API, without the server-side web UI" , flagReq ["host"] (\s opts -> Right $ setopt "host" s opts)@@ -75,6 +79,7 @@ Group { groupUnnamed = webflags , groupHidden =+ hiddenflags ++ [ flagNone ["binary-filename"] (setboolopt "binary-filename")@@ -88,6 +93,7 @@ -- hledger-web options, used in hledger-web and above data WebOpts = WebOpts { serve_ :: Bool+ , serve_api_ :: Bool , host_ :: String , port_ :: Int , base_url_ :: String@@ -98,7 +104,7 @@ } deriving (Show) defwebopts :: WebOpts-defwebopts = WebOpts def def def def def [CapView, CapAdd] Nothing def+defwebopts = WebOpts def def def def def def [CapView, CapAdd] Nothing def instance Default WebOpts where def = defwebopts @@ -119,6 +125,7 @@ return defwebopts { serve_ = boolopt "serve" rawopts+ , serve_api_ = boolopt "serve-api" rawopts , host_ = h , port_ = p , base_url_ = b
hledger-web.1 view
@@ -1,34 +1,34 @@ -.TH "hledger\-web" "1" "March 2019" "hledger\-web 1.14" "hledger User Manuals"+.TH "hledger-web" "1" "August 2019" "hledger-web 1.15" "hledger User Manuals" .SH NAME .PP-hledger\-web \- web interface for the hledger accounting tool+hledger-web - web interface for the hledger accounting tool .SH SYNOPSIS .PP-\f[C]hledger\-web\ [OPTIONS]\f[]+\f[C]hledger-web [OPTIONS]\f[R] .PD 0 .P .PD-\f[C]hledger\ web\ \-\-\ [OPTIONS]\f[]+\f[C]hledger web -- [OPTIONS]\f[R] .SH DESCRIPTION .PP-hledger is a cross\-platform program for tracking money, time, or any-other commodity, using double\-entry accounting and a simple, editable+hledger is a cross-platform program for tracking money, time, or any+other commodity, using double-entry accounting and a simple, editable file format. hledger is inspired by and largely compatible with ledger(1). .PP-hledger\-web is hledger\[aq]s web interface.+hledger-web is hledger\[aq]s web interface. It starts a simple web application for browsing and adding transactions, and optionally opens it in a web browser window if possible.-It provides a more user\-friendly UI than the hledger CLI or hledger\-ui+It provides a more user-friendly UI than the hledger CLI or hledger-ui interface, showing more at once (accounts, the current account register,-balance charts) and allowing history\-aware data entry, interactive+balance charts) and allowing history-aware data entry, interactive searching, and bookmarking. .PP-hledger\-web also lets you share a ledger with multiple users, or even+hledger-web also lets you share a ledger with multiple users, or even the public web. There is no access control, so if you need that you should put it behind a suitable web proxy.@@ -37,201 +37,139 @@ on every edit. .PP Like hledger, it reads data from one or more files in hledger journal,-timeclock, timedot, or CSV format specified with \f[C]\-f\f[], or-\f[C]$LEDGER_FILE\f[], or \f[C]$HOME/.hledger.journal\f[] (on windows,-perhaps \f[C]C:/Users/USER/.hledger.journal\f[]).+timeclock, timedot, or CSV format specified with \f[C]-f\f[R], or+\f[C]$LEDGER_FILE\f[R], or \f[C]$HOME/.hledger.journal\f[R] (on windows,+perhaps \f[C]C:/Users/USER/.hledger.journal\f[R]). For more about this see hledger(1), hledger_journal(5) etc. .SH OPTIONS .PP-Command\-line options and arguments may be used to set an initial filter+Command-line options and arguments may be used to set an initial filter on the data. These filter options are not shown in the web UI, but it will be applied in addition to any search query entered there. .PP-Note: if invoking hledger\-web as a hledger subcommand, write-\f[C]\-\-\f[] before options, as shown in the synopsis above.+Note: if invoking hledger-web as a hledger subcommand, write+\f[C]--\f[R] before options, as shown in the synopsis above. .TP-.B \f[C]\-\-serve\f[]-serve and log requests, don\[aq]t browse or auto\-exit-.RS-.RE+.B \f[C]--serve\f[R]+serve and log requests, don\[aq]t browse or auto-exit .TP-.B \f[C]\-\-host=IPADDR\f[]+.B \f[C]--serve-api\f[R]+like --serve, but serve only the JSON web API, without the server-side+web UI+.TP+.B \f[C]--host=IPADDR\f[R] listen on this IP address (default: 127.0.0.1)-.RS-.RE .TP-.B \f[C]\-\-port=PORT\f[]+.B \f[C]--port=PORT\f[R] listen on this TCP port (default: 5000)-.RS-.RE .TP-.B \f[C]\-\-base\-url=URL\f[]+.B \f[C]--base-url=URL\f[R] set the base url (default: http://IPADDR:PORT). You would change this when sharing over the network, or integrating within a larger website.-.RS-.RE .TP-.B \f[C]\-\-file\-url=URL\f[]+.B \f[C]--file-url=URL\f[R] set the static files url (default: BASEURL/static).-hledger\-web normally serves static files itself, but if you wanted to+hledger-web normally serves static files itself, but if you wanted to serve them from another server for efficiency, you would set the url with this.-.RS-.RE .TP-.B \f[C]\-\-capabilities=CAP[,CAP..]\f[]+.B \f[C]--capabilities=CAP[,CAP..]\f[R] enable the view, add, and/or manage capabilities (default: view,add)-.RS-.RE .TP-.B \f[C]\-\-capabilities\-header=HTTPHEADER\f[]+.B \f[C]--capabilities-header=HTTPHEADER\f[R] read capabilities to enable from a HTTP header, like-X\-Sandstorm\-Permissions (default: disabled)-.RS-.RE+X-Sandstorm-Permissions (default: disabled) .PP hledger input options: .TP-.B \f[C]\-f\ FILE\ \-\-file=FILE\f[]+.B \f[C]-f FILE --file=FILE\f[R] use a different input file.-For stdin, use \- (default: \f[C]$LEDGER_FILE\f[] or-\f[C]$HOME/.hledger.journal\f[])-.RS-.RE+For stdin, use - (default: \f[C]$LEDGER_FILE\f[R] or+\f[C]$HOME/.hledger.journal\f[R]) .TP-.B \f[C]\-\-rules\-file=RULESFILE\f[]+.B \f[C]--rules-file=RULESFILE\f[R] Conversion rules file to use when reading CSV (default: FILE.rules)-.RS-.RE .TP-.B \f[C]\-\-separator=CHAR\f[]+.B \f[C]--separator=CHAR\f[R] Field separator to expect when reading CSV (default: \[aq],\[aq])-.RS-.RE .TP-.B \f[C]\-\-alias=OLD=NEW\f[]+.B \f[C]--alias=OLD=NEW\f[R] rename accounts named OLD to NEW-.RS-.RE .TP-.B \f[C]\-\-anon\f[]+.B \f[C]--anon\f[R] anonymize accounts and payees-.RS-.RE .TP-.B \f[C]\-\-pivot\ FIELDNAME\f[]+.B \f[C]--pivot FIELDNAME\f[R] use some other field or tag for the account name-.RS-.RE .TP-.B \f[C]\-I\ \-\-ignore\-assertions\f[]+.B \f[C]-I --ignore-assertions\f[R] ignore any failing balance assertions-.RS-.RE .PP hledger reporting options: .TP-.B \f[C]\-b\ \-\-begin=DATE\f[]+.B \f[C]-b --begin=DATE\f[R] include postings/txns on or after this date-.RS-.RE .TP-.B \f[C]\-e\ \-\-end=DATE\f[]+.B \f[C]-e --end=DATE\f[R] include postings/txns before this date-.RS-.RE .TP-.B \f[C]\-D\ \-\-daily\f[]+.B \f[C]-D --daily\f[R] multiperiod/multicolumn report by day-.RS-.RE .TP-.B \f[C]\-W\ \-\-weekly\f[]+.B \f[C]-W --weekly\f[R] multiperiod/multicolumn report by week-.RS-.RE .TP-.B \f[C]\-M\ \-\-monthly\f[]+.B \f[C]-M --monthly\f[R] multiperiod/multicolumn report by month-.RS-.RE .TP-.B \f[C]\-Q\ \-\-quarterly\f[]+.B \f[C]-Q --quarterly\f[R] multiperiod/multicolumn report by quarter-.RS-.RE .TP-.B \f[C]\-Y\ \-\-yearly\f[]+.B \f[C]-Y --yearly\f[R] multiperiod/multicolumn report by year-.RS-.RE .TP-.B \f[C]\-p\ \-\-period=PERIODEXP\f[]+.B \f[C]-p --period=PERIODEXP\f[R] set start date, end date, and/or reporting interval all at once using-period expressions syntax (overrides the flags above)-.RS-.RE+period expressions syntax .TP-.B \f[C]\-\-date2\f[]+.B \f[C]--date2\f[R] match the secondary date instead (see command help for other effects)-.RS-.RE .TP-.B \f[C]\-U\ \-\-unmarked\f[]-include only unmarked postings/txns (can combine with \-P or \-C)-.RS-.RE+.B \f[C]-U --unmarked\f[R]+include only unmarked postings/txns (can combine with -P or -C) .TP-.B \f[C]\-P\ \-\-pending\f[]+.B \f[C]-P --pending\f[R] include only pending postings/txns-.RS-.RE .TP-.B \f[C]\-C\ \-\-cleared\f[]+.B \f[C]-C --cleared\f[R] include only cleared postings/txns-.RS-.RE .TP-.B \f[C]\-R\ \-\-real\f[]-include only non\-virtual postings-.RS-.RE+.B \f[C]-R --real\f[R]+include only non-virtual postings .TP-.B \f[C]\-NUM\ \-\-depth=NUM\f[]+.B \f[C]-NUM --depth=NUM\f[R] hide/aggregate accounts or postings more than NUM levels deep-.RS-.RE .TP-.B \f[C]\-E\ \-\-empty\f[]-show items with zero amount, normally hidden (and vice\-versa in-hledger\-ui/hledger\-web)-.RS-.RE+.B \f[C]-E --empty\f[R]+show items with zero amount, normally hidden (and vice-versa in+hledger-ui/hledger-web) .TP-.B \f[C]\-B\ \-\-cost\f[]+.B \f[C]-B --cost\f[R] convert amounts to their cost at transaction time (using the transaction price, if any)-.RS-.RE .TP-.B \f[C]\-V\ \-\-value\f[]+.B \f[C]-V --value\f[R] convert amounts to their market value on the report end date (using the most recent applicable market price, if any)-.RS-.RE .TP-.B \f[C]\-\-auto\f[]+.B \f[C]--auto\f[R] apply automated posting rules to modify transactions.-.RS-.RE .TP-.B \f[C]\-\-forecast\f[]+.B \f[C]--forecast\f[R] apply periodic transaction rules to generate future transactions, to 6 months from now or report end date.-.RS-.RE .PP When a reporting option appears more than once in the command line, the last one takes precedence.@@ -240,59 +178,55 @@ .PP hledger help options: .TP-.B \f[C]\-h\ \-\-help\f[]+.B \f[C]-h --help\f[R] show general usage (or after COMMAND, command usage)-.RS-.RE .TP-.B \f[C]\-\-version\f[]+.B \f[C]--version\f[R] show version-.RS-.RE .TP-.B \f[C]\-\-debug[=N]\f[]-show debug output (levels 1\-9, default: 1)-.RS-.RE+.B \f[C]--debug[=N]\f[R]+show debug output (levels 1-9, default: 1) .PP-A \@FILE argument will be expanded to the contents of FILE, which should-contain one command line option/argument per line.-(To prevent this, insert a \f[C]\-\-\f[] argument before.)+A \[at]FILE argument will be expanded to the contents of FILE, which+should contain one command line option/argument per line.+(To prevent this, insert a \f[C]--\f[R] argument before.) .PP-By default, hledger\-web starts the web app in "transient mode" and also-opens it in your default web browser if possible.+By default, hledger-web starts the web app in \[dq]transient mode\[dq]+and also opens it in your default web browser if possible. In this mode the web app will keep running for as long as you have it open in a browser window, and will exit after two minutes of inactivity (no requests and no browser windows viewing it).-With \f[C]\-\-serve\f[], it just runs the web app without exiting, and+With \f[C]--serve\f[R], it just runs the web app without exiting, and logs requests to the console.+With \f[C]--serve-api\f[R], only the JSON web api (see below) is served,+with the usual HTML server-side web UI disabled. .PP By default the server listens on IP address 127.0.0.1, accessible only to local requests.-You can use \f[C]\-\-host\f[] to change this, eg-\f[C]\-\-host\ 0.0.0.0\f[] to listen on all configured addresses.+You can use \f[C]--host\f[R] to change this, eg \f[C]--host 0.0.0.0\f[R]+to listen on all configured addresses. .PP-Similarly, use \f[C]\-\-port\f[] to set a TCP port other than 5000, eg-if you are running multiple hledger\-web instances.+Similarly, use \f[C]--port\f[R] to set a TCP port other than 5000, eg if+you are running multiple hledger-web instances. .PP-You can use \f[C]\-\-base\-url\f[] to change the protocol, hostname,-port and path that appear in hyperlinks, useful eg for integrating-hledger\-web within a larger website.-The default is \f[C]http://HOST:PORT/\f[] using the server\[aq]s-configured host address and TCP port (or \f[C]http://HOST\f[] if PORT is-80).+You can use \f[C]--base-url\f[R] to change the protocol, hostname, port+and path that appear in hyperlinks, useful eg for integrating+hledger-web within a larger website.+The default is \f[C]http://HOST:PORT/\f[R] using the server\[aq]s+configured host address and TCP port (or \f[C]http://HOST\f[R] if PORT+is 80). .PP-With \f[C]\-\-file\-url\f[] you can set a different base url for static-files, eg for better caching or cookie\-less serving on high performance+With \f[C]--file-url\f[R] you can set a different base url for static+files, eg for better caching or cookie-less serving on high performance websites. .SH PERMISSIONS .PP-By default, hledger\-web allows anyone who can reach it to view the+By default, hledger-web allows anyone who can reach it to view the journal and to add new transactions, but not to change existing data. .PP You can restrict who can reach it by .IP \[bu] 2-setting the IP address it listens on (see \f[C]\-\-host\f[] above).+setting the IP address it listens on (see \f[C]--host\f[R] above). By default it listens on 127.0.0.1, accessible to all users on the local machine. .IP \[bu] 2@@ -302,56 +236,62 @@ .PP You can restrict what the users who reach it can do, by .IP \[bu] 2-using the \f[C]\-\-capabilities=CAP[,CAP..]\f[] flag when you start it,+using the \f[C]--capabilities=CAP[,CAP..]\f[R] flag when you start it, enabling one or more of the following capabilities.-The default value is \f[C]view,add\f[]:+The default value is \f[C]view,add\f[R]: .RS 2 .IP \[bu] 2-\f[C]view\f[] \- allows viewing the journal file and all included files+\f[C]view\f[R] - allows viewing the journal file and all included files .IP \[bu] 2-\f[C]add\f[] \- allows adding new transactions to the main journal file+\f[C]add\f[R] - allows adding new transactions to the main journal file .IP \[bu] 2-\f[C]manage\f[] \- allows editing, uploading or downloading the main or+\f[C]manage\f[R] - allows editing, uploading or downloading the main or included files .RE .IP \[bu] 2-using the \f[C]\-\-capabilities\-header=HTTPHEADER\f[] flag to specify a+using the \f[C]--capabilities-header=HTTPHEADER\f[R] flag to specify a HTTP header from which it will read capabilities to enable.-hledger\-web on Sandstorm uses the X\-Sandstorm\-Permissions header to+hledger-web on Sandstorm uses the X-Sandstorm-Permissions header to integrate with Sandstorm\[aq]s permissions. This is disabled by default. .SH EDITING, UPLOADING, DOWNLOADING .PP-If you enable the \f[C]manage\f[] capability mentioned above, you\[aq]ll-see a new "spanner" button to the right of the search form.+If you enable the \f[C]manage\f[R] capability mentioned above,+you\[aq]ll see a new \[dq]spanner\[dq] button to the right of the search+form. Clicking this will let you edit, upload, or download the journal file or any files it includes. .PP Note, unlike any other hledger command, in this mode you (or any visitor) can alter or wipe the data files. .PP-Normally whenever a file is changed in this way, hledger\-web saves a+Normally whenever a file is changed in this way, hledger-web saves a numbered backup (assuming file permissions allow it, the disk is not-full, etc.) hledger\-web is not aware of version control systems,+full, etc.) hledger-web is not aware of version control systems, currently; if you use one, you\[aq]ll have to arrange to commit the changes yourself (eg with a cron job or a file watcher like entr). .PP-Changes which would leave the journal file(s) unparseable or non\-valid+Changes which would leave the journal file(s) unparseable or non-valid (eg with failing balance assertions) are prevented. (Probably.-This needs re\-testing.)+This needs re-testing.) .SH RELOADING .PP-hledger\-web detects changes made to the files by other means (eg if you-edit it directly, outside of hledger\-web), and it will show the new-data when you reload the page or navigate to a new page.-If a change makes a file unparseable, hledger\-web will display an error+hledger-web detects changes made to the files by other means (eg if you+edit it directly, outside of hledger-web), and it will show the new data+when you reload the page or navigate to a new page.+If a change makes a file unparseable, hledger-web will display an error message until the file has been fixed.+.PP+(Note: if you are viewing files mounted from another machine, make sure+that both machine clocks are roughly in step.) .SH JSON API .PP-In addition to the web UI, hledger\-web provides some JSON API routes.-These are similar to the API provided by the hledger\-api tool, but it-may be convenient to have them in hledger\-web also.+In addition to the web UI, hledger-web provides some API routes that+serve JSON in response to GET requests.+Currently these are same ones provided by the hledger-api tool, but+hledger-web will likely receive more attention than hledger-api in+future: .IP .nf \f[C]@@ -361,31 +301,69 @@ /commodities /accounts /accounttransactions/#AccountName-\f[]+\f[R] .fi+.PP+Also, you can append a new transaction to the journal by sending a PUT+request to \f[C]/add\f[R] (hledger-web only).+As with the web UI\[aq]s add form, hledger-web must be started with the+\f[C]add\f[R] capability for this (enabled by default).+.PP+The payload should be a valid hledger transaction as JSON, similar to+what you get from \f[C]/transactions\f[R] or+\f[C]/accounttransactions\f[R].+.PP+Another way to generate test data is with the+\f[C]readJsonFile\f[R]/\f[C]writeJsonFile\f[R] helpers in+Hledger.Web.Json, which read or write any of hledger\[aq]s JSON-capable+types from or to a file.+Eg here we write the first transaction of a sample journal:+.IP+.nf+\f[C]+$ make ghci-web+>>> :m +*Hledger.Web.Json+>>> writeJsonFile \[dq]txn.json\[dq] (head $ jtxns samplejournal)+>>> :q+$ python -m json.tool <txn.json >txn.pretty.json # optional: make human-readable+\f[R]+.fi+.PP+(sample output & discussion)+.PP+And here\[aq]s how to test adding that with curl:+.IP+.nf+\f[C]+$ curl -s http://127.0.0.1:5000/add -X PUT -H \[aq]Content-Type: application/json\[aq] --data-binary \[at]txn.pretty.json; echo+\f[R]+.fi+.PP+By default, both the server-side HTML UI and the JSON API are served.+Running with \f[C]--serve-api\f[R] disables the former, useful if you+only want to serve the API. .SH ENVIRONMENT .PP-\f[B]LEDGER_FILE\f[] The journal file path when not specified with-\f[C]\-f\f[].-Default: \f[C]~/.hledger.journal\f[] (on windows, perhaps-\f[C]C:/Users/USER/.hledger.journal\f[]).+\f[B]LEDGER_FILE\f[R] The journal file path when not specified with+\f[C]-f\f[R].+Default: \f[C]\[ti]/.hledger.journal\f[R] (on windows, perhaps+\f[C]C:/Users/USER/.hledger.journal\f[R]). .SH FILES .PP Reads data from one or more files in hledger journal, timeclock,-timedot, or CSV format specified with \f[C]\-f\f[], or-\f[C]$LEDGER_FILE\f[], or \f[C]$HOME/.hledger.journal\f[] (on windows,-perhaps \f[C]C:/Users/USER/.hledger.journal\f[]).+timedot, or CSV format specified with \f[C]-f\f[R], or+\f[C]$LEDGER_FILE\f[R], or \f[C]$HOME/.hledger.journal\f[R] (on windows,+perhaps \f[C]C:/Users/USER/.hledger.journal\f[R]). .SH BUGS .PP-The need to precede options with \f[C]\-\-\f[] when invoked from hledger+The need to precede options with \f[C]--\f[R] when invoked from hledger is awkward. .PP-\f[C]\-f\-\f[] doesn\[aq]t work (hledger\-web can\[aq]t read from-stdin).+\f[C]-f-\f[R] doesn\[aq]t work (hledger-web can\[aq]t read from stdin). .PP Query arguments and some hledger options are ignored. .PP-Does not work in text\-mode browsers.+Does not work in text-mode browsers. .PP Does not work well on small screens.
hledger-web.cabal view
@@ -1,13 +1,13 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.31.1.+-- This file has been generated from package.yaml by hpack version 0.31.2. -- -- see: https://github.com/sol/hpack ----- hash: 8eb80f6aa7e34e0b036d490c3c0f5994e3959f33045102d18cac6367c369c352+-- hash: 0edf95448e05cc75fb3c049d3ecc20264e8869497966ac5eb8783ee803dbce35 name: hledger-web-version: 1.14.1+version: 1.15 synopsis: Web interface for the hledger accounting tool description: This is hledger's web interface. It provides a more user-friendly and collaborative UI than the@@ -27,7 +27,7 @@ maintainer: Simon Michael <simon@joyful.com> license: GPL-3 license-file: LICENSE-tested-with: GHC==7.10.3, GHC==8.0.2, GHC==8.2.2, GHC==8.4.3, GHC==8.6.3+tested-with: GHC==7.10.3, GHC==8.0.2, GHC==8.2.2, GHC==8.4.3, GHC==8.6.5 build-type: Simple extra-source-files: CHANGES.md@@ -151,7 +151,7 @@ hs-source-dirs: ./. ghc-options: -Wall -fwarn-tabs- cpp-options: -DVERSION="1.14.1"+ cpp-options: -DVERSION="1.15" build-depends: Decimal , aeson@@ -169,8 +169,8 @@ , directory , filepath , hjsmin- , hledger >=1.14.2 && <1.15- , hledger-lib >=1.14.1 && <1.15+ , hledger >=1.15 && <1.16+ , hledger-lib >=1.15 && <1.16 , http-client , http-conduit , http-types@@ -211,7 +211,7 @@ hs-source-dirs: app ghc-options: -Wall -fwarn-tabs- cpp-options: -DVERSION="1.14.1"+ cpp-options: -DVERSION="1.15" build-depends: base , hledger-web
hledger-web.info view
@@ -3,7 +3,7 @@ File: hledger-web.info, Node: Top, Next: OPTIONS, Up: (dir) -hledger-web(1) hledger-web 1.14+hledger-web(1) hledger-web 1.15 ******************************* hledger-web is hledger's web interface. It starts a simple web@@ -25,6 +25,7 @@ '$LEDGER_FILE', or '$HOME/.hledger.journal' (on windows, perhaps 'C:/Users/USER/.hledger.journal'). For more about this see hledger(1), hledger_journal(5) etc.+ * Menu: * OPTIONS::@@ -49,6 +50,10 @@ '--serve' serve and log requests, don't browse or auto-exit+'--serve-api'++ like -serve, but serve only the JSON web API, without the+ server-side web UI '--host=IPADDR' listen on this IP address (default: 127.0.0.1)@@ -126,7 +131,7 @@ '-p --period=PERIODEXP' set start date, end date, and/or reporting interval all at once- using period expressions syntax (overrides the flags above)+ using period expressions syntax '--date2' match the secondary date instead (see command help for other@@ -192,7 +197,9 @@ web app will keep running for as long as you have it open in a browser window, and will exit after two minutes of inactivity (no requests and no browser windows viewing it). With '--serve', it just runs the web-app without exiting, and logs requests to the console.+app without exiting, and logs requests to the console. With+'--serve-api', only the JSON web api (see below) is served, with the+usual HTML server-side web UI disabled. By default the server listens on IP address 127.0.0.1, accessible only to local requests. You can use '--host' to change this, eg '--host@@ -281,15 +288,19 @@ file unparseable, hledger-web will display an error message until the file has been fixed. + (Note: if you are viewing files mounted from another machine, make+sure that both machine clocks are roughly in step.)+ File: hledger-web.info, Node: JSON API, Prev: RELOADING, Up: Top 5 JSON API ********** -In addition to the web UI, hledger-web provides some JSON API routes.-These are similar to the API provided by the hledger-api tool, but it-may be convenient to have them in hledger-web also.+In addition to the web UI, hledger-web provides some API routes that+serve JSON in response to GET requests. Currently these are same ones+provided by the hledger-api tool, but hledger-web will likely receive+more attention than hledger-api in future: /accountnames /transactions@@ -298,18 +309,47 @@ /accounts /accounttransactions/#AccountName + Also, you can append a new transaction to the journal by sending a+PUT request to '/add' (hledger-web only). As with the web UI's add+form, hledger-web must be started with the 'add' capability for this+(enabled by default).++ The payload should be a valid hledger transaction as JSON, similar to+what you get from '/transactions' or '/accounttransactions'.++ Another way to generate test data is with the+'readJsonFile'/'writeJsonFile' helpers in Hledger.Web.Json, which read+or write any of hledger's JSON-capable types from or to a file. Eg here+we write the first transaction of a sample journal:++$ make ghci-web+>>> :m +*Hledger.Web.Json+>>> writeJsonFile "txn.json" (head $ jtxns samplejournal)+>>> :q+$ python -m json.tool <txn.json >txn.pretty.json # optional: make human-readable++ (sample output & discussion)++ And here's how to test adding that with curl:++$ curl -s http://127.0.0.1:5000/add -X PUT -H 'Content-Type: application/json' --data-binary @txn.pretty.json; echo++ By default, both the server-side HTML UI and the JSON API are served.+Running with '--serve-api' disables the former, useful if you only want+to serve the API.+ Tag Table: Node: Top72-Node: OPTIONS1354-Ref: #options1459-Node: PERMISSIONS6549-Ref: #permissions6688-Node: EDITING UPLOADING DOWNLOADING7900-Ref: #editing-uploading-downloading8081-Node: RELOADING8915-Ref: #reloading9049-Node: JSON API9359-Ref: #json-api9453+Node: OPTIONS1355+Ref: #options1460+Node: PERMISSIONS6739+Ref: #permissions6878+Node: EDITING UPLOADING DOWNLOADING8090+Ref: #editing-uploading-downloading8271+Node: RELOADING9105+Ref: #reloading9239+Node: JSON API9672+Ref: #json-api9766 End Tag Table
hledger-web.txt view
@@ -46,6 +46,10 @@ --serve serve and log requests, don't browse or auto-exit + --serve-api+ like --serve, but serve only the JSON web API, without the+ server-side web UI+ --host=IPADDR listen on this IP address (default: 127.0.0.1) @@ -53,22 +57,22 @@ listen on this TCP port (default: 5000) --base-url=URL- set the base url (default: http://IPADDR:PORT). You would+ set the base url (default: http://IPADDR:PORT). You would change this when sharing over the network, or integrating within a larger website. --file-url=URL set the static files url (default: BASEURL/static). hledger-web- normally serves static files itself, but if you wanted to serve- them from another server for efficiency, you would set the url+ normally serves static files itself, but if you wanted to serve+ them from another server for efficiency, you would set the url with this. --capabilities=CAP[,CAP..]- enable the view, add, and/or manage capabilities (default:+ enable the view, add, and/or manage capabilities (default: view,add) --capabilities-header=HTTPHEADER- read capabilities to enable from a HTTP header, like X-Sand-+ read capabilities to enable from a HTTP header, like X-Sand- storm-Permissions (default: disabled) hledger input options:@@ -78,7 +82,7 @@ $LEDGER_FILE or $HOME/.hledger.journal) --rules-file=RULESFILE- Conversion rules file to use when reading CSV (default:+ Conversion rules file to use when reading CSV (default: FILE.rules) --separator=CHAR@@ -119,11 +123,11 @@ multiperiod/multicolumn report by year -p --period=PERIODEXP- set start date, end date, and/or reporting interval all at once- using period expressions syntax (overrides the flags above)+ set start date, end date, and/or reporting interval all at once+ using period expressions syntax --date2- match the secondary date instead (see command help for other+ match the secondary date instead (see command help for other effects) -U --unmarked@@ -142,21 +146,21 @@ hide/aggregate accounts or postings more than NUM levels deep -E --empty- show items with zero amount, normally hidden (and vice-versa in+ show items with zero amount, normally hidden (and vice-versa in hledger-ui/hledger-web) -B --cost- convert amounts to their cost at transaction time (using the+ convert amounts to their cost at transaction time (using the transaction price, if any) -V --value- convert amounts to their market value on the report end date+ convert amounts to their market value on the report end date (using the most recent applicable market price, if any) --auto apply automated posting rules to modify transactions. --forecast- apply periodic transaction rules to generate future transac-+ apply periodic transaction rules to generate future transac- tions, to 6 months from now or report end date. When a reporting option appears more than once in the command line, the@@ -176,39 +180,41 @@ show debug output (levels 1-9, default: 1) A @FILE argument will be expanded to the contents of FILE, which should- contain one command line option/argument per line. (To prevent this,+ contain one command line option/argument per line. (To prevent this, insert a -- argument before.) By default, hledger-web starts the web app in "transient mode" and also opens it in your default web browser if possible. In this mode the web app will keep running for as long as you have it open in a browser win-- dow, and will exit after two minutes of inactivity (no requests and no- browser windows viewing it). With --serve, it just runs the web app- without exiting, and logs requests to the console.+ dow, and will exit after two minutes of inactivity (no requests and no+ browser windows viewing it). With --serve, it just runs the web app+ without exiting, and logs requests to the console. With --serve-api,+ only the JSON web api (see below) is served, with the usual HTML+ server-side web UI disabled. - By default the server listens on IP address 127.0.0.1, accessible only- to local requests. You can use --host to change this, eg- --host 0.0.0.0 to listen on all configured addresses.+ By default the server listens on IP address 127.0.0.1, accessible only+ to local requests. You can use --host to change this, eg --host+ 0.0.0.0 to listen on all configured addresses. - Similarly, use --port to set a TCP port other than 5000, eg if you are+ Similarly, use --port to set a TCP port other than 5000, eg if you are running multiple hledger-web instances. - You can use --base-url to change the protocol, hostname, port and path+ You can use --base-url to change the protocol, hostname, port and path that appear in hyperlinks, useful eg for integrating hledger-web within- a larger website. The default is http://HOST:PORT/ using the server's+ a larger website. The default is http://HOST:PORT/ using the server's configured host address and TCP port (or http://HOST if PORT is 80). - With --file-url you can set a different base url for static files, eg+ With --file-url you can set a different base url for static files, eg for better caching or cookie-less serving on high performance websites. PERMISSIONS- By default, hledger-web allows anyone who can reach it to view the+ By default, hledger-web allows anyone who can reach it to view the journal and to add new transactions, but not to change existing data. You can restrict who can reach it by - o setting the IP address it listens on (see --host above). By default- it listens on 127.0.0.1, accessible to all users on the local+ o setting the IP address it listens on (see --host above). By default+ it listens on 127.0.0.1, accessible to all users on the local machine. o putting it behind an authenticating proxy, using eg apache or nginx@@ -218,51 +224,55 @@ You can restrict what the users who reach it can do, by o using the --capabilities=CAP[,CAP..] flag when you start it, enabling- one or more of the following capabilities. The default value is+ one or more of the following capabilities. The default value is view,add: o view - allows viewing the journal file and all included files o add - allows adding new transactions to the main journal file - o manage - allows editing, uploading or downloading the main or+ o manage - allows editing, uploading or downloading the main or included files - o using the --capabilities-header=HTTPHEADER flag to specify a HTTP- header from which it will read capabilities to enable. hledger-web- on Sandstorm uses the X-Sandstorm-Permissions header to integrate+ o using the --capabilities-header=HTTPHEADER flag to specify a HTTP+ header from which it will read capabilities to enable. hledger-web+ on Sandstorm uses the X-Sandstorm-Permissions header to integrate with Sandstorm's permissions. This is disabled by default. EDITING, UPLOADING, DOWNLOADING- If you enable the manage capability mentioned above, you'll see a new- "spanner" button to the right of the search form. Clicking this will- let you edit, upload, or download the journal file or any files it+ If you enable the manage capability mentioned above, you'll see a new+ "spanner" button to the right of the search form. Clicking this will+ let you edit, upload, or download the journal file or any files it includes. - Note, unlike any other hledger command, in this mode you (or any visi-+ Note, unlike any other hledger command, in this mode you (or any visi- tor) can alter or wipe the data files. - Normally whenever a file is changed in this way, hledger-web saves a- numbered backup (assuming file permissions allow it, the disk is not- full, etc.) hledger-web is not aware of version control systems, cur-- rently; if you use one, you'll have to arrange to commit the changes+ Normally whenever a file is changed in this way, hledger-web saves a+ numbered backup (assuming file permissions allow it, the disk is not+ full, etc.) hledger-web is not aware of version control systems, cur-+ rently; if you use one, you'll have to arrange to commit the changes yourself (eg with a cron job or a file watcher like entr). - Changes which would leave the journal file(s) unparseable or non-valid- (eg with failing balance assertions) are prevented. (Probably. This+ Changes which would leave the journal file(s) unparseable or non-valid+ (eg with failing balance assertions) are prevented. (Probably. This needs re-testing.) RELOADING hledger-web detects changes made to the files by other means (eg if you- edit it directly, outside of hledger-web), and it will show the new- data when you reload the page or navigate to a new page. If a change- makes a file unparseable, hledger-web will display an error message+ edit it directly, outside of hledger-web), and it will show the new+ data when you reload the page or navigate to a new page. If a change+ makes a file unparseable, hledger-web will display an error message until the file has been fixed. + (Note: if you are viewing files mounted from another machine, make sure+ that both machine clocks are roughly in step.)+ JSON API- In addition to the web UI, hledger-web provides some JSON API routes.- These are similar to the API provided by the hledger-api tool, but it- may be convenient to have them in hledger-web also.+ In addition to the web UI, hledger-web provides some API routes that+ serve JSON in response to GET requests. Currently these are same ones+ provided by the hledger-api tool, but hledger-web will likely receive+ more attention than hledger-api in future: /accountnames /transactions@@ -271,6 +281,35 @@ /accounts /accounttransactions/#AccountName + Also, you can append a new transaction to the journal by sending a PUT+ request to /add (hledger-web only). As with the web UI's add form,+ hledger-web must be started with the add capability for this (enabled+ by default).++ The payload should be a valid hledger transaction as JSON, similar to+ what you get from /transactions or /accounttransactions.++ Another way to generate test data is with the readJsonFile/writeJson-+ File helpers in Hledger.Web.Json, which read or write any of hledger's+ JSON-capable types from or to a file. Eg here we write the first+ transaction of a sample journal:++ $ make ghci-web+ >>> :m +*Hledger.Web.Json+ >>> writeJsonFile "txn.json" (head $ jtxns samplejournal)+ >>> :q+ $ python -m json.tool <txn.json >txn.pretty.json # optional: make human-readable++ (sample output & discussion)++ And here's how to test adding that with curl:++ $ curl -s http://127.0.0.1:5000/add -X PUT -H 'Content-Type: application/json' --data-binary @txn.pretty.json; echo++ By default, both the server-side HTML UI and the JSON API are served.+ Running with --serve-api disables the former, useful if you only want+ to serve the API.+ ENVIRONMENT LEDGER_FILE The journal file path when not specified with -f. Default: ~/.hledger.journal (on windows, perhaps C:/Users/USER/.hledger.jour-@@ -319,4 +358,4 @@ -hledger-web 1.14 March 2019 hledger-web(1)+hledger-web 1.15 August 2019 hledger-web(1)
templates/register.hamlet view
@@ -18,7 +18,7 @@ #{balancelabel'} <tbody>- $forall (torig, tacct, split, acct, amt, bal) <- items+ $forall (torig, tacct, split, _acct, amt, bal) <- items <tr ##{tindex torig} title="#{showTransaction torig}" style="vertical-align:top;"> <td .date> <a href="@{JournalR}#transaction-#{tindex torig}">@@ -26,7 +26,9 @@ <td> #{textElideRight 30 (tdescription tacct)} <td .account>- #{elideRight 40 acct}+ $forall (Posting { paccount = acc }, (summName,comma)) <- otherTransAccounts torig+ <a href="@?{acctlink acc}##{tindex torig}" title="#{acc}">+ #{summName}</a>#{comma} <td .amount style="text-align:right; white-space:nowrap;"> $if not split || not (isZeroMixedAmount amt) ^{mixedAmountAsHtml amt}