packages feed

hledger-web 1.26.1 → 1.27

raw patch · 13 files changed

+217/−183 lines, 13 filesdep +breakpointdep ~basedep ~hledgerdep ~hledger-libPVP ok

version bump matches the API change (PVP)

Dependencies added: breakpoint

Dependency ranges changed: base, hledger, hledger-lib

API changes (from Hackage documentation)

- Hledger.Web.Import: parseTime :: ParseTime t => TimeLocale -> String -> String -> Maybe t
- Hledger.Web.Import: readTime :: ParseTime t => TimeLocale -> String -> String -> t
- Hledger.Web.Import: readsTime :: ParseTime t => TimeLocale -> String -> ReadS t
+ Hledger.Web.Import: catchHandlerExceptions :: (Yesod site, MonadUnliftIO m) => site -> m a -> (SomeException -> m a) -> m a
+ Hledger.Web.Import: class SafeToInsert a
+ Hledger.Web.Import: dayOfWeekDiff :: DayOfWeek -> DayOfWeek -> Int
+ Hledger.Web.Import: firstDayOfWeekOnAfter :: DayOfWeek -> Day -> Day
+ Hledger.Web.Import: parseTimeMultipleM :: (MonadFail m, ParseTime t) => Bool -> TimeLocale -> [(String, String)] -> m t
+ Hledger.Web.Import: pastMidnight :: DiffTime -> TimeOfDay
+ Hledger.Web.Import: pattern YearMonthDay :: Year -> MonthOfYear -> DayOfMonth -> Day
+ Hledger.Web.Import: sinceMidnight :: TimeOfDay -> DiffTime
+ Hledger.Web.Import: type DayOfMonth = Int
+ Hledger.Web.Import: type MonthOfYear = Int
+ Hledger.Web.Import: type Year = Integer
- Hledger.Web.Foundation: type Form x = Html -> MForm (HandlerFor App) (FormResult x, Widget)
+ Hledger.Web.Foundation: type Form a = Html -> MForm Handler (FormResult a, Widget)
- Hledger.Web.Import: class Foldable (t :: Type -> Type)
+ Hledger.Web.Import: class Foldable (t :: TYPE LiftedRep -> Type)
- Hledger.Web.Import: fromGregorian :: Integer -> Int -> Int -> Day
+ Hledger.Web.Import: fromGregorian :: Year -> MonthOfYear -> DayOfMonth -> Day
- Hledger.Web.Import: fromGregorianValid :: Integer -> Int -> Int -> Maybe Day
+ Hledger.Web.Import: fromGregorianValid :: Year -> MonthOfYear -> DayOfMonth -> Maybe Day
- Hledger.Web.Import: gregorianMonthLength :: Integer -> Int -> Int
+ Hledger.Web.Import: gregorianMonthLength :: Year -> MonthOfYear -> DayOfMonth
- Hledger.Web.Import: infixl 6 +
+ Hledger.Web.Import: infixl 6 -
- Hledger.Web.Import: isLeapYear :: Integer -> Bool
+ Hledger.Web.Import: isLeapYear :: Year -> Bool
- Hledger.Web.Import: mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)
+ Hledger.Web.Import: mapAccumL :: Traversable t => (s -> a -> (s, b)) -> s -> t a -> (s, t b)
- Hledger.Web.Import: mapAccumR :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)
+ Hledger.Web.Import: mapAccumR :: Traversable t => (s -> a -> (s, b)) -> s -> t a -> (s, t b)
- Hledger.Web.Import: seq :: forall (r :: RuntimeRep) a (b :: TYPE r). a -> b -> b
+ Hledger.Web.Import: seq :: forall {r :: RuntimeRep} a (b :: TYPE r). a -> b -> b
- Hledger.Web.Import: toGregorian :: Day -> (Integer, Int, Int)
+ Hledger.Web.Import: toGregorian :: Day -> (Year, MonthOfYear, DayOfMonth)
- Hledger.Web.Import: type Form x = Html -> MForm (HandlerFor App) (FormResult x, Widget)
+ Hledger.Web.Import: type Form a = Html -> MForm Handler (FormResult a, Widget)
- Hledger.Web.Widget.AddForm: addForm :: (site ~ HandlerSite m, RenderMessage site FormMessage, MonadHandler m) => Journal -> Day -> Markup -> MForm m (FormResult Transaction, WidgetFor site ())
+ Hledger.Web.Widget.AddForm: addForm :: Journal -> Day -> Markup -> MForm Handler (FormResult (Transaction, FilePath), Widget)
- Hledger.Web.Widget.AddForm: addModal :: (MonadWidget m, r ~ Route (HandlerSite m), m ~ WidgetFor (HandlerSite m), RenderMessage (HandlerSite m) FormMessage) => r -> Journal -> Day -> m ()
+ Hledger.Web.Widget.AddForm: addModal :: Route App -> Journal -> Day -> Widget

