web: code cleanup, better web ui supporting full patterns & period expressions
New dependency: http.
This commit is contained in:
parent
4517cab686
commit
71e7f2b293
116
WebCommand.hs
116
WebCommand.hs
@ -20,6 +20,7 @@ import Happstack.State.Control (waitForTermination)
|
|||||||
import System.Cmd (system)
|
import System.Cmd (system)
|
||||||
import System.Info (os)
|
import System.Info (os)
|
||||||
import System.Exit
|
import System.Exit
|
||||||
|
import Network.HTTP (urlEncode, urlDecode, urlEncodeVars)
|
||||||
|
|
||||||
import Ledger
|
import Ledger
|
||||||
import Options
|
import Options
|
||||||
@ -27,72 +28,87 @@ import BalanceCommand
|
|||||||
import RegisterCommand
|
import RegisterCommand
|
||||||
import PrintCommand
|
import PrintCommand
|
||||||
import HistogramCommand
|
import HistogramCommand
|
||||||
|
import Utils (filterAndCacheLedgerWithOpts)
|
||||||
|
|
||||||
|
|
||||||
tcpport = 5000
|
tcpport = 5000
|
||||||
|
|
||||||
web :: [Opt] -> [String] -> Ledger -> IO ()
|
web :: [Opt] -> [String] -> Ledger -> IO ()
|
||||||
web opts args l =
|
web opts args l = do
|
||||||
|
t <- getCurrentLocalTime -- how to get this per request ?
|
||||||
if Debug `elem` opts
|
if Debug `elem` opts
|
||||||
then do
|
then do
|
||||||
putStrLn $ printf "starting web server on port %d in debug mode" tcpport
|
-- just run the server in the foreground
|
||||||
simpleHTTP nullConf{port=tcpport} handlers
|
putStrLn $ printf "starting web server on port %d in debug mode" tcpport
|
||||||
else do
|
simpleHTTP nullConf{port=tcpport} $ webHandlers opts args l t
|
||||||
putStrLn $ printf "starting web server on port %d" tcpport
|
else do
|
||||||
tid <- forkIO $ simpleHTTP nullConf{port=tcpport} handlers
|
-- start the server (in background, so we can..) then start the web browser
|
||||||
putStrLn "starting web browser"
|
putStrLn $ printf "starting web server on port %d" tcpport
|
||||||
openBrowserOn $ printf "http://localhost:%d/balance" tcpport
|
tid <- forkIO $ simpleHTTP nullConf{port=tcpport} $ webHandlers opts args l t
|
||||||
waitForTermination
|
putStrLn "starting web browser"
|
||||||
putStrLn "shutting down web server..."
|
openBrowserOn $ printf "http://localhost:%d/" tcpport
|
||||||
killThread tid
|
waitForTermination
|
||||||
putStrLn "shutdown complete"
|
putStrLn "shutting down web server..."
|
||||||
|
killThread tid
|
||||||
|
putStrLn "shutdown complete"
|
||||||
|
|
||||||
where
|
webHandlers :: [Opt] -> [String] -> Ledger -> LocalTime -> ServerPartT IO Response
|
||||||
handlers :: ServerPartT IO Response
|
webHandlers opts args l t = msum
|
||||||
handlers = msum
|
[
|
||||||
[methodSP GET $ withDataFn (look "a") $ \a -> templatise $ balancereport [a]
|
methodSP GET $ view showBalanceReport
|
||||||
,methodSP GET $ templatise $ balancereport []
|
,dir "balance" $ view showBalanceReport
|
||||||
,dir "print" $ withDataFn (look "a") $ \a -> templatise $ printreport [a]
|
,dir "register" $ view showRegisterReport
|
||||||
,dir "print" $ templatise $ printreport []
|
,dir "print" $ view showLedgerTransactions
|
||||||
,dir "register" $ withDataFn (look "a") $ \a -> templatise $ registerreport [a]
|
,dir "histogram" $ view showHistogram
|
||||||
,dir "register" $ templatise $ registerreport []
|
]
|
||||||
,dir "balance" $ withDataFn (look "a") $ \a -> templatise $ balancereport [a]
|
where
|
||||||
,dir "balance" $ templatise $ balancereport []
|
view f = withDataFn rqdata $ render f
|
||||||
,dir "histogram" $ withDataFn (look "a") $ \a -> templatise $ histogramreport [a]
|
render f (a,p) = layout (a, p) $ f opts' args' l'
|
||||||
,dir "histogram" $ templatise $ histogramreport []
|
where
|
||||||
]
|
opts' = opts ++ [Period p]
|
||||||
printreport apats = showLedgerTransactions opts (apats ++ args) l
|
args' = args ++ (map urlDecode $ words a)
|
||||||
registerreport apats = showRegisterReport opts (apats ++ args) l
|
-- re-filter the full ledger
|
||||||
balancereport [] = showBalanceReport opts args l
|
l' = filterAndCacheLedgerWithOpts opts' args' t (rawledgertext l) (rawledger l)
|
||||||
balancereport apats = showBalanceReport opts (apats ++ args) l'
|
|
||||||
where l' = cacheLedger apats (rawledger l) -- re-filter by account pattern each time
|
|
||||||
histogramreport [] = showHistogram opts args l
|
|
||||||
histogramreport apats = showHistogram opts (apats ++ args) l'
|
|
||||||
where l' = cacheLedger apats (rawledger l) -- re-filter by account pattern each time
|
|
||||||
|
|
||||||
templatise :: String -> ServerPartT IO Response
|
rqdata = do
|
||||||
templatise s = do
|
a <- look "a" `mplus` return "" -- filter patterns
|
||||||
|
p <- look "p" `mplus` return "" -- reporting period
|
||||||
|
return (a,p)
|
||||||
|
|
||||||
|
layout :: (String, String) -> String -> ServerPartT IO Response
|
||||||
|
layout (a,p) s = do
|
||||||
r <- askRq
|
r <- askRq
|
||||||
return $ setHeader "Content-Type" "text/html" $ toResponse $ maintemplate r s
|
return $ setHeader "Content-Type" "text/html" $ toResponse $ maintemplate (a,p) r s
|
||||||
|
|
||||||
maintemplate :: Request -> String -> String
|
maintemplate :: (String, String) -> Request -> String -> String
|
||||||
maintemplate r = printf (unlines
|
maintemplate (a,p) r = printf (unlines
|
||||||
["<div style=float:right>"
|
["<div style=\"float:right;text-align:right;\">"
|
||||||
,"<form action=%s>search: <input name=a value=%s></form>"
|
,"<form action=%s>"
|
||||||
|
," filter by: <input name=a size=30 value=\"%s\">"
|
||||||
|
," reporting period: <input name=p size=30 value=\"%s\">"
|
||||||
|
,resetlink
|
||||||
|
,"</form>"
|
||||||
,"</div>"
|
,"</div>"
|
||||||
,"<div align=center style=width:100%%>"
|
,"<div style=\"width:100%%; font-weight:bold;\">"
|
||||||
," <a href=balance>balance</a>"
|
," <a href=balance%s>balance</a>"
|
||||||
,"|"
|
,"|"
|
||||||
," <a href=register>register</a>"
|
," <a href=register%s>register</a>"
|
||||||
,"|"
|
,"|"
|
||||||
," <a href=print>print</a>"
|
," <a href=print%s>print</a>"
|
||||||
,"|"
|
,"|"
|
||||||
," <a href=histogram>histogram</a>"
|
," <a href=histogram%s>histogram</a>"
|
||||||
,"</div>"
|
,"</div>"
|
||||||
,"<pre>%s</pre>"
|
,"<pre>%s</pre>"
|
||||||
])
|
]) u a p q q q q
|
||||||
(dropWhile (=='/') $ rqUri r)
|
where
|
||||||
(fromMaybe "" $ queryValue "a" r)
|
u = dropWhile (=='/') $ rqUri r
|
||||||
|
-- another way to get them
|
||||||
|
-- a = fromMaybe "" $ queryValue "a" r
|
||||||
|
-- p = fromMaybe "" $ queryValue "p" r
|
||||||
|
q' = intercalate "&" $ if null a then [] else [(("a="++).urlEncode) a] ++ if null p then [] else [(("p="++).urlEncode) p]
|
||||||
|
q = if null q' then "" else '?':q'
|
||||||
|
resetlink | null a && null p = ""
|
||||||
|
| otherwise = printf " <a href=%s>reset</a>" u
|
||||||
|
|
||||||
queryValues :: String -> Request -> [String]
|
queryValues :: String -> Request -> [String]
|
||||||
queryValues q r = map (B.unpack . inputValue . snd) $ filter ((==q).fst) $ rqInputs r
|
queryValues q r = map (B.unpack . inputValue . snd) $ filter ((==q).fst) $ rqInputs r
|
||||||
|
|||||||
@ -53,7 +53,7 @@ Executable hledger
|
|||||||
Build-Depends: base, containers, haskell98, directory, parsec,
|
Build-Depends: base, containers, haskell98, directory, parsec,
|
||||||
regex-compat, regexpr>=0.5.1, old-locale, time,
|
regex-compat, regexpr>=0.5.1, old-locale, time,
|
||||||
HUnit, mtl, bytestring, filepath, process, testpack,
|
HUnit, mtl, bytestring, filepath, process, testpack,
|
||||||
regex-pcre, csv, split, utf8-string
|
regex-pcre, csv, split, utf8-string, http
|
||||||
|
|
||||||
Other-Modules:
|
Other-Modules:
|
||||||
AddCommand
|
AddCommand
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user