{-# LANGUAGE CPP, OverloadedStrings, QuasiQuotes, NamedFieldPuns #-} -- | Common page components and rendering helpers. -- For global page layout, see Application.hs. module Handler.Common where import Data.Semigroup ((<>)) import Data.Text (Text) import qualified Data.Text as T import Data.Time.Calendar (Day, toGregorian) import Text.Blaze (ToMarkup) import Text.Blaze.Internal (preEscapedString) import Yesod import Settings (manualurl) import Hledger -- -- | Navigation link, preserving parameters and possibly highlighted. -- navlink :: ViewData -> String -> AppRoute -> String -> HtmlUrl AppRoute -- navlink VD{..} s dest title = [hamlet| -- #{s} -- |] -- where u' = (dest, if null q then [] else [("q", pack q)]) -- style | dest == here = "navlinkcurrent" -- | otherwise = "navlink" :: Text -- -- | Links to the various journal editing forms. -- editlinks :: HtmlUrl AppRoute -- editlinks = [hamlet| -- edit -- \ | # -- add -- import transactions -- |] -- | Link to a topic in the manual. helplink :: Text -> Text -> HtmlUrl r helplink topic label = [hamlet|#{label}|] where u = manualurl <> if T.null topic then "" else T.cons '#' topic ---------------------------------------------------------------------- -- hledger report renderers -- | Render a "BalanceReport" as html. balanceReportAsHtml :: r -> Journal -> [QueryOpt] -> BalanceReport -> HtmlUrl r balanceReportAsHtml registerR j qopts (items, total) = [hamlet| $forall (acct, adisplay, aindent, abal) <- items
\#{indent aindent} #{adisplay} $if hasSubs acct only ^{mixedAmountAsHtml abal} ^{mixedAmountAsHtml total} |] where l = ledgerFromJournal Any j inacctClass acct = case inAccountQuery qopts of Just m' -> if m' `matchesAccount` acct then "inacct" else "" Nothing -> "" :: Text hasSubs acct = maybe True (not . null . asubs) (ledgerAccount l acct) indent a = preEscapedString $ concat $ replicate (2 + 2 * a) " " acctLink acct = (registerR, [("q", accountQuery acct)]) acctOnlyLink acct = (registerR, [("q", accountOnlyQuery acct)]) accountQuery :: AccountName -> Text accountQuery = ("inacct:" <>) . quoteIfSpaced accountOnlyQuery :: AccountName -> Text accountOnlyQuery = ("inacctonly:" <>) . quoteIfSpaced numberTransactionsReportItems :: [TransactionsReportItem] -> [(Int, Bool, Bool, TransactionsReportItem)] numberTransactionsReportItems [] = [] numberTransactionsReportItems items = number 0 nulldate items where number :: Int -> Day -> [TransactionsReportItem] -> [(Int, Bool, Bool, TransactionsReportItem)] number _ _ [] = [] number n prevd (i@(t, _, _, _, _, _):rest) = (n+1, newday, newmonth, i): number (n+1) d rest where d = tdate t newday = d /= prevd newmonth = dm /= prevdm || dy /= prevdy (dy, dm, _) = toGregorian d (prevdy, prevdm, _) = toGregorian prevd mixedAmountAsHtml :: MixedAmount -> HtmlUrl a mixedAmountAsHtml b = [hamlet| $forall t <- ts #{t}
|] where ts = T.lines . T.pack $ showMixedAmountWithoutPrice b c = case isNegativeMixedAmount b of Just True -> "negative amount" :: Text _ -> "positive amount" showErrors :: ToMarkup a => [a] -> HandlerFor m () showErrors errs = setMessage [shamlet| Errors:
$forall e <- errs \#{e}
|]