Files

CHANGES.md view
@@ -9,11 +9,33 @@ User-visible changes in hledger-web. See also the hledger changelog. +# 1.27 2022-09-01++Improvements++- Improve the add form's layout and space usage.++- Pre-fill the add form's date field.++- Highlight today in the add form's date picker.++- Focus the add form's description field by default.++- Allow an empty description in the add form.++- Use hledger 1.27++Fixes++- Respect the add form's file selector again.+  (Simon Michael, Kerstin, #1229)+ # 1.26.1 2022-07-11  - Uses hledger 1.26.1.  # 1.26 2022-06-04+ Fixes  - Don't add link URLs when printing.
Hledger/Web/Foundation.hs view
@@ -84,11 +84,12 @@ -- usually require access to the AppRoute datatype. Therefore, we -- split these actions into two functions and place them in separate files. mkYesodData "App" $(parseRoutesFile "config/routes")+-- ^ defines things like:+-- type Handler = HandlerFor App   -- HandlerT App IO, https://www.yesodweb.com/book/routing-and-handlers#routing-and-handlers_handler_monad+-- type Widget = WidgetFor App ()  -- WidgetT App IO (), https://www.yesodweb.com/book/widgets --- | A convenience alias. type AppRoute = Route App--type Form x = Html -> MForm (HandlerFor App) (FormResult x, Widget)+type Form a = Html -> MForm Handler (FormResult a, Widget)  -- Please see the documentation for the Yesod typeclass. There are a number -- of settings which can be configured by overriding methods here.
Hledger/Web/Handler/AddR.hs view
@@ -35,12 +35,11 @@    ((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)+    FormSuccess (t,f) -> do+      let t' = txnTieKnot t+      liftIO $ do+        ensureJournalFileExists f+        appendToJournalFileOrStdout f (showTransaction t')       setMessage "Transaction added."       redirect JournalR     FormMissing -> showForm view enctype@@ -52,7 +51,7 @@       sendResponse =<< defaultLayout [whamlet|         <h2>Add transaction         <div .row style="margin-top:1em">-          <form#addform.form.col-xs-12.col-md-8 method=post enctype=#{enctype}>+          <form#addform.form.col-xs-12.col-sm-11 method=post enctype=#{enctype}>             ^{view}       |] 
Hledger/Web/Handler/EditR.hs view
@@ -15,7 +15,7 @@ import Hledger.Web.Widget.Common        (fromFormSuccess, helplink, journalFile404, writeJournalTextIfValidAndChanged) -editForm :: FilePath -> Text -> Markup -> MForm Handler (FormResult Text, Widget)+editForm :: FilePath -> Text -> Form Text editForm f txt =   identifyForm "edit" $ \extra -> do     (tRes, tView) <- mreq textareaField fs (Just (Textarea txt))
Hledger/Web/Widget/AddForm.hs view
@@ -14,7 +14,7 @@ import Data.Bifunctor (first) import Data.Foldable (toList) import Data.List (dropWhileEnd, unfoldr)-import Data.Maybe (isJust)+import Data.Maybe (isJust, fromMaybe) import qualified Data.Set as S import Data.Text (Text) import Data.Text.Encoding.Base64 (encodeBase64)@@ -25,17 +25,13 @@ import Yesod  import Hledger+import Hledger.Web.Foundation (App, Handler, Widget) import Hledger.Web.Settings (widgetFile)+import Data.Function ((&)) -addModal ::-     ( MonadWidget m-     , r ~ Route (HandlerSite m)-     , m ~ WidgetFor (HandlerSite m)-     , RenderMessage (HandlerSite m) FormMessage-     )-  => r -> Journal -> Day -> m ()+addModal :: Route App -> Journal -> Day -> Widget addModal addR j today = do-  (addView, addEnctype) <- generateFormPost (addForm j today)+  (addView, addEnctype) <- handlerToWidget $ generateFormPost (addForm j today)   [whamlet| <div .modal #addmodal tabindex="-1" role="dialog" aria-labelledby="addLabel" aria-hidden="true">   <div .modal-dialog .modal-lg>@@ -48,106 +44,88 @@           ^{addView} |] -addForm ::-     (site ~ HandlerSite m, RenderMessage site FormMessage, MonadHandler m)-  => Journal-  -> Day-  -> Markup-  -> MForm m (FormResult Transaction, WidgetFor site ())+addForm :: Journal -> Day -> Markup -> MForm Handler (FormResult (Transaction,FilePath), Widget) addForm j today = identifyForm "add" $ \extra -> do-  (dateRes, dateView) <- mreq dateField dateFS Nothing-  (descRes, descView) <- mreq textField descFS Nothing-  (acctRes, _) <- mreq listField acctFS Nothing-  (amtRes, _) <- mreq listField amtFS Nothing-  let (postRes, displayRows) = validatePostings acctRes amtRes--  -- bindings used in add-form.hamlet-  let descriptions = foldMap S.fromList [journalPayeesDeclaredOrUsed j, journalDescriptions j]-      journals = fst <$> jfiles j--  pure (validateTransaction dateRes descRes postRes, $(widgetFile "add-form"))-+  let  -- bindings used in add-form.hamlet+    descriptions = foldMap S.fromList [journalPayeesDeclaredOrUsed j, journalDescriptions j]+    files = fst <$> jfiles j+  (dateRes, dateView) <- mreq dateField dateSettings Nothing+  (descRes, descView) <- mopt textField descSettings Nothing+  (acctsRes, _)       <- mreq listField acctSettings Nothing+  (amtsRes, _)        <- mreq listField amtSettings  Nothing+  (fileRes, fileView) <- mreq fileField' fileSettings Nothing+  let+    (postingsRes, displayRows) = validatePostings acctsRes amtsRes+    formRes = validateTransaction dateRes descRes postingsRes fileRes+  return (formRes, $(widgetFile "add-form"))   where-    dateFS = FieldSettings "date" Nothing Nothing (Just "date")-      [("class", "form-control input-lg"), ("placeholder", "Date")]-    descFS = FieldSettings "desc" Nothing Nothing (Just "description")-      [("class", "form-control input-lg typeahead"), ("placeholder", "Description"), ("size", "40")]-    acctFS = FieldSettings "amount" Nothing Nothing (Just "account") []-    amtFS = FieldSettings "amount" Nothing Nothing (Just "amount") []-    dateField = checkMMap (pure . validateDate) (T.pack . show) textField-    validateDate s =-      first (const ("Invalid date format" :: Text)) $-      fixSmartDateStrEither' today (T.strip s)-+    -- custom fields+    dateField = textField & checkMMap (pure . validateDate) (T.pack . show)+      where+        validateDate s =+          first (const ("Invalid date format" :: Text)) $+          fixSmartDateStrEither' today (T.strip s)     listField = Field       { fieldParse = const . pure . Right . Just . dropWhileEnd T.null-      , fieldView = error "Don't render using this!"  -- PARTIAL:+      , fieldView = error' "listField should not be used for rendering"  -- PARTIAL:       , fieldEnctype = UrlEncoded       }--    -- Used in add-form.hamlet-    toBloodhoundJson :: [Text] -> Markup-    toBloodhoundJson ts =-      -- This used to work, but since 1.16, it seems like something changed.-      -- toJSON ("a"::Text) gives String "a" instead of "a", etc.-      -- preEscapedString . escapeJSSpecialChars . show . toJSON-      preEscapedText $ T.concat [-        "[",-        T.intercalate "," $ map (-          ("{\"value\":" <>).-          (<> "}").-          -- This will convert a value such as ``hledger!`` into-          -- ``atob("aGxlZGdlciE=")``. When this gets evaluated on the client,-          -- the resulting string is ``hledger!`` again. The same data is-          -- passed, but the user-controlled bit of that string can only use-          -- characters [a-zA-Z0-9+=/], making it impossible to break out of-          -- string context.-          b64wrap-          ) ts,-        "]"-        ]-b64wrap :: Text -> Text-b64wrap = ("atob(\""<>) . (<>"\")") . encodeBase64+    fileField' :: Field Handler FilePath+    fileField' = selectFieldList [(T.pack f, f) | f <- fs] & check validateFilepath+      where+        fs = journalFilePaths j+        validateFilepath :: FilePath -> Either FormMessage FilePath+        validateFilepath f+          | f `elem` fs = Right f+          | otherwise = Left $ MsgInputNotFound $ T.pack f+    -- field settings+    dateSettings = FieldSettings "date" Nothing Nothing (Just "date") [("class", "form-control input-lg"), ("placeholder", "Date")]+    descSettings = FieldSettings "desc" Nothing Nothing (Just "description") [("class", "form-control input-lg typeahead"), ("placeholder", "Description"), ("size", "40")]+    acctSettings = FieldSettings "account" Nothing Nothing (Just "account") []+    amtSettings  = FieldSettings "amount" Nothing Nothing (Just "amount") []+    fileSettings = FieldSettings "file" Nothing Nothing (Just "file") [("class", "form-control input-lg")]  validateTransaction ::-     FormResult Day-  -> FormResult Text-  -> FormResult [Posting]-  -> FormResult Transaction-validateTransaction dateRes descRes postingsRes =-  case makeTransaction <$> dateRes <*> descRes <*> postingsRes of-    FormSuccess txn -> case balanceTransaction defbalancingopts txn of-      Left e -> FormFailure [T.pack e]-      Right txn' -> FormSuccess txn'+     FormResult Day -> FormResult (Maybe Text) -> FormResult [Posting] -> FormResult FilePath+  -> FormResult (Transaction, FilePath)+validateTransaction dateRes descRes postingsRes fileRes =+  case makeTransaction <$> dateRes <*> descRes <*> postingsRes <*> fileRes of+    FormSuccess (txn,f) -> case balanceTransaction defbalancingopts txn of+      Left e     -> FormFailure [T.pack e]+      Right txn' -> FormSuccess (txn',f)     x -> x   where-    makeTransaction date desc postings =-      nulltransaction {tdate = date, tdescription = desc, tpostings = postings}-+    makeTransaction date mdesc postings f =+      (nulltransaction {+         tdate = date+        ,tdescription = fromMaybe "" mdesc+        ,tpostings = postings+        ,tsourcepos = (initialPos f, initialPos f)+        }, f)  -- | Parse a list of postings out of a list of accounts and a corresponding list -- of amounts validatePostings ::-     FormResult [Text]-  -> FormResult [Text]+     FormResult [Text] -> FormResult [Text]   -> (FormResult [Posting], [(Int, (Text, Text, Maybe Text, Maybe Text))])-validatePostings acctRes amtRes = let+validatePostings acctsRes amtsRes = let    -- Zip accounts and amounts, fill in missing values and drop empty rows.   rows :: [(Text, Text)]-  rows = filter (/= ("", "")) $ zipDefault "" (formSuccess [] acctRes) (formSuccess [] amtRes)+  rows = filter (/= ("", "")) $ zipDefault "" (formSuccess [] acctsRes) (formSuccess [] amtsRes)    -- Parse values and check for incomplete rows with only an account or an amount.   -- The boolean in unfoldr state is for special handling of 'missingamt', where   -- one row may have only an account and not an amount.   postings :: [(Text, Text, Either (Maybe Text, Maybe Text) Posting)]   postings = unfoldr go (True, rows)-  go (True, (x, ""):y:xs) = Just ((x, "", zipRow (checkAccount x) (Left "Missing amount")), (True, y:xs))-  go (True, (x, ""):xs) = Just ((x, "", zipRow (checkAccount x) (Right missingamt)), (False, xs))-  go (False, (x, ""):xs) = Just ((x, "", zipRow (checkAccount x) (Left "Missing amount")), (False, xs))-  go (_, ("", y):xs) = Just (("", y, zipRow (Left "Missing account") (checkAmount y)), (False, xs))-  go (_, (x, y):xs) = Just ((x, y, zipRow (checkAccount x) (checkAmount y)), (True, xs))-  go (_, []) = Nothing+    where+      go (True, (x, ""):y:xs) = Just ((x, "", zipRow (checkAccount x) (Left "Missing amount")), (True, y:xs))+      go (True, (x, ""):xs) = Just ((x, "", zipRow (checkAccount x) (Right missingamt)), (False, xs))+      go (False, (x, ""):xs) = Just ((x, "", zipRow (checkAccount x) (Left "Missing amount")), (False, xs))+      go (_, ("", y):xs) = Just (("", y, zipRow (Left "Missing account") (checkAmount y)), (False, xs))+      go (_, (x, y):xs) = Just ((x, y, zipRow (checkAccount x) (checkAmount y)), (True, xs))+      go (_, []) = Nothing    zipRow (Left e) (Left e') = Left (Just e, Just e')   zipRow (Left e) (Right _) = Left (Just e, Nothing)@@ -165,7 +143,7 @@    -- Add errors to forms with zero rows if the form is not a FormMissing   result :: [(Text, Text, Either (Maybe Text, Maybe Text) Posting)]-  result = case (acctRes, amtRes) of+  result = case (acctsRes, amtsRes) of     (FormMissing, FormMissing) -> postings     _ -> case postings of       [] -> [ ("", "", Left (Just "Missing account", Just "Missing amount"))@@ -187,6 +165,30 @@    in (formResult, zip [(1 :: Int)..] display) +-- helper for add-form.hamlet+toBloodhoundJson :: [Text] -> Markup+toBloodhoundJson ts =+  -- This used to work, but since 1.16, it seems like something changed.+  -- toJSON ("a"::Text) gives String "a" instead of "a", etc.+  -- preEscapedString . escapeJSSpecialChars . show . toJSON++  preEscapedText $ T.concat [+    "[",+    T.intercalate "," $ map (+      ("{\"value\":" <>).+      (<> "}").+      -- This will convert a value such as ``hledger!`` into+      -- ``atob("aGxlZGdlciE=")``. When this gets evaluated on the client,+      -- the resulting string is ``hledger!`` again. The same data is+      -- passed, but the user-controlled bit of that string can only use+      -- characters [a-zA-Z0-9+=/], making it impossible to break out of+      -- string context.+      b64wrap+      ) ts,+    "]"+    ]+  where+    b64wrap = ("atob(\""<>) . (<>"\")") . encodeBase64  zipDefault :: a -> [a] -> [a] -> [(a, a)] zipDefault def (b:bs) (c:cs) = (b, c):(zipDefault def bs cs)
Hledger/Web/Widget/Common.hs view
@@ -118,14 +118,14 @@     map quoteIfSpaced .     filter (\term ->         not $ T.isPrefixOf "date:" term || T.isPrefixOf "date2:" term) .-    Query.words'' Query.prefixes+    Query.words'' queryprefixes  removeInacct :: Text -> [Text] removeInacct =     map quoteIfSpaced .     filter (\term ->         not $ T.isPrefixOf "inacct:" term || T.isPrefixOf "inacctonly:" term) .-    Query.words'' Query.prefixes+    Query.words'' queryprefixes  replaceInacct :: Text -> Text -> Text replaceInacct q acct = T.unwords $ acct : removeInacct q
hledger-web.1 view
@@ -1,12 +1,12 @@ -.TH "HLEDGER-WEB" "1" "July 2022" "hledger-web-1.26.1 " "hledger User Manuals"+.TH "HLEDGER-WEB" "1" "September 2022" "hledger-web-1.27 " "hledger User Manuals"    .SH NAME .PP hledger-web is a web interface (WUI) for the hledger accounting tool.-This manual is for hledger-web 1.26.1.+This manual is for hledger-web 1.27. .SH SYNOPSIS .PP \f[C]hledger-web [OPTIONS]\f[R]@@ -615,9 +615,10 @@ reboot. .PP On Windows computers, the default value is probably-\f[C]C:\[rs]Users\[rs]MyUserName\[rs].hledger.journal\f[R].+\f[C]C:\[rs]Users\[rs]YOURNAME\[rs].hledger.journal\f[R]. You can change this by running a command like this in a powershell-window:+window (let us know if you need to be an Administrator, and if this+persists across a reboot): .IP .nf \f[C]@@ -625,8 +626,8 @@ \f[R] .fi .PP-(Let us know if you need to be an Administrator, and if this persists-across a reboot.)+Or, change it in settings: see+https://www.java.com/en/download/help/path.html. .SH FILES .PP Reads data from one or more files in hledger journal, timeclock,
hledger-web.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           hledger-web-version:        1.26.1+version:        1.27 synopsis:       Web-based user interface for the hledger accounting system description:    A simple web-based user interface for the hledger accounting system,                 providing a more modern UI than the command-line or terminal interfaces.@@ -28,7 +28,7 @@ license-file:   LICENSE build-type:     Simple tested-with:-    GHC==8.8.4, GHC==8.10.4, GHC==9.0.1+    GHC==8.10.7, GHC==9.0.2, GHC==9.2.4 extra-source-files:     CHANGES.md     README.md@@ -151,14 +151,15 @@   hs-source-dirs:       ./   ghc-options: -Wall -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns-  cpp-options: -DVERSION="1.26.1"+  cpp-options: -DVERSION="1.27"   build-depends:       Decimal >=0.5.1     , aeson >=1-    , base >=4.11 && <4.17+    , base >=4.14 && <4.17     , base64     , blaze-html     , blaze-markup+    , breakpoint     , bytestring     , case-insensitive     , clientsession@@ -171,8 +172,8 @@     , extra >=1.6.3     , filepath     , hjsmin-    , hledger >=1.26.1 && <1.27-    , hledger-lib >=1.26.1 && <1.27+    , hledger ==1.27.*+    , hledger-lib ==1.27.*     , hspec     , http-client     , http-conduit@@ -212,9 +213,10 @@   hs-source-dirs:       app   ghc-options: -Wall -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns-  cpp-options: -DVERSION="1.26.1"+  cpp-options: -DVERSION="1.27"   build-depends:-      base+      base >=4.14 && <4.17+    , breakpoint     , hledger-web   if (flag(dev)) || (flag(library-only))     cpp-options: -DDEVELOPMENT@@ -232,9 +234,10 @@   hs-source-dirs:       test   ghc-options: -Wall -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns-  cpp-options: -DVERSION="1.26.1"+  cpp-options: -DVERSION="1.27"   build-depends:-      base+      base >=4.14 && <4.17+    , breakpoint     , hledger     , hledger-lib     , hledger-web
hledger-web.info view
@@ -12,7 +12,7 @@ **************  hledger-web is a web interface (WUI) for the hledger accounting tool.-This manual is for hledger-web 1.26.1.+This manual is for hledger-web 1.27.     'hledger-web [OPTIONS]' 'hledger web -- [OPTIONS]'@@ -592,13 +592,14 @@    For this to take effect you might need to 'killall Dock', or reboot.     On Windows computers, the default value is probably-'C:\Users\MyUserName\.hledger.journal'.  You can change this by running-a command like this in a powershell window:+'C:\Users\YOURNAME\.hledger.journal'.  You can change this by running a+command like this in a powershell window (let us know if you need to be+an Administrator, and if this persists across a reboot):  > setx LEDGER_FILE "C:\Users\MyUserName\finance\2021.journal" -   (Let us know if you need to be an Administrator, and if this persists-across a reboot.)+   Or, change it in settings: see+https://www.java.com/en/download/help/path.html.   File: hledger-web.info,  Node: FILES,  Next: BUGS,  Prev: ENVIRONMENT,  Up: Top@@ -631,22 +632,22 @@  Tag Table: Node: Top223-Node: OPTIONS1888-Ref: #options1993-Node: PERMISSIONS9904-Ref: #permissions10043-Node: EDITING UPLOADING DOWNLOADING11255-Ref: #editing-uploading-downloading11436-Node: RELOADING12270-Ref: #reloading12404-Node: JSON API12837-Ref: #json-api12951-Node: ENVIRONMENT18441-Ref: #environment18557-Node: FILES19791-Ref: #files19891-Node: BUGS20104-Ref: #bugs20182+Node: OPTIONS1886+Ref: #options1991+Node: PERMISSIONS9902+Ref: #permissions10041+Node: EDITING UPLOADING DOWNLOADING11253+Ref: #editing-uploading-downloading11434+Node: RELOADING12268+Ref: #reloading12402+Node: JSON API12835+Ref: #json-api12949+Node: ENVIRONMENT18439+Ref: #environment18555+Node: FILES19866+Ref: #files19966+Node: BUGS20179+Ref: #bugs20257  End Tag Table 
hledger-web.txt view
@@ -5,7 +5,7 @@  NAME        hledger-web  is  a web interface (WUI) for the hledger accounting tool.-       This manual is for hledger-web 1.26.1.+       This manual is for hledger-web 1.27.  SYNOPSIS        hledger-web [OPTIONS]@@ -537,23 +537,24 @@         For this to take effect you might need to killall Dock, or reboot. -       On Windows computers, the default value  is  probably  C:\Users\MyUser--       Name\.hledger.journal.   You  can change this by running a command like-       this in a powershell window:+       On Windows computers, the  default  value  is  probably  C:\Users\YOUR-+       NAME\.hledger.journal.   You  can change this by running a command like+       this in a powershell window (let us know if you need to be an  Adminis-+       trator, and if this persists across a reboot):                > setx LEDGER_FILE "C:\Users\MyUserName\finance\2021.journal" -       (Let us know if you need to be an Administrator, and if  this  persists-       across a reboot.)+       Or,   change   it   in   settings:   see  https://www.java.com/en/down-+       load/help/path.html.  FILES-       Reads  data from one or more files in hledger journal, timeclock, time--       dot,  or  CSV  format  specified   with   -f,   or   $LEDGER_FILE,   or-       $HOME/.hledger.journal           (on          windows,          perhaps+       Reads data from one or more files in hledger journal, timeclock,  time-+       dot,   or   CSV   format   specified   with  -f,  or  $LEDGER_FILE,  or+       $HOME/.hledger.journal          (on          windows,           perhaps        C:/Users/USER/.hledger.journal).  BUGS-       The need to precede options with -- when invoked from hledger  is  awk-+       The  need  to precede options with -- when invoked from hledger is awk-        ward.         -f- doesn't work (hledger-web can't read from stdin).@@ -567,7 +568,7 @@   REPORTING BUGS-       Report  bugs at http://bugs.hledger.org (or on the #hledger IRC channel+       Report bugs at http://bugs.hledger.org (or on the #hledger IRC  channel        or hledger mail list)  @@ -585,4 +586,4 @@   -hledger-web-1.26.1                 July 2022                    HLEDGER-WEB(1)+hledger-web-1.27                September 2022                  HLEDGER-WEB(1)
static/hledger.js view
@@ -4,16 +4,20 @@ // STARTUP  $(document).ready(function() {++  // add form helpers XXX move to addForm ?+   // date picker   // http://bootstrap-datepicker.readthedocs.io/en/latest/options.html   var dateEl = $('#dateWrap').datepicker({     showOnFocus: false,     autoclose: true,     format: 'yyyy-mm-dd',+    todayHighlight: true,     weekStart: 1 // Monday   });; -  // ensure add form always focuses its first field+  // focus and pre-fill the add form whenever it is shown   $('#addmodal')     .on('shown.bs.modal', function() {       addformFocus();@@ -163,9 +167,14 @@   $('.amount-input:last').keypress(addformAddPosting); } -// Focus the first add form field.+// Pre-fill today's date and focus the description field in the add form. function addformFocus() {-  focus($('#addform input#date'));+  $('#addform input[name=date]').val(isoDate());+  focus($('#addform input[name=description]'));+}++function isoDate() {+  return new Date().toLocaleDateString("sv");  // https://stackoverflow.com/a/58633651/84401 }  // Focus a jquery-wrapped element, working around http://stackoverflow.com/a/7046837.
templates/add-form.hamlet view
@@ -21,47 +21,42 @@   }); ^{extra} -<div .form-group>-  <div .row>-    <div .col-md-3 .col-xs-6 .col-sm-6 :isJust (fvErrors dateView):.has-error>-      <div #dateWrap .form-group.input-group.date>-        ^{fvInput dateView}-        <div .input-group-addon>-          <span .glyphicon .glyphicon-th>-      $maybe err <- fvErrors dateView-        <span .help-block .error-block>#{err}-    <div .col-md-9 .col-xs-6 .col-sm-6 :isJust (fvErrors descView):.has-error>-      <div .form-group>-        ^{fvInput descView}-      $maybe err <- fvErrors descView-        <span .help-block .error-block>#{err}-  <div .row>-    <div .col-md-3 .col-xs-6 .col-sm-6>-    <div .col-md-9 .col-xs-6 .col-sm-6>+<div .row>+  <div .col-md-3.col-sm-5.col-xs-6 :isJust (fvErrors dateView):.has-error>+    <div #dateWrap .form-group.input-group.date>+      ^{fvInput dateView}+      <div .input-group-addon>+        <span .glyphicon .glyphicon-th>+    $maybe err <- fvErrors dateView+      <span .help-block .error-block>#{err}+  <div .col-md-9.col-sm-7.col-xs-6 :isJust (fvErrors descView):.has-error>+    <div .form-group>+      ^{fvInput descView}+    $maybe err <- fvErrors descView+      <span .help-block .error-block>#{err}  <div .account-postings>   $forall (n, (acc, amt, accE, amtE)) <- displayRows-    <div .form-group .row .account-group>-      <div .col-md-8 .col-xs-8 .col-sm-8 :isJust accE:.has-error>+    <div .form-group .row .account-group style="padding-left:1em;">+      <div .col-sm-9.col-xs-9 :isJust accE:.has-error>         <input .account-input.form-control.input-lg.typeahead type=text           name=account placeholder="Account #{n}" value="#{acc}">         $maybe err <- accE           <span .help-block .error-block>_{err}-      <div .col-md-4 .col-xs-4 .col-sm-4 :isJust amtE:.has-error>+      <div .col-sm-3.col-xs-3 :isJust amtE:.has-error>         <input .amount-input.form-control.input-lg type=text           name=amount placeholder="Amount #{n}" value="#{amt}">         $maybe err <- amtE           <span .help-block .error-block>_{err}  <div .row>-  <div .col-md-8 .col-xs-8 .col-sm-8>-  <div .col-md-4 .col-xs-4 .col-sm-4>-    <button type=submit .btn .btn-default .btn-lg name=submit>add--$if length journals > 1-  <br>-  <span .input-lg>to:-    <select #journalselect .form-control.input-lg name=journal style="width:auto; display:inline-block;">-      $forall p <- journals-        <option value=#{p}>#{p}-<span .small style="padding-left:2em;">+  <div .col-sm-9.col-xs-9>+    $if length files > 1+      Add to:+      &nbsp;+      <div style="display:inline-block; width:auto;" .form-group :isJust (fvErrors fileView):.has-error>+        ^{fvInput fileView}+        $maybe err <- fvErrors fileView+          <span .help-block .error-block>#{err}+  <div .col-sm-3.col-xs-3 style="text-align:right;">+    <button type=submit .btn .btn-default .btn-lg name=submit style="font-weight:bold;">Save
templates/manage.hamlet view
@@ -2,7 +2,7 @@   Your journal's files  <div.row>-  <div .col-xs-12.col-sm-8.col-md-6>+  <div .col-md-6.col-sm-8.col-xs-12>     <table .table.table-condensed>       <thead>         <th>