packages feed

hledger-web 1.9.2 → 1.10

raw patch · 51 files changed

+1636/−1913 lines, 51 filesdep +case-insensitivedep +conduitdep +semigroupsdep −base-compatdep −hspecdep −parsecdep ~basedep ~hledgerdep ~hledger-libPVP ok

version bump matches the API change (PVP)

Dependencies added: case-insensitive, conduit, semigroups

Dependencies removed: base-compat, hspec, parsec, safe, yesod-test

Dependency ranges changed: base, hledger, hledger-lib, megaparsec

API changes (from Hackage documentation)

- Application: getApplicationDev :: IO (Int, Application)
- Application: instance Yesod.Core.Class.Dispatch.YesodDispatch Foundation.App
- Application: makeApplication :: WebOpts -> Journal -> AppConfig DefaultEnv Extra -> IO Application
- Application: makeFoundation :: AppConfig DefaultEnv Extra -> WebOpts -> IO App
- Foundation: App :: AppConfig DefaultEnv Extra -> Static -> Manager -> WebOpts -> IORef Journal -> App
- Foundation: MsgHello :: AppMessage
- Foundation: VD :: WebOpts -> AppRoute -> Maybe Html -> Day -> Journal -> String -> Query -> [QueryOpt] -> Query -> [QueryOpt] -> Bool -> Bool -> ViewData
- Foundation: [am] :: ViewData -> Query
- Foundation: [aopts] :: ViewData -> [QueryOpt]
- Foundation: [appJournal] :: App -> IORef Journal
- Foundation: [appOpts] :: App -> WebOpts
- Foundation: [getStatic] :: App -> Static
- Foundation: [here] :: ViewData -> AppRoute
- Foundation: [httpManager] :: App -> Manager
- Foundation: [j] :: ViewData -> Journal
- Foundation: [m] :: ViewData -> Query
- Foundation: [msg] :: ViewData -> Maybe Html
- Foundation: [opts] :: ViewData -> WebOpts
- Foundation: [q] :: ViewData -> String
- Foundation: [qopts] :: ViewData -> [QueryOpt]
- Foundation: [settings] :: App -> AppConfig DefaultEnv Extra
- Foundation: [showpostings] :: ViewData -> Bool
- Foundation: [showsidebar] :: ViewData -> Bool
- Foundation: [today] :: ViewData -> Day
- Foundation: addform :: Text -> ViewData -> HtmlUrl AppRoute
- Foundation: data App
- Foundation: data AppMessage
- Foundation: data ViewData
- Foundation: getExtra :: Handler Extra
- Foundation: getLastMessage :: Handler (Maybe Html)
- Foundation: getViewData :: Handler ViewData
- Foundation: instance GHC.Classes.Eq (Yesod.Routes.Class.Route Foundation.App)
- Foundation: instance GHC.Read.Read (Yesod.Routes.Class.Route Foundation.App)
- Foundation: instance GHC.Show.Show (Yesod.Routes.Class.Route Foundation.App)
- Foundation: instance GHC.Show.Show Foundation.ViewData
- Foundation: instance GHC.Show.Show Text.Blaze.Internal.Markup
- Foundation: instance Text.Shakespeare.I18N.RenderMessage Foundation.App Foundation.AppMessage
- Foundation: instance Text.Shakespeare.I18N.RenderMessage Foundation.App Yesod.Form.Types.FormMessage
- Foundation: instance Yesod.Core.Class.Yesod.Yesod Foundation.App
- Foundation: instance Yesod.Routes.Class.ParseRoute Foundation.App
- Foundation: instance Yesod.Routes.Class.RenderRoute Foundation.App
- Foundation: instance Yesod.Routes.Class.RouteAttrs Foundation.App
- Foundation: journalradio :: [FilePath] -> HtmlUrl AppRoute
- Foundation: journalselect :: [FilePath] -> HtmlUrl AppRoute
- Foundation: nullviewdata :: ViewData
- Foundation: resourcesApp :: [ResourceTree String]
- Foundation: type AppRoute = Route App
- Foundation: type Form x = Html -> MForm (HandlerFor App) (FormResult x, Widget)
- Foundation: type Handler = HandlerFor App
- Foundation: type Widget = WidgetFor App ()
- Foundation: viewdataWithDateAndParams :: Day -> String -> String -> String -> ViewData
- Handler.AddForm: AddForm :: Day -> Maybe Text -> Maybe Text -> AddForm
- Handler.AddForm: [addFormDate] :: AddForm -> Day
- Handler.AddForm: [addFormDescription] :: AddForm -> Maybe Text
- Handler.AddForm: [addFormJournalFile] :: AddForm -> Maybe Text
- Handler.AddForm: data AddForm
- Handler.AddForm: instance GHC.Show.Show Handler.AddForm.AddForm
- Handler.AddForm: postAddForm :: Handler Html
- Handler.Common: accountOnlyQuery :: AccountName -> String
- Handler.Common: accountQuery :: AccountName -> String
- Handler.Common: accountUrl :: AppRoute -> AccountName -> (AppRoute, [(Text, Text)])
- Handler.Common: balanceReportAsHtml :: WebOpts -> ViewData -> BalanceReport -> HtmlUrl AppRoute
- Handler.Common: helplink :: String -> String -> HtmlUrl AppRoute
- Handler.Common: hledgerLayout :: ViewData -> String -> HtmlUrl AppRoute -> HandlerFor App Html
- Handler.Common: mixedAmountAsHtml :: MixedAmount -> Html
- Handler.Common: nulltemplate :: HtmlUrl AppRoute
- Handler.Common: numberTransactionsReportItems :: [TransactionsReportItem] -> [(Int, Bool, Bool, Bool, TransactionsReportItem)]
- Handler.Common: searchform :: ViewData -> HtmlUrl AppRoute
- Handler.Common: sidebar :: ViewData -> HtmlUrl AppRoute
- Handler.Common: topbar :: ViewData -> HtmlUrl AppRoute
- Handler.JournalR: getJournalR :: Handler Html
- Handler.JournalR: journalTransactionsReportAsHtml :: WebOpts -> ViewData -> TransactionsReport -> HtmlUrl AppRoute
- Handler.JournalR: postJournalR :: Handler Html
- Handler.RegisterR: getRegisterR :: Handler Html
- Handler.RegisterR: postRegisterR :: Handler Html
- Handler.RegisterR: registerChartHtml :: [(CommoditySymbol, (String, [TransactionsReportItem]))] -> HtmlUrl AppRoute
- Handler.RegisterR: registerItemsHtml :: WebOpts -> ViewData -> TransactionsReport -> HtmlUrl AppRoute
- Handler.RegisterR: registerReportHtml :: WebOpts -> ViewData -> TransactionsReport -> HtmlUrl AppRoute
- Handler.RootR: getRootR :: Handler Html
- Handler.SidebarR: getSidebarR :: Handler Html
- Handler.Utils: dayToJsTimestamp :: Day -> Integer
- Handler.Utils: numbered :: [a] -> [(Int, a)]
- Hledger.Web.Main: withJournalDo' :: WebOpts -> (WebOpts -> Journal -> IO ()) -> IO ()
- Settings: Extra :: Text -> Maybe Text -> Maybe Text -> Extra
- Settings: [extraAnalytics] :: Extra -> Maybe Text
- Settings: [extraCopyright] :: Extra -> Text
- Settings: [extraStaticRoot] :: Extra -> Maybe Text
- Settings: data Extra
- Settings: defbaseurl :: String -> Int -> String
- Settings: defhost :: String
- Settings: defport :: Int
- Settings: hledgerorgurl :: String
- Settings: instance GHC.Show.Show Settings.Extra
- Settings: manualurl :: String
- Settings: parseExtra :: DefaultEnv -> Object -> Parser Extra
- Settings: staticDir :: FilePath
- Settings: staticRoot :: AppConfig DefaultEnv Extra -> Text
- Settings: widgetFile :: String -> Q Exp
- Settings: widgetFileSettings :: WidgetFileSettings
- Settings.Development: development :: Bool
- Settings.Development: production :: Bool
- Settings.StaticFiles: css_bootstrap_css :: StaticRoute
- Settings.StaticFiles: css_bootstrap_css_map :: StaticRoute
- Settings.StaticFiles: css_bootstrap_datepicker_standalone_min_css :: StaticRoute
- Settings.StaticFiles: css_bootstrap_min_css :: StaticRoute
- Settings.StaticFiles: css_bootstrap_theme_css :: StaticRoute
- Settings.StaticFiles: css_bootstrap_theme_css_map :: StaticRoute
- Settings.StaticFiles: css_bootstrap_theme_min_css :: StaticRoute
- Settings.StaticFiles: fonts_glyphicons_halflings_regular_eot :: StaticRoute
- Settings.StaticFiles: fonts_glyphicons_halflings_regular_svg :: StaticRoute
- Settings.StaticFiles: fonts_glyphicons_halflings_regular_ttf :: StaticRoute
- Settings.StaticFiles: fonts_glyphicons_halflings_regular_woff :: StaticRoute
- Settings.StaticFiles: hledger_css :: StaticRoute
- Settings.StaticFiles: hledger_js :: StaticRoute
- Settings.StaticFiles: js_bootstrap_datepicker_min_js :: StaticRoute
- Settings.StaticFiles: js_bootstrap_js :: StaticRoute
- Settings.StaticFiles: js_bootstrap_min_js :: StaticRoute
- Settings.StaticFiles: js_excanvas_js :: StaticRoute
- Settings.StaticFiles: js_excanvas_min_js :: StaticRoute
- Settings.StaticFiles: js_jquery_cookie_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_canvas_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_canvas_min_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_categories_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_categories_min_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_crosshair_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_crosshair_min_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_errorbars_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_errorbars_min_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_fillbetween_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_fillbetween_min_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_image_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_image_min_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_min_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_navigate_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_navigate_min_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_pie_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_pie_min_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_resize_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_resize_min_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_selection_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_selection_min_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_stack_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_stack_min_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_symbol_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_symbol_min_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_threshold_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_threshold_min_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_time_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_time_min_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_tooltip_js :: StaticRoute
- Settings.StaticFiles: js_jquery_flot_tooltip_min_js :: StaticRoute
- Settings.StaticFiles: js_jquery_hotkeys_js :: StaticRoute
- Settings.StaticFiles: js_jquery_js :: StaticRoute
- Settings.StaticFiles: js_jquery_min_js :: StaticRoute
- Settings.StaticFiles: js_jquery_url_js :: StaticRoute
- Settings.StaticFiles: js_typeahead_bundle_js :: StaticRoute
- Settings.StaticFiles: js_typeahead_bundle_min_js :: StaticRoute
- Settings.StaticFiles: staticSite :: IO Static
+ Hledger.Web.Application: instance Yesod.Core.Class.Dispatch.YesodDispatch Hledger.Web.Foundation.App
+ Hledger.Web.Application: makeApplication :: WebOpts -> Journal -> AppConfig DefaultEnv Extra -> IO Application
+ Hledger.Web.Application: makeFoundation :: AppConfig DefaultEnv Extra -> WebOpts -> IO App
+ Hledger.Web.Foundation: App :: AppConfig DefaultEnv Extra -> Static -> Manager -> WebOpts -> IORef Journal -> App
+ Hledger.Web.Foundation: VD :: WebOpts -> Day -> Journal -> Text -> Query -> [QueryOpt] -> [Capability] -> ViewData
+ Hledger.Web.Foundation: [appJournal] :: App -> IORef Journal
+ Hledger.Web.Foundation: [appOpts] :: App -> WebOpts
+ Hledger.Web.Foundation: [caps] :: ViewData -> [Capability]
+ Hledger.Web.Foundation: [getStatic] :: App -> Static
+ Hledger.Web.Foundation: [httpManager] :: App -> Manager
+ Hledger.Web.Foundation: [j] :: ViewData -> Journal
+ Hledger.Web.Foundation: [m] :: ViewData -> Query
+ Hledger.Web.Foundation: [opts] :: ViewData -> WebOpts
+ Hledger.Web.Foundation: [q] :: ViewData -> Text
+ Hledger.Web.Foundation: [qopts] :: ViewData -> [QueryOpt]
+ Hledger.Web.Foundation: [settings] :: App -> AppConfig DefaultEnv Extra
+ Hledger.Web.Foundation: [today] :: ViewData -> Day
+ Hledger.Web.Foundation: data App
+ Hledger.Web.Foundation: data ViewData
+ Hledger.Web.Foundation: getCurrentJournal :: IORef Journal -> CliOpts -> Day -> Handler (Journal, Maybe String)
+ Hledger.Web.Foundation: getViewData :: Handler ViewData
+ Hledger.Web.Foundation: instance GHC.Classes.Eq (Yesod.Routes.Class.Route Hledger.Web.Foundation.App)
+ Hledger.Web.Foundation: instance GHC.Read.Read (Yesod.Routes.Class.Route Hledger.Web.Foundation.App)
+ Hledger.Web.Foundation: instance GHC.Show.Show (Yesod.Routes.Class.Route Hledger.Web.Foundation.App)
+ Hledger.Web.Foundation: instance GHC.Show.Show Hledger.Web.Foundation.ViewData
+ Hledger.Web.Foundation: instance GHC.Show.Show Text.Blaze.Internal.Markup
+ Hledger.Web.Foundation: instance Text.Shakespeare.I18N.RenderMessage Hledger.Web.Foundation.App Yesod.Form.Types.FormMessage
+ Hledger.Web.Foundation: instance Yesod.Core.Class.Yesod.Yesod Hledger.Web.Foundation.App
+ Hledger.Web.Foundation: instance Yesod.Routes.Class.ParseRoute Hledger.Web.Foundation.App
+ Hledger.Web.Foundation: instance Yesod.Routes.Class.RenderRoute Hledger.Web.Foundation.App
+ Hledger.Web.Foundation: instance Yesod.Routes.Class.RouteAttrs Hledger.Web.Foundation.App
+ Hledger.Web.Foundation: resourcesApp :: [ResourceTree String]
+ Hledger.Web.Foundation: shouldShowSidebar :: Handler Bool
+ Hledger.Web.Foundation: type AppRoute = Route App
+ Hledger.Web.Foundation: type Form x = Html -> MForm (HandlerFor App) (FormResult x, Widget)
+ Hledger.Web.Foundation: type Handler = HandlerFor App
+ Hledger.Web.Foundation: type Widget = WidgetFor App ()
+ Hledger.Web.Handler.AddR: getAddR :: Handler ()
+ Hledger.Web.Handler.AddR: postAddR :: Handler ()
+ Hledger.Web.Handler.Common: getDownloadR :: FilePath -> Handler TypedContent
+ Hledger.Web.Handler.Common: getFaviconR :: MonadHandler m => m ()
+ Hledger.Web.Handler.Common: getManageR :: Handler Html
+ Hledger.Web.Handler.Common: getRobotsR :: MonadHandler m => m ()
+ Hledger.Web.Handler.Common: getRootR :: Handler Html
+ Hledger.Web.Handler.EditR: getEditR :: FilePath -> Handler ()
+ Hledger.Web.Handler.EditR: postEditR :: FilePath -> Handler ()
+ Hledger.Web.Handler.JournalR: getJournalR :: Handler Html
+ Hledger.Web.Handler.RegisterR: dayToJsTimestamp :: Day -> Integer
+ Hledger.Web.Handler.RegisterR: getRegisterR :: Handler Html
+ Hledger.Web.Handler.RegisterR: registerChartHtml :: [(CommoditySymbol, (String, [TransactionsReportItem]))] -> HtmlUrl AppRoute
+ Hledger.Web.Handler.UploadR: getUploadR :: FilePath -> Handler ()
+ Hledger.Web.Handler.UploadR: postUploadR :: FilePath -> Handler ()
+ Hledger.Web.Import: (!!) :: () => [a] -> Int -> a
+ Hledger.Web.Import: (!=.) :: PersistField typ => EntityField v typ -> typ -> Filter v
+ Hledger.Web.Import: ($!) :: () => a -> b -> a -> b
+ Hledger.Web.Import: ($) :: () => a -> b -> a -> b
+ Hledger.Web.Import: (&&) :: Bool -> Bool -> Bool
+ Hledger.Web.Import: (*) :: Num a => a -> a -> a
+ Hledger.Web.Import: (**) :: Floating a => a -> a -> a
+ Hledger.Web.Import: (*=.) :: PersistField typ => EntityField v typ -> typ -> Update v
+ Hledger.Web.Import: (*>) :: Applicative f => f a -> f b -> f b
+ Hledger.Web.Import: (+) :: Num a => a -> a -> a
+ Hledger.Web.Import: (++) :: () => [a] -> [a] -> [a]
+ Hledger.Web.Import: (+=.) :: PersistField typ => EntityField v typ -> typ -> Update v
+ Hledger.Web.Import: (-) :: Num a => a -> a -> a
+ Hledger.Web.Import: (-=.) :: PersistField typ => EntityField v typ -> typ -> Update v
+ Hledger.Web.Import: (.) :: () => b -> c -> a -> b -> a -> c
+ Hledger.Web.Import: (.:) :: FromJSON a => Object -> Text -> Parser a
+ Hledger.Web.Import: (.=) :: (KeyValue kv, ToJSON v) => Text -> v -> kv
+ Hledger.Web.Import: (/) :: Fractional a => a -> a -> a
+ Hledger.Web.Import: (/<-.) :: PersistField typ => EntityField v typ -> [typ] -> Filter v
+ Hledger.Web.Import: (/=) :: Eq a => a -> a -> Bool
+ Hledger.Web.Import: (/=.) :: PersistField typ => EntityField v typ -> typ -> Update v
+ Hledger.Web.Import: (:#:) :: a -> b -> Fragment a b
+ Hledger.Web.Import: (<$!>) :: Monad m => a -> b -> m a -> m b
+ Hledger.Web.Import: (<$) :: Functor f => a -> f b -> f a
+ Hledger.Web.Import: (<$>) :: Functor f => a -> b -> f a -> f b
+ Hledger.Web.Import: (<) :: Ord a => a -> a -> Bool
+ Hledger.Web.Import: (<*) :: Applicative f => f a -> f b -> f a
+ Hledger.Web.Import: (<*>) :: Applicative f => f a -> b -> f a -> f b
+ Hledger.Web.Import: (<-.) :: PersistField typ => EntityField v typ -> [typ] -> Filter v
+ Hledger.Web.Import: (<.) :: PersistField typ => EntityField v typ -> typ -> Filter v
+ Hledger.Web.Import: (<=) :: Ord a => a -> a -> Bool
+ Hledger.Web.Import: (<=.) :: PersistField typ => EntityField v typ -> typ -> Filter v
+ Hledger.Web.Import: (<=<) :: Monad m => b -> m c -> a -> m b -> a -> m c
+ Hledger.Web.Import: (<>) :: Semigroup a => a -> a -> a
+ Hledger.Web.Import: (=.) :: PersistField typ => EntityField v typ -> typ -> Update v
+ Hledger.Web.Import: (=<<) :: Monad m => a -> m b -> m a -> m b
+ Hledger.Web.Import: (==) :: Eq a => a -> a -> Bool
+ Hledger.Web.Import: (==.) :: PersistField typ => EntityField v typ -> typ -> Filter v
+ Hledger.Web.Import: (>) :: Ord a => a -> a -> Bool
+ Hledger.Web.Import: (>.) :: PersistField typ => EntityField v typ -> typ -> Filter v
+ Hledger.Web.Import: (>=) :: Ord a => a -> a -> Bool
+ Hledger.Web.Import: (>=.) :: PersistField typ => EntityField v typ -> typ -> Filter v
+ Hledger.Web.Import: (>=>) :: Monad m => a -> m b -> b -> m c -> a -> m c
+ Hledger.Web.Import: (>>) :: Monad m => m a -> m b -> m b
+ Hledger.Web.Import: (>>=) :: Monad m => m a -> a -> m b -> m b
+ Hledger.Web.Import: (^) :: (Num a, Integral b) => a -> b -> a
+ Hledger.Web.Import: (^^) :: (Fractional a, Integral b) => a -> b -> a
+ Hledger.Web.Import: (||) :: Bool -> Bool -> Bool
+ Hledger.Web.Import: (||.) :: () => [Filter v] -> [Filter v] -> [Filter v]
+ Hledger.Web.Import: AForm :: (HandlerSite m, [Text]) -> Maybe (Env, FileEnv) -> Ints -> m (FormResult a, [FieldView HandlerSite m] -> [FieldView HandlerSite m], Ints, Enctype) -> AForm a
+ Hledger.Web.Import: Active :: Checkmark
+ Hledger.Web.Import: Add :: PersistUpdate
+ Hledger.Web.Import: AddCookie :: !SetCookie -> Header
+ Hledger.Web.Import: App :: AppConfig DefaultEnv Extra -> Static -> Manager -> WebOpts -> IORef Journal -> App
+ Hledger.Web.Import: ApprootMaster :: !master -> Text -> Approot master
+ Hledger.Web.Import: ApprootRelative :: Approot master
+ Hledger.Web.Import: ApprootRequest :: !master -> Request -> Text -> Approot master
+ Hledger.Web.Import: ApprootStatic :: !Text -> Approot master
+ Hledger.Web.Import: Array :: !Array -> Value
+ Hledger.Web.Import: Assign :: PersistUpdate
+ Hledger.Web.Import: AuthenticationRequired :: AuthResult
+ Hledger.Web.Import: Authorized :: AuthResult
+ Hledger.Web.Import: BackendSpecificFilter :: Text -> PersistFilter
+ Hledger.Web.Import: BackendSpecificUpdate :: Text -> PersistUpdate
+ Hledger.Web.Import: BadMethod :: !Method -> ErrorResponse
+ Hledger.Web.Import: Bool :: !Bool -> Value
+ Hledger.Web.Import: BottomOfBody :: ScriptLoadPosition master
+ Hledger.Web.Import: BottomOfHeadAsync :: !BottomOfHeadAsync master -> ScriptLoadPosition master
+ Hledger.Web.Import: BottomOfHeadBlocking :: ScriptLoadPosition master
+ Hledger.Web.Import: ByMaybeAttr :: WhyNullable
+ Hledger.Web.Import: ByNullableAttr :: WhyNullable
+ Hledger.Web.Import: CapAdd :: Capability
+ Hledger.Web.Import: CapManage :: Capability
+ Hledger.Web.Import: CapView :: Capability
+ Hledger.Web.Import: CompositeDef :: ![FieldDef] -> ![Attr] -> CompositeDef
+ Hledger.Web.Import: CompositeRef :: CompositeDef -> ReferenceDef
+ Hledger.Web.Import: ContentBuilder :: !Builder -> !Maybe Int -> Content
+ Hledger.Web.Import: ContentDontEvaluate :: !Content -> Content
+ Hledger.Web.Import: ContentFile :: !FilePath -> !Maybe FilePart -> Content
+ Hledger.Web.Import: ContentSource :: !ConduitT () Flush Builder ResourceT IO () -> Content
+ Hledger.Web.Import: CssBuilder :: Builder -> CssBuilder
+ Hledger.Web.Import: DBName :: Text -> DBName
+ Hledger.Web.Import: DBRunner :: forall a. () => YesodDB site a -> HandlerFor site a -> DBRunner site
+ Hledger.Web.Import: DeleteCookie :: !ByteString -> !ByteString -> Header
+ Hledger.Web.Import: Divide :: PersistUpdate
+ Hledger.Web.Import: DontFullyEvaluate :: a -> DontFullyEvaluate a
+ Hledger.Web.Import: EQ :: Ordering
+ Hledger.Web.Import: EmbedEntityDef :: !HaskellName -> ![EmbedFieldDef] -> EmbedEntityDef
+ Hledger.Web.Import: EmbedFieldDef :: !DBName -> Maybe EmbedEntityDef -> Maybe HaskellName -> EmbedFieldDef
+ Hledger.Web.Import: EmbedRef :: EmbedEntityDef -> ReferenceDef
+ Hledger.Web.Import: Entity :: Key record -> record -> Entity record
+ Hledger.Web.Import: EntityDef :: !HaskellName -> !DBName -> !FieldDef -> ![Attr] -> ![FieldDef] -> ![UniqueDef] -> ![ForeignDef] -> ![Text] -> !Map Text [ExtraLine] -> !Bool -> EntityDef
+ Hledger.Web.Import: EntityJSON :: Name -> Name -> EntityJSON
+ Hledger.Web.Import: Eq :: PersistFilter
+ Hledger.Web.Import: Extra :: Text -> Maybe Text -> Maybe Text -> Extra
+ Hledger.Web.Import: FTApp :: FieldType -> FieldType -> FieldType
+ Hledger.Web.Import: FTList :: FieldType -> FieldType
+ Hledger.Web.Import: FTTypeCon :: Maybe Text -> Text -> FieldType
+ Hledger.Web.Import: False :: Bool
+ Hledger.Web.Import: Field :: [Text] -> [FileInfo] -> m Either SomeMessage HandlerSite m Maybe a -> FieldViewFunc m a -> Enctype -> Field a
+ Hledger.Web.Import: FieldDef :: !HaskellName -> !DBName -> !FieldType -> !SqlType -> ![Attr] -> !Bool -> !ReferenceDef -> FieldDef
+ Hledger.Web.Import: FieldSettings :: SomeMessage master -> Maybe SomeMessage master -> Maybe Text -> Maybe Text -> [(Text, Text)] -> FieldSettings master
+ Hledger.Web.Import: FieldView :: Markup -> Maybe Markup -> Text -> WidgetFor site () -> Maybe Markup -> Bool -> FieldView site
+ Hledger.Web.Import: FileUploadDisk :: !InternalState -> BackEnd FilePath -> FileUpload
+ Hledger.Web.Import: FileUploadMemory :: !BackEnd ByteString -> FileUpload
+ Hledger.Web.Import: FileUploadSource :: !BackEnd ConduitT () ByteString ResourceT IO () -> FileUpload
+ Hledger.Web.Import: ForeignDef :: !HaskellName -> !DBName -> !HaskellName -> !DBName -> ![(ForeignFieldDef, ForeignFieldDef)] -> ![Attr] -> Bool -> ForeignDef
+ Hledger.Web.Import: ForeignRef :: !HaskellName -> !FieldType -> ReferenceDef
+ Hledger.Web.Import: FormFailure :: [Text] -> FormResult a
+ Hledger.Web.Import: FormInput :: HandlerSite m -> [Text] -> Env -> FileEnv -> m Either DText a -> FormInput a
+ Hledger.Web.Import: FormMissing :: FormResult a
+ Hledger.Web.Import: FormSuccess :: a -> FormResult a
+ Hledger.Web.Import: GT :: Ordering
+ Hledger.Web.Import: Ge :: PersistFilter
+ Hledger.Web.Import: Gt :: PersistFilter
+ Hledger.Web.Import: HaskellName :: Text -> HaskellName
+ Hledger.Web.Import: Header :: !CI ByteString -> !ByteString -> Header
+ Hledger.Web.Import: In :: PersistFilter
+ Hledger.Web.Import: Inactive :: Checkmark
+ Hledger.Web.Import: IntCons :: Int -> Ints -> Ints
+ Hledger.Web.Import: IntSingle :: Int -> Ints
+ Hledger.Web.Import: InternalError :: !Text -> ErrorResponse
+ Hledger.Web.Import: InvalidArgs :: ![Text] -> ErrorResponse
+ Hledger.Web.Import: Just :: a -> Maybe a
+ Hledger.Web.Import: KeyNotFound :: String -> UpdateException
+ Hledger.Web.Import: LT :: Ordering
+ Hledger.Web.Import: Le :: PersistFilter
+ Hledger.Web.Import: Left :: a -> Either a b
+ Hledger.Web.Import: LevelDebug :: LogLevel
+ Hledger.Web.Import: LevelError :: LogLevel
+ Hledger.Web.Import: LevelInfo :: LogLevel
+ Hledger.Web.Import: LevelOther :: Text -> LogLevel
+ Hledger.Web.Import: LevelWarn :: LogLevel
+ Hledger.Web.Import: LiteApp :: Method -> [Text] -> Maybe LiteHandler TypedContent -> LiteApp
+ Hledger.Web.Import: LocalTime :: Day -> TimeOfDay -> LocalTime
+ Hledger.Web.Import: Lt :: PersistFilter
+ Hledger.Web.Import: ModJulianDate :: Rational -> UniversalTime
+ Hledger.Web.Import: ModifiedJulianDay :: Integer -> Day
+ Hledger.Web.Import: MsgBoolNo :: FormMessage
+ Hledger.Web.Import: MsgBoolYes :: FormMessage
+ Hledger.Web.Import: MsgCsrfWarning :: FormMessage
+ Hledger.Web.Import: MsgDelete :: FormMessage
+ Hledger.Web.Import: MsgInputNotFound :: Text -> FormMessage
+ Hledger.Web.Import: MsgInvalidBool :: Text -> FormMessage
+ Hledger.Web.Import: MsgInvalidDay :: FormMessage
+ Hledger.Web.Import: MsgInvalidEmail :: Text -> FormMessage
+ Hledger.Web.Import: MsgInvalidEntry :: Text -> FormMessage
+ Hledger.Web.Import: MsgInvalidHour :: Text -> FormMessage
+ Hledger.Web.Import: MsgInvalidInteger :: Text -> FormMessage
+ Hledger.Web.Import: MsgInvalidMinute :: Text -> FormMessage
+ Hledger.Web.Import: MsgInvalidNumber :: Text -> FormMessage
+ Hledger.Web.Import: MsgInvalidSecond :: Text -> FormMessage
+ Hledger.Web.Import: MsgInvalidTimeFormat :: FormMessage
+ Hledger.Web.Import: MsgInvalidUrl :: Text -> FormMessage
+ Hledger.Web.Import: MsgSelectNone :: FormMessage
+ Hledger.Web.Import: MsgValueRequired :: FormMessage
+ Hledger.Web.Import: Multipart :: Enctype
+ Hledger.Web.Import: Multiply :: PersistUpdate
+ Hledger.Web.Import: Ne :: PersistFilter
+ Hledger.Web.Import: NoReference :: ReferenceDef
+ Hledger.Web.Import: NotAuthenticated :: ErrorResponse
+ Hledger.Web.Import: NotFound :: ErrorResponse
+ Hledger.Web.Import: NotIn :: PersistFilter
+ Hledger.Web.Import: NotNullable :: IsNullable
+ Hledger.Web.Import: Nothing :: Maybe a
+ Hledger.Web.Import: Null :: Value
+ Hledger.Web.Import: Nullable :: !WhyNullable -> IsNullable
+ Hledger.Web.Import: Number :: !Scientific -> Value
+ Hledger.Web.Import: Object :: !Object -> Value
+ Hledger.Web.Import: OnlyUniqueException :: String -> OnlyUniqueException
+ Hledger.Web.Import: Option :: Text -> a -> Text -> Option a
+ Hledger.Web.Import: OptionList :: [Option a] -> Text -> Maybe a -> OptionList a
+ Hledger.Web.Import: PageContent :: !Html -> !HtmlUrl url -> !HtmlUrl url -> PageContent url
+ Hledger.Web.Import: PermissionDenied :: !Text -> ErrorResponse
+ Hledger.Web.Import: PersistBool :: Bool -> PersistValue
+ Hledger.Web.Import: PersistByteString :: ByteString -> PersistValue
+ Hledger.Web.Import: PersistDay :: Day -> PersistValue
+ Hledger.Web.Import: PersistDbSpecific :: ByteString -> PersistValue
+ Hledger.Web.Import: PersistDouble :: Double -> PersistValue
+ Hledger.Web.Import: PersistError :: Text -> PersistException
+ Hledger.Web.Import: PersistForeignConstraintUnmet :: Text -> PersistException
+ Hledger.Web.Import: PersistInt64 :: Int64 -> PersistValue
+ Hledger.Web.Import: PersistInvalidField :: Text -> PersistException
+ Hledger.Web.Import: PersistList :: [PersistValue] -> PersistValue
+ Hledger.Web.Import: PersistMap :: [(Text, PersistValue)] -> PersistValue
+ Hledger.Web.Import: PersistMarshalError :: Text -> PersistException
+ Hledger.Web.Import: PersistMongoDBError :: Text -> PersistException
+ Hledger.Web.Import: PersistMongoDBUnsupported :: Text -> PersistException
+ Hledger.Web.Import: PersistNull :: PersistValue
+ Hledger.Web.Import: PersistObjectId :: ByteString -> PersistValue
+ Hledger.Web.Import: PersistRational :: Rational -> PersistValue
+ Hledger.Web.Import: PersistText :: Text -> PersistValue
+ Hledger.Web.Import: PersistTimeOfDay :: TimeOfDay -> PersistValue
+ Hledger.Web.Import: PersistUTCTime :: UTCTime -> PersistValue
+ Hledger.Web.Import: RepJson :: Content -> RepJson
+ Hledger.Web.Import: RepPlain :: Content -> RepPlain
+ Hledger.Web.Import: RepXml :: Content -> RepXml
+ Hledger.Web.Import: Right :: b -> Either a b
+ Hledger.Web.Import: SelfReference :: ReferenceDef
+ Hledger.Web.Import: SessionBackend :: Request -> IO (SessionMap, SaveSession) -> SessionBackend
+ Hledger.Web.Import: SqlBlob :: SqlType
+ Hledger.Web.Import: SqlBool :: SqlType
+ Hledger.Web.Import: SqlDay :: SqlType
+ Hledger.Web.Import: SqlDayTime :: SqlType
+ Hledger.Web.Import: SqlInt32 :: SqlType
+ Hledger.Web.Import: SqlInt64 :: SqlType
+ Hledger.Web.Import: SqlNumeric :: Word32 -> Word32 -> SqlType
+ Hledger.Web.Import: SqlOther :: Text -> SqlType
+ Hledger.Web.Import: SqlReal :: SqlType
+ Hledger.Web.Import: SqlString :: SqlType
+ Hledger.Web.Import: SqlTime :: SqlType
+ Hledger.Web.Import: String :: !Text -> Value
+ Hledger.Web.Import: Subtract :: PersistUpdate
+ Hledger.Web.Import: Textarea :: Text -> Textarea
+ Hledger.Web.Import: TimeLocale :: [(String, String)] -> [(String, String)] -> (String, String) -> String -> String -> String -> String -> [TimeZone] -> TimeLocale
+ Hledger.Web.Import: TimeOfDay :: Int -> Int -> Pico -> TimeOfDay
+ Hledger.Web.Import: TimeZone :: Int -> Bool -> String -> TimeZone
+ Hledger.Web.Import: True :: Bool
+ Hledger.Web.Import: TypedContent :: !ContentType -> !Content -> TypedContent
+ Hledger.Web.Import: UTCTime :: Day -> DiffTime -> UTCTime
+ Hledger.Web.Import: Unauthorized :: !Text -> AuthResult
+ Hledger.Web.Import: UniqueDef :: !HaskellName -> !DBName -> ![(HaskellName, DBName)] -> ![Attr] -> UniqueDef
+ Hledger.Web.Import: UpsertError :: String -> UpdateException
+ Hledger.Web.Import: UrlEncoded :: Enctype
+ Hledger.Web.Import: VD :: WebOpts -> Day -> Journal -> Text -> Query -> [QueryOpt] -> [Capability] -> ViewData
+ Hledger.Web.Import: WaiSubsite :: Application -> WaiSubsite
+ Hledger.Web.Import: WaiSubsiteWithAuth :: Application -> WaiSubsiteWithAuth
+ Hledger.Web.Import: YesodRequest :: ![(Text, Text)] -> ![(Text, Text)] -> !Request -> ![Text] -> !Maybe Text -> !SessionMap -> ![ContentType] -> YesodRequest
+ Hledger.Web.Import: ZonedTime :: LocalTime -> TimeZone -> ZonedTime
+ Hledger.Web.Import: [Asc] :: SelectOpt record
+ Hledger.Web.Import: [BackendFilter] :: Filter record
+ Hledger.Web.Import: [BackendUpdate] :: Update record
+ Hledger.Web.Import: [Desc] :: SelectOpt record
+ Hledger.Web.Import: [FilterAnd] :: Filter record
+ Hledger.Web.Import: [FilterOr] :: Filter record
+ Hledger.Web.Import: [Filter] :: Filter record
+ Hledger.Web.Import: [LimitTo] :: SelectOpt record
+ Hledger.Web.Import: [OffsetBy] :: SelectOpt record
+ Hledger.Web.Import: [SomeMessage] :: SomeMessage master
+ Hledger.Web.Import: [SomePersistField] :: SomePersistField
+ Hledger.Web.Import: [Update] :: Update record
+ Hledger.Web.Import: [amPm] :: TimeLocale -> (String, String)
+ Hledger.Web.Import: [appJournal] :: App -> IORef Journal
+ Hledger.Web.Import: [appOpts] :: App -> WebOpts
+ Hledger.Web.Import: [caps] :: ViewData -> [Capability]
+ Hledger.Web.Import: [compositeAttrs] :: CompositeDef -> ![Attr]
+ Hledger.Web.Import: [compositeFields] :: CompositeDef -> ![FieldDef]
+ Hledger.Web.Import: [dateFmt] :: TimeLocale -> String
+ Hledger.Web.Import: [dateTimeFmt] :: TimeLocale -> String
+ Hledger.Web.Import: [emFieldCycle] :: EmbedFieldDef -> Maybe HaskellName
+ Hledger.Web.Import: [emFieldDB] :: EmbedFieldDef -> !DBName
+ Hledger.Web.Import: [emFieldEmbed] :: EmbedFieldDef -> Maybe EmbedEntityDef
+ Hledger.Web.Import: [embeddedFields] :: EmbedEntityDef -> ![EmbedFieldDef]
+ Hledger.Web.Import: [embeddedHaskell] :: EmbedEntityDef -> !HaskellName
+ Hledger.Web.Import: [entityAttrs] :: EntityDef -> ![Attr]
+ Hledger.Web.Import: [entityDB] :: EntityDef -> !DBName
+ Hledger.Web.Import: [entityDerives] :: EntityDef -> ![Text]
+ Hledger.Web.Import: [entityExtra] :: EntityDef -> !Map Text [ExtraLine]
+ Hledger.Web.Import: [entityFields] :: EntityDef -> ![FieldDef]
+ Hledger.Web.Import: [entityForeigns] :: EntityDef -> ![ForeignDef]
+ Hledger.Web.Import: [entityFromJSON] :: EntityJSON -> Name
+ Hledger.Web.Import: [entityHaskell] :: EntityDef -> !HaskellName
+ Hledger.Web.Import: [entityId] :: EntityDef -> !FieldDef
+ Hledger.Web.Import: [entityKey] :: Entity record -> Key record
+ Hledger.Web.Import: [entitySum] :: EntityDef -> !Bool
+ Hledger.Web.Import: [entityToJSON] :: EntityJSON -> Name
+ Hledger.Web.Import: [entityUniques] :: EntityDef -> ![UniqueDef]
+ Hledger.Web.Import: [entityVal] :: Entity record -> record
+ Hledger.Web.Import: [extraAnalytics] :: Extra -> Maybe Text
+ Hledger.Web.Import: [extraCopyright] :: Extra -> Text
+ Hledger.Web.Import: [extraStaticRoot] :: Extra -> Maybe Text
+ Hledger.Web.Import: [fieldAttrs] :: FieldDef -> ![Attr]
+ Hledger.Web.Import: [fieldDB] :: FieldDef -> !DBName
+ Hledger.Web.Import: [fieldEnctype] :: Field a -> Enctype
+ Hledger.Web.Import: [fieldHaskell] :: FieldDef -> !HaskellName
+ Hledger.Web.Import: [fieldParse] :: Field a -> [Text] -> [FileInfo] -> m Either SomeMessage HandlerSite m Maybe a
+ Hledger.Web.Import: [fieldReference] :: FieldDef -> !ReferenceDef
+ Hledger.Web.Import: [fieldSqlType] :: FieldDef -> !SqlType
+ Hledger.Web.Import: [fieldStrict] :: FieldDef -> !Bool
+ Hledger.Web.Import: [fieldType] :: FieldDef -> !FieldType
+ Hledger.Web.Import: [fieldView] :: Field a -> FieldViewFunc m a
+ Hledger.Web.Import: [foreignAttrs] :: ForeignDef -> ![Attr]
+ Hledger.Web.Import: [foreignConstraintNameDBName] :: ForeignDef -> !DBName
+ Hledger.Web.Import: [foreignConstraintNameHaskell] :: ForeignDef -> !HaskellName
+ Hledger.Web.Import: [foreignFields] :: ForeignDef -> ![(ForeignFieldDef, ForeignFieldDef)]
+ Hledger.Web.Import: [foreignNullable] :: ForeignDef -> Bool
+ Hledger.Web.Import: [foreignRefTableDBName] :: ForeignDef -> !DBName
+ Hledger.Web.Import: [foreignRefTableHaskell] :: ForeignDef -> !HaskellName
+ Hledger.Web.Import: [fsAttrs] :: FieldSettings master -> [(Text, Text)]
+ Hledger.Web.Import: [fsId] :: FieldSettings master -> Maybe Text
+ Hledger.Web.Import: [fsLabel] :: FieldSettings master -> SomeMessage master
+ Hledger.Web.Import: [fsName] :: FieldSettings master -> Maybe Text
+ Hledger.Web.Import: [fsTooltip] :: FieldSettings master -> Maybe SomeMessage master
+ Hledger.Web.Import: [fvErrors] :: FieldView site -> Maybe Markup
+ Hledger.Web.Import: [fvId] :: FieldView site -> Text
+ Hledger.Web.Import: [fvInput] :: FieldView site -> WidgetFor site ()
+ Hledger.Web.Import: [fvLabel] :: FieldView site -> Markup
+ Hledger.Web.Import: [fvRequired] :: FieldView site -> Bool
+ Hledger.Web.Import: [fvTooltip] :: FieldView site -> Maybe Markup
+ Hledger.Web.Import: [getModJulianDate] :: UniversalTime -> Rational
+ Hledger.Web.Import: [getStatic] :: App -> Static
+ Hledger.Web.Import: [httpManager] :: App -> Manager
+ Hledger.Web.Import: [j] :: ViewData -> Journal
+ Hledger.Web.Import: [knownTimeZones] :: TimeLocale -> [TimeZone]
+ Hledger.Web.Import: [localDay] :: LocalTime -> Day
+ Hledger.Web.Import: [localTimeOfDay] :: LocalTime -> TimeOfDay
+ Hledger.Web.Import: [m] :: ViewData -> Query
+ Hledger.Web.Import: [months] :: TimeLocale -> [(String, String)]
+ Hledger.Web.Import: [olOptions] :: OptionList a -> [Option a]
+ Hledger.Web.Import: [olReadExternal] :: OptionList a -> Text -> Maybe a
+ Hledger.Web.Import: [optionDisplay] :: Option a -> Text
+ Hledger.Web.Import: [optionExternalValue] :: Option a -> Text
+ Hledger.Web.Import: [optionInternalValue] :: Option a -> a
+ Hledger.Web.Import: [opts] :: ViewData -> WebOpts
+ Hledger.Web.Import: [pageBody] :: PageContent url -> !HtmlUrl url
+ Hledger.Web.Import: [pageHead] :: PageContent url -> !HtmlUrl url
+ Hledger.Web.Import: [pageTitle] :: PageContent url -> !Html
+ Hledger.Web.Import: [q] :: ViewData -> Text
+ Hledger.Web.Import: [qopts] :: ViewData -> [QueryOpt]
+ Hledger.Web.Import: [reqAccept] :: YesodRequest -> ![ContentType]
+ Hledger.Web.Import: [reqCookies] :: YesodRequest -> ![(Text, Text)]
+ Hledger.Web.Import: [reqGetParams] :: YesodRequest -> ![(Text, Text)]
+ Hledger.Web.Import: [reqLangs] :: YesodRequest -> ![Text]
+ Hledger.Web.Import: [reqSession] :: YesodRequest -> !SessionMap
+ Hledger.Web.Import: [reqToken] :: YesodRequest -> !Maybe Text
+ Hledger.Web.Import: [reqWaiRequest] :: YesodRequest -> !Request
+ Hledger.Web.Import: [runDBRunner] :: DBRunner site -> forall a. () => YesodDB site a -> HandlerFor site a
+ Hledger.Web.Import: [runWaiSubsiteWithAuth] :: WaiSubsiteWithAuth -> Application
+ Hledger.Web.Import: [runWaiSubsite] :: WaiSubsite -> Application
+ Hledger.Web.Import: [sbLoadSession] :: SessionBackend -> Request -> IO (SessionMap, SaveSession)
+ Hledger.Web.Import: [settings] :: App -> AppConfig DefaultEnv Extra
+ Hledger.Web.Import: [time12Fmt] :: TimeLocale -> String
+ Hledger.Web.Import: [timeFmt] :: TimeLocale -> String
+ Hledger.Web.Import: [timeZoneMinutes] :: TimeZone -> Int
+ Hledger.Web.Import: [timeZoneName] :: TimeZone -> String
+ Hledger.Web.Import: [timeZoneSummerOnly] :: TimeZone -> Bool
+ Hledger.Web.Import: [toModifiedJulianDay] :: Day -> Integer
+ Hledger.Web.Import: [todHour] :: TimeOfDay -> Int
+ Hledger.Web.Import: [todMin] :: TimeOfDay -> Int
+ Hledger.Web.Import: [todSec] :: TimeOfDay -> Pico
+ Hledger.Web.Import: [today] :: ViewData -> Day
+ Hledger.Web.Import: [unAForm] :: AForm a -> (HandlerSite m, [Text]) -> Maybe (Env, FileEnv) -> Ints -> m (FormResult a, [FieldView HandlerSite m] -> [FieldView HandlerSite m], Ints, Enctype)
+ Hledger.Web.Import: [unCssBuilder] :: CssBuilder -> Builder
+ Hledger.Web.Import: [unDBName] :: DBName -> Text
+ Hledger.Web.Import: [unDontFullyEvaluate] :: DontFullyEvaluate a -> a
+ Hledger.Web.Import: [unFormInput] :: FormInput a -> HandlerSite m -> [Text] -> Env -> FileEnv -> m Either DText a
+ Hledger.Web.Import: [unHaskellName] :: HaskellName -> Text
+ Hledger.Web.Import: [unLiteApp] :: LiteApp -> Method -> [Text] -> Maybe LiteHandler TypedContent
+ Hledger.Web.Import: [unTextarea] :: Textarea -> Text
+ Hledger.Web.Import: [uniqueAttrs] :: UniqueDef -> ![Attr]
+ Hledger.Web.Import: [uniqueDBName] :: UniqueDef -> !DBName
+ Hledger.Web.Import: [uniqueFields] :: UniqueDef -> ![(HaskellName, DBName)]
+ Hledger.Web.Import: [uniqueHaskell] :: UniqueDef -> !HaskellName
+ Hledger.Web.Import: [utctDayTime] :: UTCTime -> DiffTime
+ Hledger.Web.Import: [utctDay] :: UTCTime -> Day
+ Hledger.Web.Import: [wDays] :: TimeLocale -> [(String, String)]
+ Hledger.Web.Import: [zonedTimeToLocalTime] :: ZonedTime -> LocalTime
+ Hledger.Web.Import: [zonedTimeZone] :: ZonedTime -> TimeZone
+ Hledger.Web.Import: aFormToForm :: (Monad m, HandlerSite m ~ site) => AForm m a -> MForm m (FormResult a, [FieldView site] -> [FieldView site])
+ Hledger.Web.Import: abs :: Num a => a -> a
+ Hledger.Web.Import: acceptsJson :: MonadHandler m => m Bool
+ Hledger.Web.Import: acos :: Floating a => a -> a
+ Hledger.Web.Import: acosh :: Floating a => a -> a
+ Hledger.Web.Import: addContentDispositionFileName :: MonadHandler m => Text -> m ()
+ Hledger.Web.Import: addDays :: Integer -> Day -> Day
+ Hledger.Web.Import: addGregorianMonthsClip :: Integer -> Day -> Day
+ Hledger.Web.Import: addGregorianMonthsRollOver :: Integer -> Day -> Day
+ Hledger.Web.Import: addGregorianYearsClip :: Integer -> Day -> Day
+ Hledger.Web.Import: addGregorianYearsRollOver :: Integer -> Day -> Day
+ Hledger.Web.Import: addHeader :: MonadHandler m => Text -> Text -> m ()
+ Hledger.Web.Import: addMessage :: MonadHandler m => Text -> Html -> m ()
+ Hledger.Web.Import: addMessageI :: (MonadHandler m, RenderMessage HandlerSite m msg) => Text -> msg -> m ()
+ Hledger.Web.Import: addScript :: MonadWidget m => Route HandlerSite m -> m ()
+ Hledger.Web.Import: addScriptAttrs :: MonadWidget m => Route HandlerSite m -> [(Text, Text)] -> m ()
+ Hledger.Web.Import: addScriptEither :: MonadWidget m => Either Route HandlerSite m Text -> m ()
+ Hledger.Web.Import: addScriptRemote :: MonadWidget m => Text -> m ()
+ Hledger.Web.Import: addScriptRemoteAttrs :: MonadWidget m => Text -> [(Text, Text)] -> m ()
+ Hledger.Web.Import: addStaticContent :: Yesod site => Text -> Text -> ByteString -> HandlerFor site Maybe Either Text (Route site, [(Text, Text)])
+ Hledger.Web.Import: addStylesheet :: MonadWidget m => Route HandlerSite m -> m ()
+ Hledger.Web.Import: addStylesheetAttrs :: MonadWidget m => Route HandlerSite m -> [(Text, Text)] -> m ()
+ Hledger.Web.Import: addStylesheetEither :: MonadWidget m => Either Route HandlerSite m Text -> m ()
+ Hledger.Web.Import: addStylesheetRemote :: MonadWidget m => Text -> m ()
+ Hledger.Web.Import: addStylesheetRemoteAttrs :: MonadWidget m => Text -> [(Text, Text)] -> m ()
+ Hledger.Web.Import: addUTCTime :: NominalDiffTime -> UTCTime -> UTCTime
+ Hledger.Web.Import: all :: Foldable t => a -> Bool -> t a -> Bool
+ Hledger.Web.Import: alreadyExpired :: MonadHandler m => m ()
+ Hledger.Web.Import: and :: Foldable t => t Bool -> Bool
+ Hledger.Web.Import: any :: Foldable t => a -> Bool -> t a -> Bool
+ Hledger.Web.Import: aopt :: MonadHandler m => Field m a -> FieldSettings HandlerSite m -> Maybe Maybe a -> AForm m Maybe a
+ Hledger.Web.Import: ap :: Monad m => m a -> b -> m a -> m b
+ Hledger.Web.Import: appendFile :: FilePath -> String -> IO ()
+ Hledger.Web.Import: applyEnv :: PersistConfig c => c -> IO c
+ Hledger.Web.Import: approot :: Yesod site => Approot site
+ Hledger.Web.Import: areq :: (RenderMessage site FormMessage, HandlerSite m ~ site, MonadHandler m) => Field m a -> FieldSettings site -> Maybe a -> AForm m a
+ Hledger.Web.Import: array :: ToJSON a => [a] -> Value
+ Hledger.Web.Import: asTypeOf :: () => a -> a -> a
+ Hledger.Web.Import: asWidgetT :: () => WidgetT site m () -> WidgetT site m ()
+ Hledger.Web.Import: asin :: Floating a => a -> a
+ Hledger.Web.Import: asinh :: Floating a => a -> a
+ Hledger.Web.Import: askFiles :: Monad m => MForm m Maybe FileEnv
+ Hledger.Web.Import: askParams :: Monad m => MForm m Maybe Env
+ Hledger.Web.Import: askUnliftIO :: MonadUnliftIO m => m UnliftIO m
+ Hledger.Web.Import: asum :: (Foldable t, Alternative f) => t f a -> f a
+ Hledger.Web.Import: atan :: Floating a => a -> a
+ Hledger.Web.Import: atan2 :: RealFloat a => a -> a -> a
+ Hledger.Web.Import: atanh :: Floating a => a -> a
+ Hledger.Web.Import: authRoute :: Yesod site => site -> Maybe Route site
+ Hledger.Web.Import: authorizationCheck :: Yesod site => HandlerFor site ()
+ Hledger.Web.Import: badMethod :: MonadHandler m => m a
+ Hledger.Web.Import: belongsTo :: (PersistStoreRead backend, PersistEntity ent1, PersistRecordBackend ent2 backend, MonadIO m) => ent1 -> Maybe Key ent2 -> ent1 -> ReaderT backend m Maybe ent2
+ Hledger.Web.Import: belongsToJust :: (PersistStoreRead backend, PersistEntity ent1, PersistRecordBackend ent2 backend, MonadIO m) => ent1 -> Key ent2 -> ent1 -> ReaderT backend m ent2
+ Hledger.Web.Import: bimap :: Bifunctor p => a -> b -> c -> d -> p a c -> p b d
+ Hledger.Web.Import: boolField :: (Monad m, RenderMessage HandlerSite m FormMessage) => Field m Bool
+ Hledger.Web.Import: breadcrumb :: YesodBreadcrumbs site => Route site -> HandlerFor site (Text, Maybe Route site)
+ Hledger.Web.Import: breadcrumbs :: YesodBreadcrumbs site => HandlerFor site (Text, [(Route site, Text)])
+ Hledger.Web.Import: break :: () => a -> Bool -> [a] -> ([a], [a])
+ Hledger.Web.Import: buildTime :: ParseTime t => TimeLocale -> [(Char, String)] -> Maybe t
+ Hledger.Web.Import: cacheSeconds :: MonadHandler m => Int -> m ()
+ Hledger.Web.Import: cached :: (MonadHandler m, Typeable a) => m a -> m a
+ Hledger.Web.Import: cachedBy :: (MonadHandler m, Typeable a) => ByteString -> m a -> m a
+ Hledger.Web.Import: cassius :: QuasiQuoter
+ Hledger.Web.Import: catMaybes :: () => [Maybe a] -> [a]
+ Hledger.Web.Import: ceiling :: (RealFrac a, Integral b) => a -> b
+ Hledger.Web.Import: check :: (Monad m, RenderMessage HandlerSite m msg) => a -> Either msg a -> Field m a -> Field m a
+ Hledger.Web.Import: checkBool :: (Monad m, RenderMessage HandlerSite m msg) => a -> Bool -> msg -> Field m a -> Field m a
+ Hledger.Web.Import: checkBoxField :: Monad m => Field m Bool
+ Hledger.Web.Import: checkCsrfHeaderNamed :: MonadHandler m => CI ByteString -> m ()
+ Hledger.Web.Import: checkCsrfHeaderOrParam :: (MonadHandler m, MonadLogger m) => CI ByteString -> Text -> m ()
+ Hledger.Web.Import: checkCsrfParamNamed :: MonadHandler m => Text -> m ()
+ Hledger.Web.Import: checkM :: (Monad m, RenderMessage HandlerSite m msg) => a -> m Either msg a -> Field m a -> Field m a
+ Hledger.Web.Import: checkMMap :: (Monad m, RenderMessage HandlerSite m msg) => a -> m Either msg b -> b -> a -> Field m a -> Field m b
+ Hledger.Web.Import: checkUnique :: (MonadIO m, PersistRecordBackend record backend, PersistUniqueRead backend) => record -> ReaderT backend m Maybe Unique record
+ Hledger.Web.Import: checkboxesField :: Eq a => HandlerFor site OptionList a -> Field HandlerFor site [a]
+ Hledger.Web.Import: checkboxesFieldList :: (Eq a, RenderMessage site msg) => [(msg, a)] -> Field HandlerFor site [a]
+ Hledger.Web.Import: class Functor f => Applicative (f :: * -> *)
+ Hledger.Web.Import: class BackendCompatible sup sub
+ Hledger.Web.Import: class Bifunctor (p :: * -> * -> *)
+ Hledger.Web.Import: class Bounded a
+ Hledger.Web.Import: class Default a
+ Hledger.Web.Import: class (PersistStoreWrite backend, PersistEntity record, BaseBackend backend ~ PersistEntityBackend record) => DeleteCascade record backend
+ Hledger.Web.Import: class Enum a
+ Hledger.Web.Import: class Eq a
+ Hledger.Web.Import: class Fractional a => Floating a
+ Hledger.Web.Import: class Foldable (t :: * -> *)
+ Hledger.Web.Import: class FormatTime t
+ Hledger.Web.Import: class Num a => Fractional a
+ Hledger.Web.Import: class FromJSON a
+ Hledger.Web.Import: class Functor (f :: * -> *)
+ Hledger.Web.Import: class ToTypedContent a => HasContentType a
+ Hledger.Web.Import: class HasPersistBackend backend where {
+ Hledger.Web.Import: class (Real a, Enum a) => Integral a
+ Hledger.Web.Import: class HasPersistBackend backend => IsPersistBackend backend
+ Hledger.Web.Import: class Applicative m => Monad (m :: * -> *)
+ Hledger.Web.Import: class (MonadResource m, MonadLogger m) => MonadHandler (m :: * -> *) where {
+ Hledger.Web.Import: class Monad m => MonadIO (m :: * -> *)
+ Hledger.Web.Import: class Monad m => MonadLogger (m :: * -> *)
+ Hledger.Web.Import: class (Alternative m, Monad m) => MonadPlus (m :: * -> *)
+ Hledger.Web.Import: class MonadIO m => MonadResource (m :: * -> *)
+ Hledger.Web.Import: class MonadTrans (t :: * -> * -> * -> *)
+ Hledger.Web.Import: class MonadIO m => MonadUnliftIO (m :: * -> *)
+ Hledger.Web.Import: class MonadHandler m => MonadWidget (m :: * -> *)
+ Hledger.Web.Import: class Semigroup a => Monoid a
+ Hledger.Web.Import: class Num a
+ Hledger.Web.Import: class Eq a => Ord a
+ Hledger.Web.Import: class RenderRoute a => ParseRoute a
+ Hledger.Web.Import: class ParseTime t
+ Hledger.Web.Import: class PathMultiPiece s
+ Hledger.Web.Import: class PathPiece s
+ Hledger.Web.Import: class PersistConfig c where {
+ Hledger.Web.Import: class PersistCore backend where {
+ Hledger.Web.Import: class (PersistField Key record, ToJSON Key record, FromJSON Key record, Show Key record, Read Key record, Eq Key record, Ord Key record) => PersistEntity record where {
+ Hledger.Web.Import: class PersistField a
+ Hledger.Web.Import: class (PersistCore backend, PersistStoreRead backend) => PersistQueryRead backend
+ Hledger.Web.Import: class (PersistQueryRead backend, PersistStoreWrite backend) => PersistQueryWrite backend
+ Hledger.Web.Import: class (Show BackendKey backend, Read BackendKey backend, Eq BackendKey backend, Ord BackendKey backend, PersistCore backend, PersistField BackendKey backend, ToJSON BackendKey backend, FromJSON BackendKey backend) => PersistStoreRead backend
+ Hledger.Web.Import: class (Show BackendKey backend, Read BackendKey backend, Eq BackendKey backend, Ord BackendKey backend, PersistStoreRead backend, PersistField BackendKey backend, ToJSON BackendKey backend, FromJSON BackendKey backend) => PersistStoreWrite backend
+ Hledger.Web.Import: class (PersistCore backend, PersistStoreRead backend) => PersistUniqueRead backend
+ Hledger.Web.Import: class (PersistUniqueRead backend, PersistStoreWrite backend) => PersistUniqueWrite backend
+ Hledger.Web.Import: class Read a
+ Hledger.Web.Import: class (Num a, Ord a) => Real a
+ Hledger.Web.Import: class (RealFrac a, Floating a) => RealFloat a
+ Hledger.Web.Import: class (Real a, Fractional a) => RealFrac a
+ Hledger.Web.Import: class RedirectUrl master a
+ Hledger.Web.Import: class RenderMessage master message
+ Hledger.Web.Import: class RenderRoute a => RouteAttrs a
+ Hledger.Web.Import: class Semigroup a
+ Hledger.Web.Import: class Show a
+ Hledger.Web.Import: class (PersistEntity record, PersistEntityBackend record ~ backend, PersistCore backend) => ToBackendKey backend record
+ Hledger.Web.Import: class ToContent a
+ Hledger.Web.Import: class ToFlushBuilder a
+ Hledger.Web.Import: class ToJSON a
+ Hledger.Web.Import: class ToMessage a
+ Hledger.Web.Import: class ToContent a => ToTypedContent a
+ Hledger.Web.Import: class ToWidget site a
+ Hledger.Web.Import: class ToWidgetBody site a
+ Hledger.Web.Import: class ToWidgetHead site a
+ Hledger.Web.Import: class ToWidgetMedia site a
+ Hledger.Web.Import: class (Functor t, Foldable t) => Traversable (t :: * -> *)
+ Hledger.Web.Import: class RenderRoute site => Yesod site
+ Hledger.Web.Import: class YesodBreadcrumbs site
+ Hledger.Web.Import: class Yesod site => YesodDispatch site
+ Hledger.Web.Import: class Monad YesodDB site => YesodPersist site where {
+ Hledger.Web.Import: class YesodPersist site => YesodPersistRunner site
+ Hledger.Web.Import: class YesodSubDispatch sub master
+ Hledger.Web.Import: cleanPath :: Yesod site => site -> [Text] -> Either [Text] [Text]
+ Hledger.Web.Import: clearSession :: MonadHandler m => m ()
+ Hledger.Web.Import: clearUltDest :: MonadHandler m => m ()
+ Hledger.Web.Import: clientSessionBackend :: Key -> IO ClientSessionDateCache -> SessionBackend
+ Hledger.Web.Import: clientSessionDateCacher :: NominalDiffTime -> IO (IO ClientSessionDateCache, IO ())
+ Hledger.Web.Import: compare :: Ord a => a -> a -> Ordering
+ Hledger.Web.Import: concat :: Foldable t => t [a] -> [a]
+ Hledger.Web.Import: concatMap :: Foldable t => a -> [b] -> t a -> [b]
+ Hledger.Web.Import: const :: () => a -> b -> a
+ Hledger.Web.Import: contentTypeTypes :: ContentType -> (ByteString, ByteString)
+ Hledger.Web.Import: convertField :: Functor m => a -> b -> b -> a -> Field m a -> Field m b
+ Hledger.Web.Import: cos :: Floating a => a -> a
+ Hledger.Web.Import: cosh :: Floating a => a -> a
+ Hledger.Web.Import: count :: (PersistQueryRead backend, MonadIO m, PersistRecordBackend record backend) => [Filter record] -> ReaderT backend m Int
+ Hledger.Web.Import: createPoolConfig :: PersistConfig c => c -> IO PersistConfigPool c
+ Hledger.Web.Import: csrfCheckMiddleware :: () => HandlerFor site res -> HandlerFor site Bool -> CI ByteString -> Text -> HandlerFor site res
+ Hledger.Web.Import: csrfSetCookieMiddleware :: () => HandlerFor site res -> SetCookie -> HandlerFor site res
+ Hledger.Web.Import: css_bootstrap_css :: StaticRoute
+ Hledger.Web.Import: css_bootstrap_css_map :: StaticRoute
+ Hledger.Web.Import: css_bootstrap_datepicker_standalone_min_css :: StaticRoute
+ Hledger.Web.Import: css_bootstrap_min_css :: StaticRoute
+ Hledger.Web.Import: css_bootstrap_theme_css :: StaticRoute
+ Hledger.Web.Import: css_bootstrap_theme_css_map :: StaticRoute
+ Hledger.Web.Import: css_bootstrap_theme_min_css :: StaticRoute
+ Hledger.Web.Import: curry :: () => (a, b) -> c -> a -> b -> c
+ Hledger.Web.Import: customErrorMessage :: Monad m => SomeMessage HandlerSite m -> Field m a -> Field m a
+ Hledger.Web.Import: customizeSessionCookies :: SetCookie -> SetCookie -> SessionBackend -> SessionBackend
+ Hledger.Web.Import: cycle :: () => [a] -> [a]
+ Hledger.Web.Import: data App
+ Hledger.Web.Import: data Approot master
+ Hledger.Web.Import: data AuthResult
+ Hledger.Web.Import: data Bool
+ Hledger.Web.Import: data ByteString
+ Hledger.Web.Import: data Capability
+ Hledger.Web.Import: data Char
+ Hledger.Web.Import: data Checkmark
+ Hledger.Web.Import: data CompositeDef
+ Hledger.Web.Import: data Content
+ Hledger.Web.Import: data DiffTime
+ Hledger.Web.Import: data Double
+ Hledger.Web.Import: data Either a b
+ Hledger.Web.Import: data EmbedEntityDef
+ Hledger.Web.Import: data EmbedFieldDef
+ Hledger.Web.Import: data Enctype
+ Hledger.Web.Import: data Entity record
+ Hledger.Web.Import: data EntityDef
+ Hledger.Web.Import: data EntityJSON
+ Hledger.Web.Import: data ErrorResponse
+ Hledger.Web.Import: data Extra
+ Hledger.Web.Import: data Field (m :: * -> *) a
+ Hledger.Web.Import: data FieldDef
+ Hledger.Web.Import: data FieldSettings master
+ Hledger.Web.Import: data FieldType
+ Hledger.Web.Import: data FieldView site
+ Hledger.Web.Import: data FileInfo
+ Hledger.Web.Import: data FileUpload
+ Hledger.Web.Import: data Filter record
+ Hledger.Web.Import: data Float
+ Hledger.Web.Import: data ForeignDef
+ Hledger.Web.Import: data FormMessage
+ Hledger.Web.Import: data FormResult a
+ Hledger.Web.Import: data Fragment a b
+ Hledger.Web.Import: data HandlerFor site a
+ Hledger.Web.Import: data Header
+ Hledger.Web.Import: data IO a
+ Hledger.Web.Import: data Int
+ Hledger.Web.Import: data Integer
+ Hledger.Web.Import: data Ints
+ Hledger.Web.Import: data IsNullable
+ Hledger.Web.Import: data LocalTime
+ Hledger.Web.Import: data LogLevel
+ Hledger.Web.Import: data Maybe a
+ Hledger.Web.Import: data MkPersistSettings
+ Hledger.Web.Import: data NominalDiffTime
+ Hledger.Web.Import: data OnlyUniqueException
+ Hledger.Web.Import: data Option a
+ Hledger.Web.Import: data OptionList a
+ Hledger.Web.Import: data Ordering
+ Hledger.Web.Import: data PageContent url
+ Hledger.Web.Import: data PersistException
+ Hledger.Web.Import: data PersistFilter
+ Hledger.Web.Import: data PersistUpdate
+ Hledger.Web.Import: data PersistValue
+ Hledger.Web.Import: data ProvidedRep (m :: * -> *)
+ Hledger.Web.Import: data ReferenceDef
+ Hledger.Web.Import: data ScriptLoadPosition master
+ Hledger.Web.Import: data SelectOpt record
+ Hledger.Web.Import: data SomeMessage master
+ Hledger.Web.Import: data SomePersistField
+ Hledger.Web.Import: data SqlType
+ Hledger.Web.Import: data SubHandlerFor sub master a
+ Hledger.Web.Import: data Text
+ Hledger.Web.Import: data TimeLocale
+ Hledger.Web.Import: data TimeOfDay
+ Hledger.Web.Import: data TimeZone
+ Hledger.Web.Import: data TypedContent
+ Hledger.Web.Import: data UTCTime
+ Hledger.Web.Import: data UniqueDef
+ Hledger.Web.Import: data Update record
+ Hledger.Web.Import: data UpdateException
+ Hledger.Web.Import: data Value
+ Hledger.Web.Import: data ViewData
+ Hledger.Web.Import: data Void
+ Hledger.Web.Import: data WhyNullable
+ Hledger.Web.Import: data WidgetFor site a
+ Hledger.Web.Import: data Word
+ Hledger.Web.Import: data YesodRequest
+ Hledger.Web.Import: data ZonedTime
+ Hledger.Web.Import: data family Unique record :: *;
+ Hledger.Web.Import: dayField :: (Monad m, RenderMessage HandlerSite m FormMessage) => Field m Day
+ Hledger.Web.Import: dayFractionToTimeOfDay :: Rational -> TimeOfDay
+ Hledger.Web.Import: decodeFloat :: RealFloat a => a -> (Integer, Int)
+ Hledger.Web.Import: def :: Default a => a
+ Hledger.Web.Import: defaultClientSessionBackend :: Int -> FilePath -> IO SessionBackend
+ Hledger.Web.Import: defaultCsrfCheckMiddleware :: Yesod site => HandlerFor site res -> HandlerFor site res
+ Hledger.Web.Import: defaultCsrfCookieName :: ByteString
+ Hledger.Web.Import: defaultCsrfHeaderName :: CI ByteString
+ Hledger.Web.Import: defaultCsrfMiddleware :: Yesod site => HandlerFor site res -> HandlerFor site res
+ Hledger.Web.Import: defaultCsrfParamName :: Text
+ Hledger.Web.Import: defaultCsrfSetCookieMiddleware :: () => HandlerFor site res -> HandlerFor site res
+ Hledger.Web.Import: defaultErrorHandler :: Yesod site => ErrorResponse -> HandlerFor site TypedContent
+ Hledger.Web.Import: defaultFormMessage :: FormMessage -> Text
+ Hledger.Web.Import: defaultGetDBRunner :: (IsSqlBackend backend, YesodPersistBackend site ~ backend) => site -> Pool backend -> HandlerFor site (DBRunner site, HandlerFor site ())
+ Hledger.Web.Import: defaultLayout :: Yesod site => WidgetFor site () -> HandlerFor site Html
+ Hledger.Web.Import: defaultLayoutJson :: (Yesod site, ToJSON a) => WidgetFor site () -> HandlerFor site a -> HandlerFor site TypedContent
+ Hledger.Web.Import: defaultMakeLogger :: IO Logger
+ Hledger.Web.Import: defaultMessageLoggerSource :: LogSource -> LogLevel -> IO Bool -> Logger -> Loc -> LogSource -> LogLevel -> LogStr -> IO ()
+ Hledger.Web.Import: defaultMessageWidget :: Yesod site => Html -> HtmlUrl Route site -> WidgetFor site ()
+ Hledger.Web.Import: defaultMiddlewaresNoLogging :: Middleware
+ Hledger.Web.Import: defaultRunDB :: PersistConfig c => site -> c -> site -> PersistConfigPool c -> PersistConfigBackend c HandlerFor site a -> HandlerFor site a
+ Hledger.Web.Import: defaultShouldLogIO :: LogSource -> LogLevel -> IO Bool
+ Hledger.Web.Import: defaultTimeLocale :: TimeLocale
+ Hledger.Web.Import: defaultYesodMiddleware :: Yesod site => HandlerFor site res -> HandlerFor site res
+ Hledger.Web.Import: defbaseurl :: String -> Int -> String
+ Hledger.Web.Import: defhost :: String
+ Hledger.Web.Import: defport :: Int
+ Hledger.Web.Import: delete :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> ReaderT backend m ()
+ Hledger.Web.Import: deleteBy :: (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> ReaderT backend m ()
+ Hledger.Web.Import: deleteCascade :: (DeleteCascade record backend, MonadIO m) => Key record -> ReaderT backend m ()
+ Hledger.Web.Import: deleteCascadeWhere :: (MonadIO m, DeleteCascade record backend, PersistQueryWrite backend) => [Filter record] -> ReaderT backend m ()
+ Hledger.Web.Import: deleteCookie :: MonadHandler m => Text -> Text -> m ()
+ Hledger.Web.Import: deleteSession :: MonadHandler m => Text -> m ()
+ Hledger.Web.Import: deleteWhere :: (PersistQueryWrite backend, MonadIO m, PersistRecordBackend record backend) => [Filter record] -> ReaderT backend m ()
+ Hledger.Web.Import: derivePersistField :: String -> Q [Dec]
+ Hledger.Web.Import: derivePersistFieldJSON :: String -> Q [Dec]
+ Hledger.Web.Import: development :: Bool
+ Hledger.Web.Import: diffDays :: Day -> Day -> Integer
+ Hledger.Web.Import: diffTimeToPicoseconds :: DiffTime -> Integer
+ Hledger.Web.Import: diffUTCTime :: UTCTime -> UTCTime -> NominalDiffTime
+ Hledger.Web.Import: dispatchTo :: ToTypedContent a => LiteHandler a -> Writer LiteApp ()
+ Hledger.Web.Import: div :: Integral a => a -> a -> a
+ Hledger.Web.Import: divMod :: Integral a => a -> a -> (a, a)
+ Hledger.Web.Import: doubleField :: (Monad m, RenderMessage HandlerSite m FormMessage) => Field m Double
+ Hledger.Web.Import: drop :: () => Int -> [a] -> [a]
+ Hledger.Web.Import: dropWhile :: () => a -> Bool -> [a] -> [a]
+ Hledger.Web.Import: either :: () => a -> c -> b -> c -> Either a b -> c
+ Hledger.Web.Import: elem :: (Foldable t, Eq a) => a -> t a -> Bool
+ Hledger.Web.Import: emailField :: (Monad m, RenderMessage HandlerSite m FormMessage) => Field m Text
+ Hledger.Web.Import: emptyContent :: Content
+ Hledger.Web.Import: encodeFloat :: RealFloat a => Integer -> Int -> a
+ Hledger.Web.Import: entityDef :: (PersistEntity record, Monad m) => m record -> EntityDef
+ Hledger.Web.Import: entityIdFromJSON :: (PersistEntity record, FromJSON record, FromJSON Key record) => Value -> Parser Entity record
+ Hledger.Web.Import: entityIdToJSON :: (PersistEntity record, ToJSON record, ToJSON Key record) => Entity record -> Value
+ Hledger.Web.Import: entityKeyFields :: EntityDef -> [FieldDef]
+ Hledger.Web.Import: entityPrimary :: EntityDef -> Maybe CompositeDef
+ Hledger.Web.Import: entityValues :: PersistEntity record => Entity record -> [PersistValue]
+ Hledger.Web.Import: enumFrom :: Enum a => a -> [a]
+ Hledger.Web.Import: enumFromThen :: Enum a => a -> a -> [a]
+ Hledger.Web.Import: enumFromThenTo :: Enum a => a -> a -> a -> [a]
+ Hledger.Web.Import: enumFromTo :: Enum a => a -> a -> [a]
+ Hledger.Web.Import: envClientSessionBackend :: Int -> String -> IO SessionBackend
+ Hledger.Web.Import: error :: HasCallStack => [Char] -> a
+ Hledger.Web.Import: errorHandler :: Yesod site => ErrorResponse -> HandlerFor site TypedContent
+ Hledger.Web.Import: errorWithoutStackTrace :: () => [Char] -> a
+ Hledger.Web.Import: even :: Integral a => a -> Bool
+ Hledger.Web.Import: exp :: Floating a => a -> a
+ Hledger.Web.Import: expiresAt :: MonadHandler m => UTCTime -> m ()
+ Hledger.Web.Import: exponent :: RealFloat a => a -> Int
+ Hledger.Web.Import: fail :: Monad m => String -> m a
+ Hledger.Web.Import: fieldLens :: PersistEntity record => EntityField record field -> forall (f :: * -> *). Functor f => field -> f field -> Entity record -> f Entity record
+ Hledger.Web.Import: fieldSettingsLabel :: RenderMessage site msg => msg -> FieldSettings site
+ Hledger.Web.Import: fileAFormOpt :: MonadHandler m => FieldSettings HandlerSite m -> AForm m Maybe FileInfo
+ Hledger.Web.Import: fileAFormReq :: (MonadHandler m, RenderMessage HandlerSite m FormMessage) => FieldSettings HandlerSite m -> AForm m FileInfo
+ Hledger.Web.Import: fileField :: Monad m => Field m FileInfo
+ Hledger.Web.Import: fileSource :: MonadResource m => FileInfo -> ConduitT () ByteString m ()
+ Hledger.Web.Import: fileSourceByteString :: MonadResource m => FileInfo -> m ByteString
+ Hledger.Web.Import: fileUpload :: Yesod site => site -> RequestBodyLength -> FileUpload
+ Hledger.Web.Import: filter :: () => a -> Bool -> [a] -> [a]
+ Hledger.Web.Import: filterM :: Applicative m => a -> m Bool -> [a] -> m [a]
+ Hledger.Web.Import: find :: Foldable t => a -> Bool -> t a -> Maybe a
+ Hledger.Web.Import: first :: Bifunctor p => a -> b -> p a c -> p b c
+ Hledger.Web.Import: flip :: () => a -> b -> c -> b -> a -> c
+ Hledger.Web.Import: floatDigits :: RealFloat a => a -> Int
+ Hledger.Web.Import: floatRadix :: RealFloat a => a -> Integer
+ Hledger.Web.Import: floatRange :: RealFloat a => a -> (Int, Int)
+ Hledger.Web.Import: floor :: (RealFrac a, Integral b) => a -> b
+ Hledger.Web.Import: fmap :: Functor f => a -> b -> f a -> f b
+ Hledger.Web.Import: fmapDefault :: Traversable t => a -> b -> t a -> t b
+ Hledger.Web.Import: fold :: (Foldable t, Monoid m) => t m -> m
+ Hledger.Web.Import: foldM :: (Foldable t, Monad m) => b -> a -> m b -> b -> t a -> m b
+ Hledger.Web.Import: foldM_ :: (Foldable t, Monad m) => b -> a -> m b -> b -> t a -> m ()
+ Hledger.Web.Import: foldMap :: (Foldable t, Monoid m) => a -> m -> t a -> m
+ Hledger.Web.Import: foldMapDefault :: (Traversable t, Monoid m) => a -> m -> t a -> m
+ Hledger.Web.Import: foldl :: Foldable t => b -> a -> b -> b -> t a -> b
+ Hledger.Web.Import: foldl' :: Foldable t => b -> a -> b -> b -> t a -> b
+ Hledger.Web.Import: foldl1 :: Foldable t => a -> a -> a -> t a -> a
+ Hledger.Web.Import: foldlM :: (Foldable t, Monad m) => b -> a -> m b -> b -> t a -> m b
+ Hledger.Web.Import: foldr :: Foldable t => a -> b -> b -> b -> t a -> b
+ Hledger.Web.Import: foldr' :: Foldable t => a -> b -> b -> b -> t a -> b
+ Hledger.Web.Import: foldr1 :: Foldable t => a -> a -> a -> t a -> a
+ Hledger.Web.Import: foldrM :: (Foldable t, Monad m) => a -> b -> m b -> b -> t a -> m b
+ Hledger.Web.Import: fonts_glyphicons_halflings_regular_eot :: StaticRoute
+ Hledger.Web.Import: fonts_glyphicons_halflings_regular_svg :: StaticRoute
+ Hledger.Web.Import: fonts_glyphicons_halflings_regular_ttf :: StaticRoute
+ Hledger.Web.Import: fonts_glyphicons_halflings_regular_woff :: StaticRoute
+ Hledger.Web.Import: for :: (Traversable t, Applicative f) => t a -> a -> f b -> f t b
+ Hledger.Web.Import: forM :: (Traversable t, Monad m) => t a -> a -> m b -> m t b
+ Hledger.Web.Import: forM_ :: (Foldable t, Monad m) => t a -> a -> m b -> m ()
+ Hledger.Web.Import: for_ :: (Foldable t, Applicative f) => t a -> a -> f b -> f ()
+ Hledger.Web.Import: forever :: Applicative f => f a -> f b
+ Hledger.Web.Import: forkHandler :: () => SomeException -> HandlerFor site () -> HandlerFor site () -> HandlerFor site ()
+ Hledger.Web.Import: formToAForm :: (HandlerSite m ~ site, Monad m) => MForm m (FormResult a, [FieldView site]) -> AForm m a
+ Hledger.Web.Import: formatCharacter :: FormatTime t => Char -> Maybe TimeLocale -> Maybe NumericPadOption -> Maybe Int -> t -> String
+ Hledger.Web.Import: formatLogMessage :: IO ZonedDate -> Loc -> LogSource -> LogLevel -> LogStr -> IO LogStr
+ Hledger.Web.Import: formatRFC1123 :: UTCTime -> Text
+ Hledger.Web.Import: formatRFC822 :: UTCTime -> Text
+ Hledger.Web.Import: formatTime :: FormatTime t => TimeLocale -> String -> t -> String
+ Hledger.Web.Import: formatW3 :: UTCTime -> Text
+ Hledger.Web.Import: fromBackendKey :: ToBackendKey backend record => BackendKey backend -> Key record
+ Hledger.Web.Import: fromEnum :: Enum a => a -> Int
+ Hledger.Web.Import: fromGregorian :: Integer -> Int -> Int -> Day
+ Hledger.Web.Import: fromGregorianValid :: Integer -> Int -> Int -> Maybe Day
+ Hledger.Web.Import: fromInteger :: Num a => Integer -> a
+ Hledger.Web.Import: fromIntegral :: (Integral a, Num b) => a -> b
+ Hledger.Web.Import: fromJust :: () => Maybe a -> a
+ Hledger.Web.Import: fromLeft :: () => a -> Either a b -> a
+ Hledger.Web.Import: fromMaybe :: () => a -> Maybe a -> a
+ Hledger.Web.Import: fromPathMultiPiece :: PathMultiPiece s => [Text] -> Maybe s
+ Hledger.Web.Import: fromPathPiece :: PathPiece s => Text -> Maybe s
+ Hledger.Web.Import: fromPersistValue :: PersistField a => PersistValue -> Either Text a
+ Hledger.Web.Import: fromPersistValueJSON :: FromJSON a => PersistValue -> Either Text a
+ Hledger.Web.Import: fromPersistValueText :: PersistValue -> Either Text Text
+ Hledger.Web.Import: fromPersistValues :: PersistEntity record => [PersistValue] -> Either Text record
+ Hledger.Web.Import: fromRational :: Fractional a => Rational -> a
+ Hledger.Web.Import: fromRight :: () => b -> Either a b -> b
+ Hledger.Web.Import: fst :: () => (a, b) -> a
+ Hledger.Web.Import: gcd :: Integral a => a -> a -> a
+ Hledger.Web.Import: generateFormGet :: MonadHandler m => Markup -> MForm m a -> m (a, Enctype)
+ Hledger.Web.Import: generateFormGet' :: MonadHandler m => Markup -> MForm m (FormResult a, xml) -> m (xml, Enctype)
+ Hledger.Web.Import: generateFormPost :: (RenderMessage HandlerSite m FormMessage, MonadHandler m) => Markup -> MForm m (FormResult a, xml) -> m (xml, Enctype)
+ Hledger.Web.Import: get :: (PersistStoreRead backend, MonadIO m, PersistRecordBackend record backend) => Key record -> ReaderT backend m Maybe record
+ Hledger.Web.Import: get404 :: (MonadIO m, PersistStoreRead backend, PersistRecordBackend val backend) => Key val -> ReaderT backend m val
+ Hledger.Web.Import: getApprootText :: () => Approot site -> site -> Request -> Text
+ Hledger.Web.Import: getBy :: (PersistUniqueRead backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> ReaderT backend m Maybe Entity record
+ Hledger.Web.Import: getBy404 :: (PersistUniqueRead backend, PersistRecordBackend val backend, MonadIO m) => Unique val -> ReaderT backend m Entity val
+ Hledger.Web.Import: getByValue :: (MonadIO m, PersistUniqueRead backend, PersistRecordBackend record backend) => record -> ReaderT backend m Maybe Entity record
+ Hledger.Web.Import: getChar :: IO Char
+ Hledger.Web.Import: getContentType :: (HasContentType a, Monad m) => m a -> ContentType
+ Hledger.Web.Import: getContents :: IO String
+ Hledger.Web.Import: getCurrentJournal :: IORef Journal -> CliOpts -> Day -> Handler (Journal, Maybe String)
+ Hledger.Web.Import: getCurrentRoute :: MonadHandler m => m Maybe Route HandlerSite m
+ Hledger.Web.Import: getCurrentTime :: IO UTCTime
+ Hledger.Web.Import: getCurrentTimeZone :: IO TimeZone
+ Hledger.Web.Import: getDBRunner :: YesodPersistRunner site => HandlerFor site (DBRunner site, HandlerFor site ())
+ Hledger.Web.Import: getEntity :: (PersistStoreRead backend, PersistRecordBackend e backend, MonadIO m) => Key e -> ReaderT backend m Maybe Entity e
+ Hledger.Web.Import: getExpires :: MonadIO m => Int -> m UTCTime
+ Hledger.Web.Import: getGetMaxExpires :: IO IO Text
+ Hledger.Web.Import: getJust :: (PersistStoreRead backend, Show Key record, PersistRecordBackend record backend, MonadIO m) => Key record -> ReaderT backend m record
+ Hledger.Web.Import: getJustEntity :: (PersistEntityBackend record ~ BaseBackend backend, MonadIO m, PersistEntity record, PersistStoreRead backend) => Key record -> ReaderT backend m Entity record
+ Hledger.Web.Import: getLine :: IO String
+ Hledger.Web.Import: getMany :: (PersistStoreRead backend, MonadIO m, PersistRecordBackend record backend) => [Key record] -> ReaderT backend m Map Key record record
+ Hledger.Web.Import: getMessage :: MonadHandler m => m Maybe Html
+ Hledger.Web.Import: getMessageRender :: (MonadHandler m, RenderMessage HandlerSite m message) => m message -> Text
+ Hledger.Web.Import: getMessages :: MonadHandler m => m [(Text, Html)]
+ Hledger.Web.Import: getPersistMap :: PersistValue -> Either Text [(Text, PersistValue)]
+ Hledger.Web.Import: getPostParams :: MonadHandler m => m [(Text, Text)]
+ Hledger.Web.Import: getRequest :: MonadHandler m => m YesodRequest
+ Hledger.Web.Import: getRouteToParent :: MonadHandler m => m Route SubHandlerSite m -> Route HandlerSite m
+ Hledger.Web.Import: getSession :: MonadHandler m => m SessionMap
+ Hledger.Web.Import: getSubCurrentRoute :: MonadHandler m => m Maybe Route SubHandlerSite m
+ Hledger.Web.Import: getSubYesod :: MonadHandler m => m SubHandlerSite m
+ Hledger.Web.Import: getTimeZone :: UTCTime -> IO TimeZone
+ Hledger.Web.Import: getTime_resolution :: DiffTime
+ Hledger.Web.Import: getUrlRender :: MonadHandler m => m Route HandlerSite m -> Text
+ Hledger.Web.Import: getUrlRenderParams :: MonadHandler m => m Route HandlerSite m -> [(Text, Text)] -> Text
+ Hledger.Web.Import: getViewData :: Handler ViewData
+ Hledger.Web.Import: getYesod :: MonadHandler m => m HandlerSite m
+ Hledger.Web.Import: getZonedTime :: IO ZonedTime
+ Hledger.Web.Import: getsYesod :: MonadHandler m => HandlerSite m -> a -> m a
+ Hledger.Web.Import: giveUrlRenderer :: MonadHandler m => Route HandlerSite m -> [(Text, Text)] -> Text -> output -> m output
+ Hledger.Web.Import: gregorianMonthLength :: Integer -> Int -> Int
+ Hledger.Web.Import: guard :: Alternative f => Bool -> f ()
+ Hledger.Web.Import: guessApproot :: () => Approot site
+ Hledger.Web.Import: guessApprootOr :: () => Approot site -> Approot site
+ Hledger.Web.Import: hamlet :: QuasiQuoter
+ Hledger.Web.Import: hamletToRepHtml :: MonadHandler m => HtmlUrl Route HandlerSite m -> m Html
+ Hledger.Web.Import: handlerToIO :: MonadIO m => HandlerFor site HandlerFor site a -> m a
+ Hledger.Web.Import: handlerToWidget :: () => HandlerFor site a -> WidgetFor site a
+ Hledger.Web.Import: hasValidCsrfHeaderNamed :: MonadHandler m => CI ByteString -> m Bool
+ Hledger.Web.Import: hasValidCsrfParamNamed :: MonadHandler m => Text -> m Bool
+ Hledger.Web.Import: hiddenField :: (Monad m, PathPiece p, RenderMessage HandlerSite m FormMessage) => Field m p
+ Hledger.Web.Import: hledger_css :: StaticRoute
+ Hledger.Web.Import: hledger_js :: StaticRoute
+ Hledger.Web.Import: hledgerorgurl :: Text
+ Hledger.Web.Import: hoursToTimeZone :: Int -> TimeZone
+ Hledger.Web.Import: htmlField :: (Monad m, RenderMessage HandlerSite m FormMessage) => Field m Html
+ Hledger.Web.Import: id :: () => a -> a
+ Hledger.Web.Import: identifyForm :: Monad m => Text -> Markup -> MForm m (FormResult a, WidgetFor HandlerSite m ()) -> Markup -> MForm m (FormResult a, WidgetFor HandlerSite m ())
+ Hledger.Web.Import: ihamletToHtml :: (MonadHandler m, RenderMessage HandlerSite m message) => HtmlUrlI18n message Route HandlerSite m -> m Html
+ Hledger.Web.Import: ihamletToRepHtml :: (MonadHandler m, RenderMessage HandlerSite m message) => HtmlUrlI18n message Route HandlerSite m -> m Html
+ Hledger.Web.Import: infix 4 ==.
+ Hledger.Web.Import: infixl 3 ||.
+ Hledger.Web.Import: infixl 4 <$!>
+ Hledger.Web.Import: infixl 9 !!
+ Hledger.Web.Import: infixr 0 $!
+ Hledger.Web.Import: infixr 1 =<<
+ Hledger.Web.Import: infixr 2 ||
+ Hledger.Web.Import: infixr 3 =.
+ Hledger.Web.Import: infixr 5 ++
+ Hledger.Web.Import: infixr 8 ^
+ Hledger.Web.Import: infixr 9 .
+ Hledger.Web.Import: insert :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> ReaderT backend m Key record
+ Hledger.Web.Import: insert400 :: (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend val backend) => val -> ReaderT backend m Key val
+ Hledger.Web.Import: insert400_ :: (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend val backend) => val -> ReaderT backend m ()
+ Hledger.Web.Import: insertBy :: (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend) => record -> ReaderT backend m Either Entity record Key record
+ Hledger.Web.Import: insertEntity :: (PersistStoreWrite backend, PersistRecordBackend e backend, MonadIO m) => e -> ReaderT backend m Entity e
+ Hledger.Web.Import: insertEntityMany :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [Entity record] -> ReaderT backend m ()
+ Hledger.Web.Import: insertKey :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> record -> ReaderT backend m ()
+ Hledger.Web.Import: insertMany :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m [Key record]
+ Hledger.Web.Import: insertMany_ :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m ()
+ Hledger.Web.Import: insertRecord :: (PersistEntityBackend record ~ BaseBackend backend, PersistEntity record, MonadIO m, PersistStoreWrite backend) => record -> ReaderT backend m record
+ Hledger.Web.Import: insertUnique :: (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> ReaderT backend m Maybe Key record
+ Hledger.Web.Import: insertUniqueEntity :: (MonadIO m, PersistRecordBackend record backend, PersistUniqueWrite backend) => record -> ReaderT backend m Maybe Entity record
+ Hledger.Web.Import: insert_ :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> ReaderT backend m ()
+ Hledger.Web.Import: intField :: (Monad m, Integral i, RenderMessage HandlerSite m FormMessage) => Field m i
+ Hledger.Web.Import: interact :: String -> String -> IO ()
+ Hledger.Web.Import: invalidArgs :: MonadHandler m => [Text] -> m a
+ Hledger.Web.Import: invalidArgsI :: (MonadHandler m, RenderMessage HandlerSite m msg) => [msg] -> m a
+ Hledger.Web.Import: ioError :: () => IOError -> IO a
+ Hledger.Web.Import: iopt :: Monad m => Field m a -> Text -> FormInput m Maybe a
+ Hledger.Web.Import: ireq :: (Monad m, RenderMessage HandlerSite m FormMessage) => Field m a -> Text -> FormInput m a
+ Hledger.Web.Import: isAuthorized :: Yesod site => Route site -> Bool -> HandlerFor site AuthResult
+ Hledger.Web.Import: isDenormalized :: RealFloat a => a -> Bool
+ Hledger.Web.Import: isIEEE :: RealFloat a => a -> Bool
+ Hledger.Web.Import: isInfinite :: RealFloat a => a -> Bool
+ Hledger.Web.Import: isJust :: () => Maybe a -> Bool
+ Hledger.Web.Import: isLeapYear :: Integer -> Bool
+ Hledger.Web.Import: isLeft :: () => Either a b -> Bool
+ Hledger.Web.Import: isNaN :: RealFloat a => a -> Bool
+ Hledger.Web.Import: isNegativeZero :: RealFloat a => a -> Bool
+ Hledger.Web.Import: isNothing :: () => Maybe a -> Bool
+ Hledger.Web.Import: isRight :: () => Either a b -> Bool
+ Hledger.Web.Import: isWriteRequest :: Yesod site => Route site -> HandlerFor site Bool
+ Hledger.Web.Import: iso8601DateFormat :: Maybe String -> String
+ Hledger.Web.Import: iterate :: () => a -> a -> a -> [a]
+ Hledger.Web.Import: join :: Monad m => m m a -> m a
+ Hledger.Web.Import: joinPath :: Yesod site => site -> Text -> [Text] -> [(Text, Text)] -> Builder
+ Hledger.Web.Import: jsAttributes :: Yesod site => site -> [(Text, Text)]
+ Hledger.Web.Import: jsLoader :: Yesod site => site -> ScriptLoadPosition site
+ Hledger.Web.Import: js_bootstrap_datepicker_min_js :: StaticRoute
+ Hledger.Web.Import: js_bootstrap_js :: StaticRoute
+ Hledger.Web.Import: js_bootstrap_min_js :: StaticRoute
+ Hledger.Web.Import: js_excanvas_js :: StaticRoute
+ Hledger.Web.Import: js_excanvas_min_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_cookie_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_canvas_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_canvas_min_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_categories_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_categories_min_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_crosshair_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_crosshair_min_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_errorbars_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_errorbars_min_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_fillbetween_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_fillbetween_min_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_image_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_image_min_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_min_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_navigate_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_navigate_min_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_pie_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_pie_min_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_resize_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_resize_min_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_selection_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_selection_min_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_stack_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_stack_min_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_symbol_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_symbol_min_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_threshold_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_threshold_min_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_time_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_time_min_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_tooltip_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_flot_tooltip_min_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_hotkeys_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_min_js :: StaticRoute
+ Hledger.Web.Import: js_jquery_url_js :: StaticRoute
+ Hledger.Web.Import: js_typeahead_bundle_js :: StaticRoute
+ Hledger.Web.Import: js_typeahead_bundle_min_js :: StaticRoute
+ Hledger.Web.Import: jsonEncodingOrRedirect :: (MonadHandler m, ToJSON a) => Route HandlerSite m -> a -> m Encoding
+ Hledger.Web.Import: jsonOrRedirect :: (MonadHandler m, ToJSON a) => Route HandlerSite m -> a -> m Value
+ Hledger.Web.Import: jsonToRepJson :: (Monad m, ToJSON a) => a -> m Value
+ Hledger.Web.Import: julius :: QuasiQuoter
+ Hledger.Web.Import: keyAndEntityFields :: EntityDef -> [FieldDef]
+ Hledger.Web.Import: keyFromValues :: PersistEntity record => [PersistValue] -> Either Text Key record
+ Hledger.Web.Import: keyToValues :: PersistEntity record => Key record -> [PersistValue]
+ Hledger.Web.Import: keyValueEntityFromJSON :: (PersistEntity record, FromJSON record, FromJSON Key record) => Value -> Parser Entity record
+ Hledger.Web.Import: keyValueEntityToJSON :: (PersistEntity record, ToJSON record, ToJSON Key record) => Entity record -> Value
+ Hledger.Web.Import: languages :: MonadHandler m => m [Text]
+ Hledger.Web.Import: laxSameSiteSessions :: IO Maybe SessionBackend -> IO Maybe SessionBackend
+ Hledger.Web.Import: lcm :: Integral a => a -> a -> a
+ Hledger.Web.Import: lefts :: () => [Either a b] -> [a]
+ Hledger.Web.Import: length :: Foldable t => t a -> Int
+ Hledger.Web.Import: lensPTH :: () => s -> a -> s -> b -> t -> Lens s t a b
+ Hledger.Web.Import: lex :: ReadS String
+ Hledger.Web.Import: lift :: (MonadTrans t, Monad m) => m a -> t m a
+ Hledger.Web.Import: liftHandler :: MonadHandler m => HandlerFor HandlerSite m a -> m a
+ Hledger.Web.Import: liftIO :: MonadIO m => IO a -> m a
+ Hledger.Web.Import: liftM :: Monad m => a1 -> r -> m a1 -> m r
+ Hledger.Web.Import: liftM2 :: Monad m => a1 -> a2 -> r -> m a1 -> m a2 -> m r
+ Hledger.Web.Import: liftM3 :: Monad m => a1 -> a2 -> a3 -> r -> m a1 -> m a2 -> m a3 -> m r
+ Hledger.Web.Import: liftM4 :: Monad m => a1 -> a2 -> a3 -> a4 -> r -> m a1 -> m a2 -> m a3 -> m a4 -> m r
+ Hledger.Web.Import: liftM5 :: Monad m => a1 -> a2 -> a3 -> a4 -> a5 -> r -> m a1 -> m a2 -> m a3 -> m a4 -> m a5 -> m r
+ Hledger.Web.Import: liftPersist :: (MonadIO m, MonadReader backend m, HasPersistBackend backend) => ReaderT BaseBackend backend IO b -> m b
+ Hledger.Web.Import: liftResourceT :: MonadResource m => ResourceT IO a -> m a
+ Hledger.Web.Import: liftSubHandler :: MonadHandler m => SubHandlerFor SubHandlerSite m HandlerSite m a -> m a
+ Hledger.Web.Import: liftWidget :: MonadWidget m => WidgetFor HandlerSite m a -> m a
+ Hledger.Web.Import: limitOffsetOrder :: PersistEntity val => [SelectOpt val] -> (Int, Int, [SelectOpt val])
+ Hledger.Web.Import: lines :: String -> [String]
+ Hledger.Web.Import: listToJSON :: [PersistValue] -> Text
+ Hledger.Web.Import: listToMaybe :: () => [a] -> Maybe a
+ Hledger.Web.Import: liteApp :: Writer LiteApp () -> LiteApp
+ Hledger.Web.Import: loadClientSession :: Key -> IO ClientSessionDateCache -> ByteString -> Request -> IO (SessionMap, SaveSession)
+ Hledger.Web.Import: loadConfig :: PersistConfig c => Value -> Parser c
+ Hledger.Web.Import: localTimeToUT1 :: Rational -> LocalTime -> UniversalTime
+ Hledger.Web.Import: localTimeToUTC :: TimeZone -> LocalTime -> UTCTime
+ Hledger.Web.Import: localToUTCTimeOfDay :: TimeZone -> TimeOfDay -> (Integer, TimeOfDay)
+ Hledger.Web.Import: log :: Floating a => a -> a
+ Hledger.Web.Import: logBase :: Floating a => a -> a -> a
+ Hledger.Web.Import: logDebug :: Q Exp
+ Hledger.Web.Import: logDebugS :: Q Exp
+ Hledger.Web.Import: logError :: Q Exp
+ Hledger.Web.Import: logErrorS :: Q Exp
+ Hledger.Web.Import: logInfo :: Q Exp
+ Hledger.Web.Import: logInfoS :: Q Exp
+ Hledger.Web.Import: logOther :: Text -> Q Exp
+ Hledger.Web.Import: logOtherS :: Q Exp
+ Hledger.Web.Import: logWarn :: Q Exp
+ Hledger.Web.Import: logWarnS :: Q Exp
+ Hledger.Web.Import: lookup :: Eq a => a -> [(a, b)] -> Maybe b
+ Hledger.Web.Import: lookupBasicAuth :: MonadHandler m => m Maybe (Text, Text)
+ Hledger.Web.Import: lookupBearerAuth :: MonadHandler m => m Maybe Text
+ Hledger.Web.Import: lookupCookie :: MonadHandler m => Text -> m Maybe Text
+ Hledger.Web.Import: lookupCookies :: MonadHandler m => Text -> m [Text]
+ Hledger.Web.Import: lookupFile :: MonadHandler m => Text -> m Maybe FileInfo
+ Hledger.Web.Import: lookupFiles :: MonadHandler m => Text -> m [FileInfo]
+ Hledger.Web.Import: lookupGetParam :: MonadHandler m => Text -> m Maybe Text
+ Hledger.Web.Import: lookupGetParams :: MonadHandler m => Text -> m [Text]
+ Hledger.Web.Import: lookupHeader :: MonadHandler m => CI ByteString -> m Maybe ByteString
+ Hledger.Web.Import: lookupHeaders :: MonadHandler m => CI ByteString -> m [ByteString]
+ Hledger.Web.Import: lookupPostParam :: (MonadResource m, MonadHandler m) => Text -> m Maybe Text
+ Hledger.Web.Import: lookupPostParams :: (MonadResource m, MonadHandler m) => Text -> m [Text]
+ Hledger.Web.Import: lookupSession :: MonadHandler m => Text -> m Maybe Text
+ Hledger.Web.Import: lookupSessionBS :: MonadHandler m => Text -> m Maybe ByteString
+ Hledger.Web.Import: lucius :: QuasiQuoter
+ Hledger.Web.Import: mFormToWForm :: (MonadHandler m, HandlerSite m ~ site) => MForm m (a, FieldView site) -> WForm m a
+ Hledger.Web.Import: makeLogger :: Yesod site => site -> IO Logger
+ Hledger.Web.Import: makeSessionBackend :: Yesod site => site -> IO Maybe SessionBackend
+ Hledger.Web.Import: makeTimeOfDayValid :: Int -> Int -> Pico -> Maybe TimeOfDay
+ Hledger.Web.Import: manualurl :: Text
+ Hledger.Web.Import: map :: () => a -> b -> [a] -> [b]
+ Hledger.Web.Import: mapAccumL :: Traversable t => a -> b -> (a, c) -> a -> t b -> (a, t c)
+ Hledger.Web.Import: mapAccumR :: Traversable t => a -> b -> (a, c) -> a -> t b -> (a, t c)
+ Hledger.Web.Import: mapAndUnzipM :: Applicative m => a -> m (b, c) -> [a] -> m ([b], [c])
+ Hledger.Web.Import: mapM :: (Traversable t, Monad m) => a -> m b -> t a -> m t b
+ Hledger.Web.Import: mapM_ :: (Foldable t, Monad m) => a -> m b -> t a -> m ()
+ Hledger.Web.Import: mapMaybe :: () => a -> Maybe b -> [a] -> [b]
+ Hledger.Web.Import: mapToJSON :: [(Text, PersistValue)] -> Text
+ Hledger.Web.Import: mappend :: Monoid a => a -> a -> a
+ Hledger.Web.Import: max :: Ord a => a -> a -> a
+ Hledger.Web.Import: maxBound :: Bounded a => a
+ Hledger.Web.Import: maximum :: (Foldable t, Ord a) => t a -> a
+ Hledger.Web.Import: maximumBy :: Foldable t => a -> a -> Ordering -> t a -> a
+ Hledger.Web.Import: maximumContentLength :: Yesod site => site -> Maybe Route site -> Maybe Word64
+ Hledger.Web.Import: maybe :: () => b -> a -> b -> Maybe a -> b
+ Hledger.Web.Import: maybeAuthorized :: Yesod site => Route site -> Bool -> HandlerT site IO Maybe Route site
+ Hledger.Web.Import: maybeToList :: () => Maybe a -> [a]
+ Hledger.Web.Import: mconcat :: Monoid a => [a] -> a
+ Hledger.Web.Import: mempty :: Monoid a => a
+ Hledger.Web.Import: messageLoggerSource :: Yesod site => site -> Logger -> Loc -> LogSource -> LogLevel -> LogStr -> IO ()
+ Hledger.Web.Import: mfilter :: MonadPlus m => a -> Bool -> m a -> m a
+ Hledger.Web.Import: midday :: TimeOfDay
+ Hledger.Web.Import: midnight :: TimeOfDay
+ Hledger.Web.Import: min :: Ord a => a -> a -> a
+ Hledger.Web.Import: minBound :: Bounded a => a
+ Hledger.Web.Import: minimum :: (Foldable t, Ord a) => t a -> a
+ Hledger.Web.Import: minimumBy :: Foldable t => a -> a -> Ordering -> t a -> a
+ Hledger.Web.Import: minutesToTimeZone :: Int -> TimeZone
+ Hledger.Web.Import: mkDefaultMiddlewares :: Logger -> IO Middleware
+ Hledger.Web.Import: mkDeleteCascade :: MkPersistSettings -> [EntityDef] -> Q [Dec]
+ Hledger.Web.Import: mkMessage :: String -> FilePath -> Lang -> Q [Dec]
+ Hledger.Web.Import: mkMessageFor :: String -> String -> FilePath -> Lang -> Q [Dec]
+ Hledger.Web.Import: mkMessageVariant :: String -> String -> FilePath -> Lang -> Q [Dec]
+ Hledger.Web.Import: mkMigrate :: String -> [EntityDef] -> Q [Dec]
+ Hledger.Web.Import: mkOptionList :: () => [Option a] -> OptionList a
+ Hledger.Web.Import: mkPersist :: MkPersistSettings -> [EntityDef] -> Q [Dec]
+ Hledger.Web.Import: mkPersistSettings :: Type -> MkPersistSettings
+ Hledger.Web.Import: mkSave :: String -> [EntityDef] -> Q [Dec]
+ Hledger.Web.Import: mkYesod :: String -> [ResourceTree String] -> Q [Dec]
+ Hledger.Web.Import: mkYesodData :: String -> [ResourceTree String] -> Q [Dec]
+ Hledger.Web.Import: mkYesodDispatch :: String -> [ResourceTree String] -> Q [Dec]
+ Hledger.Web.Import: mkYesodSubData :: String -> [ResourceTree String] -> Q [Dec]
+ Hledger.Web.Import: mkYesodSubDispatch :: () => [ResourceTree a] -> Q Exp
+ Hledger.Web.Import: mkYesodWith :: [[String]] -> String -> [String] -> [ResourceTree String] -> Q [Dec]
+ Hledger.Web.Import: mod :: Integral a => a -> a -> a
+ Hledger.Web.Import: mopt :: (site ~ HandlerSite m, MonadHandler m) => Field m a -> FieldSettings site -> Maybe Maybe a -> MForm m (FormResult Maybe a, FieldView site)
+ Hledger.Web.Import: mplus :: MonadPlus m => m a -> m a -> m a
+ Hledger.Web.Import: mreq :: (RenderMessage site FormMessage, HandlerSite m ~ site, MonadHandler m) => Field m a -> FieldSettings site -> Maybe a -> MForm m (FormResult a, FieldView site)
+ Hledger.Web.Import: msum :: (Foldable t, MonadPlus m) => t m a -> m a
+ Hledger.Web.Import: multiEmailField :: (Monad m, RenderMessage HandlerSite m FormMessage) => Field m [Text]
+ Hledger.Web.Import: multiSelectField :: Eq a => HandlerFor site OptionList a -> Field HandlerFor site [a]
+ Hledger.Web.Import: multiSelectFieldList :: (Eq a, RenderMessage site msg) => [(msg, a)] -> Field HandlerFor site [a]
+ Hledger.Web.Import: mzero :: MonadPlus m => m a
+ Hledger.Web.Import: negate :: Num a => a -> a
+ Hledger.Web.Import: neverExpires :: MonadHandler m => m ()
+ Hledger.Web.Import: newFormIdent :: Monad m => MForm m Text
+ Hledger.Web.Import: newIdent :: MonadHandler m => m Text
+ Hledger.Web.Import: newtype AForm (m :: * -> *) a
+ Hledger.Web.Import: newtype CssBuilder
+ Hledger.Web.Import: newtype DBName
+ Hledger.Web.Import: newtype DBRunner site
+ Hledger.Web.Import: newtype Day
+ Hledger.Web.Import: newtype DontFullyEvaluate a
+ Hledger.Web.Import: newtype FormInput (m :: * -> *) a
+ Hledger.Web.Import: newtype HaskellName
+ Hledger.Web.Import: newtype LiteApp
+ Hledger.Web.Import: newtype RepJson
+ Hledger.Web.Import: newtype RepPlain
+ Hledger.Web.Import: newtype RepXml
+ Hledger.Web.Import: newtype SessionBackend
+ Hledger.Web.Import: newtype Textarea
+ Hledger.Web.Import: newtype UniversalTime
+ Hledger.Web.Import: newtype WaiSubsite
+ Hledger.Web.Import: newtype WaiSubsiteWithAuth
+ Hledger.Web.Import: nominalDay :: NominalDiffTime
+ Hledger.Web.Import: not :: Bool -> Bool
+ Hledger.Web.Import: notAuthenticated :: MonadHandler m => m a
+ Hledger.Web.Import: notElem :: (Foldable t, Eq a) => a -> t a -> Bool
+ Hledger.Web.Import: notFound :: MonadHandler m => m a
+ Hledger.Web.Import: notModified :: MonadHandler m => m a
+ Hledger.Web.Import: null :: Foldable t => t a -> Bool
+ Hledger.Web.Import: object :: [Pair] -> Value
+ Hledger.Web.Import: odd :: Integral a => a -> Bool
+ Hledger.Web.Import: onMethod :: Method -> Writer LiteApp () -> Writer LiteApp ()
+ Hledger.Web.Import: onStatic :: Text -> Writer LiteApp () -> Writer LiteApp ()
+ Hledger.Web.Import: onlyUnique :: (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend) => record -> ReaderT backend m Unique record
+ Hledger.Web.Import: optionsEnum :: (MonadHandler m, Show a, Enum a, Bounded a) => m OptionList a
+ Hledger.Web.Import: optionsPairs :: (MonadHandler m, RenderMessage HandlerSite m msg) => [(msg, a)] -> m OptionList a
+ Hledger.Web.Import: optionsPersist :: (YesodPersist site, PersistQueryRead backend, PathPiece Key a, RenderMessage site msg, YesodPersistBackend site ~ backend, PersistRecordBackend a backend) => [Filter a] -> [SelectOpt a] -> a -> msg -> HandlerFor site OptionList Entity a
+ Hledger.Web.Import: optionsPersistKey :: (YesodPersist site, PersistQueryRead backend, PathPiece Key a, RenderMessage site msg, backend ~ YesodPersistBackend site, PersistRecordBackend a backend) => [Filter a] -> [SelectOpt a] -> a -> msg -> HandlerFor site OptionList Key a
+ Hledger.Web.Import: or :: Foldable t => t Bool -> Bool
+ Hledger.Web.Import: otherwise :: Bool
+ Hledger.Web.Import: packPTH :: String -> Text
+ Hledger.Web.Import: parseCheckJsonBody :: (MonadHandler m, FromJSON a) => m Result a
+ Hledger.Web.Import: parseDate :: String -> Either FormMessage Day
+ Hledger.Web.Import: parseExtra :: DefaultEnv -> Object -> Parser Extra
+ Hledger.Web.Import: parseHelper :: (Monad m, RenderMessage site FormMessage) => Text -> Either FormMessage a -> [Text] -> [FileInfo] -> m Either SomeMessage site Maybe a
+ Hledger.Web.Import: parseHelperGen :: (Monad m, RenderMessage site msg) => Text -> Either msg a -> [Text] -> [FileInfo] -> m Either SomeMessage site Maybe a
+ Hledger.Web.Import: parseJSON :: FromJSON a => Value -> Parser a
+ Hledger.Web.Import: parseJSONList :: FromJSON a => Value -> Parser [a]
+ Hledger.Web.Import: parseJsonBody :: (MonadHandler m, FromJSON a) => m Result a
+ Hledger.Web.Import: parseJsonBody_ :: (MonadHandler m, FromJSON a) => m a
+ Hledger.Web.Import: parseReferences :: PersistSettings -> Text -> Q Exp
+ Hledger.Web.Import: parseRoute :: ParseRoute a => ([Text], [(Text, Text)]) -> Maybe Route a
+ Hledger.Web.Import: parseRoutes :: QuasiQuoter
+ Hledger.Web.Import: parseRoutesFile :: FilePath -> Q Exp
+ Hledger.Web.Import: parseRoutesFileNoCheck :: FilePath -> Q Exp
+ Hledger.Web.Import: parseRoutesNoCheck :: QuasiQuoter
+ Hledger.Web.Import: parseTime :: Text -> Either FormMessage TimeOfDay
+ Hledger.Web.Import: parseTimeM :: (Monad m, ParseTime t) => Bool -> TimeLocale -> String -> String -> m t
+ Hledger.Web.Import: parseTimeOrError :: ParseTime t => Bool -> TimeLocale -> String -> String -> t
+ Hledger.Web.Import: partitionEithers :: () => [Either a b] -> ([a], [b])
+ Hledger.Web.Import: passwordField :: (Monad m, RenderMessage HandlerSite m FormMessage) => Field m Text
+ Hledger.Web.Import: permissionDenied :: MonadHandler m => Text -> m a
+ Hledger.Web.Import: permissionDeniedI :: (RenderMessage HandlerSite m msg, MonadHandler m) => msg -> m a
+ Hledger.Web.Import: persistBackend :: HasPersistBackend backend => backend -> BaseBackend backend
+ Hledger.Web.Import: persistFieldDef :: PersistEntity record => EntityField record typ -> FieldDef
+ Hledger.Web.Import: persistFieldFromEntity :: MkPersistSettings -> EntityDef -> Q [Dec]
+ Hledger.Web.Import: persistFileWith :: PersistSettings -> FilePath -> Q Exp
+ Hledger.Web.Import: persistIdField :: PersistEntity record => EntityField record Key record
+ Hledger.Web.Import: persistLowerCase :: QuasiQuoter
+ Hledger.Web.Import: persistManyFileWith :: PersistSettings -> [FilePath] -> Q Exp
+ Hledger.Web.Import: persistUniqueKeys :: PersistEntity record => record -> [Unique record]
+ Hledger.Web.Import: persistUniqueToFieldNames :: PersistEntity record => Unique record -> [(HaskellName, DBName)]
+ Hledger.Web.Import: persistUniqueToValues :: PersistEntity record => Unique record -> [PersistValue]
+ Hledger.Web.Import: persistUpperCase :: QuasiQuoter
+ Hledger.Web.Import: persistWith :: PersistSettings -> QuasiQuoter
+ Hledger.Web.Import: pi :: Floating a => a
+ Hledger.Web.Import: picosecondsToDiffTime :: Integer -> DiffTime
+ Hledger.Web.Import: preEscapedToMarkup :: ToMarkup a => a -> Markup
+ Hledger.Web.Import: pred :: Enum a => a -> a
+ Hledger.Web.Import: print :: Show a => a -> IO ()
+ Hledger.Web.Import: product :: (Foldable t, Num a) => t a -> a
+ Hledger.Web.Import: production :: Bool
+ Hledger.Web.Import: projectBackend :: BackendCompatible sup sub => sub -> sup
+ Hledger.Web.Import: properFraction :: (RealFrac a, Integral b) => a -> (b, a)
+ Hledger.Web.Import: provideJson :: (Monad m, ToJSON a) => a -> Writer Endo [ProvidedRep m] ()
+ Hledger.Web.Import: provideRep :: (Monad m, HasContentType a) => m a -> Writer Endo [ProvidedRep m] ()
+ Hledger.Web.Import: provideRepType :: (Monad m, ToContent a) => ContentType -> m a -> Writer Endo [ProvidedRep m] ()
+ Hledger.Web.Import: pure :: Applicative f => a -> f a
+ Hledger.Web.Import: putChar :: Char -> IO ()
+ Hledger.Web.Import: putMany :: (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m ()
+ Hledger.Web.Import: putStr :: String -> IO ()
+ Hledger.Web.Import: putStrLn :: String -> IO ()
+ Hledger.Web.Import: quot :: Integral a => a -> a -> a
+ Hledger.Web.Import: quotRem :: Integral a => a -> a -> (a, a)
+ Hledger.Web.Import: radioField :: (Eq a, RenderMessage site FormMessage) => HandlerFor site OptionList a -> Field HandlerFor site a
+ Hledger.Web.Import: radioFieldList :: (Eq a, RenderMessage site FormMessage, RenderMessage site msg) => [(msg, a)] -> Field HandlerFor site a
+ Hledger.Web.Import: rawRequestBody :: MonadHandler m => ConduitT i ByteString m ()
+ Hledger.Web.Import: read :: Read a => String -> a
+ Hledger.Web.Import: readIO :: Read a => String -> IO a
+ Hledger.Web.Import: readIntegral :: Num a => String -> Maybe a
+ Hledger.Web.Import: readList :: Read a => ReadS [a]
+ Hledger.Web.Import: readLn :: Read a => IO a
+ Hledger.Web.Import: readPTime :: ParseTime t => Bool -> TimeLocale -> String -> ReadP t
+ Hledger.Web.Import: readParen :: () => Bool -> ReadS a -> ReadS a
+ Hledger.Web.Import: readSTime :: ParseTime t => Bool -> TimeLocale -> String -> ReadS t
+ Hledger.Web.Import: readTime :: ParseTime t => TimeLocale -> String -> String -> t
+ Hledger.Web.Import: reads :: Read a => ReadS a
+ Hledger.Web.Import: readsPrec :: Read a => Int -> ReadS a
+ Hledger.Web.Import: readsTime :: ParseTime t => TimeLocale -> String -> ReadS t
+ Hledger.Web.Import: realToFrac :: (Real a, Fractional b) => a -> b
+ Hledger.Web.Import: recip :: Fractional a => a -> a
+ Hledger.Web.Import: redirect :: (MonadHandler m, RedirectUrl HandlerSite m url) => url -> m a
+ Hledger.Web.Import: redirectToPost :: (MonadHandler m, RedirectUrl HandlerSite m url) => url -> m a
+ Hledger.Web.Import: redirectUltDest :: (RedirectUrl HandlerSite m url, MonadHandler m) => url -> m a
+ Hledger.Web.Import: redirectWith :: (MonadHandler m, RedirectUrl HandlerSite m url) => Status -> url -> m a
+ Hledger.Web.Import: rem :: Integral a => a -> a -> a
+ Hledger.Web.Import: renderBootstrap :: Monad m => FormRender m a
+ Hledger.Web.Import: renderBootstrap2 :: Monad m => FormRender m a
+ Hledger.Web.Import: renderCssUrl :: () => url -> [(Text, Text)] -> Text -> CssUrl url -> Text
+ Hledger.Web.Import: renderDivs :: Monad m => FormRender m a
+ Hledger.Web.Import: renderDivsNoLabels :: Monad m => FormRender m a
+ Hledger.Web.Import: renderJavascriptUrl :: () => url -> [(Text, Text)] -> Text -> JavascriptUrl url -> Text
+ Hledger.Web.Import: renderMessage :: RenderMessage master message => master -> [Lang] -> message -> Text
+ Hledger.Web.Import: renderTable :: Monad m => FormRender m a
+ Hledger.Web.Import: repJson :: ToContent a => a -> RepJson
+ Hledger.Web.Import: repPlain :: ToContent a => a -> RepPlain
+ Hledger.Web.Import: repXml :: ToContent a => a -> RepXml
+ Hledger.Web.Import: repeat :: () => a -> [a]
+ Hledger.Web.Import: replace :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> record -> ReaderT backend m ()
+ Hledger.Web.Import: replaceOrAddHeader :: MonadHandler m => Text -> Text -> m ()
+ 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: replicate :: () => Int -> a -> [a]
+ Hledger.Web.Import: replicateM :: Applicative m => Int -> m a -> m [a]
+ Hledger.Web.Import: replicateM_ :: Applicative m => Int -> m a -> m ()
+ Hledger.Web.Import: repsert :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> record -> ReaderT backend m ()
+ Hledger.Web.Import: repsertMany :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [(Key record, record)] -> ReaderT backend m ()
+ Hledger.Web.Import: requireCheckJsonBody :: (MonadHandler m, FromJSON a) => m a
+ Hledger.Web.Import: requireJsonBody :: (MonadHandler m, FromJSON a) => m a
+ Hledger.Web.Import: resourcesApp :: [ResourceTree String]
+ Hledger.Web.Import: respond :: (Monad m, ToContent a) => ContentType -> a -> m TypedContent
+ Hledger.Web.Import: respondSource :: () => ContentType -> ConduitT () Flush Builder HandlerFor site () -> HandlerFor site TypedContent
+ Hledger.Web.Import: respondSourceDB :: YesodPersistRunner site => ContentType -> ConduitT () Flush Builder YesodDB site () -> HandlerFor site TypedContent
+ Hledger.Web.Import: return :: Monad m => a -> m a
+ Hledger.Web.Import: returnJson :: (Monad m, ToJSON a) => a -> m Value
+ Hledger.Web.Import: returnJsonEncoding :: (Monad m, ToJSON a) => a -> m Encoding
+ Hledger.Web.Import: reverse :: () => [a] -> [a]
+ Hledger.Web.Import: rfc822DateFormat :: String
+ Hledger.Web.Import: rights :: () => [Either a b] -> [b]
+ Hledger.Web.Import: round :: (RealFrac a, Integral b) => a -> b
+ Hledger.Web.Import: routeAttrs :: RouteAttrs a => Route a -> Set Text
+ Hledger.Web.Import: runDB :: YesodPersist site => YesodDB site a -> HandlerFor site a
+ Hledger.Web.Import: runDBSource :: YesodPersistRunner site => ConduitT () a YesodDB site () -> ConduitT () a HandlerFor site ()
+ Hledger.Web.Import: runFakeHandler :: (Yesod site, MonadIO m) => SessionMap -> site -> Logger -> site -> HandlerT site IO a -> m Either ErrorResponse a
+ Hledger.Web.Import: runFormGet :: MonadHandler m => Markup -> MForm m a -> m (a, Enctype)
+ Hledger.Web.Import: runFormPost :: (RenderMessage HandlerSite m FormMessage, MonadResource m, MonadHandler m) => Markup -> MForm m (FormResult a, xml) -> m ((FormResult a, xml), Enctype)
+ Hledger.Web.Import: runFormPostNoToken :: MonadHandler m => Markup -> MForm m a -> m (a, Enctype)
+ Hledger.Web.Import: runInputGet :: MonadHandler m => FormInput m a -> m a
+ Hledger.Web.Import: runInputGetResult :: MonadHandler m => FormInput m a -> m FormResult a
+ Hledger.Web.Import: runInputPost :: MonadHandler m => FormInput m a -> m a
+ Hledger.Web.Import: runInputPostResult :: MonadHandler m => FormInput m a -> m FormResult a
+ Hledger.Web.Import: runPool :: (PersistConfig c, MonadUnliftIO m) => c -> PersistConfigBackend c m a -> PersistConfigPool c -> m a
+ Hledger.Web.Import: runRequestBody :: MonadHandler m => m RequestBodyContents
+ Hledger.Web.Import: scaleFloat :: RealFloat a => Int -> a -> a
+ Hledger.Web.Import: scanl :: () => b -> a -> b -> b -> [a] -> [b]
+ Hledger.Web.Import: scanl1 :: () => a -> a -> a -> [a] -> [a]
+ Hledger.Web.Import: scanr :: () => a -> b -> b -> b -> [a] -> [b]
+ Hledger.Web.Import: scanr1 :: () => a -> a -> a -> [a] -> [a]
+ Hledger.Web.Import: searchField :: (Monad m, RenderMessage HandlerSite m FormMessage) => AutoFocus -> Field m Text
+ Hledger.Web.Import: second :: Bifunctor p => b -> c -> p a b -> p a c
+ Hledger.Web.Import: secondsToDiffTime :: Integer -> DiffTime
+ Hledger.Web.Import: selectField :: (Eq a, RenderMessage site FormMessage) => HandlerFor site OptionList a -> Field HandlerFor site a
+ Hledger.Web.Import: selectFieldList :: (Eq a, RenderMessage site FormMessage, RenderMessage site msg) => [(msg, a)] -> Field HandlerFor site a
+ Hledger.Web.Import: selectFirst :: (PersistQueryRead backend, MonadIO m, PersistRecordBackend record backend) => [Filter record] -> [SelectOpt record] -> ReaderT backend m Maybe Entity 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: selectKeysList :: (MonadIO m, PersistQueryRead backend, PersistRecordBackend record backend) => [Filter record] -> [SelectOpt record] -> ReaderT backend m [Key record]
+ Hledger.Web.Import: selectKeysRes :: (PersistQueryRead backend, MonadIO m1, MonadIO m2, PersistRecordBackend record backend) => [Filter record] -> [SelectOpt record] -> ReaderT backend m1 Acquire ConduitM () Key record m2 ()
+ Hledger.Web.Import: selectList :: (MonadIO m, PersistQueryRead backend, PersistRecordBackend record backend) => [Filter record] -> [SelectOpt record] -> ReaderT backend m [Entity record]
+ Hledger.Web.Import: selectRep :: MonadHandler m => Writer Endo [ProvidedRep m] () -> m TypedContent
+ 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: selectSourceRes :: (PersistQueryRead backend, PersistRecordBackend record backend, MonadIO m1, MonadIO m2) => [Filter record] -> [SelectOpt record] -> ReaderT backend m1 Acquire ConduitM () Entity record m2 ()
+ Hledger.Web.Import: sendChunk :: (Monad m, ToFlushBuilder a) => a -> ConduitT i Flush Builder m ()
+ Hledger.Web.Import: sendChunkBS :: Monad m => ByteString -> ConduitT i Flush Builder m ()
+ Hledger.Web.Import: sendChunkHtml :: Monad m => Html -> ConduitT i Flush Builder m ()
+ Hledger.Web.Import: sendChunkLBS :: Monad m => ByteString -> ConduitT i Flush Builder m ()
+ Hledger.Web.Import: sendChunkLazyText :: Monad m => Text -> ConduitT i Flush Builder m ()
+ Hledger.Web.Import: sendChunkText :: Monad m => Text -> ConduitT i Flush Builder m ()
+ Hledger.Web.Import: sendFile :: MonadHandler m => ContentType -> FilePath -> m a
+ Hledger.Web.Import: sendFilePart :: MonadHandler m => ContentType -> FilePath -> Integer -> Integer -> m a
+ Hledger.Web.Import: sendFlush :: Monad m => ConduitT i Flush Builder m ()
+ Hledger.Web.Import: sendRawResponse :: (MonadHandler m, MonadUnliftIO m) => ConduitT () ByteString IO () -> ConduitT ByteString Void IO () -> m () -> m a
+ Hledger.Web.Import: sendRawResponseNoConduit :: (MonadHandler m, MonadUnliftIO m) => IO ByteString -> ByteString -> IO () -> m () -> m a
+ Hledger.Web.Import: sendResponse :: (MonadHandler m, ToTypedContent c) => c -> m a
+ Hledger.Web.Import: sendResponseCreated :: MonadHandler m => Route HandlerSite m -> m a
+ Hledger.Web.Import: sendResponseStatus :: (MonadHandler m, ToTypedContent c) => Status -> c -> m a
+ Hledger.Web.Import: sendStatusJSON :: (MonadHandler m, ToJSON c) => Status -> c -> m a
+ Hledger.Web.Import: sendWaiApplication :: MonadHandler m => Application -> m b
+ Hledger.Web.Import: sendWaiResponse :: MonadHandler m => Response -> m b
+ Hledger.Web.Import: seq :: () => a -> b -> b
+ Hledger.Web.Import: sequence :: (Traversable t, Monad m) => t m a -> m t a
+ Hledger.Web.Import: sequenceA :: (Traversable t, Applicative f) => t f a -> f t a
+ Hledger.Web.Import: sequenceA_ :: (Foldable t, Applicative f) => t f a -> f ()
+ Hledger.Web.Import: sequence_ :: (Foldable t, Monad m) => t m a -> m ()
+ Hledger.Web.Import: setCookie :: MonadHandler m => SetCookie -> m ()
+ Hledger.Web.Import: setCsrfCookie :: MonadHandler m => m ()
+ Hledger.Web.Import: setCsrfCookieWithCookie :: MonadHandler m => SetCookie -> m ()
+ Hledger.Web.Import: setEtag :: MonadHandler m => Text -> m ()
+ Hledger.Web.Import: setHeader :: MonadHandler m => Text -> Text -> m ()
+ Hledger.Web.Import: setLanguage :: MonadHandler m => Text -> m ()
+ Hledger.Web.Import: setMessage :: MonadHandler m => Html -> m ()
+ Hledger.Web.Import: setMessageI :: (MonadHandler m, RenderMessage HandlerSite m msg) => msg -> m ()
+ Hledger.Web.Import: setSession :: MonadHandler m => Text -> Text -> m ()
+ Hledger.Web.Import: setSessionBS :: MonadHandler m => Text -> ByteString -> m ()
+ Hledger.Web.Import: setTitle :: MonadWidget m => Html -> m ()
+ Hledger.Web.Import: setTitleI :: (MonadWidget m, RenderMessage HandlerSite m msg) => msg -> m ()
+ Hledger.Web.Import: setUltDest :: (MonadHandler m, RedirectUrl HandlerSite m url) => url -> m ()
+ Hledger.Web.Import: setUltDestCurrent :: MonadHandler m => m ()
+ Hledger.Web.Import: setUltDestReferer :: MonadHandler m => m ()
+ Hledger.Web.Import: setWeakEtag :: MonadHandler m => Text -> m ()
+ Hledger.Web.Import: shamlet :: QuasiQuoter
+ Hledger.Web.Import: share :: [[EntityDef] -> Q [Dec]] -> [EntityDef] -> Q [Dec]
+ Hledger.Web.Import: shouldLogIO :: Yesod site => site -> LogSource -> LogLevel -> IO Bool
+ Hledger.Web.Import: shouldShowSidebar :: Handler Bool
+ Hledger.Web.Import: show :: Show a => a -> String
+ Hledger.Web.Import: showChar :: Char -> ShowS
+ Hledger.Web.Import: showGregorian :: Day -> String
+ Hledger.Web.Import: showIntegral :: Integral a => a -> String
+ Hledger.Web.Import: showList :: Show a => [a] -> ShowS
+ Hledger.Web.Import: showParen :: Bool -> ShowS -> ShowS
+ Hledger.Web.Import: showString :: String -> ShowS
+ Hledger.Web.Import: shows :: Show a => a -> ShowS
+ Hledger.Web.Import: showsPrec :: Show a => Int -> a -> ShowS
+ Hledger.Web.Import: significand :: RealFloat a => a -> a
+ Hledger.Web.Import: signum :: Num a => a -> a
+ Hledger.Web.Import: simpleContentType :: ContentType -> ContentType
+ Hledger.Web.Import: sin :: Floating a => a -> a
+ Hledger.Web.Import: sinh :: Floating a => a -> a
+ Hledger.Web.Import: snd :: () => (a, b) -> b
+ Hledger.Web.Import: span :: () => a -> Bool -> [a] -> ([a], [a])
+ Hledger.Web.Import: splitAt :: () => Int -> [a] -> ([a], [a])
+ Hledger.Web.Import: sqlOnlySettings :: MkPersistSettings
+ Hledger.Web.Import: sqlSettings :: MkPersistSettings
+ Hledger.Web.Import: sqrt :: Floating a => a -> a
+ Hledger.Web.Import: sslOnlyMiddleware :: () => Int -> HandlerFor site res -> HandlerFor site res
+ Hledger.Web.Import: sslOnlySessions :: IO Maybe SessionBackend -> IO Maybe SessionBackend
+ Hledger.Web.Import: staticDir :: FilePath
+ Hledger.Web.Import: staticRoot :: AppConfig DefaultEnv Extra -> Text
+ Hledger.Web.Import: staticSite :: IO Static
+ Hledger.Web.Import: strictSameSiteSessions :: IO Maybe SessionBackend -> IO Maybe SessionBackend
+ Hledger.Web.Import: subtract :: Num a => a -> a -> a
+ Hledger.Web.Import: succ :: Enum a => a -> a
+ Hledger.Web.Import: sum :: (Foldable t, Num a) => t a -> a
+ Hledger.Web.Import: take :: () => Int -> [a] -> [a]
+ Hledger.Web.Import: takeWhile :: () => a -> Bool -> [a] -> [a]
+ Hledger.Web.Import: tan :: Floating a => a -> a
+ Hledger.Web.Import: tanh :: Floating a => a -> a
+ Hledger.Web.Import: textField :: (Monad m, RenderMessage HandlerSite m FormMessage) => Field m Text
+ Hledger.Web.Import: textareaField :: (Monad m, RenderMessage HandlerSite m FormMessage) => Field m Textarea
+ Hledger.Web.Import: timeField :: (Monad m, RenderMessage HandlerSite m FormMessage) => Field m TimeOfDay
+ Hledger.Web.Import: timeFieldTypeText :: (Monad m, RenderMessage HandlerSite m FormMessage) => Field m TimeOfDay
+ Hledger.Web.Import: timeFieldTypeTime :: (Monad m, RenderMessage HandlerSite m FormMessage) => Field m TimeOfDay
+ Hledger.Web.Import: timeOfDayToDayFraction :: TimeOfDay -> Rational
+ Hledger.Web.Import: timeOfDayToTime :: TimeOfDay -> DiffTime
+ Hledger.Web.Import: timeToTimeOfDay :: DiffTime -> TimeOfDay
+ Hledger.Web.Import: timeZoneOffsetString :: TimeZone -> String
+ Hledger.Web.Import: timeZoneOffsetString' :: Maybe Char -> TimeZone -> String
+ Hledger.Web.Import: toBackendKey :: ToBackendKey backend record => Key record -> BackendKey backend
+ Hledger.Web.Import: toContent :: ToContent a => a -> Content
+ Hledger.Web.Import: toEmbedEntityDef :: EntityDef -> EmbedEntityDef
+ Hledger.Web.Import: toEncoding :: ToJSON a => a -> Encoding
+ Hledger.Web.Import: toEncodingList :: ToJSON a => [a] -> Encoding
+ Hledger.Web.Import: toEnum :: Enum a => Int -> a
+ Hledger.Web.Import: toFlushBuilder :: ToFlushBuilder a => a -> Flush Builder
+ Hledger.Web.Import: toGregorian :: Day -> (Integer, Int, Int)
+ Hledger.Web.Import: toHtml :: ToMarkup a => a -> Html
+ Hledger.Web.Import: toInteger :: Integral a => a -> Integer
+ Hledger.Web.Import: toJSON :: ToJSON a => a -> Value
+ Hledger.Web.Import: toJSONList :: ToJSON a => [a] -> Value
+ Hledger.Web.Import: toJsonText :: ToJSON j => j -> Text
+ Hledger.Web.Import: toList :: Foldable t => t a -> [a]
+ Hledger.Web.Import: toMessage :: ToMessage a => a -> Text
+ Hledger.Web.Import: toPathMultiPiece :: PathMultiPiece s => s -> [Text]
+ Hledger.Web.Import: toPathPiece :: PathPiece s => s -> Text
+ Hledger.Web.Import: toPersistFields :: PersistEntity record => record -> [SomePersistField]
+ Hledger.Web.Import: toPersistValue :: PersistField a => a -> PersistValue
+ Hledger.Web.Import: toPersistValueJSON :: ToJSON a => a -> PersistValue
+ Hledger.Web.Import: toRational :: Real a => a -> Rational
+ Hledger.Web.Import: toTextUrl :: (RedirectUrl master a, MonadHandler m, HandlerSite m ~ master) => a -> m Text
+ Hledger.Web.Import: toTypedContent :: ToTypedContent a => a -> TypedContent
+ Hledger.Web.Import: toWaiApp :: YesodDispatch site => site -> IO Application
+ Hledger.Web.Import: toWaiAppPlain :: YesodDispatch site => site -> IO Application
+ Hledger.Web.Import: toWaiAppYre :: YesodDispatch site => YesodRunnerEnv site -> Application
+ Hledger.Web.Import: toWidget :: (ToWidget site a, MonadWidget m, HandlerSite m ~ site) => a -> m ()
+ Hledger.Web.Import: toWidgetBody :: (ToWidgetBody site a, MonadWidget m, HandlerSite m ~ site) => a -> m ()
+ Hledger.Web.Import: toWidgetHead :: (ToWidgetHead site a, MonadWidget m, HandlerSite m ~ site) => a -> m ()
+ Hledger.Web.Import: toWidgetMedia :: (ToWidgetMedia site a, MonadWidget m, HandlerSite m ~ site) => Text -> a -> m ()
+ Hledger.Web.Import: traverse :: (Traversable t, Applicative f) => a -> f b -> t a -> f t b
+ Hledger.Web.Import: traverse_ :: (Foldable t, Applicative f) => a -> f b -> t a -> f ()
+ Hledger.Web.Import: truncate :: (RealFrac a, Integral b) => a -> b
+ Hledger.Web.Import: type AppRoute = Route App
+ Hledger.Web.Import: type Application = Request -> Response -> IO ResponseReceived -> IO ResponseReceived
+ Hledger.Web.Import: type Attr = Text
+ Hledger.Web.Import: type AutoFocus = Bool
+ Hledger.Web.Import: type BottomOfHeadAsync master = [Text] -> Maybe HtmlUrl Route master -> HtmlUrl Route master
+ Hledger.Web.Import: type ContentType = ByteString
+ Hledger.Web.Import: type CssUrl url = url -> [(Text, Text)] -> Text -> Css
+ Hledger.Web.Import: type Env = Map Text [Text]
+ Hledger.Web.Import: type ExtraLine = [Text]
+ Hledger.Web.Import: type FieldViewFunc (m :: * -> *) a = Text -> Text -> [(Text, Text)] -> Either Text a -> Bool -> WidgetFor HandlerSite m ()
+ Hledger.Web.Import: type FileEnv = Map Text [FileInfo]
+ Hledger.Web.Import: type FilePath = String
+ Hledger.Web.Import: type ForeignFieldDef = (HaskellName, DBName)
+ Hledger.Web.Import: type Form x = Html -> MForm (HandlerFor App) (FormResult x, Widget)
+ Hledger.Web.Import: type FormRender (m :: * -> *) a = AForm m a -> Markup -> MForm m (FormResult a, WidgetFor HandlerSite m ())
+ Hledger.Web.Import: type Handler = HandlerFor App
+ Hledger.Web.Import: type HandlerT site (m :: * -> *) = HandlerFor site
+ Hledger.Web.Import: type Html = Markup
+ Hledger.Web.Import: type HtmlUrl url = Render url -> Html
+ Hledger.Web.Import: type IOError = IOException
+ Hledger.Web.Import: type JavascriptUrl url = url -> [(Text, Text)] -> Text -> Javascript
+ Hledger.Web.Import: type Lang = Text
+ Hledger.Web.Import: type LiteHandler = HandlerFor LiteApp
+ Hledger.Web.Import: type LiteWidget = WidgetFor LiteApp
+ Hledger.Web.Import: type MForm (m :: * -> *) a = RWST (Maybe (Env, FileEnv), HandlerSite m, [Lang]) Enctype Ints m a
+ Hledger.Web.Import: type Markup = MarkupM ()
+ Hledger.Web.Import: type NumericPadOption = Maybe Char
+ Hledger.Web.Import: type PersistQuery a = PersistQueryWrite a
+ Hledger.Web.Import: type PersistRecordBackend record backend = (PersistEntity record, PersistEntityBackend record ~ BaseBackend backend)
+ Hledger.Web.Import: type PersistStore a = PersistStoreWrite a
+ Hledger.Web.Import: type PersistUnique a = PersistUniqueWrite a
+ Hledger.Web.Import: type Rational = Ratio Integer
+ Hledger.Web.Import: type ReadS a = String -> [(a, String)]
+ Hledger.Web.Import: type RepHtml = Html
+ Hledger.Web.Import: type RequestBodyContents = ([(Text, Text)], [(Text, FileInfo)])
+ Hledger.Web.Import: type SessionMap = Map Text ByteString
+ Hledger.Web.Import: type ShowS = String -> String
+ Hledger.Web.Import: type String = [Char]
+ Hledger.Web.Import: type Texts = [Text]
+ Hledger.Web.Import: type WForm (m :: * -> *) a = MForm WriterT [FieldView HandlerSite m] m a
+ Hledger.Web.Import: type Widget = WidgetFor App ()
+ Hledger.Web.Import: type WidgetT site (m :: * -> *) = WidgetFor site
+ Hledger.Web.Import: type YesodDB site = ReaderT YesodPersistBackend site HandlerFor site
+ Hledger.Web.Import: type family SubHandlerSite (m :: * -> *) :: *;
+ Hledger.Web.Import: typeAtom :: ContentType
+ Hledger.Web.Import: typeCss :: ContentType
+ Hledger.Web.Import: typeFlv :: ContentType
+ Hledger.Web.Import: typeGif :: ContentType
+ Hledger.Web.Import: typeHtml :: ContentType
+ Hledger.Web.Import: typeJavascript :: ContentType
+ Hledger.Web.Import: typeJpeg :: ContentType
+ Hledger.Web.Import: typeJson :: ContentType
+ Hledger.Web.Import: typeOctet :: ContentType
+ Hledger.Web.Import: typeOgv :: ContentType
+ Hledger.Web.Import: typePlain :: ContentType
+ Hledger.Web.Import: typePng :: ContentType
+ Hledger.Web.Import: typeRss :: ContentType
+ Hledger.Web.Import: typeSvg :: ContentType
+ Hledger.Web.Import: typeXml :: ContentType
+ Hledger.Web.Import: unauthorizedI :: (MonadHandler m, RenderMessage HandlerSite m msg) => msg -> m AuthResult
+ Hledger.Web.Import: uncurry :: () => a -> b -> c -> (a, b) -> c
+ Hledger.Web.Import: undefined :: HasCallStack => a
+ Hledger.Web.Import: unfoldr :: () => b -> Maybe (a, b) -> b -> [a]
+ Hledger.Web.Import: unless :: Applicative f => Bool -> f () -> f ()
+ Hledger.Web.Import: unlines :: [String] -> String
+ Hledger.Web.Import: until :: () => a -> Bool -> a -> a -> a -> a
+ Hledger.Web.Import: unwords :: [String] -> String
+ Hledger.Web.Import: unzip :: () => [(a, b)] -> ([a], [b])
+ Hledger.Web.Import: unzip3 :: () => [(a, b, c)] -> ([a], [b], [c])
+ Hledger.Web.Import: update :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> [Update record] -> ReaderT backend m ()
+ Hledger.Web.Import: updateGet :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> [Update record] -> ReaderT backend m record
+ Hledger.Web.Import: updateWhere :: (PersistQueryWrite backend, MonadIO m, PersistRecordBackend record backend) => [Filter record] -> [Update record] -> ReaderT backend m ()
+ Hledger.Web.Import: upsert :: (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> [Update record] -> ReaderT backend m Entity record
+ Hledger.Web.Import: upsertBy :: (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> record -> [Update record] -> ReaderT backend m Entity record
+ Hledger.Web.Import: urlField :: (Monad m, RenderMessage HandlerSite m FormMessage) => Field m Text
+ Hledger.Web.Import: urlParamRenderOverride :: Yesod site => site -> Route site -> [(Text, Text)] -> Maybe Builder
+ Hledger.Web.Import: userError :: String -> IOError
+ Hledger.Web.Import: ut1ToLocalTime :: Rational -> UniversalTime -> LocalTime
+ Hledger.Web.Import: utc :: TimeZone
+ Hledger.Web.Import: utcToLocalTime :: TimeZone -> UTCTime -> LocalTime
+ Hledger.Web.Import: utcToLocalTimeOfDay :: TimeZone -> TimeOfDay -> (Integer, TimeOfDay)
+ Hledger.Web.Import: utcToLocalZonedTime :: UTCTime -> IO ZonedTime
+ Hledger.Web.Import: utcToZonedTime :: TimeZone -> UTCTime -> ZonedTime
+ Hledger.Web.Import: void :: Functor f => f a -> f ()
+ Hledger.Web.Import: wFormToAForm :: MonadHandler m => WForm m FormResult a -> AForm m a
+ Hledger.Web.Import: wFormToMForm :: (MonadHandler m, HandlerSite m ~ site) => WForm m a -> MForm m (a, [FieldView site])
+ Hledger.Web.Import: waiRequest :: MonadHandler m => m Request
+ Hledger.Web.Import: warp :: YesodDispatch site => Int -> site -> IO ()
+ Hledger.Web.Import: warpDebug :: YesodDispatch site => Int -> site -> IO ()
+ Hledger.Web.Import: warpEnv :: YesodDispatch site => site -> IO ()
+ Hledger.Web.Import: whamlet :: QuasiQuoter
+ Hledger.Web.Import: whamletFile :: FilePath -> Q Exp
+ Hledger.Web.Import: whamletFileWithSettings :: HamletSettings -> FilePath -> Q Exp
+ Hledger.Web.Import: when :: Applicative f => Bool -> f () -> f ()
+ Hledger.Web.Import: widgetFile :: String -> Q Exp
+ Hledger.Web.Import: widgetFileSettings :: WidgetFileSettings
+ Hledger.Web.Import: widgetToPageContent :: Yesod site => WidgetFor site () -> HandlerFor site PageContent Route site
+ Hledger.Web.Import: withDynamic :: PathPiece p => p -> Writer LiteApp () -> Writer LiteApp ()
+ Hledger.Web.Import: withDynamicMulti :: PathMultiPiece ps => ps -> Writer LiteApp () -> Writer LiteApp ()
+ Hledger.Web.Import: withRunInIO :: MonadUnliftIO m => forall a. () => m a -> IO a -> IO b -> m b
+ Hledger.Web.Import: withUrlRenderer :: MonadHandler m => Route HandlerSite m -> [(Text, Text)] -> Text -> output -> m output
+ Hledger.Web.Import: wopt :: (MonadHandler m, HandlerSite m ~ site) => Field m a -> FieldSettings site -> Maybe Maybe a -> WForm m FormResult Maybe a
+ Hledger.Web.Import: words :: String -> [String]
+ Hledger.Web.Import: wreq :: (RenderMessage site FormMessage, HandlerSite m ~ site, MonadHandler m) => Field m a -> FieldSettings site -> Maybe a -> WForm m FormResult a
+ Hledger.Web.Import: xhamlet :: QuasiQuoter
+ Hledger.Web.Import: yesodDispatch :: YesodDispatch site => YesodRunnerEnv site -> Application
+ Hledger.Web.Import: yesodMiddleware :: (Yesod site, ToTypedContent res) => HandlerFor site res -> HandlerFor site res
+ Hledger.Web.Import: yesodRender :: Yesod y => y -> ResolvedApproot -> Route y -> [(Text, Text)] -> Text
+ Hledger.Web.Import: yesodRunner :: (ToTypedContent res, Yesod site) => HandlerFor site res -> YesodRunnerEnv site -> Maybe Route site -> Application
+ Hledger.Web.Import: yesodSubDispatch :: YesodSubDispatch sub master => YesodSubRunnerEnv sub master -> Application
+ Hledger.Web.Import: yesodVersion :: String
+ Hledger.Web.Import: yesodWithInternalState :: Yesod site => site -> Maybe Route site -> InternalState -> IO a -> IO a
+ Hledger.Web.Import: zip :: () => [a] -> [b] -> [(a, b)]
+ Hledger.Web.Import: zip3 :: () => [a] -> [b] -> [c] -> [(a, b, c)]
+ Hledger.Web.Import: zipWith :: () => a -> b -> c -> [a] -> [b] -> [c]
+ Hledger.Web.Import: zipWith3 :: () => a -> b -> c -> d -> [a] -> [b] -> [c] -> [d]
+ Hledger.Web.Import: zipWithM :: Applicative m => a -> b -> m c -> [a] -> [b] -> m [c]
+ Hledger.Web.Import: zipWithM_ :: Applicative m => a -> b -> m c -> [a] -> [b] -> m ()
+ Hledger.Web.Import: zonedTimeToUTC :: ZonedTime -> UTCTime
+ Hledger.Web.Import: }
+ Hledger.Web.Main: hledgerWebDev :: IO (Int, Application)
+ Hledger.Web.Main: withJournalDoWeb :: WebOpts -> (WebOpts -> Journal -> IO a) -> IO a
+ Hledger.Web.Settings: Extra :: Text -> Maybe Text -> Maybe Text -> Extra
+ Hledger.Web.Settings: [extraAnalytics] :: Extra -> Maybe Text
+ Hledger.Web.Settings: [extraCopyright] :: Extra -> Text
+ Hledger.Web.Settings: [extraStaticRoot] :: Extra -> Maybe Text
+ Hledger.Web.Settings: data Extra
+ Hledger.Web.Settings: defbaseurl :: String -> Int -> String
+ Hledger.Web.Settings: defhost :: String
+ Hledger.Web.Settings: defport :: Int
+ Hledger.Web.Settings: development :: Bool
+ Hledger.Web.Settings: hledgerorgurl :: Text
+ Hledger.Web.Settings: instance GHC.Show.Show Hledger.Web.Settings.Extra
+ Hledger.Web.Settings: manualurl :: Text
+ Hledger.Web.Settings: parseExtra :: DefaultEnv -> Object -> Parser Extra
+ Hledger.Web.Settings: production :: Bool
+ Hledger.Web.Settings: staticDir :: FilePath
+ Hledger.Web.Settings: staticRoot :: AppConfig DefaultEnv Extra -> Text
+ Hledger.Web.Settings: widgetFile :: String -> Q Exp
+ Hledger.Web.Settings: widgetFileSettings :: WidgetFileSettings
+ Hledger.Web.Settings.StaticFiles: css_bootstrap_css :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: css_bootstrap_css_map :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: css_bootstrap_datepicker_standalone_min_css :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: css_bootstrap_min_css :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: css_bootstrap_theme_css :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: css_bootstrap_theme_css_map :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: css_bootstrap_theme_min_css :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: fonts_glyphicons_halflings_regular_eot :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: fonts_glyphicons_halflings_regular_svg :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: fonts_glyphicons_halflings_regular_ttf :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: fonts_glyphicons_halflings_regular_woff :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: hledger_css :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: hledger_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_bootstrap_datepicker_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_bootstrap_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_bootstrap_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_excanvas_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_excanvas_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_cookie_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_canvas_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_canvas_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_categories_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_categories_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_crosshair_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_crosshair_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_errorbars_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_errorbars_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_fillbetween_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_fillbetween_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_image_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_image_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_navigate_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_navigate_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_pie_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_pie_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_resize_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_resize_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_selection_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_selection_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_stack_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_stack_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_symbol_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_symbol_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_threshold_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_threshold_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_time_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_time_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_tooltip_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_flot_tooltip_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_hotkeys_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_jquery_url_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_typeahead_bundle_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: js_typeahead_bundle_min_js :: StaticRoute
+ Hledger.Web.Settings.StaticFiles: staticSite :: IO Static
+ Hledger.Web.WebOptions: CapAdd :: Capability
+ Hledger.Web.WebOptions: CapManage :: Capability
+ Hledger.Web.WebOptions: CapView :: Capability
+ Hledger.Web.WebOptions: [capabilitiesHeader_] :: WebOpts -> Maybe (CI ByteString)
+ Hledger.Web.WebOptions: [capabilities_] :: WebOpts -> [Capability]
+ Hledger.Web.WebOptions: capabilityFromBS :: ByteString -> Either ByteString Capability
+ Hledger.Web.WebOptions: capabilityFromText :: Text -> Either Text Capability
+ Hledger.Web.WebOptions: data Capability
+ Hledger.Web.WebOptions: instance Data.Default.Class.Default Hledger.Web.WebOptions.WebOpts
+ Hledger.Web.WebOptions: instance GHC.Classes.Eq Hledger.Web.WebOptions.Capability
+ Hledger.Web.WebOptions: instance GHC.Classes.Ord Hledger.Web.WebOptions.Capability
+ Hledger.Web.WebOptions: instance GHC.Enum.Bounded Hledger.Web.WebOptions.Capability
+ Hledger.Web.WebOptions: instance GHC.Enum.Enum Hledger.Web.WebOptions.Capability
+ Hledger.Web.WebOptions: instance GHC.Show.Show Hledger.Web.WebOptions.Capability
+ 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: addModal :: (MonadWidget m, r ~ Route (HandlerSite m), m ~ WidgetFor (HandlerSite m), RenderMessage (HandlerSite m) FormMessage) => r -> Journal -> Day -> m ()
+ Hledger.Web.Widget.Common: accountOnlyQuery :: AccountName -> Text
+ Hledger.Web.Widget.Common: accountQuery :: AccountName -> Text
+ Hledger.Web.Widget.Common: balanceReportAsHtml :: Eq r => (r, r) -> r -> Bool -> Journal -> [QueryOpt] -> BalanceReport -> HtmlUrl r
+ Hledger.Web.Widget.Common: fromFormSuccess :: Applicative m => m a -> FormResult a -> m a
+ Hledger.Web.Widget.Common: helplink :: Text -> Text -> HtmlUrl r
+ Hledger.Web.Widget.Common: journalFile404 :: FilePath -> Journal -> HandlerFor m (FilePath, Text)
+ Hledger.Web.Widget.Common: mixedAmountAsHtml :: MixedAmount -> HtmlUrl a
+ Hledger.Web.Widget.Common: writeValidJournal :: MonadHandler m => FilePath -> Text -> m (Either String ())
- Hledger.Web.WebOptions: WebOpts :: Bool -> String -> Int -> String -> Maybe String -> CliOpts -> WebOpts
+ Hledger.Web.WebOptions: WebOpts :: Bool -> String -> Int -> String -> Maybe String -> [Capability] -> Maybe (CI ByteString) -> CliOpts -> WebOpts
- Hledger.Web.WebOptions: webflags :: [Flag [([Char], [Char])]]
+ Hledger.Web.WebOptions: webflags :: [Flag [(String, String)]]
- Hledger.Web.WebOptions: webmode :: Mode [([Char], [Char])]
+ Hledger.Web.WebOptions: webmode :: Mode [(String, String)]

Files

− Application.hs
@@ -1,88 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# LANGUAGE CPP, OverloadedStrings, TemplateHaskell #-}-module Application-    ( makeApplication-    , getApplicationDev-    , makeFoundation-    ) where--import Data.Default-import Data.IORef-import Import-import Yesod.Default.Config-import Yesod.Default.Main-import Yesod.Default.Handlers-import Network.Wai.Middleware.RequestLogger (logStdoutDev, logStdout)-import Network.HTTP.Conduit (newManager)-import Prelude (head)---- adapt to http-conduit 1.x or 2.x when cabal macros are available, otherwise assume 2.x-#ifdef MIN_VERSION_http_conduit-#if MIN_VERSION_http_conduit(2,0,0)-#define http_conduit_2-#endif-#else-#define http_conduit_2-#endif-#ifdef http_conduit_2-import Network.HTTP.Client (defaultManagerSettings)-#else-import Network.HTTP.Conduit (def)-#endif---- Import all relevant handler modules here.--- Don't forget to add new modules to your cabal file!-import Handler.RootR-import Handler.JournalR-import Handler.RegisterR-import Handler.SidebarR--import Hledger.Web.WebOptions (WebOpts(..), defwebopts)-import Hledger.Data (Journal, nulljournal)-import Hledger.Read (readJournalFile)-import Hledger.Utils (error')-import Hledger.Cli.CliOptions (defcliopts, journalFilePathFromOpts)---- 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--- comments there for more details.-mkYesodDispatch "App" resourcesApp---- This function allocates resources (such as a database connection pool),--- performs initialization and creates a WAI application. This is also the--- place to put your migrate statements to have automatic database--- migrations handled by Yesod.-makeApplication :: WebOpts -> Journal -> AppConfig DefaultEnv Extra -> IO Application-makeApplication opts j conf = do-    foundation <- makeFoundation conf opts-    writeIORef (appJournal foundation) j-    app <- toWaiAppPlain foundation-    return $ logWare app-  where-    logWare | development  = logStdoutDev-            | serve_ opts  = logStdout-            | otherwise    = id--makeFoundation :: AppConfig DefaultEnv Extra -> WebOpts -> IO App-makeFoundation conf opts = do-    manager <- newManager-#ifdef http_conduit_2-               defaultManagerSettings-#else-               def-#endif-    s <- staticSite-    jref <- newIORef nulljournal-    return $ App conf s manager opts jref---- for yesod devel--- uses the journal specified by the LEDGER_FILE env var, or ~/.hledger.journal-getApplicationDev :: IO (Int, Application)-getApplicationDev = do-  f <- head `fmap` journalFilePathFromOpts defcliopts -- XXX head should be safe for now-  j <- either error' id `fmap` readJournalFile def f-  defaultDevelApp loader (makeApplication defwebopts j)-  where-    loader = Yesod.Default.Config.loadConfig (configSettings Development)-        { csParseExtra = parseExtra-        }
CHANGES view
@@ -1,6 +1,21 @@ User-visible changes in hledger-web. See also hledger, hledger-lib.  +# 1.10 (2018/6/30)++* multiple -f options, and --auto, work again++* view, add, edit permissions can be set at CLI or by Sandstorm HTTP header++* the edit form has been revived, for whole-journal editing++* the journal can now be uploaded and downloaded++* the e key toggles empty accounts in the sidebar++* use hledger-lib 1.10++ # 1.9.2 (2018/4/30)  * use hledger-lib 1.9.1
− Foundation.hs
@@ -1,397 +0,0 @@-{-# LANGUAGE CPP, MultiParamTypeClasses, OverloadedStrings, RecordWildCards, QuasiQuotes, TemplateHaskell, TypeFamilies, TypeSynonymInstances, FlexibleInstances #-}-{---Define the web application's foundation, in the usual Yesod style.-See a default Yesod app's comments for more details of each part.---}-module Foundation where--import Prelude-#if !MIN_VERSION_base(4,8,0)-import Control.Applicative ((<$>))-#endif-import Data.IORef-import Yesod-import Yesod.Static-import Yesod.Default.Config-#ifndef DEVELOPMENT-import Yesod.Default.Util (addStaticContentExternal)-#endif-import Network.HTTP.Conduit (Manager)--- import qualified Settings-import Settings.StaticFiles-import Settings (staticRoot, widgetFile, Extra (..))-#ifndef DEVELOPMENT-import Settings (staticDir)-import Text.Jasmine (minifym)-#endif-import Text.Blaze.Html.Renderer.String (renderHtml)-import Text.Hamlet (hamletFile)--import Hledger.Web.WebOptions-import Hledger.Data.Types--- import Hledger.Web.Settings--- import Hledger.Web.Settings.StaticFiles---- for addform-import Data.List-import Data.Maybe-import Data.Text as Text (Text,pack,unpack)-import Data.Time.Calendar-#if BLAZE_HTML_0_4-import Text.Blaze (preEscapedString, Markup)-#else-import Text.Blaze (Markup)-import Text.Blaze.Internal (preEscapedString)-#endif-import Text.JSON-import Hledger.Data.Journal-import Hledger.Query-import Hledger hiding (is)-import Hledger.Cli hiding (version)----- | The site argument for your application. This can be a good place to--- keep settings and values requiring initialization before your application--- starts running, such as database connections. Every handler will have--- access to the data present here.-data App = App-    { settings :: AppConfig DefaultEnv Extra-    , getStatic :: Static -- ^ Settings for static file serving.-    , httpManager :: Manager-      ---    , appOpts    :: WebOpts-    , appJournal :: IORef Journal-    }---- Set up i18n messages. See the message folder.-mkMessage "App" "messages" "en"---- This is where we define all of the routes in our application. For a full--- explanation of the syntax, please see:--- http://www.yesodweb.com/book/handler------ This function does three things:------ * Creates the route datatype AppRoute. Every valid URL in your---   application can be represented as a value of this type.--- * Creates the associated type:---       type instance Route App = AppRoute--- * Creates the value resourcesApp which contains information on the---   resources declared below. This is used in Handler.hs by the call to---   mkYesodDispatch------ What this function does *not* do is create a YesodSite instance for--- App. Creating that instance requires all of the handler functions--- for our application to be in scope. However, the handler functions--- 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")---- | A convenience alias.-type AppRoute = Route App--#if MIN_VERSION_yesod(1,6,0)-type Form x = Html -> MForm (HandlerFor App) (FormResult x, Widget)-#else-type Form x = Html -> MForm (HandlerT App IO) (FormResult x, Widget)-#endif---- Please see the documentation for the Yesod typeclass. There are a number--- of settings which can be configured by overriding methods here.-instance Yesod App where-    approot = ApprootMaster $ appRoot . settings----    -- Store session data on the client in encrypted cookies,---    -- default session idle timeout is 120 minutes---    makeSessionBackend _ = fmap Just $ defaultClientSessionBackend---                             (120 * 60)---                             ".hledger-web_client_session_key.aes"-    -- don't use session data-    makeSessionBackend _ = return Nothing--    defaultLayout widget = do-        master <- getYesod-        lastmsg <- getMessage-        vd@VD{..} <- getViewData--        -- We break up the default layout into two components:-        -- default-layout is the contents of the body tag, and-        -- default-layout-wrapper is the entire page. Since the final-        -- value passed to hamletToRepHtml cannot be a widget, this allows-        -- you to use normal widget features in default-layout.--    --     pc <- widgetToPageContent $ do-    --         $(widgetFile "normalize")-    --         addStylesheet $ StaticR css_bootstrap_css-    --         $(widgetFile "default-layout")-    --     hamletToRepHtml $(hamletFile "templates/default-layout-wrapper.hamlet")--        pc <- widgetToPageContent $ do-            addStylesheet $ StaticR css_bootstrap_min_css-            addStylesheet $ StaticR css_bootstrap_datepicker_standalone_min_css-             -- load these things early, in HEAD:-            toWidgetHead [hamlet|-                          <script type="text/javascript" src="@{StaticR js_jquery_min_js}">-                          <script type="text/javascript" src="@{StaticR js_typeahead_bundle_min_js}">-                         |]-            addScript $ StaticR js_bootstrap_min_js-            -- addScript $ StaticR js_typeahead_bundle_min_js-            addScript $ StaticR js_bootstrap_datepicker_min_js-            addScript $ StaticR js_jquery_url_js-            addScript $ StaticR js_jquery_cookie_js-            addScript $ StaticR js_jquery_hotkeys_js-            addScript $ StaticR js_jquery_flot_min_js-            addScript $ StaticR js_jquery_flot_time_min_js-            addScript $ StaticR js_jquery_flot_tooltip_min_js-            toWidget [hamlet| \<!--[if lte IE 8]> <script type="text/javascript" src="@{StaticR js_excanvas_min_js}"></script> <![endif]--> |]-            addStylesheet $ StaticR hledger_css-            addScript $ StaticR hledger_js-            $(widgetFile "default-layout")--        staticRootUrl <- (staticRoot . settings) <$> getYesod-        withUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet")--    -- TODO outdated, still needed ?-    -- This is done to provide an optimization for serving static files from-    -- a separate domain. Please see the staticRoot setting in Settings.hs-    -- urlRenderOverride y (StaticR s) =-    --     Just $ uncurry (joinPath y (Settings.staticRoot $ settings y)) $ renderRoute s-    urlParamRenderOverride _ _ _ = Nothing--#ifndef DEVELOPMENT-    -- This function creates static content files in the static folder-    -- and names them based on a hash of their content. This allows-    -- expiration dates to be set far in the future without worry of-    -- users receiving stale content.-    addStaticContent = addStaticContentExternal minifym base64md5 Settings.staticDir (StaticR . flip StaticRoute [])-#endif--    -- Place Javascript at bottom of the body tag so the rest of the page loads first-    jsLoader _ = BottomOfBody---- This instance is required to use forms. You can modify renderMessage to--- achieve customized and internationalized form validation messages.-instance RenderMessage App FormMessage where-    renderMessage _ _ = defaultFormMessage---- | Get the 'Extra' value, used to hold data from the settings.yml file.-getExtra :: Handler Extra-getExtra = fmap (appExtra . settings) getYesod---- Note: previous versions of the scaffolding included a deliver function to--- send emails. Unfortunately, there are too many different options for us to--- give a reasonable default. Instead, the information is available on the--- wiki:------ https://github.com/yesodweb/yesod/wiki/Sending-email---------------------------------------------------------------------------- template and handler utilities---- view data, used by the add form and handlers---- | A bundle of data useful for hledger-web request handlers and templates.-data ViewData = VD {-     opts         :: WebOpts    -- ^ the command-line options at startup-    ,here         :: AppRoute   -- ^ the current route-    ,msg          :: Maybe Html -- ^ the current UI message if any, possibly from the current request-    ,today        :: Day        -- ^ today's date (for queries containing relative dates)-    ,j            :: Journal    -- ^ the up-to-date parsed unfiltered journal-    ,q            :: String     -- ^ the current q parameter, the main query expression-    ,m            :: Query    -- ^ a query parsed from the q parameter-    ,qopts        :: [QueryOpt] -- ^ query options parsed from the q parameter-    ,am           :: Query    -- ^ a query parsed from the accounts sidebar query expr ("a" parameter)-    ,aopts        :: [QueryOpt] -- ^ query options parsed from the accounts sidebar query expr-    ,showpostings :: Bool       -- ^ current p parameter, 1 or 0 shows/hides all postings where applicable-    ,showsidebar  :: Bool       -- ^ current showsidebar cookie value-    } deriving (Show)--instance Show Text.Blaze.Markup where show _ = "<blaze markup>"---- | Make a default ViewData, using day 0 as today's date.-nullviewdata :: ViewData-nullviewdata = viewdataWithDateAndParams nulldate "" "" ""---- | Make a ViewData using the given date and request parameters, and defaults elsewhere.-viewdataWithDateAndParams :: Day -> String -> String -> String -> ViewData-viewdataWithDateAndParams d q a p =-    let (querymatcher,queryopts) = parseQuery d (pack q)-        (acctsmatcher,acctsopts) = parseQuery d (pack a)-    in VD {-           opts         = defwebopts-          ,j            = nulljournal-          ,here         = RootR-          ,msg          = Nothing-          ,today        = d-          ,q            = q-          ,m            = querymatcher-          ,qopts        = queryopts-          ,am           = acctsmatcher-          ,aopts        = acctsopts-          ,showpostings = p == "1"-          ,showsidebar  = True-          }---- | Gather data used by handlers and templates in the current request.-getViewData :: Handler ViewData-getViewData = do-  mhere      <- getCurrentRoute-  case mhere of-    Nothing -> return nullviewdata-    Just here -> do-      app        <- getYesod-      let opts@WebOpts{cliopts_=copts@CliOpts{reportopts_=ropts}} = appOpts app-      today      <- liftIO getCurrentDay-      (j, merr)  <- getCurrentJournal app copts{reportopts_=ropts{no_elide_=True}} today-      lastmsg    <- getLastMessage-      let msg = maybe lastmsg (Just . toHtml) merr-      q          <- getParameterOrNull "q"-      a          <- getParameterOrNull "a"-      p          <- getParameterOrNull "p"-      -- sidebar visibility: show it, unless there is a showsidebar cookie-      -- set to "0", or a ?sidebar=0 query parameter.-      msidebarparam <- lookupGetParam "sidebar"-      msidebarcookie <- reqCookies <$> getRequest >>= return . lookup "showsidebar"-      let showsidebar = maybe (msidebarcookie /= Just "0") (/="0") msidebarparam--      return (viewdataWithDateAndParams today q a p){-                   opts=opts-                  ,msg=msg-                  ,here=here-                  ,today=today-                  ,j=j-                  ,showsidebar=showsidebar-                  }-        where-          -- | 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-          -- ui message.-          getCurrentJournal :: App -> CliOpts -> Day -> Handler (Journal, Maybe String)-          getCurrentJournal app opts d = do-            -- XXX put this inside atomicModifyIORef' for thread safety-            j <- liftIO $ readIORef $ appJournal app-            (ej, changed) <- liftIO $ journalReloadIfChanged opts d j-            -- re-apply any initial filter specified at startup-            let initq = queryFromOpts d $ reportopts_ opts-                ej' = filterJournalTransactions initq <$> ej-            if not changed-             then return (j,Nothing)-             else case ej' of-                    Right j' -> do liftIO $ writeIORef (appJournal app) j'-                                   return (j',Nothing)-                    Left e   -> do setMessage $ "error while reading" {- ++ ": " ++ e-}-                                   return (j, Just e)--          -- | Get the named request parameter, or the empty string if not present.-          getParameterOrNull :: String -> Handler String-          getParameterOrNull p = unpack `fmap` fromMaybe "" <$> lookupGetParam (pack p)---- | Get the message that was set by the last request, in a--- referentially transparent manner (allowing multiple reads).-getLastMessage :: Handler (Maybe Html)-getLastMessage = cached getMessage---- add form dialog, part of the default template---- | Add transaction form.-addform :: Text -> ViewData -> HtmlUrl AppRoute-addform _ vd@VD{..} = [hamlet|--<script>-  jQuery(document).ready(function() {--    /* set up typeahead fields */--    descriptionsSuggester = new Bloodhound({-      local:#{listToJsonValueObjArrayStr descriptions},-      limit:100,-      datumTokenizer: function(d) { return [d.value]; },-      queryTokenizer: function(q) { return [q]; }-    });-    descriptionsSuggester.initialize();--    accountsSuggester = new Bloodhound({-      local:#{listToJsonValueObjArrayStr accts},-      limit:100,-      datumTokenizer: function(d) { return [d.value]; },-      queryTokenizer: function(q) { return [q]; }-      /*-        datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),-        datumTokenizer: Bloodhound.tokenizers.whitespace(d.value)-        queryTokenizer: Bloodhound.tokenizers.whitespace-      */-    });-    accountsSuggester.initialize();--    enableTypeahead(jQuery('input#description'), descriptionsSuggester);-    enableTypeahead(jQuery('input#account1, input#account2, input#account3, input#account4'), accountsSuggester);--  });--<form#addform method=POST .form>- <div .form-group>-  <div .row>-   <div .col-md-3 .col-xs-6 .col-sm-6>-    <div #dateWrap .input-group .date>-     <input #date required lang=en name=date .form-control .input-lg placeholder="Date" >-     <div .input-group-addon>-      <span .glyphicon .glyphicon-th>-   <div .col-md-9 .col-xs-6 .col-sm-6>-    <input #description required .typeahead .form-control .input-lg type=text size=40 name=description placeholder="Description">- <div .account-postings>-  $forall n <- postingnums-    ^{postingfields vd n}- <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 filepaths > 1-  <br>-  <span class="input-lg">to:-   ^{journalselect filepaths}- <span style="padding-left:2em;">-  <span .small>-    Enter a value in the last field for-    <a href="#" onclick="addformAddPosting(); return false;">more-    (or ctrl +, ctrl -)-|]- where-  descriptions = sort $ nub $ map tdescription $ jtxns j-  accts = journalAccountNamesDeclaredOrImplied j-  escapeJSSpecialChars = regexReplaceCI "</script>" "<\\/script>" -- #236-  listToJsonValueObjArrayStr as  = preEscapedString $ escapeJSSpecialChars $ encode $ JSArray $ map (\a -> JSObject $ toJSObject [("value", showJSON a)]) as-  numpostings = 4-  postingnums = [1..numpostings]-  filepaths = map fst $ jfiles j-  postingfields :: ViewData -> Int -> HtmlUrl AppRoute-  postingfields _ n = [hamlet|-<div .form-group .row .account-group ##{grpvar}>- <div .col-md-8 .col-xs-8 .col-sm-8>-  <input ##{acctvar} .account-input .typeahead .form-control .input-lg type=text name=#{acctvar} placeholder="#{acctph}">- <div .col-md-4 .col-xs-4 .col-sm-4>-  <input ##{amtvar} .amount-input .form-control .input-lg type=text name=#{amtvar} placeholder="#{amtph}">-|]-   where-    acctvar = "account" ++ show n-    acctph = "Account " ++ show n-    amtvar = "amount" ++ show n-    amtph = "Amount " ++ show n-    grpvar = "grp" ++ show n--journalselect :: [FilePath] -> HtmlUrl AppRoute-journalselect journalfilepaths = [hamlet|-<select id=journalselect name=journal onchange="/*journalSelect(event)*/" class="form-control input-lg" style="width:auto; display:inline-block;">- $forall p <- journalfilepaths-  <option value=#{p}>#{p}-|]--journalradio :: [FilePath] -> HtmlUrl AppRoute-journalradio journalfilepaths = [hamlet|- $forall p <- journalfilepaths-  <div style="white-space:nowrap;">-   <span class="input-lg" style="position:relative; top:-8px; left:8px;">#{p}-   <input name=journal type=radio value=#{p} class="form-control" style="width:auto; display:inline;">-|]-
− Handler/AddForm.hs
@@ -1,124 +0,0 @@-{-# LANGUAGE CPP, FlexibleContexts, OverloadedStrings, QuasiQuotes, RecordWildCards, TypeFamilies #-}--- | Add form data & handler. (The layout and js are defined in--- Foundation so that the add form can be in the default layout for--- all views.)--module Handler.AddForm where--import Import--#if !MIN_VERSION_base(4,8,0)-import Control.Applicative-#endif-import Control.Monad.State.Strict (evalStateT)-import Data.Either (lefts,rights)-import Data.List (sort)-import qualified Data.List as L (head) -- qualified keeps dev & prod builds warning-free-import Data.Text (append, pack, unpack)-import qualified Data.Text as T-import Data.Time.Calendar-import Text.Megaparsec.Compat (digitChar, eof, some, string, runParser, ParseError, MPErr)--import Hledger.Utils-import Hledger.Data-import Hledger.Read-import Hledger.Cli.Commands.Add (appendToJournalFileOrStdout)----- Part of the data required from the add form.--- Don't know how to handle the variable posting fields with yesod-form yet.-data AddForm = AddForm-    { addFormDate         :: Day-    , addFormDescription  :: Maybe Text -- String-    -- , addFormPostings     :: [(AccountName, String)]-    , addFormJournalFile  :: Maybe Text -- FilePath-    }-  deriving Show--postAddForm :: Handler Html-postAddForm = do-  let showErrors errs = do-        -- error $ show errs -- XXX uncomment to prevent redirect for debugging-        setMessage [shamlet|-                    Errors:<br>-                    $forall e<-errs-                     \#{e}<br>-                   |]-  -- 1. process the fixed fields with yesod-form--  VD{..} <- getViewData-  let-      validateJournalFile :: Text -> Either FormMessage Text-      validateJournalFile f-        | unpack f `elem` journalFilePaths j = Right f-        | otherwise                          = Left $ MsgInvalidEntry $ pack "the selected journal file \"" `append` f `append` "\"is unknown"--      validateDate :: Text -> Handler (Either FormMessage Day)-      validateDate s = return $-        case fixSmartDateStrEither' today $ T.pack $ strip $ unpack s of-          Right d  -> Right d-          Left _   -> Left $ MsgInvalidEntry $ pack "could not parse date \"" `append` s `append` pack "\":" -- ++ show e)--  formresult <- runInputPostResult $ AddForm-    <$> ireq (checkMMap validateDate (pack . show) textField) "date"-    <*> iopt textField "description"-    <*> iopt (check validateJournalFile textField) "journal"-  -  ok <- case formresult of-    FormMissing      -> showErrors ["there is no form data"::String] >> return False-    FormFailure errs -> showErrors errs >> return False-    FormSuccess dat  -> do-      let AddForm{-             addFormDate       =date-            ,addFormDescription=mdesc-            ,addFormJournalFile=mjournalfile-            } = dat-          desc = maybe "" unpack mdesc-          journalfile = maybe (journalFilePath j) unpack mjournalfile--      -- 2. the fixed fields look good; now process the posting fields adhocly,-      -- getting either errors or a balanced transaction--      (params,_) <- runRequestBody-      let numberedParams s =-            reverse $ dropWhile (T.null . snd) $ reverse $ sort-            [ (n,v) | (k,v) <- params-                    , let en = parsewith (paramnamep s) k :: Either (ParseError Char MPErr) Int-                    , isRight en-                    , let Right n = en-                    ]-            where paramnamep s = do {string s; n <- some digitChar; eof; return (read n :: Int)}-          acctparams = numberedParams "account"-          amtparams  = numberedParams "amount"-          num = length acctparams-          paramErrs | num == 0 = ["at least one posting must be entered"]-                    | map fst acctparams == [1..num] &&-                      map fst amtparams `elem` [[1..num], [1..num-1]] = []-                    | otherwise = ["the posting parameters are malformed"]-          eaccts = map (runParser (accountnamep <* eof) "" . textstrip  . snd) acctparams-          eamts  = map (runParser (evalStateT (amountp <* eof) mempty) "" . textstrip . snd) amtparams-          (accts, acctErrs) = (rights eaccts, map show $ lefts eaccts)-          (amts', amtErrs)  = (rights eamts, map show $ lefts eamts)-          amts | length amts' == num = amts'-               | otherwise           = amts' ++ [missingamt]-          errs = if not (null paramErrs) then paramErrs else (acctErrs ++ amtErrs)-          etxn | not $ null errs = Left errs-               | otherwise = either (\e -> Left [L.head $ lines e]) Right-                              (balanceTransaction Nothing $ nulltransaction {-                                  tdate=date-                                 ,tdescription=T.pack desc-                                 ,tpostings=[nullposting{paccount=acct, pamount=Mixed [amt]} | (acct,amt) <- zip accts amts]-                                 })-      case etxn of-       Left errs -> showErrors errs >> return False-       Right t -> do-        -- 3. all fields look good and form a balanced transaction; append it to the file-        liftIO $ do ensureJournalFileExists journalfile-                    appendToJournalFileOrStdout journalfile $-                      showTransaction $-                      txnTieKnot -- XXX move into balanceTransaction-                      t-        setMessage [shamlet|<span>Transaction added.|]-        return True--  if ok then redirect JournalR else redirect (JournalR, [("add","1")])
− Handler/Common.hs
@@ -1,251 +0,0 @@-{-# LANGUAGE CPP, OverloadedStrings, QuasiQuotes, RecordWildCards #-}--- | Common page components and rendering helpers.--- For global page layout, see Application.hs.--module Handler.Common where--import Import---- import Data.Text (Text)-import qualified Data.Text as T-import Data.Time.Calendar-import System.FilePath (takeFileName)-#if BLAZE_HTML_0_4-import Text.Blaze (preEscapedString)-#else-import Text.Blaze.Internal (preEscapedString)-#endif-import Text.Printf--import Hledger.Utils-import Hledger.Data-import Hledger.Query-import Hledger.Reports-import Hledger.Cli.CliOptions-import Hledger.Web.WebOptions------------------------------------------------------------------------------------ Common page layout---- | Standard hledger-web page layout.-#if MIN_VERSION_yesod(1,6,0)-hledgerLayout :: ViewData -> String -> HtmlUrl AppRoute -> HandlerFor App Html-#else-hledgerLayout :: ViewData -> String -> HtmlUrl AppRoute -> HandlerT App IO Html-#endif-hledgerLayout vd title content = do-  defaultLayout $ do-      setTitle $ toHtml $ title ++ " - hledger-web"-      toWidget [hamlet|-         ^{topbar vd}-         ^{sidebar vd}-         <div #main-content .col-xs-12 .#{showmd} .#{showsm}>-          ^{searchform vd}-          ^{content}-      |]-  where-    showmd = if showsidebar vd then "col-md-8" else "col-md-12" :: String-    showsm = if showsidebar vd then "col-sm-8" else "col-sm-12" :: String---- | Global toolbar/heading area.-topbar :: ViewData -> HtmlUrl AppRoute-topbar VD{..} = [hamlet|-<div#spacer .#{showsm} .#{showmd} .col-xs-2>- <h1>-  <button .visible-xs .btn .btn-default type="button" data-toggle="offcanvas">-   <span .glyphicon .glyphicon-align-left .tgl-icon>-<div#topbar .col-md-8 .col-sm-8 .col-xs-10>- <h1>#{title}--|]-  where-    title = takeFileName $ journalFilePath j-    showmd = if showsidebar then "col-md-4" else "col-any-0" :: String-    showsm = if showsidebar then "col-sm-4" else "" :: String---- | The sidebar used on most views.-sidebar :: ViewData -> HtmlUrl AppRoute-sidebar vd@VD{..} =- [hamlet|- <div #sidebar-menu .#{showmd} .#{showsm} .sidebar-offcanvas>-  <table .main-menu .table>-   <tr .#{journalcurrent}>-    <td .top .acct>-     <a href=@{JournalR} .#{journalcurrent} title="Show general journal entries, most recent first">Journal-    <td .top>-   ^{accounts}-|]- where-  journalcurrent = if here == JournalR then "inacct" else "" :: String-  ropts = reportopts_ $ cliopts_ opts-  -- flip the default for items with zero amounts, show them by default-  ropts' = ropts{empty_=not $ empty_ ropts}-  accounts = balanceReportAsHtml opts vd $ balanceReport ropts' am j-  showmd = if showsidebar then "col-md-4" else "col-any-0" :: String-  showsm = if showsidebar then "col-sm-4" else "" :: String---- -- | Navigation link, preserving parameters and possibly highlighted.--- navlink :: ViewData -> String -> AppRoute -> String -> HtmlUrl AppRoute--- navlink VD{..} s dest title = [hamlet|--- <a##{s}link.#{style} href=@?{u'} title="#{title}">#{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|--- <a#editformlink href="#" onclick="return editformToggle(event)" title="Toggle journal edit form">edit--- \ | #--- <a#addformlink href="#" onclick="return addformToggle(event)" title="Toggle transaction add form">add--- <a#importformlink href="#" onclick="return importformToggle(event)" style="display:none;">import transactions--- |]---- | Search form for entering custom queries to filter journal data.-searchform :: ViewData -> HtmlUrl AppRoute-searchform VD{..} = [hamlet|-<div#searchformdiv .row>- <form#searchform .form-inline method=GET>-  <div .form-group .col-md-12 .col-sm-12 .col-xs-12>-    <div #searchbar .input-group>-     <input .form-control name=q value=#{q} title="Enter hledger search patterns to filter the data below" placeholder="Search">-     <div .input-group-btn>-      $if filtering-       <a href=@{here} .btn .btn-default title="Clear search terms">-        <span .glyphicon .glyphicon-remove-circle>-      <button .btn .btn-default type=submit title="Apply search terms">-       <span .glyphicon .glyphicon-search>-      <button .btn .btn-default type=button data-toggle="modal" data-target="#helpmodal" title="Show search and general help">?-|]- where-  filtering = not $ null q---- -- | Edit journal form.--- editform :: ViewData -> HtmlUrl AppRoute--- editform VD{..} = [hamlet|--- <form#editform method=POST style=display:none;>---  <h2#contenttitle>#{title}>---  <table.form>---   $if manyfiles---    <tr>---     <td colspan=2>---      Editing ^{journalselect $ files j}---   <tr>---    <td colspan=2>---     <!-- XXX textarea ids are unquoted journal file paths here, not valid html -->---     $forall f <- files j---      <textarea id=#{fst f}_textarea name=text rows=25 cols=80 style=display:none; disabled=disabled>---       \#{snd f}---   <tr#addbuttonrow>---    <td>---     <span.help>^{formathelp}---    <td>---     <span.help>---      Are you sure ? This will overwrite the journal. #---     <input type=hidden name=action value=edit>---     <input type=submit name=submit value="save journal">---     \ or #---     <a href="#" onclick="return editformToggle(event)">cancel--- |]---   where---     title = "Edit journal" :: String---     manyfiles = length (files j) > 1---     formathelp = helplink "file-format" "file format help"---- -- | Import journal form.--- importform :: HtmlUrl AppRoute--- importform = [hamlet|--- <form#importform method=POST style=display:none;>---  <table.form>---   <tr>---    <td>---     <input type=file name=file>---     <input type=hidden name=action value=import>---     <input type=submit name=submit value="import from file">---     \ or #---     <a href="#" onclick="return importformToggle(event)">cancel--- |]---- | Link to a topic in the manual.-helplink :: String -> String -> HtmlUrl AppRoute-helplink topic label = [hamlet|-<a href=#{u} target=hledgerhelp>#{label}-|]-    where u = manualurl ++ if null topic then "" else '#':topic--nulltemplate :: HtmlUrl AppRoute-nulltemplate = [hamlet||]---------------------------------------------------------------------------- hledger report renderers---- | Render a "BalanceReport" as html.-balanceReportAsHtml :: WebOpts -> ViewData -> BalanceReport -> HtmlUrl AppRoute-balanceReportAsHtml _ vd@VD{..} (items',total) =- [hamlet|-  $forall i <- items-   ^{itemAsHtml vd i}-  <tr .total>-   <td>-   <td>-    #{mixedAmountAsHtml total}-|]- where-   l = ledgerFromJournal Any j-   inacctmatcher = inAccountQuery qopts-   items = items' -- maybe items' (\m -> filter (matchesAccount m . \(a,_,_,_)->a) items') showacctmatcher-   itemAsHtml :: ViewData -> BalanceReportItem -> HtmlUrl AppRoute-   itemAsHtml _ (acct, adisplay, aindent, abal) = [hamlet|-<tr .#{inacctclass}>- <td .acct>-  <div .ff-wrapper>-   \#{indent}-   <a href="@?{acctquery}" .#{inacctclass} title="Show transactions affecting this account and subaccounts">#{adisplay}-   $if hassubs-    <a href="@?{acctonlyquery}" .only .hidden-sm .hidden-xs title="Show transactions affecting this account but not subaccounts">only- <td>-  #{mixedAmountAsHtml abal}-|]-     where-       hassubs = not $ maybe False (null.asubs) $ ledgerAccount l acct-       inacctclass = case inacctmatcher of-                       Just m' -> if m' `matchesAccount` acct then "inacct" else ""-                       Nothing -> "" :: String-       indent = preEscapedString $ concat $ replicate (2 * (1+aindent)) "&nbsp;"-       acctquery = (RegisterR, [("q", T.pack $ accountQuery acct)])-       acctonlyquery = (RegisterR, [("q", T.pack $ accountOnlyQuery acct)])--accountQuery :: AccountName -> String-accountQuery a = "inacct:" ++ T.unpack (quoteIfSpaced a) -- (accountNameToAccountRegex a)--accountOnlyQuery :: AccountName -> String-accountOnlyQuery a = "inacctonly:" ++ T.unpack (quoteIfSpaced a ) -- (accountNameToAccountRegex a)--accountUrl :: AppRoute -> AccountName -> (AppRoute, [(Text, Text)])-accountUrl r a = (r, [("q", T.pack $ accountQuery a)])---- stringIfLongerThan :: Int -> String -> String--- stringIfLongerThan n s = if length s > n then s else ""--numberTransactionsReportItems :: [TransactionsReportItem] -> [(Int,Bool,Bool,Bool,TransactionsReportItem)]-numberTransactionsReportItems [] = []-numberTransactionsReportItems items = number 0 nulldate items-  where-    number :: Int -> Day -> [TransactionsReportItem] -> [(Int,Bool,Bool,Bool,TransactionsReportItem)]-    number _ _ [] = []-    number n prevd (i@(Transaction{tdate=d},_,_,_,_,_):rest)  = (n+1,newday,newmonth,newyear,i): number (n+1) d rest-        where-          newday = d/=prevd-          newmonth = dm/=prevdm || dy/=prevdy-          newyear = dy/=prevdy-          (dy,dm,_) = toGregorian d-          (prevdy,prevdm,_) = toGregorian prevd--mixedAmountAsHtml :: MixedAmount -> Html-mixedAmountAsHtml b = preEscapedString $ unlines $ map addclass $ lines $ showMixedAmountWithoutPrice b-    where addclass = printf "<span class=\"%s\">%s</span><br/>" (c :: String)-          c = case isNegativeMixedAmount b of Just True -> "negative amount"-                                              _         -> "positive amount"-
− Handler/JournalR.hs
@@ -1,88 +0,0 @@-{-# LANGUAGE OverloadedStrings, QuasiQuotes, RecordWildCards #-}--- | /journal handlers.--module Handler.JournalR where---- import Data.Text (Text)-import qualified Data.Text as T-import Import--import Handler.AddForm-import Handler.Common--import Hledger.Data-import Hledger.Query-import Hledger.Reports-import Hledger.Utils-import Hledger.Cli.CliOptions-import Hledger.Web.WebOptions---- | The formatted journal view, with sidebar.-getJournalR :: Handler Html-getJournalR = do-  vd@VD{..} <- getViewData-  let -- XXX like registerReportAsHtml-      inacct = inAccount qopts-      -- injournal = isNothing inacct-      filtering = m /= Any-      -- showlastcolumn = if injournal && not filtering then False else True-      title = case inacct of-                Nothing       -> "General Journal"++s2-                Just (a,inclsubs) -> "Transactions in "++T.unpack a++s1++s2-                                      where s1 = if inclsubs then "" else " (excluding subaccounts)"-                where-                  s2 = if filtering then ", filtered" else ""-      maincontent = journalTransactionsReportAsHtml opts vd $ journalTransactionsReport (reportopts_ $ cliopts_ opts) j m-  hledgerLayout vd "journal" [hamlet|-       <div .row>-        <h2 #contenttitle>#{title}-        <!-- p>Journal entries record movements of commodities between accounts. -->-        <a #addformlink role="button" style="cursor:pointer; margin-top:1em;" data-toggle="modal" data-target="#addmodal" title="Add a new transaction to the journal" href="#">Add a transaction-       <div .table-responsive>-        ^{maincontent}-     |]--postJournalR :: Handler Html-postJournalR = postAddForm---- | Render a "TransactionsReport" as html for the formatted journal view.-journalTransactionsReportAsHtml :: WebOpts -> ViewData -> TransactionsReport -> HtmlUrl AppRoute-journalTransactionsReportAsHtml _ vd (_,items) = [hamlet|-<table .transactionsreport .table .table-condensed>- <thead>-  <th .date style="text-align:left;">-   Date-  <th .description style="text-align:left;">Description-  <th .account style="text-align:left;">Account-  <th .amount style="text-align:right;">Amount- $forall i <- numberTransactionsReportItems items-  ^{itemAsHtml vd i}- |]- where--- .#{datetransition}-   itemAsHtml :: ViewData -> (Int, Bool, Bool, Bool, TransactionsReportItem) -> HtmlUrl AppRoute-   itemAsHtml VD{..} (_, _, _, _, (torig, _, split, _, amt, _)) = [hamlet|-<tr .title #transaction-#{tindex torig}>- <td .date nowrap>#{date}- <td .description colspan=2>#{textElideRight 60 desc}- <td .amount style="text-align:right;">-  $if showamt-   \#{mixedAmountAsHtml amt}-$forall p' <- tpostings torig- <tr .item .posting title="#{show torig}">-  <td .nonhead>-  <td .nonhead>-  <td .nonhead>-   &nbsp;-   <a href="@?{acctlink (paccount p')}##{tindex torig}" title="#{paccount p'}">#{elideAccountName 40 $ paccount p'}-  <td .amount .nonhead style="text-align:right;">#{mixedAmountAsHtml $ pamount p'}-|]-     where-       acctlink a = (RegisterR, [("q", T.pack $ accountQuery a)])-       -- datetransition | newm = "newmonth"-       --                | newd = "newday"-       --                | otherwise = "" :: String-       (date, desc) = (show $ tdate torig, tdescription torig)-       -- acctquery = (here, [("q", T.pack $ accountQuery acct)])-       showamt = not split || not (isZeroMixedAmount amt)-
− Handler/RegisterR.hs
@@ -1,181 +0,0 @@-{-# LANGUAGE OverloadedStrings, QuasiQuotes, RecordWildCards #-}--- | /register handlers.--module Handler.RegisterR where--import Import--import Data.List-import Data.Maybe--- import Data.Text (Text)-import qualified Data.Text as T-import Safe--import Handler.AddForm-import Handler.Common-import Handler.Utils--import Hledger.Data-import Hledger.Query-import Hledger.Reports-import Hledger.Utils-import Hledger.Cli.CliOptions-import Hledger.Web.WebOptions---- | The main journal/account register view, with accounts sidebar.-getRegisterR :: Handler Html-getRegisterR = do-  vd@VD{..} <- getViewData-  -- staticRootUrl <- (staticRoot . settings) <$> getYesod-  let -- injournal = isNothing inacct-      filtering = m /= Any-      -- title = "Transactions in "++a++s1++s2-      title = T.unpack a++s1++s2-               where-                 (a,inclsubs) = fromMaybe ("all accounts",True) $ inAccount qopts-                 s1 = if inclsubs then "" else " (excluding subaccounts)"-                 s2 = if filtering then ", filtered" else ""-      maincontent = registerReportHtml opts vd $ accountTransactionsReport (reportopts_ $ cliopts_ opts) j m $ fromMaybe Any $ inAccountQuery qopts-  hledgerLayout vd "register" [hamlet|-       <h2 #contenttitle>#{title}-       <!-- p>Transactions affecting this account, with running balance. -->-       ^{maincontent}-     |]--postRegisterR :: Handler Html-postRegisterR = postAddForm---- Generate html for an account register, including a balance chart and transaction list.-registerReportHtml :: WebOpts -> ViewData -> TransactionsReport -> HtmlUrl AppRoute-registerReportHtml opts vd r = [hamlet|- <div .hidden-xs>-  ^{registerChartHtml $ transactionsReportByCommodity r}- ^{registerItemsHtml opts vd r}-|]---- Generate html for a transaction list from an "TransactionsReport".-registerItemsHtml :: WebOpts -> ViewData -> TransactionsReport -> HtmlUrl AppRoute-registerItemsHtml _ vd (balancelabel,items) = [hamlet|-<div .table-responsive>- <table.registerreport .table .table-striped .table-condensed>-  <thead>-   <tr>-    <th style="text-align:left;">-     Date-     <span .glyphicon .glyphicon-chevron-up>-    <th style="text-align:left;">Description-    <th style="text-align:left;">To/From Account(s)-    <th style="text-align:right; white-space:normal;">Amount Out/In-    <th style="text-align:right; white-space:normal;">#{balancelabel'}-  $forall i <- numberTransactionsReportItems items-   ^{itemAsHtml vd i}- |]- where-   insomeacct = isJust $ inAccount $ qopts vd-   balancelabel' = if insomeacct then balancelabel else "Total"--   -- filtering = m /= Any-   itemAsHtml :: ViewData -> (Int, Bool, Bool, Bool, TransactionsReportItem) -> HtmlUrl AppRoute-   itemAsHtml VD{..} (n, newd, newm, _, (torig, tacct, split, acct, amt, bal)) = [hamlet|--<tr ##{tindex torig} .item.#{evenodd}.#{firstposting}.#{datetransition} title="#{show torig}" style="vertical-align:top;">- <td .date>-  <a href="@{JournalR}#transaction-#{tindex torig}">#{date}- <td .description title="#{show torig}">#{textElideRight 30 desc}- <td .account>#{elideRight 40 acct}- <td .amount style="text-align:right; white-space:nowrap;">-  $if showamt-   \#{mixedAmountAsHtml amt}- <td .balance style="text-align:right;">#{mixedAmountAsHtml bal}-|]--     where-       evenodd = if even n then "even" else "odd" :: String-       datetransition | newm = "newmonth"-                      | newd = "newday"-                      | otherwise = "" :: String-       (firstposting, date, desc) = (False, show $ tdate tacct, tdescription tacct)-       -- acctquery = (here, [("q", pack $ accountQuery acct)])-       showamt = not split || not (isZeroMixedAmount amt)---- | Generate javascript/html for a register balance line chart based on--- the provided "TransactionsReportItem"s.-               -- registerChartHtml :: forall t (t1 :: * -> *) t2 t3 t4 t5.-               --                      Data.Foldable.Foldable t1 =>-               --                      t1 (Transaction, t2, t3, t4, t5, MixedAmount)-               --                      -> t -> Text.Blaze.Internal.HtmlM ()-registerChartHtml :: [(CommoditySymbol, (String, [TransactionsReportItem]))] -> HtmlUrl AppRoute-registerChartHtml percommoditytxnreports =- -- have to make sure plot is not called when our container (maincontent)- -- is hidden, eg with add form toggled- [hamlet|-<label #register-chart-label style=""><br>-<div #register-chart style="height:150px; margin-bottom:1em; display:block;">-<script type=text/javascript>- \$(document).ready(function() {-   var $chartdiv = $('#register-chart');-   if ($chartdiv.is(':visible')) {-     \$('#register-chart-label').text('#{charttitle}');-     var seriesData = [-      $forall (c,(_,items)) <- percommoditytxnreports-       /* we render each commodity using two series:-        * one with extra data points added to show a stepped balance line */-       {-        data: [-          $forall i <- reverse items-           [-            #{dayToJsTimestamp $ triDate i},-            #{simpleMixedAmountQuantity $ triCommodityBalance c i}-           ],-          /* [] */-        ],-        label: '#{shownull $ T.unpack c}',-        color: #{colorForCommodity c},-        lines: {-          show: true,-          steps: true,-        },-        points: {-          show: false,-        },-        clickable: false,-        hoverable: false,-       },-       /* and one with the original data, showing one clickable, hoverable point per transaction */-       {-        data: [-          $forall i <- reverse items-           [-            #{dayToJsTimestamp $ triDate i},-            #{simpleMixedAmountQuantity $ triCommodityBalance c i},-            '#{showMixedAmountWithZeroCommodity $ triCommodityAmount c i}',-            '#{showMixedAmountWithZeroCommodity $ triCommodityBalance c i}',-            '#{concat $ intersperse "\\n" $ lines  $ show $ triOrigTransaction i}',-            #{tindex $ triOrigTransaction i}-           ],-          /* [] */-        ],-        label: '',-        color: #{colorForCommodity c},-        lines: {-          show: false,-        },-        points: {-          show: true,-        },-       },-     ]-     var plot = registerChart($chartdiv, seriesData);-     \$chartdiv.bind("plotclick", registerChartClick);-   };- });-|]-           -- [#{dayToJsTimestamp $ ltrace "\ndate" $ triDate i}, #{ltrace "balancequantity" $ simpleMixedAmountQuantity $ triCommodityBalance c i}, '#{ltrace "balance" $ show $ triCommodityBalance c i}, '#{ltrace "amount" $ show $ triCommodityAmount c i}''],- where-   charttitle = case maybe "" (fst.snd) $ headMay percommoditytxnreports-           of "" -> ""-              s  -> s++":"-   colorForCommodity = fromMaybe 0 . flip lookup commoditiesIndex-   commoditiesIndex = zip (map fst percommoditytxnreports) [0..] :: [(CommoditySymbol,Int)]-   simpleMixedAmountQuantity = maybe 0 aquantity . headMay . amounts-   shownull c = if null c then " " else c
− Handler/RootR.hs
@@ -1,8 +0,0 @@--- | Site root and misc. handlers.--module Handler.RootR where--import Import--getRootR :: Handler Html-getRootR = redirect defaultroute where defaultroute = JournalR
− Handler/SidebarR.hs
@@ -1,15 +0,0 @@-{-# LANGUAGE OverloadedStrings, QuasiQuotes, RecordWildCards #-}--- | /sidebar--module Handler.SidebarR where--import Import--import Handler.Common---- | Render just the accounts sidebar, useful when opening the sidebar.-getSidebarR :: Handler Html-getSidebarR = do-  vd <- getViewData-  withUrlRenderer [hamlet|^{sidebar vd}|]-
− Handler/Utils.hs
@@ -1,20 +0,0 @@-{-# LANGUAGE CPP #-}--- | Web handler utilities. More of these are in Foundation.hs, where--- they can be used in the default template.--module Handler.Utils where--import Prelude-import Data.Time.Calendar-import Data.Time.Clock-import Data.Time.Format-#if !(MIN_VERSION_time(1,5,0))-import System.Locale (defaultTimeLocale)-#endif--numbered :: [a] -> [(Int,a)]-numbered = zip [1..]--dayToJsTimestamp :: Day -> Integer-dayToJsTimestamp d = read (formatTime defaultTimeLocale "%s" t) * 1000 -- XXX read-                     where t = UTCTime d (secondsToDiffTime 0)
Hledger/Web.hs view
@@ -2,12 +2,12 @@ Re-export the modules of the hledger-web program. -} -module Hledger.Web (-                     module Hledger.Web.WebOptions,-                     module Hledger.Web.Main,-                     tests_Hledger_Web-              )-where+module Hledger.Web+  ( module Hledger.Web.WebOptions+  , module Hledger.Web.Main+  , tests_Hledger_Web+  ) where+ import Test.HUnit  import Hledger.Web.WebOptions
+ Hledger/Web/Application.hs view
@@ -0,0 +1,53 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE ViewPatterns #-}++module Hledger.Web.Application+  ( makeApplication+  , makeFoundation+  ) where++import Data.IORef (newIORef, writeIORef)+import Network.Wai.Middleware.RequestLogger (logStdoutDev, logStdout)+import Network.HTTP.Client (defaultManagerSettings)+import Network.HTTP.Conduit (newManager)+import Yesod.Default.Config++import Hledger.Data (Journal, nulljournal)+import Hledger.Web.Handler.AddR (getAddR, postAddR)+import Hledger.Web.Handler.Common+       (getDownloadR, getFaviconR, getManageR, getRobotsR, getRootR)+import Hledger.Web.Handler.EditR (getEditR, postEditR)+import Hledger.Web.Handler.UploadR (getUploadR, postUploadR)+import Hledger.Web.Handler.JournalR (getJournalR)+import Hledger.Web.Handler.RegisterR (getRegisterR)+import Hledger.Web.Import+import Hledger.Web.WebOptions (WebOpts(serve_))++-- 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+-- comments there for more details.+mkYesodDispatch "App" resourcesApp++-- This function allocates resources (such as a database connection pool),+-- performs initialization and creates a WAI application. This is also the+-- place to put your migrate statements to have automatic database+-- migrations handled by Yesod.+makeApplication :: WebOpts -> Journal -> AppConfig DefaultEnv Extra -> IO Application+makeApplication opts' j' conf' = do+    foundation <- makeFoundation conf' opts'+    writeIORef (appJournal foundation) j'+    logWare <$> toWaiApp foundation+  where+    logWare | development  = logStdoutDev+            | serve_ opts' = logStdout+            | otherwise    = id++makeFoundation :: AppConfig DefaultEnv Extra -> WebOpts -> IO App+makeFoundation conf opts' = do+    manager <- newManager defaultManagerSettings+    s <- staticSite+    jref <- newIORef nulljournal+    return $ App conf s manager opts' jref
+ Hledger/Web/Foundation.hs view
@@ -0,0 +1,232 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE ViewPatterns #-}++-- | Define the web application's foundation, in the usual Yesod style.+--   See a default Yesod app's comments for more details of each part.++module Hledger.Web.Foundation where++import Control.Monad (join)+import qualified Data.ByteString.Char8 as BC+import Data.Traversable (for)+import Data.IORef (IORef, readIORef, writeIORef)+import Data.Maybe (fromMaybe)+import Data.Monoid ((<>))+import Data.Text (Text)+import qualified Data.Text as T+import Data.Time.Calendar (Day)+import Network.HTTP.Conduit (Manager)+import Network.Wai (requestHeaders)+import System.FilePath (takeFileName)+import Text.Blaze (Markup)+import Text.Hamlet (hamletFile)+import Yesod+import Yesod.Static+import Yesod.Default.Config++#ifndef DEVELOPMENT+import Hledger.Web.Settings (staticDir)+import Text.Jasmine (minifym)+import Yesod.Default.Util (addStaticContentExternal)+#endif++import Hledger+import Hledger.Cli (CliOpts(..), journalReloadIfChanged)+import Hledger.Web.Settings (Extra(..), widgetFile)+import Hledger.Web.Settings.StaticFiles+import Hledger.Web.WebOptions+import Hledger.Web.Widget.Common (balanceReportAsHtml)++-- | The site argument for your application. This can be a good place to+-- keep settings and values requiring initialization before your application+-- starts running, such as database connections. Every handler will have+-- access to the data present here.+data App = App+    { settings :: AppConfig DefaultEnv Extra+    , getStatic :: Static -- ^ Settings for static file serving.+    , httpManager :: Manager+      --+    , appOpts    :: WebOpts+    , appJournal :: IORef Journal+    }+++-- This is where we define all of the routes in our application. For a full+-- explanation of the syntax, please see:+-- http://www.yesodweb.com/book/handler+--+-- This function does three things:+--+-- * Creates the route datatype AppRoute. Every valid URL in your+--   application can be represented as a value of this type.+-- * Creates the associated type:+--       type instance Route App = AppRoute+-- * Creates the value resourcesApp which contains information on the+--   resources declared below. This is used in Handler.hs by the call to+--   mkYesodDispatch+--+-- What this function does *not* do is create a YesodSite instance for+-- App. Creating that instance requires all of the handler functions+-- for our application to be in scope. However, the handler functions+-- 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")++-- | A convenience alias.+type AppRoute = Route App++#if MIN_VERSION_yesod(1,6,0)+type Form x = Html -> MForm (HandlerFor App) (FormResult x, Widget)+#else+type Form x = Html -> MForm (HandlerT App IO) (FormResult x, Widget)+#endif++-- Please see the documentation for the Yesod typeclass. There are a number+-- of settings which can be configured by overriding methods here.+instance Yesod App where+  approot = ApprootMaster $ appRoot . settings++  makeSessionBackend _ = Just <$> defaultClientSessionBackend 120 ".hledger-web_client_session_key.aes"++  defaultLayout widget = do+    master <- getYesod+    here <- fromMaybe RootR <$> getCurrentRoute+    VD {caps, j, m, opts, q, qopts} <- getViewData+    msg <- getMessage+    showSidebar <- shouldShowSidebar+    hideEmptyAccts <- (== Just "1") . lookup "hideemptyaccts" . reqCookies <$> getRequest++    let ropts = reportopts_ (cliopts_ opts)+        -- flip the default for items with zero amounts, show them by default+        ropts' = ropts { empty_ = not (empty_ ropts) }+        accounts =+          balanceReportAsHtml (JournalR, RegisterR) here hideEmptyAccts j qopts $+          balanceReport ropts' m j++        topShowmd = if showSidebar then "col-md-4" else "col-any-0" :: Text+        topShowsm = if showSidebar then "col-sm-4" else "" :: Text+        sideShowmd = if showSidebar then "col-md-4" else "col-any-0" :: Text+        sideShowsm = if showSidebar then "col-sm-4" else "" :: Text+        mainShowmd = if showSidebar then "col-md-8" else "col-md-12" :: Text+        mainShowsm = if showSidebar then "col-sm-8" else "col-sm-12" :: Text++    -- We break up the default layout into two components:+    -- default-layout is the contents of the body tag, and+    -- default-layout-wrapper is the entire page. Since the final+    -- value passed to hamletToRepHtml cannot be a widget, this allows+    -- you to use normal widget features in default-layout.+    pc <- widgetToPageContent $ do+      addStylesheet $ StaticR css_bootstrap_min_css+      addStylesheet $ StaticR css_bootstrap_datepicker_standalone_min_css+      -- load these things early, in HEAD:+      toWidgetHead [hamlet|+        <script type="text/javascript" src="@{StaticR js_jquery_min_js}">+        <script type="text/javascript" src="@{StaticR js_typeahead_bundle_min_js}">+      |]+      addScript $ StaticR js_bootstrap_min_js+      addScript $ StaticR js_bootstrap_datepicker_min_js+      addScript $ StaticR js_jquery_url_js+      addScript $ StaticR js_jquery_cookie_js+      addScript $ StaticR js_jquery_hotkeys_js+      addScript $ StaticR js_jquery_flot_min_js+      addScript $ StaticR js_jquery_flot_time_min_js+      addScript $ StaticR js_jquery_flot_tooltip_min_js+      toWidget [hamlet| \<!--[if lte IE 8]> <script type="text/javascript" src="@{StaticR js_excanvas_min_js}"></script> <![endif]--> |]+      addStylesheet $ StaticR hledger_css+      addScript $ StaticR hledger_js+      $(widgetFile "default-layout")++    withUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet")++#ifndef DEVELOPMENT+  -- This function creates static content files in the static folder+  -- and names them based on a hash of their content. This allows+  -- expiration dates to be set far in the future without worry of+  -- users receiving stale content.+  addStaticContent = addStaticContentExternal minifym base64md5 staticDir (StaticR . flip StaticRoute [])+#endif++-- This instance is required to use forms. You can modify renderMessage to+-- achieve customized and internationalized form validation messages.+instance RenderMessage App FormMessage where+    renderMessage _ _ = defaultFormMessage+++----------------------------------------------------------------------+-- template and handler utilities++-- view data, used by the add form and handlers+-- XXX Parameter p - show/hide postings++-- | A bundle of data useful for hledger-web request handlers and templates.+data ViewData = VD+  { opts  :: WebOpts    -- ^ the command-line options at startup+  , today :: Day        -- ^ today's date (for queries containing relative dates)+  , j     :: Journal    -- ^ the up-to-date parsed unfiltered journal+  , q     :: Text       -- ^ the current q parameter, the main query expression+  , m     :: Query      -- ^ a query parsed from the q parameter+  , qopts :: [QueryOpt] -- ^ query options parsed from the q parameter+  , caps  :: [Capability] -- ^ capabilities enabled for this request+  } deriving (Show)++instance Show Text.Blaze.Markup where show _ = "<blaze markup>"++-- | Gather data used by handlers and templates in the current request.+getViewData :: Handler ViewData+getViewData = do+  App {appOpts = opts, appJournal} <- getYesod+  today <- liftIO getCurrentDay+  let copts = cliopts_ opts+  (j, merr) <-+    getCurrentJournal+      appJournal+      copts {reportopts_ = (reportopts_ copts) {no_elide_ = True}}+      today+  maybe (pure ()) (setMessage . toHtml) merr+  q <- fromMaybe "" <$> lookupGetParam "q"+  let (m, qopts) = parseQuery today q+  caps <- case capabilitiesHeader_ opts of+    Nothing -> return (capabilities_ opts)+    Just h -> do+      hs <- fmap (BC.split ',' . snd) . filter ((== h) . fst) . requestHeaders <$> waiRequest+      fmap join . for (join hs) $ \x -> case capabilityFromBS x of+        Left e -> [] <$ addMessage "" ("Unknown permission: " <> toHtml (BC.unpack e))+        Right c -> pure [c]+  return VD {opts, today, j, q, m, qopts, caps}++-- | 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++-- | 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+-- ui message.+getCurrentJournal :: IORef Journal -> CliOpts -> Day -> Handler (Journal, Maybe String)+getCurrentJournal jref opts d = do+  -- XXX put this inside atomicModifyIORef' for thread safety+  j <- liftIO (readIORef jref)+  (ej, changed) <- liftIO $ journalReloadIfChanged opts d j+  -- re-apply any initial filter specified at startup+  let initq = queryFromOpts d (reportopts_ opts)+  case (changed, filterJournalTransactions initq <$> ej) of+    (False, _) -> return (j, Nothing)+    (True, Right j') -> do+      liftIO $ writeIORef jref j'+      return (j',Nothing)+    (True, Left e) -> do+      setMessage "error while reading journal"+      return (j, Just e)
+ Hledger/Web/Handler/AddR.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Hledger.Web.Handler.AddR+  ( getAddR+  , postAddR+  ) where++import Hledger+import Hledger.Cli.Commands.Add (appendToJournalFileOrStdout)+import Hledger.Web.Import+import Hledger.Web.Widget.AddForm (addForm)+import Hledger.Web.Widget.Common (fromFormSuccess)++getAddR :: Handler ()+getAddR = postAddR++postAddR :: Handler ()+postAddR = do+  VD{caps, j, today} <- getViewData+  when (CapAdd `notElem` caps) (permissionDenied "Missing the 'add' capability")++  ((res, view), enctype) <- runFormPost $ addForm j today+  t <- txnTieKnot <$> fromFormSuccess (showForm view enctype) res+  -- XXX(?) move into balanceTransaction+  liftIO $ ensureJournalFileExists (journalFilePath j)+  liftIO $ appendToJournalFileOrStdout (journalFilePath j) (showTransaction t)+  setMessage "Transaction added."+  redirect JournalR+  where+    showForm view enctype =+      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}>+            ^{view}+      |]
+ Hledger/Web/Handler/Common.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}++module Hledger.Web.Handler.Common+  ( getDownloadR+  , getFaviconR+  , getManageR+  , getRobotsR+  , getRootR+  ) where++import qualified Data.Text as T+import Yesod.Default.Handlers (getFaviconR, getRobotsR)++import Hledger (jfiles)+import Hledger.Web.Import+import Hledger.Web.Widget.Common (journalFile404)++getRootR :: Handler Html+getRootR = redirect JournalR++getManageR :: Handler Html+getManageR = do+  VD{caps, j} <- getViewData+  when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability")+  defaultLayout $ do+    setTitle "Manage journal"+    $(widgetFile "manage")++getDownloadR :: FilePath -> Handler TypedContent+getDownloadR f = do+  VD{caps, j} <- getViewData+  when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability")+  (f', txt) <- journalFile404 f j+  addHeader "Content-Disposition" ("attachment; filename=\"" <> T.pack f' <> "\"")+  sendResponse ("text/plain" :: ByteString, toContent txt)
+ Hledger/Web/Handler/EditR.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}++module Hledger.Web.Handler.EditR+  ( getEditR+  , postEditR+  ) where++import Hledger.Web.Import+import Hledger.Web.Widget.Common+       (fromFormSuccess, helplink, journalFile404, writeValidJournal)++editForm :: FilePath -> Text -> Markup -> MForm Handler (FormResult Text, Widget)+editForm f txt =+  identifyForm "edit" $ \extra -> do+    (tRes, tView) <- mreq textareaField fs (Just (Textarea txt))+    pure (unTextarea <$> tRes, $(widgetFile "edit-form"))+  where+    fs = FieldSettings "text" mzero mzero mzero [("class", "form-control"), ("rows", "25")]++getEditR :: FilePath -> Handler ()+getEditR = postEditR++postEditR :: FilePath -> Handler ()+postEditR f = do+  VD {caps, j} <- getViewData+  when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability")++  (f', txt) <- journalFile404 f j+  ((res, view), enctype) <- runFormPost (editForm f' txt)+  text <- fromFormSuccess (showForm view enctype) res+  writeValidJournal f text >>= \case+    Left e -> do+      setMessage $ "Failed to load journal: " <> toHtml e+      showForm view enctype+    Right () -> do+      setMessage $ "Saved journal " <> toHtml f <> "\n"+      redirect JournalR+  where+    showForm view enctype =+      sendResponse <=< defaultLayout $ do+        setTitle "Edit journal"+        [whamlet|<form method=post enctype=#{enctype}>^{view}|]
+ Hledger/Web/Handler/JournalR.hs view
@@ -0,0 +1,31 @@+-- | /journal handlers.++{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}++module Hledger.Web.Handler.JournalR where++import Hledger+import Hledger.Cli.CliOptions+import Hledger.Web.Import+import Hledger.Web.WebOptions+import Hledger.Web.Widget.AddForm (addModal)+import Hledger.Web.Widget.Common (accountQuery, mixedAmountAsHtml)++-- | The formatted journal view, with sidebar.+getJournalR :: Handler Html+getJournalR = do+  VD{caps, j, m, opts, qopts, today} <- getViewData+  when (CapView `notElem` caps) (permissionDenied "Missing the 'view' capability")+  let title = case inAccount qopts of+        Nothing -> "General Journal"+        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++  defaultLayout $ do+    setTitle "journal - hledger-web"+    $(widgetFile "journal")
+ Hledger/Web/Handler/RegisterR.hs view
@@ -0,0 +1,60 @@+-- | /register handlers.++{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}++module Hledger.Web.Handler.RegisterR where++import Data.List (intersperse)+import qualified Data.Text as T+import Text.Hamlet (hamletFile)++import Hledger+import Hledger.Cli.CliOptions+import Hledger.Web.Import+import Hledger.Web.WebOptions+import Hledger.Web.Widget.AddForm (addModal)+import Hledger.Web.Widget.Common (mixedAmountAsHtml)++-- | The main journal/account register view, with accounts sidebar.+getRegisterR :: Handler Html+getRegisterR = do+  VD{caps, j, m, opts, qopts, today} <- getViewData+  when (CapView `notElem` caps) (permissionDenied "Missing the 'view' capability")++  let (a,inclsubs) = fromMaybe ("all accounts",True) $ inAccount qopts+      s1 = if inclsubs then "" else " (excluding subaccounts)"+      s2 = if m /= Any then ", filtered" else ""+      header = a <> s1 <> s2++  let ropts = reportopts_ (cliopts_ opts)+      acctQuery = fromMaybe Any (inAccountQuery qopts)+      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")++-- | Generate javascript/html for a register balance line chart based on+-- the provided "TransactionsReportItem"s.+registerChartHtml :: [(CommoditySymbol, (String, [TransactionsReportItem]))] -> HtmlUrl AppRoute+registerChartHtml percommoditytxnreports = $(hamletFile "templates/chart.hamlet")+ -- have to make sure plot is not called when our container (maincontent)+ -- is hidden, eg with add form toggled+ where+   charttitle = case maybe "" (fst . snd) $ listToMaybe percommoditytxnreports of+     "" -> ""+     s  -> s <> ":"+   colorForCommodity = fromMaybe 0 . flip lookup commoditiesIndex+   commoditiesIndex = zip (map fst percommoditytxnreports) [0..] :: [(CommoditySymbol,Int)]+   simpleMixedAmountQuantity = maybe 0 aquantity . listToMaybe . amounts+   shownull c = if null c then " " else c++dayToJsTimestamp :: Day -> Integer+dayToJsTimestamp d =+  read (formatTime defaultTimeLocale "%s" t) * 1000 -- XXX read+  where+    t = UTCTime d (secondsToDiffTime 0)
+ Hledger/Web/Handler/UploadR.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}++module Hledger.Web.Handler.UploadR+  ( getUploadR+  , postUploadR+  ) where++import qualified Data.ByteString.Lazy as BL+import Data.Conduit (connect)+import Data.Conduit.Binary (sinkLbs)+import qualified Data.Text.Encoding as TE++import Hledger.Web.Import+import Hledger.Web.Widget.Common (fromFormSuccess, journalFile404, writeValidJournal)++uploadForm :: FilePath -> Markup -> MForm Handler (FormResult FileInfo, Widget)+uploadForm f =+  identifyForm "upload" $ \extra -> do+    (res, _) <- mreq fileField fs Nothing+    -- Ignoring the view - setting the name of the element is enough here+    pure (res, $(widgetFile "upload-form"))+  where+    fs = FieldSettings "file" Nothing (Just "file") (Just "file") []++getUploadR :: FilePath -> Handler ()+getUploadR = postUploadR++postUploadR :: FilePath -> Handler ()+postUploadR f = do+  VD {caps, j} <- getViewData+  when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability")++  (f', _) <- journalFile404 f j+  ((res, view), enctype) <- runFormPost (uploadForm f')+  fi <- fromFormSuccess (showForm view enctype) res+  lbs <- BL.toStrict <$> connect (fileSource fi) sinkLbs++  -- Try to parse as UTF-8+  -- XXX Unfortunate - how to parse as system locale?+  text <- case TE.decodeUtf8' lbs of+    Left e -> do+      setMessage $+        "Encoding error: '" <> toHtml (show e) <> "'. " <>+        "If your file is not UTF-8 encoded, try the 'edit form', " <>+        "where the transcoding should be handled by the browser."+      showForm view enctype+    Right text -> return text+  writeValidJournal f text >>= \case+    Left e -> do+      setMessage $ "Failed to load journal: " <> toHtml e+      showForm view enctype+    Right () -> do+      setMessage $ "File " <> toHtml f <> " uploaded successfully"+      redirect JournalR+  where+    showForm view enctype =+      sendResponse <=< defaultLayout $ do+        setTitle "Upload journal"+        [whamlet|<form method=post enctype=#{enctype}>^{view}|]
+ Hledger/Web/Import.hs view
@@ -0,0 +1,31 @@+{-# LANGUAGE CPP #-}+module Hledger.Web.Import+  ( module Import+  ) where++import           Prelude              as Import hiding (head, init, last,+                                                 readFile, tail, writeFile)+import           Yesod                as Import hiding (Route (..))++import           Control.Monad        as Import+import           Data.Bifunctor       as Import+import           Data.ByteString      as Import (ByteString)+import           Data.Default         as Import+import           Data.Either          as Import+import           Data.Foldable        as Import+import           Data.List            as Import (unfoldr)+import           Data.Maybe           as Import+import           Data.Text            as Import (Text)+import           Data.Time            as Import hiding (parseTime)+import           Data.Traversable     as Import+import           Data.Void            as Import (Void)+import           Text.Blaze           as Import (Markup)++import           Hledger.Web.Foundation           as Import+import           Hledger.Web.Settings             as Import+import           Hledger.Web.Settings.StaticFiles as Import+import           Hledger.Web.WebOptions           as Import (Capability(..))++#if !(MIN_VERSION_base(4,11,0))+import           Data.Monoid          as Import ((<>))+#endif
Hledger/Web/Main.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE CPP, OverloadedStrings #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-} {-|  hledger-web - a hledger add-on providing a web interface.@@ -7,32 +8,26 @@  -} -module Hledger.Web.Main-where+module Hledger.Web.Main where --- yesod scaffold imports-import Yesod.Default.Config --(fromArgs)--- import Yesod.Default.Main   (defaultMain)-import Settings            --  (parseExtra)-import Application          (makeApplication)-import Data.String+import Control.Monad (when)+import Data.String (fromString)+import qualified Data.Text as T+import Network.Wai (Application) import Network.Wai.Handler.Warp (runSettings, defaultSettings, setHost, setPort) import Network.Wai.Handler.Launch (runHostPortUrl)----#if !MIN_VERSION_base(4,8,0)-import Control.Applicative ((<$>))-#endif-import Control.Monad-import Data.Default-import Data.Text (pack)+import Prelude hiding (putStrLn) import System.Exit (exitSuccess) import System.IO (hFlush, stdout)-import Text.Printf-import Prelude hiding (putStrLn)+import Text.Printf (printf)+import Yesod.Default.Config+import Yesod.Default.Main (defaultDevelApp)  import Hledger-import Hledger.Utils.UTF8IOCompat (putStrLn) import Hledger.Cli hiding (progname,prognameandversion)+import Hledger.Utils.UTF8IOCompat (putStrLn)+import Hledger.Web.Application (makeApplication)+import Hledger.Web.Settings (Extra(..), parseExtra) import Hledger.Web.WebOptions  @@ -42,30 +37,39 @@   when (debug_ (cliopts_ opts) > 0) $ printf "%s\n" prognameandversion >> printf "opts: %s\n" (show opts)   runWith opts +hledgerWebDev :: IO (Int, Application)+hledgerWebDev =+  withJournalDoWeb defwebopts (\o j -> defaultDevelApp loader $ makeApplication o j)+  where+    loader =+      Yesod.Default.Config.loadConfig+        (configSettings Development) {csParseExtra = parseExtra}+ runWith :: WebOpts -> IO () runWith opts-  | "help"            `inRawOpts` (rawopts_ $ cliopts_ opts) = putStr (showModeUsage webmode) >> exitSuccess-  | "version"         `inRawOpts` (rawopts_ $ cliopts_ opts) = putStrLn prognameandversion >> exitSuccess-  | "binary-filename" `inRawOpts` (rawopts_ $ cliopts_ opts) = putStrLn (binaryfilename progname)-  | otherwise = do-    requireJournalFileExists =<< (head `fmap` journalFilePathFromOpts (cliopts_ opts)) -- XXX head should be safe for now-    withJournalDo' opts web+  | "help"            `inRawOpts` rawopts_ (cliopts_ opts) = putStr (showModeUsage webmode) >> exitSuccess+  | "version"         `inRawOpts` rawopts_ (cliopts_ opts) = putStrLn prognameandversion >> exitSuccess+  | "binary-filename" `inRawOpts` rawopts_ (cliopts_ opts) = putStrLn (binaryfilename progname)+  | otherwise = withJournalDoWeb opts web -withJournalDo' :: WebOpts -> (WebOpts -> Journal -> IO ()) -> IO ()-withJournalDo' opts@WebOpts {cliopts_ = cliopts} cmd = do-  f <- head `fmap` journalFilePathFromOpts cliopts -- XXX head should be safe for now+-- | A version of withJournalDo specialised for hledger-web.+-- Disallows the special - file to avoid some bug,+-- takes WebOpts rather than CliOpts.+withJournalDoWeb :: WebOpts -> (WebOpts -> Journal -> IO a) -> IO a+withJournalDoWeb opts@WebOpts {cliopts_ = copts} cmd = do+  journalpaths <- journalFilePathFromOpts copts    -- https://github.com/simonmichael/hledger/issues/202-  -- -f- gives [Error#yesod-core] <stdin>: hGetContents: illegal operation (handle is closed) for some reason-  -- Also we may be writing to this file. Just disallow it.-  when (f == "-") $ error' "hledger-web doesn't support -f -, please specify a file path"+  -- -f- gives [Error#yesod-core] <stdin>: hGetContents: illegal operation (handle is closed)+  -- Also we may try to write to this file. Just disallow -.+  when ("-" `elem` journalpaths) $  -- always non-empty+    error' "hledger-web doesn't support -f -, please specify a file path"+  mapM_ requireJournalFileExists journalpaths -  let fn = cmd opts-         . pivotByOpts cliopts-         . anonymiseByOpts cliopts-       <=< journalApplyValue (reportopts_ cliopts)-       <=< journalAddForecast cliopts-  readJournalFile def f >>= either error' fn+  -- keep synced with withJournalDo  TODO refactor+  readJournalFiles (inputopts_ copts) journalpaths+  >>= mapM (journalTransform copts)+  >>= either error' (cmd opts)  -- | The web command. web :: WebOpts -> Journal -> IO ()@@ -76,11 +80,11 @@       h = host_ opts       p = port_ opts       u = base_url_ opts-      staticRoot = pack <$> file_url_ opts+      staticRoot = T.pack <$> file_url_ opts       appconfig = AppConfig{appEnv = Development                            ,appHost = fromString h                            ,appPort = p-                           ,appRoot = pack u+                           ,appRoot = T.pack u                            ,appExtra = Extra "" Nothing staticRoot                            }   app <- makeApplication opts j' appconfig@@ -90,10 +94,7 @@     then do       putStrLn "Press ctrl-c to quit"       hFlush stdout-      let warpsettings =-            setHost (fromString h) $-            setPort p $-            defaultSettings+      let warpsettings = setHost (fromString h) (setPort p defaultSettings)       Network.Wai.Handler.Warp.runSettings warpsettings app     else do       putStrLn "Starting web browser..."
+ Hledger/Web/Settings.hs view
@@ -0,0 +1,100 @@+{-# LANGUAGE CPP, OverloadedStrings, QuasiQuotes #-}+-- | Settings are centralized, as much as possible, into this file. This+-- includes database connection settings, static file locations, etc.+-- In addition, you can configure a number of different aspects of Yesod+-- by overriding methods in the Yesod typeclass. That instance is+-- declared in the Foundation.hs file.+module Hledger.Web.Settings where++import Data.Default (def)+import Data.Semigroup ((<>))+import Data.Text (Text)+import Data.Yaml+import Language.Haskell.TH.Syntax (Q, Exp)+import Text.Hamlet+import Text.Shakespeare.Text (st)+import Yesod.Default.Config+import Yesod.Default.Util++development :: Bool+development =+#if DEVELOPMENT+  True+#else+  False+#endif++production :: Bool+production = not development++hledgerorgurl :: Text+hledgerorgurl = "http://hledger.org"++manualurl :: Text+manualurl = hledgerorgurl <> "/manual"++-- | The default IP address to listen on. May be overridden with --host.+defhost :: String+defhost = "127.0.0.1"++-- | The default TCP port to listen on. May be overridden with --port.+defport :: Int+defport = 5000++defbaseurl :: String -> Int -> String+defbaseurl host port =+  "http://" ++ host ++ if port /= 80 then ":" ++ show port else ""++-- Static setting below. Changing these requires a recompile++-- | The location of static files on your system. This is a file system+-- path. The default value works properly with your scaffolded site.+staticDir :: FilePath+staticDir = "static"++-- | The base URL for your static files. As you can see by the default+-- value, this can simply be "static" appended to your application root.+-- A powerful optimization can be serving static files from a separate+-- domain name. This allows you to use a web server optimized for static+-- files, more easily set expires and cache values, and avoid possibly+-- costly transference of cookies on static files. For more information,+-- please see:+--   http://code.google.com/speed/page-speed/docs/request.html#ServeFromCookielessDomain+--+-- If you change the resource pattern for StaticR in Foundation.hs, you will+-- have to make a corresponding change here.+--+-- To see how this value is used, see urlRenderOverride in Foundation.hs+staticRoot :: AppConfig DefaultEnv Extra -> Text+staticRoot conf = case extraStaticRoot $ appExtra conf of+                    Just root -> root+                    Nothing -> [st|#{appRoot conf}/static|]++-- | Settings for 'widgetFile', such as which template languages to support and+-- default Hamlet settings.+widgetFileSettings :: WidgetFileSettings+widgetFileSettings = def+    { wfsHamletSettings = defaultHamletSettings+        { hamletNewlines = AlwaysNewlines+        }+    }++-- The rest of this file contains settings which rarely need changing by a+-- user.++widgetFile :: String -> Q Exp+widgetFile = (if development then widgetFileReload+                             else widgetFileNoReload)+              widgetFileSettings++data Extra = Extra+    { extraCopyright  :: Text+    , extraAnalytics  :: Maybe Text -- ^ Google Analytics+    , extraStaticRoot :: Maybe Text+    } deriving Show++parseExtra :: DefaultEnv -> Object -> Parser Extra+parseExtra _ o = Extra+    <$> o .:  "copyright"+    <*> o .:? "analytics"+    <*> o .:? "staticRoot"
+ Hledger/Web/Settings/StaticFiles.hs view
@@ -0,0 +1,31 @@+{-# LANGUAGE TemplateHaskell #-}+module Hledger.Web.Settings.StaticFiles where++import System.IO (stdout, hFlush)+import Yesod.Static (Static, embed, publicFiles, staticDevel)++import Hledger.Web.Settings (staticDir, development)++-- | use this to create your static file serving site+-- staticSite :: IO Static.Static+-- staticSite = if development then Static.staticDevel staticDir+--                             else Static.static      staticDir+--+-- | This generates easy references to files in the static directory at compile time,+--   giving you compile-time verification that referenced files exist.+--   Warning: any files added to your static directory during run-time can't be+--   accessed this way. You'll have to use their FilePath or URL to access them.+-- $(staticFiles Settings.staticDir)+++staticSite :: IO Static+staticSite =+  if development+   then (do+            putStrLn ("Using web files from: " ++ staticDir ++ "/") >> hFlush stdout+            staticDevel staticDir)+   else (do+            -- putStrLn "Using built-in web files" >> hFlush stdout+            return $(embed staticDir))++$(publicFiles staticDir)
Hledger/Web/WebOptions.hs view
@@ -1,17 +1,20 @@ {-# LANGUAGE CPP #-}-module Hledger.Web.WebOptions-where-import Prelude-import Data.Default-#if !MIN_VERSION_base(4,8,0)-import Data.Functor.Compat ((<$>))-#endif-import Data.Maybe-import System.Environment+{-# LANGUAGE OverloadedStrings #-}+module Hledger.Web.WebOptions where -import Hledger.Cli hiding (progname,version,prognameandversion)-import Settings+import Data.ByteString (ByteString)+import qualified Data.ByteString.Char8 as BC+import Data.CaseInsensitive (CI, mk)+import Control.Monad (join)+import Data.Default (Default(def))+import Data.Maybe (fromMaybe)+import qualified Data.Text as T+import Data.Text (Text)+import System.Environment (getArgs) +import Hledger.Cli hiding (progname, version)+import Hledger.Web.Settings (defhost, defport, defbaseurl)+ progname, version :: String progname = "hledger-web" #ifdef VERSION@@ -22,81 +25,137 @@ prognameandversion :: String prognameandversion = progname ++ " " ++ version :: String -webflags :: [Flag [([Char], [Char])]]-webflags = [-  flagNone ["serve","server"]   (setboolopt "serve") ("serve and log requests, don't browse or auto-exit")- ,flagReq  ["host"]     (\s opts -> Right $ setopt "host" s opts) "IPADDR" ("listen on this IP address (default: "++defhost++")")- ,flagReq  ["port"]     (\s opts -> Right $ setopt "port" s opts) "PORT" ("listen on this TCP port (default: "++show defport++")")- ,flagReq  ["base-url"] (\s opts -> Right $ setopt "base-url" s opts) "BASEURL" ("set the base url (default: http://IPADDR:PORT)")- ,flagReq  ["file-url"] (\s opts -> Right $ setopt "file-url" s opts) "FILEURL" ("set the static files url (default: BASEURL/static)")- ]+webflags :: [Flag [(String, String)]]+webflags =+  [ flagNone+      ["serve", "server"]+      (setboolopt "serve")+      "serve and log requests, don't browse or auto-exit"+  , flagReq+      ["host"]+      (\s opts -> Right $ setopt "host" s opts)+      "IPADDR"+      ("listen on this IP address (default: " ++ defhost ++ ")")+  , flagReq+      ["port"]+      (\s opts -> Right $ setopt "port" s opts)+      "PORT"+      ("listen on this TCP port (default: " ++ show defport ++ ")")+  , flagReq+      ["base-url"]+      (\s opts -> Right $ setopt "base-url" s opts)+      "BASEURL"+      "set the base url (default: http://IPADDR:PORT)"+  , flagReq+      ["file-url"]+      (\s opts -> Right $ setopt "file-url" s opts)+      "FILEURL"+      "set the static files url (default: BASEURL/static)"+  , flagReq+      ["capabilities"]+      (\s opts -> Right $ setopt "capabilities" s opts)+      "CAP,CAP2"+      "enable these capabilities - comma-separated, possible values are: view, add, manage (default: view,add)"+  , flagReq+      ["capabilities-header"]+      (\s opts -> Right $ setopt "capabilities-header" s opts)+      "HEADER"+      "read enabled capabilities from a HTTP header (e.g. X-Sandstorm-Permissions, disabled by default)"+  ] -webmode :: Mode [([Char], [Char])]-webmode =  (mode "hledger-web" [("command","web")]-            "start serving the hledger web interface"-            (argsFlag "[PATTERNS]") []){-              modeGroupFlags = Group {-                                groupUnnamed = webflags-                               ,groupHidden = [flagNone ["binary-filename"] (setboolopt "binary-filename") "show the download filename for this executable, and exit"]-                               ,groupNamed = [generalflagsgroup1]-                               }-             ,modeHelpSuffix=[-                  -- "Reads your ~/.hledger.journal file, or another specified by $LEDGER_FILE or -f, and starts the full-window curses ui."-                 ]-           }+webmode :: Mode [(String, String)]+webmode =+  (mode+     "hledger-web"+     [("command", "web")]+     "start serving the hledger web interface"+     (argsFlag "[PATTERNS]")+     [])+  { modeGroupFlags =+      Group+      { groupUnnamed = webflags+      , groupHidden =+          [ flagNone+              ["binary-filename"]+              (setboolopt "binary-filename")+              "show the download filename for this executable, and exit"+          ]+      , groupNamed = [generalflagsgroup1]+      }+  , modeHelpSuffix = []+  }  -- hledger-web options, used in hledger-web and above-data WebOpts = WebOpts {-     serve_    :: Bool-    ,host_     :: String-    ,port_     :: Int-    ,base_url_ :: String-    ,file_url_ :: Maybe String-    ,cliopts_  :: CliOpts- } deriving (Show)+data WebOpts = WebOpts+  { serve_ :: Bool+  , host_ :: String+  , port_ :: Int+  , base_url_ :: String+  , file_url_ :: Maybe String+  , capabilities_ :: [Capability]+  , capabilitiesHeader_ :: Maybe (CI ByteString)+  , cliopts_ :: CliOpts+  } deriving (Show)  defwebopts :: WebOpts-defwebopts = WebOpts-    def-    def-    def-    def-    def-    def+defwebopts = WebOpts def def def def def [CapView, CapAdd] Nothing def --- instance Default WebOpts where def = defwebopts+instance Default WebOpts where def = defwebopts  rawOptsToWebOpts :: RawOpts -> IO WebOpts-rawOptsToWebOpts rawopts = checkWebOpts <$> do-  cliopts <- rawOptsToCliOpts rawopts-  let-    h = fromMaybe defhost $ maybestringopt "host" rawopts-    p = fromMaybe defport $ maybeintopt "port" rawopts-    b = maybe (defbaseurl h p) stripTrailingSlash $ maybestringopt "base-url" rawopts-  return defwebopts {-              serve_ = boolopt "serve" rawopts-             ,host_ = h-             ,port_ = p-             ,base_url_ = b-             ,file_url_ = stripTrailingSlash <$> maybestringopt "file-url" rawopts-             ,cliopts_   = cliopts-             }+rawOptsToWebOpts rawopts =+  checkWebOpts <$> do+    cliopts <- rawOptsToCliOpts rawopts+    let h = fromMaybe defhost $ maybestringopt "host" rawopts+        p = fromMaybe defport $ maybeintopt "port" rawopts+        b =+          maybe (defbaseurl h p) stripTrailingSlash $+          maybestringopt "base-url" rawopts+        caps' = join $ T.splitOn "," . T.pack <$> listofstringopt "capabilities" rawopts+        caps = case traverse capabilityFromText caps' of+          Left e -> error' ("Unknown capability: " ++ T.unpack e)+          Right [] -> [CapView, CapAdd]+          Right xs -> xs+    return+      defwebopts+      { serve_ = boolopt "serve" rawopts+      , host_ = h+      , port_ = p+      , base_url_ = b+      , file_url_ = stripTrailingSlash <$> maybestringopt "file-url" rawopts+      , capabilities_ = caps+      , capabilitiesHeader_ = mk . BC.pack <$> maybestringopt "capabilities-header" rawopts+      , cliopts_ = cliopts+      }   where-    stripTrailingSlash = reverse . dropWhile (=='/') . reverse -- yesod don't like it+    stripTrailingSlash = reverse . dropWhile (== '/') . reverse -- yesod don't like it  checkWebOpts :: WebOpts -> WebOpts-checkWebOpts wopts =-  either usageError (const wopts) $ do-    let h = host_ wopts-    if any (not . (`elem` ".0123456789")) h-    then Left $ "--host requires an IP address, not "++show h-    else Right ()+checkWebOpts wopts = do+  let h = host_ wopts+  if any (`notElem` (".0123456789" :: String)) h+    then usageError $ "--host requires an IP address, not " ++ show h+    else wopts  getHledgerWebOpts :: IO WebOpts---getHledgerWebOpts = processArgs webmode >>= return . decodeRawOpts >>= rawOptsToWebOpts getHledgerWebOpts = do-  args <- getArgs >>= expandArgsAt-  let args' = replaceNumericFlags args -  let cmdargopts = either usageError id $ process webmode args'-  rawOptsToWebOpts $ decodeRawOpts cmdargopts +  args <- fmap replaceNumericFlags . expandArgsAt =<< getArgs+  rawOptsToWebOpts . decodeRawOpts . either usageError id $ process webmode args +data Capability+  = CapView+  | CapAdd+  | CapManage+  deriving (Eq, Ord, Bounded, Enum, Show)++capabilityFromText :: Text -> Either Text Capability+capabilityFromText "view" = Right CapView+capabilityFromText "add" = Right CapAdd+capabilityFromText "manage" = Right CapManage+capabilityFromText x = Left x++capabilityFromBS :: ByteString -> Either ByteString Capability+capabilityFromBS "view" = Right CapView+capabilityFromBS "add" = Right CapAdd+capabilityFromBS "manage" = Right CapManage+capabilityFromBS x = Left x
+ Hledger/Web/Widget/AddForm.hs view
@@ -0,0 +1,144 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TemplateHaskell #-}++module Hledger.Web.Widget.AddForm+  ( addForm+  , addModal+  ) where++import Control.Monad.State.Strict (evalStateT)+import Data.Bifunctor (first)+import Data.List (dropWhileEnd, nub, sort, unfoldr)+import Data.Maybe (isJust)+import Data.Semigroup ((<>))+import Data.Text (Text)+import qualified Data.Text as T+import Data.Time (Day)+import Text.Blaze.Internal (Markup, preEscapedString)+import Text.JSON+import Text.Megaparsec (eof, parseErrorPretty, runParser)+import Yesod++import Hledger+import Hledger.Web.Settings (widgetFile)++addModal ::+     ( MonadWidget m+     , r ~ Route (HandlerSite m)+#if MIN_VERSION_yesod(1,6,0)+     , m ~ WidgetFor (HandlerSite m)+#else+     , m ~ WidgetT (HandlerSite m) IO+#endif+     , RenderMessage (HandlerSite m) FormMessage+     )+  => r -> Journal -> Day -> m ()+addModal addR j today = do+  (addView, addEnctype) <- generateFormPost (addForm j today)+  [whamlet|+<div .modal #addmodal tabindex="-1" role="dialog" aria-labelledby="addLabel" aria-hidden="true">+  <div .modal-dialog .modal-lg>+    <div .modal-content>+      <div .modal-header>+        <button type="button" .close data-dismiss="modal" aria-hidden="true">&times;+        <h3 .modal-title #addLabel>Add a transaction+      <div .modal-body>+        <form#addform.form action=@{addR} method=POST enctype=#{addEnctype}>+          ^{addView}+|]++addForm ::+     (site ~ HandlerSite m, RenderMessage site FormMessage, MonadHandler m)+  => Journal+  -> Day+  -> Markup+#if MIN_VERSION_yesod(1,6,0)+  -> MForm m (FormResult Transaction, WidgetFor site ())+#else+  -> MForm m (FormResult Transaction, WidgetT site IO ())+#endif+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 (msgs', postRes) = case validatePostings <$> acctRes <*> amtRes of+        FormSuccess (Left es) -> (es, FormFailure ["Postings validation failed"])+        FormSuccess (Right xs) -> ([], FormSuccess xs)+        FormMissing -> ([], FormMissing)+        FormFailure es -> ([], FormFailure es)+      msgs = zip [(1 :: Int)..] $ msgs' ++ replicate (4 - length msgs') ("", "", Nothing, Nothing)++  let descriptions = sort $ nub $ tdescription <$> jtxns j+      escapeJSSpecialChars = regexReplaceCI "</script>" "<\\/script>" -- #236+      listToJsonValueObjArrayStr = preEscapedString . escapeJSSpecialChars .+        encode . JSArray . fmap (\a -> JSObject $ toJSObject [("value", showJSON a)])+      journals = fst <$> jfiles j++  pure (makeTransaction <$> dateRes <*> descRes <*> postRes, $(widgetFile "add-form"))+  where+    makeTransaction date desc postings =+      nulltransaction {tdate = date, tdescription = desc, tpostings = postings}++    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)++    listField = Field+      { fieldParse = const . pure . Right . Just . dropWhileEnd T.null+      , fieldView = error "Don't render using this!"+      , fieldEnctype = UrlEncoded+      }++validatePostings :: [Text] -> [Text] -> Either [(Text, Text, Maybe Text, Maybe Text)] [Posting]+validatePostings a b =+  case traverse id $ (\(_, _, x) -> x) <$> postings of+    Left _ -> Left $ foldr catPostings [] postings+    Right [] -> Left+      [ ("", "", Just "Missing account", Just "Missing amount")+      , ("", "", Just "Missing account", Nothing)+      ]+    Right [p] -> Left+      [ (paccount p, T.pack . showMixedAmountWithoutPrice $ pamount p, Nothing, Nothing)+      , ("", "", Just "Missing account", Nothing)+      ]+    Right xs -> Right xs+  where+    postings = unfoldr go (True, a, b)++    go (_, x:xs, y:ys) = Just ((x, y, zipPosting (validateAccount x) (validateAmount y)), (True, xs, ys))+    go (True, x:y:xs, []) = Just ((x, "", zipPosting (validateAccount x) (Left "Missing amount")), (True, y:xs, []))+    go (True, x:xs, []) = Just ((x, "", zipPosting (validateAccount x) (Right missingamt)), (False, xs, []))+    go (False, x:xs, []) = Just ((x, "", zipPosting (validateAccount x) (Left "Missing amount")), (False, xs, []))+    go (_, [], y:ys) = Just (("", y, zipPosting (Left "Missing account") (validateAmount y)), (False, [], ys))+    go (_, [], []) = Nothing++    zipPosting = zipEither (\acc amt -> nullposting {paccount = acc, pamount = Mixed [amt]})++    catPostings (t, t', Left (e, e')) xs = (t, t', e, e') : xs+    catPostings (t, t', Right _) xs = (t, t', Nothing, Nothing) : xs++    errorToFormMsg = first (("Invalid value: " <>) . T.pack . parseErrorPretty)+    validateAccount = errorToFormMsg . runParser (accountnamep <* eof) "" . T.strip+    validateAmount = errorToFormMsg . runParser (evalStateT (amountp <* eof) mempty) "" . T.strip++-- Modification of Align, from the `these` package+zipEither :: (a -> a' -> r) -> Either e a -> Either e' a' -> Either (Maybe e, Maybe e') r+zipEither f a b = case (a, b) of+  (Right a', Right b') -> Right (f a' b')+  (Left a', Right _) -> Left (Just a', Nothing)+  (Right _, Left b') -> Left (Nothing, Just b')+  (Left a', Left b') -> Left (Just a', Just b')
+ Hledger/Web/Widget/Common.hs view
@@ -0,0 +1,89 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}++module Hledger.Web.Widget.Common+  ( accountQuery+  , accountOnlyQuery+  , balanceReportAsHtml+  , helplink+  , mixedAmountAsHtml+  , fromFormSuccess+  , writeValidJournal+  , journalFile404+  ) where++import Data.Default (def)+import Data.Foldable (find, for_)+import Data.Semigroup ((<>))+import Data.Text (Text)+import qualified Data.Text as T+import System.FilePath (takeFileName)+import Text.Blaze ((!), textValue)+import qualified Text.Blaze.Html5 as H+import qualified Text.Blaze.Html5.Attributes as A+import Text.Blaze.Internal (preEscapedString)+import Text.Hamlet (hamletFile)+import Yesod++import Hledger+import Hledger.Cli.Utils (writeFileWithBackupIfChanged)+import Hledger.Web.Settings (manualurl)++#if MIN_VERSION_yesod(1,6,0)+journalFile404 :: FilePath -> Journal -> HandlerFor m (FilePath, Text)+#else+journalFile404 :: FilePath -> Journal -> HandlerT m IO (FilePath, Text)+#endif+journalFile404 f j =+  case find ((== f) . fst) (jfiles j) of+    Just (_, txt) -> pure (takeFileName f, txt)+    Nothing -> notFound++fromFormSuccess :: Applicative m => m a -> FormResult a -> m a+fromFormSuccess h FormMissing = h+fromFormSuccess h (FormFailure _) = h+fromFormSuccess _ (FormSuccess a) = pure a++writeValidJournal :: MonadHandler m => FilePath -> Text -> m (Either String ())+writeValidJournal f txt =+  liftIO (readJournal def (Just f) txt) >>= \case+    Left e -> return (Left e)+    Right _ -> do+      _ <- liftIO (writeFileWithBackupIfChanged f txt)+      return (Right ())+++-- | Link to a topic in the manual.+helplink :: Text -> Text -> HtmlUrl r+helplink topic label _ = H.a ! A.href u ! A.target "hledgerhelp" $ toHtml label+  where u = textValue $ manualurl <> if T.null topic then "" else T.cons '#' topic++-- | Render a "BalanceReport" as html.+balanceReportAsHtml :: Eq r => (r, r) -> r -> Bool -> Journal -> [QueryOpt] -> BalanceReport -> HtmlUrl r+balanceReportAsHtml (journalR, registerR) here hideEmpty j qopts (items, total) =+  $(hamletFile "templates/balance-report.hamlet")+  where+    l = ledgerFromJournal Any j+    indent a = preEscapedString $ concat $ replicate (2 + 2 * a) "&nbsp;"+    hasSubAccounts acct = maybe True (not . null . asubs) (ledgerAccount l acct)+    matchesAcctSelector acct = Just True == ((`matchesAccount` acct) <$> inAccountQuery qopts)++accountQuery :: AccountName -> Text+accountQuery = ("inacct:" <>) .  quoteIfSpaced++accountOnlyQuery :: AccountName -> Text+accountOnlyQuery = ("inacctonly:" <>) . quoteIfSpaced++mixedAmountAsHtml :: MixedAmount -> HtmlUrl a+mixedAmountAsHtml b _ =+  for_ (lines (showMixedAmountWithoutPrice b)) $ \t -> do+    H.span ! A.class_ c $ toHtml t+    H.br+  where+    c = case isNegativeMixedAmount b of+      Just True -> "negative amount"+      _ -> "positive amount"
− Import.hs
@@ -1,22 +0,0 @@-{-# LANGUAGE CPP #-}-module Import-    ( module Import-    ) where--import           Prelude              as Import hiding (head, init, last,-                                                 readFile, tail, writeFile)-import           Yesod                as Import hiding (Route (..))--#if !MIN_VERSION_base(4,8,0)-import           Control.Applicative  as Import (pure, (<$>), (<*>))-#endif-import           Data.Text            as Import (Text)--import           Foundation           as Import-import           Settings             as Import-import           Settings.Development as Import-import           Settings.StaticFiles as Import--#if !(MIN_VERSION_base(4,11,0))-import           Data.Monoid          as Import ((<>))-#endif
− Settings.hs
@@ -1,92 +0,0 @@-{-# LANGUAGE CPP, OverloadedStrings, QuasiQuotes #-}--- | Settings are centralized, as much as possible, into this file. This--- includes database connection settings, static file locations, etc.--- In addition, you can configure a number of different aspects of Yesod--- by overriding methods in the Yesod typeclass. That instance is--- declared in the Foundation.hs file.-module Settings where--import Prelude-import Text.Shakespeare.Text (st)-import Language.Haskell.TH.Syntax-import Yesod.Default.Config-import Yesod.Default.Util-import Data.Text (Text)-import Data.Yaml-#if !MIN_VERSION_base(4,8,0)-import Control.Applicative-#endif-import Settings.Development-import Data.Default (def)-import Text.Hamlet---hledgerorgurl, manualurl :: String-hledgerorgurl     = "http://hledger.org"-manualurl         = hledgerorgurl++"/manual"---- | The default IP address to listen on. May be overridden with --host.-defhost :: String-defhost = "127.0.0.1"---- | The default TCP port to listen on. May be overridden with --port.-defport :: Int-defport = 5000--defbaseurl :: String -> Int -> String-defbaseurl host port =-  "http://" ++ host ++ if port /= 80 then ":" ++ show port else ""---- Static setting below. Changing these requires a recompile---- | The location of static files on your system. This is a file system--- path. The default value works properly with your scaffolded site.-staticDir :: FilePath-staticDir = "static"---- | The base URL for your static files. As you can see by the default--- value, this can simply be "static" appended to your application root.--- A powerful optimization can be serving static files from a separate--- domain name. This allows you to use a web server optimized for static--- files, more easily set expires and cache values, and avoid possibly--- costly transference of cookies on static files. For more information,--- please see:---   http://code.google.com/speed/page-speed/docs/request.html#ServeFromCookielessDomain------ If you change the resource pattern for StaticR in Foundation.hs, you will--- have to make a corresponding change here.------ To see how this value is used, see urlRenderOverride in Foundation.hs-staticRoot :: AppConfig DefaultEnv Extra -> Text-staticRoot conf = case extraStaticRoot $ appExtra conf of-                    Just root -> root-                    Nothing -> [st|#{appRoot conf}/static|]---- | Settings for 'widgetFile', such as which template languages to support and--- default Hamlet settings.-widgetFileSettings :: WidgetFileSettings-widgetFileSettings = def-    { wfsHamletSettings = defaultHamletSettings-        { hamletNewlines = AlwaysNewlines-        }-    }---- The rest of this file contains settings which rarely need changing by a--- user.--widgetFile :: String -> Q Exp-widgetFile = (if development then widgetFileReload-                             else widgetFileNoReload)-              widgetFileSettings--data Extra = Extra-    { extraCopyright  :: Text-    , extraAnalytics  :: Maybe Text -- ^ Google Analytics-    , extraStaticRoot :: Maybe Text-    } deriving Show--parseExtra :: DefaultEnv -> Object -> Parser Extra-parseExtra _ o = Extra-    <$> o .:  "copyright"-    <*> o .:? "analytics"-    <*> o .:? "staticRoot"
− Settings/Development.hs
@@ -1,15 +0,0 @@-{-# LANGUAGE CPP #-}-module Settings.Development where--import Prelude--development :: Bool-development =-#if DEVELOPMENT-  True-#else-  False-#endif--production :: Bool-production = not development
− Settings/StaticFiles.hs
@@ -1,33 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}-module Settings.StaticFiles where--import Prelude (IO, putStrLn, (++), (>>), return)-import System.IO (stdout, hFlush)-import Yesod.Static-import qualified Yesod.Static as Static-import Settings (staticDir)-import Settings.Development---- | use this to create your static file serving site--- staticSite :: IO Static.Static--- staticSite = if development then Static.staticDevel staticDir---                             else Static.static      staticDir------ | This generates easy references to files in the static directory at compile time,---   giving you compile-time verification that referenced files exist.---   Warning: any files added to your static directory during run-time can't be---   accessed this way. You'll have to use their FilePath or URL to access them.--- $(staticFiles Settings.staticDir)---staticSite :: IO Static.Static-staticSite =-  if development-   then (do-            putStrLn ("Using web files from: " ++ staticDir ++ "/") >> hFlush stdout-            Static.staticDevel staticDir)-   else (do-            -- putStrLn "Using built-in web files" >> hFlush stdout-            return $(Static.embed staticDir))--$(publicFiles staticDir)
config/routes view
@@ -1,10 +1,13 @@ /favicon.ico     FaviconR        GET /robots.txt      RobotsR         GET /static          StaticR         Static getStatic+ /                RootR           GET-/journal         JournalR        GET POST-/register        RegisterR       GET POST-/sidebar         SidebarR        GET+/journal         JournalR        GET+/register        RegisterR       GET+/add             AddR            GET POST --- /accounts        AccountsR       GET--- /api/accounts    AccountsJsonR   GET+/manage             ManageR         GET+/edit/#FilePath     EditR           GET POST+/upload/#FilePath   UploadR         GET POST+/download/#FilePath DownloadR       GET
hledger-web.1 view
@@ -1,5 +1,5 @@ -.TH "hledger\-web" "1" "April 2018" "hledger\-web 1.9.1" "hledger User Manuals"+.TH "hledger\-web" "1" "June 2018" "hledger\-web 1.9.99" "hledger User Manuals"   
hledger-web.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 1872196bf7e9ff50fae0f3ea64ea81d1155799a2779617be58c9acf7f6aabce8+-- hash: 819abf18972b92028b9ccb3e8b1c5404368f8ca74e855c6fa226884dd01995a8  name:           hledger-web-version:        1.9.2+version:        1.10 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@@ -25,7 +25,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.1+tested-with:    GHC==7.10.3, GHC==8.0.2, GHC==8.2.2, GHC==8.4.1 build-type:     Simple cabal-version:  >= 1.10 extra-source-files:@@ -38,7 +38,6 @@     hledger-web.1     hledger-web.info     hledger-web.txt-    messages/en.msg     README     static/css/bootstrap-datepicker.standalone.min.css     static/css/bootstrap-theme.css@@ -97,8 +96,16 @@     static/js/jquery.url.js     static/js/typeahead.bundle.js     static/js/typeahead.bundle.min.js+    templates/add-form.hamlet+    templates/balance-report.hamlet+    templates/chart.hamlet     templates/default-layout-wrapper.hamlet     templates/default-layout.hamlet+    templates/edit-form.hamlet+    templates/journal.hamlet+    templates/manage.hamlet+    templates/register.hamlet+    templates/upload-form.hamlet  source-repository head   type: git@@ -120,50 +127,52 @@   default: True  library+  hs-source-dirs:+      ./.   exposed-modules:-      Application-      Foundation-      Handler.AddForm-      Handler.Common-      Handler.JournalR-      Handler.RegisterR-      Handler.RootR-      Handler.SidebarR-      Handler.Utils       Hledger.Web+      Hledger.Web.Application+      Hledger.Web.Foundation+      Hledger.Web.Handler.AddR+      Hledger.Web.Handler.Common+      Hledger.Web.Handler.EditR+      Hledger.Web.Handler.JournalR+      Hledger.Web.Handler.RegisterR+      Hledger.Web.Handler.UploadR+      Hledger.Web.Import       Hledger.Web.Main+      Hledger.Web.Settings+      Hledger.Web.Settings.StaticFiles       Hledger.Web.WebOptions-      Import-      Settings-      Settings.Development-      Settings.StaticFiles+      Hledger.Web.Widget.AddForm+      Hledger.Web.Widget.Common   other-modules:       Paths_hledger_web-  ghc-options: -Wall -fno-warn-unused-do-bind -fno-warn-name-shadowing -fno-warn-missing-signatures -fno-warn-type-defaults -fno-warn-orphans-  cpp-options: -DVERSION="1.9.2"+  ghc-options: -Wall -fwarn-tabs+  cpp-options: -DVERSION="1.10"   build-depends:       HUnit     , base >=4.8 && <4.12-    , base-compat >=0.8.1     , blaze-html     , blaze-markup     , bytestring+    , case-insensitive     , clientsession     , cmdargs >=0.10+    , conduit     , conduit-extra >=1.1     , data-default     , directory     , filepath     , hjsmin-    , hledger >=1.9.1 && <2.0-    , hledger-lib >=1.9.1 && <2.0+    , hledger >=1.10 && <1.11+    , hledger-lib >=1.10 && <1.11     , http-client     , http-conduit     , json-    , megaparsec >=5.0+    , megaparsec >=6.4.1     , mtl-    , parsec >=3-    , safe >=0.2+    , semigroups     , shakespeare >=2.0.2.2     , template-haskell     , text >=1.2@@ -178,10 +187,8 @@     , yesod-core >=1.4 && <1.7     , yesod-form >=1.4 && <1.7     , yesod-static >=1.4 && <1.7-  if (flag(dev)) || (flag(library-only))-    cpp-options: -DDEVELOPMENT-  if flag(dev)-    ghc-options: -O0+  if impl(ghc >=8)+    ghc-options: -Wcompat -Wincomplete-uni-patterns -Wincomplete-record-updates -Wredundant-constraints   default-language: Haskell2010  executable hledger-web@@ -190,109 +197,15 @@       Paths_hledger_web   hs-source-dirs:       app-  ghc-options: -Wall -fno-warn-unused-do-bind -fno-warn-name-shadowing -fno-warn-missing-signatures -fno-warn-type-defaults -fno-warn-orphans-  cpp-options: -DVERSION="1.9.2"+  ghc-options: -Wall -fwarn-tabs+  cpp-options: -DVERSION="1.10"   build-depends:-      HUnit-    , base >=4.8 && <4.12-    , base-compat >=0.8.1-    , blaze-html-    , blaze-markup-    , bytestring-    , clientsession-    , cmdargs >=0.10-    , conduit-extra >=1.1-    , data-default-    , directory-    , filepath-    , hjsmin-    , hledger >=1.9.1 && <2.0-    , hledger-lib >=1.9.1 && <2.0+      base     , hledger-web-    , http-client-    , http-conduit-    , json-    , megaparsec >=5.0-    , mtl-    , parsec >=3-    , safe >=0.2-    , shakespeare >=2.0.2.2-    , template-haskell-    , text >=1.2-    , time >=1.5-    , transformers-    , wai-    , wai-extra-    , wai-handler-launch >=1.3-    , warp-    , yaml-    , yesod >=1.4 && <1.7-    , yesod-core >=1.4 && <1.7-    , yesod-form >=1.4 && <1.7-    , yesod-static >=1.4 && <1.7-  if (flag(dev)) || (flag(library-only))-    cpp-options: -DDEVELOPMENT-  if flag(dev)-    ghc-options: -O0+  if impl(ghc >=8)+    ghc-options: -Wcompat -Wincomplete-uni-patterns -Wincomplete-record-updates -Wredundant-constraints   if flag(library-only)     buildable: False   if flag(threaded)     ghc-options: -threaded-  default-language: Haskell2010--test-suite test-  type: exitcode-stdio-1.0-  main-is: main.hs-  other-modules:-      HomeTest-      TestImport-      Paths_hledger_web-  hs-source-dirs:-      tests-  ghc-options: -Wall -fno-warn-unused-do-bind -fno-warn-name-shadowing -fno-warn-missing-signatures -fno-warn-type-defaults -fno-warn-orphans-  cpp-options: -DVERSION="1.9.2"-  build-depends:-      HUnit-    , base >=4.8 && <4.12-    , base-compat >=0.8.1-    , blaze-html-    , blaze-markup-    , bytestring-    , clientsession-    , cmdargs >=0.10-    , conduit-extra >=1.1-    , data-default-    , directory-    , filepath-    , hjsmin-    , hledger >=1.9.1 && <2.0-    , hledger-lib >=1.9.1 && <2.0-    , hledger-web-    , hspec-    , http-client-    , http-conduit-    , json-    , megaparsec >=5.0-    , mtl-    , parsec >=3-    , safe >=0.2-    , shakespeare >=2.0.2.2-    , template-haskell-    , text >=1.2-    , time >=1.5-    , transformers-    , wai-    , wai-extra-    , wai-handler-launch >=1.3-    , warp-    , yaml-    , yesod >=1.4 && <1.7-    , yesod-core >=1.4 && <1.7-    , yesod-form >=1.4 && <1.7-    , yesod-static >=1.4 && <1.7-    , yesod-test-  if (flag(dev)) || (flag(library-only))-    cpp-options: -DDEVELOPMENT-  if flag(dev)-    ghc-options: -O0   default-language: Haskell2010
hledger-web.info view
@@ -3,8 +3,8 @@  File: hledger-web.info,  Node: Top,  Next: OPTIONS,  Up: (dir) -hledger-web(1) hledger-web 1.9.1-********************************+hledger-web(1) hledger-web 1.9.99+*********************************  hledger-web is hledger's web interface.  It starts a simple web application for browsing and adding transactions, and optionally opens@@ -209,7 +209,7 @@  Tag Table: Node: Top72-Node: OPTIONS3156-Ref: #options3241+Node: OPTIONS3158+Ref: #options3243  End Tag Table
hledger-web.txt view
@@ -248,4 +248,4 @@   -hledger-web 1.9.1                 April 2018                    hledger-web(1)+hledger-web 1.9.99                 June 2018                    hledger-web(1)
− messages/en.msg
@@ -1,1 +0,0 @@-Hello: Hello
static/hledger.css view
@@ -20,38 +20,7 @@ /*------------------------------------------------------------------------------------------*/ /* 4. typeahead styles */ -/*-.typeahead,-.tt-query, .tt-hint {-  width: 396px;-  height: 30px;-  padding: 8px 12px;-  font-size: 24px;-  line-height: 30px;-  border: 2px solid #ccc;-  -webkit-border-radius: 8px;-     -moz-border-radius: 8px;-          border-radius: 8px;-  outline: none;-}--.typeahead {-  background-color: #fff;-}--.typeahead:focus {-  border: 2px solid #0097cf;-}--.tt-query {-  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);-     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);-          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);-}--*/-.tt-hint {   color: #bbb; } @@ -70,9 +39,6 @@   max-height:300px; } -.tt-suggestions {-}- .tt-suggestion {   padding: 3px 20px;   font-size: 18px;@@ -82,7 +48,6 @@ .tt-suggestion.tt-cursor {   color: #fff;   background-color: #0097cf;- }  .tt-suggestion p {@@ -100,7 +65,7 @@  ul {     list-style-type: none;-	  padding: 0;+    padding: 0; }  #main-content {@@ -136,51 +101,37 @@  #sidebar-menu .main-menu a {     display: inline;-	  font-size: 16px;-	  font-weight: 500;-	  color: #2F2F2F;-	  padding: 4px 20px;+    font-size: 16px;+    font-weight: 500;+    color: #2F2F2F;+    padding: 4px 20px; }  #sidebar-menu .main-menu a:hover {-	  color: #11427D;-	  text-decoration: none;-	  background-color: transparent;+    color: #11427D;+    text-decoration: none;+    background-color: transparent; } -#sidebar-menu .main-menu .only{+#sidebar-menu .main-menu .only {     visibility: hidden;     padding: 1px; } -#sidebar-menu .main-menu tr:hover > td > div > .only {+#sidebar-menu .main-menu tr:hover .only {     visibility: visible; } -#sidebar-menu .main-menu .only:hover{-    border-left: none;-}-#sidebar-menu .main-menu .balance {-    float: right;-}--#sidebar-menu .main-menu .total {-    border-left: none;-    border-right: none;-    border-bottom: none;-    border-top: 1px solid black;-}--#sidebar-menu .main-menu .inacct {+#sidebar-menu .main-menu .inacct, #sidebar-menu .main-menu .inacct .acct-name {     font-weight: bold;-	  color: #11427D;+    color: #11427D;     background-color: #f9f9f9; }  #sidebar-menu .main-menu .amount {     float: right;     overflow-x:auto;-	  font-weight: 500 !important;+    font-weight: 500 !important; }  #sidebar-menu .main-menu .acct {@@ -188,7 +139,7 @@     vertical-align:bottom; } -.transactionsreport .nonhead {+.transactionsreport .posting td {     border: none !important; } @@ -200,24 +151,6 @@     whitespace: nowrap; } -#main-content {-   /*-    -webkit-transition: width 0.3s ease, margin 0.3s ease;-    -moz-transition: width 0.3s ease, margin 0.3s ease;-    -o-transition: width 0.3s ease, margin 0.3s ease;-    transition: width 0.3s ease, margin 0.3s ease;-*/-}--#sidebar-menu {-    /*-    -webkit-transition: width 0.3s ease, margin 0.3s ease,opacity 0.3s ease,height 1s ease 1s;-    -moz-transition: width 0.3s ease, margin 0.3s ease,opacity 0.3s ease,height 1s ease 1s;-    -o-transition: width 0.3s ease, margin 0.3s ease,opacity 0.3s ease,height 1s ease 1s;-    transition: width 0.3s ease, margin 0.3s ease,opacity 0.3s ease,height 1s ease 1s;-*/-}- .col-any-0 {     width:0 !important;     height:0 !important;@@ -227,10 +160,6 @@  .tgl-icon {     font-size:large;-}--#searchbar {-    width: 100% !important; }  @media screen and (max-width: 768px) {
static/hledger.js view
@@ -4,9 +4,13 @@ // STARTUP  $(document).ready(function() {-  // cache the input element as a variable-  // for minor performance   benefits-  var dateEl = $('#dateWrap');+  // date picker+  // http://bootstrap-datepicker.readthedocs.io/en/latest/options.html+  var dateEl = $('#dateWrap').datepicker({+    showOnFocus: false,+    autoclose: true,+    format: 'yyyy-mm-dd'+  });;    // ensure add form always focuses its first field   $('#addmodal')@@ -18,36 +22,22 @@       dateEl.datepicker('hide');     }); -  // show add form if ?add=1-  if ($.url.param('add')) { addformShow(true); }--  // date picker-  // http://bootstrap-datepicker.readthedocs.io/en/latest/options.html-  dateEl.datepicker({-    showOnFocus: false,-    autoclose: true,-    format: 'yyyy-mm-dd'-  });--  // sidebar account hover handlers-  $('#sidebar td a').mouseenter(function(){ $(this).parent().addClass('mouseover'); });-  $('#sidebar td').mouseleave(function(){ $(this).removeClass('mouseover'); });-   // keyboard shortcuts   // 'body' seems to hold focus better than document in FF   $('body').bind('keydown', 'h',       function(){ $('#helpmodal').modal('toggle'); return false; });   $('body').bind('keydown', 'shift+/', function(){ $('#helpmodal').modal('toggle'); return false; });   $('body').bind('keydown', 'j',       function(){ location.href = document.hledgerWebBaseurl+'/journal'; return false; });   $('body').bind('keydown', 's',       function(){ sidebarToggle(); return false; });+  $('body').bind('keydown', 'e',       function(){ emptyAccountsToggle(); return false; });   $('body').bind('keydown', 'a',       function(){ addformShow(); return false; });   $('body').bind('keydown', 'n',       function(){ addformShow(); return false; });   $('body').bind('keydown', 'f',       function(){ $('#searchform input').focus(); return false; });+  $('body, #addform input, #addform select').bind('keydown', 'ctrl++',       addformAddPosting);   $('body, #addform input, #addform select').bind('keydown', 'ctrl+shift+=', addformAddPosting);   $('body, #addform input, #addform select').bind('keydown', 'ctrl+=',       addformAddPosting);   $('body, #addform input, #addform select').bind('keydown', 'ctrl+-',       addformDeletePosting);   $('.amount-input:last').keypress(addformAddPosting); -   // highlight the entry from the url hash   if (window.location.hash && $(window.location.hash)[0]) {     $(window.location.hash).addClass('highlighted');@@ -78,10 +68,9 @@         position: 'sw'       },       grid: {-        markings:-         function (axes) {+        markings: function () {           var now = Date.now();-          var markings = [+          return [             {               xaxis: { to: now }, // past               yaxis: { to: 0 },   // <0@@ -103,7 +92,6 @@               lineWidth:1             },           ];-          return markings;         },         hoverable: true,         autoHighlight: true,@@ -127,16 +115,17 @@ }  function registerChartClick(ev, pos, item) {-  if (item) {-    targetselector = '#'+item.series.data[item.dataIndex][5];-    $target = $(targetselector);-    if ($target.length) {-      window.location.hash = targetselector;-      $('html, body').animate({-        scrollTop: $target.offset().top-      }, 1000);-    }+  if (!item) {+    return;   }+  var targetselector = '#' + item.series.data[item.dataIndex][5];+  var $target = $(targetselector);+  if ($target.length) {+    window.location.hash = targetselector;+    $('html, body').animate({+      scrollTop: $target.offset().top+    }, 1000);+  } }  //----------------------------------------------------------------------@@ -174,59 +163,46 @@  // Insert another posting row in the add form. function addformAddPosting() {-  $('.amount-input:last').off('keypress');-  // do nothing if it's not currently visible-  if (!$('#addform').is(':visible')) return;-  // save a copy of last row-  var lastrow = $('#addform .form-group:last').clone();+  if (!$('#addform').is(':visible')) {+    return;+  } -  // replace the submit button with an amount field, clear and renumber it, add the keybindings-  var num = $('#addform .account-group').length;+  var prevLastRow = $('#addform .account-group:last');+  prevLastRow.off('keypress'); -  // insert the new last row-  $('#addform .account-postings').append(lastrow);-  // TODO: Enable typehead on dynamically created inputs+  // Clone the currently last row+  $('#addform .account-postings').append(prevLastRow.clone());+  var num = $('#addform .account-group').length; -  var $acctinput = $('.account-input:last');-  var $amntinput = $('.amount-input:last');   // clear and renumber the field, add keybindings-  $acctinput-    .val('')-    .prop('id','account'+(num+1))-    .prop('name','account'+(num+1))-    .prop('placeholder','Account '+(num+1));-  //lastrow.find('input') // not :last this time-  $acctinput-    .bind('keydown', 'ctrl+shift+=', addformAddPosting)-    .bind('keydown', 'ctrl+=', addformAddPosting)-    .bind('keydown', 'ctrl+-', addformDeletePosting);--  $amntinput+  // XXX Enable typehead on dynamically created inputs+  $('.amount-input:last')     .val('')-    .prop('id','amount'+(num+1))-    .prop('name','amount'+(num+1))-    .prop('placeholder','Amount '+(num+1))+    .prop('placeholder','Amount ' + num)     .keypress(addformAddPosting); -  $acctinput+  $('.account-input:last')+    .val('')+    .prop('placeholder', 'Account ' + num)+    .bind('keydown', 'ctrl++', addformAddPosting)     .bind('keydown', 'ctrl+shift+=', addformAddPosting)     .bind('keydown', 'ctrl+=', addformAddPosting)     .bind('keydown', 'ctrl+-', addformDeletePosting);- }  // Remove the add form's last posting row, if empty, keeping at least two. function addformDeletePosting() {-  var num = $('#addform .account-group').length;-  if (num <= 2) return;+  if ($('#addform .account-group').length <= 2) {+    return;+  }   // remember if the last row's field or button had focus   var focuslost =     $('.account-input:last').is(':focus')     || $('.amount-input:last').is(':focus');   // delete last row   $('#addform .account-group:last').remove();-  if(focuslost){-    focus($('account-input:last'));+  if (focuslost) {+    focus($('.account-input:last'));   }   // Rebind keypress   $('.amount-input:last').keypress(addformAddPosting);@@ -242,46 +218,7 @@   $.cookie('showsidebar', $('#sidebar-menu').hasClass('col-any-0') ? '0' : '1'); } -//-----------------------------------------------------------------------// MISC--function enableTypeahead($el, suggester) {-  return $el.typeahead(-    {-      highlight: true-    },-    {-      source: suggester.ttAdapter()-    }-  );+function emptyAccountsToggle() {+  $('.acct.empty').parent().toggleClass('hide');+  $.cookie('hideemptyaccts', $.cookie('hideemptyaccts') === '1' ? '0' : '1') }--// function journalSelect(ev) {-//   var textareas = $('textarea', $('form#editform'));-//   for (i=0; i<textareas.length; i++) {-//     textareas[i].style.display = 'none';-//     textareas[i].disabled = true;-//   }-//   var targ = getTarget(ev);-//   if (targ.value) {-//     var journalid = targ.value+'_textarea';-//     var textarea = document.getElementById(journalid);-//   }-//   else {-//     var textarea = textareas[0];-//   }-//   textarea.style.display = 'block';-//   textarea.disabled = false;-//   return true;-// }--// // Get the current event's target in a robust way.-// // http://www.quirksmode.org/js/events_properties.html-// function getTarget(ev) {-//   var targ;-//   if (!ev) var ev = window.event;-//   if (ev.target) targ = ev.target;-//   else if (ev.srcElement) targ = ev.srcElement;-//   if (targ.nodeType == 3) targ = targ.parentNode;-//   return targ;-// }
+ templates/add-form.hamlet view
@@ -0,0 +1,71 @@+<script>+  jQuery(document).ready(function() {+    descriptionsSuggester = new Bloodhound({+      local:#{listToJsonValueObjArrayStr descriptions},+      limit:100,+      datumTokenizer: function(d) { return [d.value]; },+      queryTokenizer: function(q) { return [q]; }+    });+    descriptionsSuggester.initialize();++    accountsSuggester = new Bloodhound({+      local:#{listToJsonValueObjArrayStr (journalAccountNamesDeclaredOrImplied j)},+      limit:100,+      datumTokenizer: function(d) { return [d.value]; },+      queryTokenizer: function(q) { return [q]; }+    });+    accountsSuggester.initialize();++    jQuery('input[name=description]').typeahead({ highlight: true }, { source: descriptionsSuggester.ttAdapter() });+    jQuery('input[name=account]').typeahead({ highlight: true }, { source: accountsSuggester.ttAdapter() });+  });+^{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 .account-postings>+  $forall (n, (acc, amt, accE, amtE)) <- msgs+    <div .form-group .row .account-group>+      <div .col-md-8 .col-xs-8 .col-sm-8 :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>+        <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;">+  Enter a value in the last field for #+  <a href="#" onclick="addformAddPosting(); return false;">+    more+  \ (or ctrl +, ctrl -)
+ templates/balance-report.hamlet view
@@ -0,0 +1,25 @@+<tr :here == journalR:.inacct>+  <td .top .acct>+    <a href=@{journalR} :here == journalR:.inacct+       title="Show general journal entries, most recent first">+      Journal+  <td .top>+$forall (acct, adisplay, aindent, abal) <- items+  <tr+     :matchesAcctSelector acct:.inacct+     :isZeroMixedAmount abal && hideEmpty:.hide>+    <td .acct :isZeroMixedAmount abal:.empty>+      <div .ff-wrapper>+        \#{indent aindent}+        <a.acct-name href="@?{(registerR, [("q", accountQuery acct)])}"+           title="Show transactions affecting this account and subaccounts">+          #{adisplay}+        $if hasSubAccounts acct+          <a href="@?{(registerR, [("q", accountOnlyQuery acct)])}" .only.hidden-sm.hidden-xs+             title="Show transactions affecting this account but not subaccounts">only+    <td>+      ^{mixedAmountAsHtml abal}+<tr .total>+  <td>+  <td>+    ^{mixedAmountAsHtml total}
+ templates/chart.hamlet view
@@ -0,0 +1,59 @@+<label #register-chart-label style=""><br>+<div #register-chart style="height:150px; margin-bottom:1em; display:block;">+<script type=text/javascript>+ \$(document).ready(function() {+   var $chartdiv = $('#register-chart');+   if ($chartdiv.is(':visible')) {+     \$('#register-chart-label').text('#{charttitle}');+     var seriesData = [+      $forall (c,(_,items)) <- percommoditytxnreports+       /* we render each commodity using two series:+        * one with extra data points added to show a stepped balance line */+       {+        data: [+          $forall i <- reverse items+           [+            #{dayToJsTimestamp $ triDate i},+            #{simpleMixedAmountQuantity $ triCommodityBalance c i}+           ],+        ],+        label: '#{shownull $ T.unpack c}',+        color: #{colorForCommodity c},+        lines: {+          show: true,+          steps: true,+        },+        points: {+          show: false,+        },+        clickable: false,+        hoverable: false,+       },+       /* and one with the original data, showing one clickable, hoverable point per transaction */+       {+        data: [+          $forall i <- reverse items+           [+            #{dayToJsTimestamp $ triDate i},+            #{simpleMixedAmountQuantity $ triCommodityBalance c i},+            '#{showMixedAmountWithZeroCommodity $ triCommodityAmount c i}',+            '#{showMixedAmountWithZeroCommodity $ triCommodityBalance c i}',+            '#{concat $ intersperse "\\n" $ lines  $ show $ triOrigTransaction i}',+            #{tindex $ triOrigTransaction i}+           ],+          /* [] */+        ],+        label: '',+        color: #{colorForCommodity c},+        lines: {+          show: false,+        },+        points: {+          show: true,+        },+       },+     ]+     var plot = registerChart($chartdiv, seriesData);+     \$chartdiv.bind("plotclick", registerChartClick);+   };+ });
templates/default-layout-wrapper.hamlet view
@@ -29,7 +29,7 @@             <div .row .row-offcanvas .row-offcanvas-left>               ^{pageBody pc}             <footer>-                #{extraCopyright $ appExtra $ settings master}+              #{extraCopyright $ appExtra $ settings master}          $maybe analytics <- extraAnalytics $ appExtra $ settings master             <script>@@ -47,61 +47,3 @@             <script>                 window.attachEvent('onload',function(){CFInstall.check({mode:'overlay'})})         \<![endif]-->--        <div .modal.fade #helpmodal tabindex="-1" role="dialog" aria-labelledby="helpLabel" aria-hidden="true">-          <div .modal-dialog .modal-lg>-            <div .modal-content>-              <div .modal-header>-                <button type="button" .close data-dismiss="modal" aria-hidden="true">&times;-                <h3 .modal-title #helpLabel>Help-              <div .modal-body>-                <div .row>-                  <div .col-xs-6>-                    <p>-                      <b>Keyboard shortcuts-                      <ul>-                        <li> <code>h</code> or maybe <code>?</code> - view this help (escape or click to exit)-                        <li> <code>j</code> - go to the Journal view (home)-                        <li> <code>a</code> - add a transaction (escape to cancel)-                        <li> <code>s</code> - toggle sidebar-                        <li> <code>f</code> - focus search form ("find")-                    <p>-                      <b>General-                      <ul>-                        <li> The Journal view shows general journal entries, representing zero-sum movements of money (or other commodity) between hierarchical accounts-                        <li> The sidebar shows the resulting accounts and their final balances-                        <li> Parent account balances include subaccount balances-                        <li> Multiple currencies in balances are displayed one above the other-                        <li> Click account name links to see transactions affecting that account, with running balance-                        <li> Click date links to see journal entries on that date-                  <div .col-xs-6>-                    <p>-                      <b>Search-                      <ul>-                        <li> <code>acct:REGEXP</code> - filter on to/from account-                        <li> <code>desc:REGEXP</code> - filter on description-                        <li> <code>date:PERIODEXP</code>, <code>date2:PERIODEXP</code> - filter on date or secondary date-                        <li> <code>code:REGEXP</code> - filter on transaction's code (eg check number)-                        <li> <code>status:*</code>, <code>status:!</code>, <code>status:</code> - filter on transaction's cleared status (cleared, pending, uncleared)-                        <!-- <li> <code>empty:BOOL</code> - filter on whether amount is zero -->-                        <li> <code>amt:N</code>, <code>amt:&lt;N</code>, <code>amt:&gt;N</code> - filter on the unsigned amount magnitude. Or with a sign before N, filter on the signed value. (Single-commodity amounts only.)-                        <li> <code>cur:REGEXP</code> - filter on the currency/commodity symbol (must match all of it). Dollar sign must be written as <code>\$</code>-                        <li> <code>tag:NAME</code>, <code>tag:NAME=REGEX</code> - filter on tag name, or tag name and value-                        <!-- <li> <code>depth:N</code> - filter out accounts below this depth -->-                        <li> <code>real:BOOL</code> - filter on postings' real/virtual-ness-                        <li> Enclose search patterns containing spaces in single or double quotes-                        <li> Prepend <code>not:</code> to negate a search term-                        <li> Multiple search terms on different fields are AND'ed, multiple search terms on the same field are OR'ed-                        <li> These search terms also work with command-line hledger--        <div .modal #addmodal tabindex="-1" role="dialog" aria-labelledby="addLabel" aria-hidden="true">-          <div .modal-dialog .modal-lg>-            <div .modal-content>-              <div .modal-header>-                <button type="button" .close data-dismiss="modal" aria-hidden="true">&times;-                <h3 .modal-title #addLabel>Add a transaction-              <div .modal-body>-                $maybe m <- lastmsg-                  $if isPrefixOf "Errors" (renderHtml m)-                    <div #message>#{m}-                ^{addform staticRootUrl vd}
templates/default-layout.hamlet view
@@ -1,4 +1,81 @@-$maybe m <- lastmsg-  $if not $ isPrefixOf "Errors" (renderHtml m)-    <div #message>#{m}-^{widget}++<div#spacer .col-xs-2.#{topShowsm}.#{topShowmd}>+  <h1>+    <button .visible-xs.btn.btn-default type="button" data-toggle="offcanvas">+      <span .glyphicon.glyphicon-align-left.tgl-icon>++<div#topbar .col-md-8 .col-sm-8 .col-xs-10>+  <h1>#{takeFileName (journalFilePath j)}++$if elem CapView caps+  <div#sidebar-menu .sidebar-offcanvas.#{sideShowmd}.#{sideShowsm}>+    <table .main-menu .table>+      ^{accounts}++<div#main-content .col-xs-12.#{mainShowmd}.#{mainShowsm}>+  $maybe m <- msg+    <div #message .alert.alert-info>#{m}+  $if elem CapView caps+    <form#searchform.input-group method=GET>+      <input .form-control name=q value=#{q} placeholder="Search"+        title="Enter hledger search patterns to filter the data below">+      <div .input-group-btn>+        $if not (T.null q)+          <a href=@{here} .btn .btn-default title="Clear search terms">+            <span .glyphicon .glyphicon-remove-circle>+        <button .btn .btn-default type=submit title="Apply search terms">+          <span .glyphicon .glyphicon-search>+        $if elem CapManage caps+          <a href="@{ManageR}" .btn.btn-default title="Manage journal files">+            <span .glyphicon .glyphicon-wrench>+        <button .btn .btn-default type=button data-toggle="modal" data-target="#helpmodal"+           title="Show search and general help">+          <span .glyphicon .glyphicon-question-sign>+  ^{widget}++<div .modal.fade #helpmodal tabindex="-1" role="dialog" aria-labelledby="helpLabel" aria-hidden="true">+  <div .modal-dialog .modal-lg>+    <div .modal-content>+      <div .modal-header>+        <button type="button" .close data-dismiss="modal" aria-hidden="true">&times;+        <h3 .modal-title #helpLabel>Help+      <div .modal-body>+        <div .row>+          <div .col-xs-6>+            <p>+              <b>Keyboard shortcuts+              <ul>+                <li> <code>h</code> or maybe <code>?</code> - view this help (escape or click to exit)+                <li> <code>j</code> - go to the Journal view (home)+                <li> <code>a</code> - add a transaction (escape to cancel)+                <li> <code>s</code> - toggle sidebar+                <li> <code>f</code> - focus search form ("find")+                <li> <code>e</code> - hide empty accounts in sidebar+            <p>+              <b>General+              <ul>+                <li> The Journal view shows general journal entries, representing zero-sum movements of money (or other commodity) between hierarchical accounts+                <li> The sidebar shows the resulting accounts and their final balances+                <li> Parent account balances include subaccount balances+                <li> Multiple currencies in balances are displayed one above the other+                <li> Click account name links to see transactions affecting that account, with running balance+                <li> Click date links to see journal entries on that date+          <div .col-xs-6>+            <p>+              <b>Search+              <ul>+                <li> <code>acct:REGEXP</code> - filter on to/from account+                <li> <code>desc:REGEXP</code> - filter on description+                <li> <code>date:PERIODEXP</code>, <code>date2:PERIODEXP</code> - filter on date or secondary date+                <li> <code>code:REGEXP</code> - filter on transaction's code (eg check number)+                <li> <code>status:*</code>, <code>status:!</code>, <code>status:</code> - filter on transaction's cleared status (cleared, pending, uncleared)+                <!-- <li> <code>empty:BOOL</code> - filter on whether amount is zero -->+                <li> <code>amt:N</code>, <code>amt:&lt;N</code>, <code>amt:&gt;N</code> - filter on the unsigned amount magnitude. Or with a sign before N, filter on the signed value. (Single-commodity amounts only.)+                <li> <code>cur:REGEXP</code> - filter on the currency/commodity symbol (must match all of it). Dollar sign must be written as <code>\$</code>+                <li> <code>tag:NAME</code>, <code>tag:NAME=REGEX</code> - filter on tag name, or tag name and value+                <!-- <li> <code>depth:N</code> - filter out accounts below this depth -->+                <li> <code>real:BOOL</code> - filter on postings' real/virtual-ness+                <li> Enclose search patterns containing spaces in single or double quotes+                <li> Prepend <code>not:</code> to negate a search term+                <li> Multiple search terms on different fields are AND'ed, multiple search terms on the same field are OR'ed+                <li> These search terms also work with command-line hledger
+ templates/edit-form.hamlet view
@@ -0,0 +1,17 @@+#{extra}+<h2>+  Edit file #+  <i>#{f}+<div.alert.alert-danger>+  Are you sure? This will overwrite your journal!+<table.table.table-condensed>+  <tr>+    <td colspan=2 style="border:0">+      ^{fvInput tView}+  <tr>+    <td style="border:0">+      <span.help>+        ^{helplink "file-format" "File format help"}+    <td .text-right style="border:0">+      <a.btn.btn-default href="@{ManageR}">Go back+      <input.btn.btn-default type=submit value="Save">
+ templates/journal.hamlet view
@@ -0,0 +1,39 @@+<h2>+  #{title'}++$if elem CapAdd caps+  <a #addformlink href="#" role="button" style="cursor:pointer; margin-top:1em;"+     data-toggle="modal" data-target="#addmodal" title="Add a new transaction to the journal">+    Add a transaction++<div .table-responsive>+  <table .transactionsreport .table .table-condensed>+    <thead>+      <th .date style="text-align:left;">Date+      <th .description style="text-align:left;">Description+      <th .account style="text-align:left;">Account+      <th .amount style="text-align:right;">Amount++    $forall (torig, _, split, _, amt, _) <- items+      <tr .title #transaction-#{tindex torig}>+        <td .date nowrap>+          #{show (tdate torig)}+        <td colspan=2>+          #{textElideRight 60 (tdescription torig)}+        <td .amount style="text-align:right;">+          $if not split && not (isZeroMixedAmount amt)+            ^{mixedAmountAsHtml amt}++      $forall Posting { paccount = acc, pamount = amt } <- tpostings torig+        <tr .posting title="#{show torig}">+          <td>+          <td>+          <td>+            &nbsp;+            <a href="@?{acctlink acc}##{tindex torig}" title="#{acc}">+              #{elideAccountName 40 acc}+          <td .amount style="text-align:right;">+            ^{mixedAmountAsHtml amt}++$if elem CapAdd caps+  ^{addModal AddR j today}
+ templates/manage.hamlet view
@@ -0,0 +1,22 @@+<h2>+  Your journal's files++<div.row>+  <div .col-xs-12.col-sm-8.col-md-6>+    <table .table.table-condensed>+      <thead>+        <th>+          File+        <th>+      <tbody>+        $forall (path, _) <- jfiles j+          <tr>+            <td style="vertical-align:middle">+              #{path}+            <td style="text-align:right">+              <a.btn.btn-default href=@{EditR path}>+                Edit+              <a.btn.btn-default href=@{UploadR path}>+                Upload+              <a.btn.btn-default href=@{DownloadR path}>+                Download
+ templates/register.hamlet view
@@ -0,0 +1,37 @@+<h2>+  #{header}++<div .hidden-xs>+  ^{registerChartHtml $ transactionsReportByCommodity r}++<div.table-responsive>+  <table .table.table-striped.table-condensed>+    <thead>+      <tr>+        <th style="text-align:left;">+          Date+          <span .glyphicon.glyphicon-chevron-up>+        <th style="text-align:left;">Description+        <th style="text-align:left;">To/From Account(s)+        <th style="text-align:right; white-space:normal;">Amount Out/In+        <th style="text-align:right; white-space:normal;">+          #{balancelabel'}++    <tbody>+      $forall (torig, tacct, split, acct, amt, bal) <- items+        <tr ##{tindex torig} title="#{show torig}" style="vertical-align:top;">+          <td .date>+            <a href="@{JournalR}#transaction-#{tindex torig}">+              #{show (tdate tacct)}+          <td title="#{show torig}">+            #{textElideRight 30 (tdescription tacct)}+          <td .account>+            #{elideRight 40 acct}+          <td .amount style="text-align:right; white-space:nowrap;">+            $if not split || not (isZeroMixedAmount amt)+              ^{mixedAmountAsHtml amt}+          <td style="text-align:right;">+            ^{mixedAmountAsHtml bal}++$if elem CapAdd caps+  ^{addModal AddR j today}
+ templates/upload-form.hamlet view
@@ -0,0 +1,14 @@+<h2>+  Upload to file #+  <i>#{f}+<div.alert.alert-danger>+  Are you sure? This will overwrite your journal!+<div.form-group>+  <label .btn.btn-primary for="file">+    <input type=file id=file name=file style="display:none"+      onchange="\$('#file-info').html(this.files[0].name)" />+    Select file+  <span .label.label-info id="file-info">+<div.form-group>+  <input .btn.btn-default type=submit value="Upload">+#{extra}
− tests/HomeTest.hs
@@ -1,25 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-module HomeTest-    ( homeSpecs-    ) where--import TestImport--homeSpecs :: Specs-homeSpecs =-  ydescribe "Some hledger-web tests" $--    yit "serves a reasonable-looking register page" $ do-      get RegisterR-      statusIs 200-      bodyContains "accounts"--      -- post "/" $ do-      --   addNonce-      --   fileByLabel "Choose a file" "tests/main.hs" "text/plain" -- talk about self-reference-      --   byLabel "What's on the file?" "Some Content"--      -- statusIs 200-      -- htmlCount ".message" 1-      -- htmlAllContain ".message" "Some Content"-      -- htmlAllContain ".message" "text/plain"
− tests/TestImport.hs
@@ -1,12 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-module TestImport-    ( module Yesod.Test-    , module Foundation-    , Specs-    ) where--import Yesod.Test--import Foundation--type Specs = YesodSpec App
− tests/main.hs
@@ -1,24 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--module Main where--import Import-import Yesod.Default.Config-import Yesod.Test-import Test.Hspec (hspec)-import Application (makeFoundation)-import Hledger.Web.WebOptions (defwebopts)--import HomeTest--main :: IO ()-main = do-    conf <- Yesod.Default.Config.loadConfig $ (configSettings Testing)-                    { csParseExtra = parseExtra-                    }-    foundation <- makeFoundation conf defwebopts-    hspec $ do-      yesodSpec foundation $ do-        homeSpecs