web: cleanup, enable jquery, use auto-completing combo fields on add form
This commit is contained in:
parent
f3ffef2d8a
commit
8c8395778c
@ -12,6 +12,7 @@ import System.FilePath ((</>), takeFileName)
|
|||||||
import System.IO.Storage (withStore, putValue, getValue)
|
import System.IO.Storage (withStore, putValue, getValue)
|
||||||
import Text.ParserCombinators.Parsec (parse)
|
import Text.ParserCombinators.Parsec (parse)
|
||||||
import Yesod
|
import Yesod
|
||||||
|
import Yesod.Helpers.Static
|
||||||
|
|
||||||
import Hledger.Cli.Commands.Add (journalAddTransaction)
|
import Hledger.Cli.Commands.Add (journalAddTransaction)
|
||||||
import Hledger.Cli.Commands.Balance
|
import Hledger.Cli.Commands.Balance
|
||||||
@ -28,36 +29,43 @@ import Paths_hledger_make (getDataFileName)
|
|||||||
#else
|
#else
|
||||||
import Paths_hledger (getDataFileName)
|
import Paths_hledger (getDataFileName)
|
||||||
#endif
|
#endif
|
||||||
|
-- import Hledger.Cli.Commands.Web.Templates
|
||||||
|
|
||||||
|
|
||||||
defhost = "localhost"
|
defhost = "localhost"
|
||||||
defport = 5000
|
defport = 5000
|
||||||
defbaseurl = printf "http://%s:%d" defhost defport :: String
|
|
||||||
browserstartdelay = 100000 -- microseconds
|
browserstartdelay = 100000 -- microseconds
|
||||||
hledgerurl = "http://hledger.org"
|
hledgerorgurl = "http://hledger.org"
|
||||||
manualurl = hledgerurl++"/MANUAL.html"
|
manualurl = hledgerorgurl++"/MANUAL.html"
|
||||||
|
|
||||||
data HledgerWebApp = HledgerWebApp {
|
data HledgerWebApp = HledgerWebApp {
|
||||||
appRoot :: String
|
appRoot :: String
|
||||||
,appWebdir :: FilePath
|
,appDir :: FilePath
|
||||||
,appOpts :: [Opt]
|
,appOpts :: [Opt]
|
||||||
,appArgs :: [String]
|
,appArgs :: [String]
|
||||||
,appJournal :: Journal
|
,appJournal :: Journal
|
||||||
|
,appStatic :: Static
|
||||||
}
|
}
|
||||||
|
|
||||||
mkYesod "HledgerWebApp" [$parseRoutes|
|
mkYesod "HledgerWebApp" [$parseRoutes|
|
||||||
/ IndexPage GET
|
/static StaticR Static appStatic
|
||||||
/style.css StyleCss GET
|
/ IndexR GET
|
||||||
/journalonly JournalOnlyPage GET POST
|
/journalonly JournalOnlyR GET POST
|
||||||
/registeronly RegisterOnlyPage GET
|
/registeronly RegisterOnlyR GET
|
||||||
/accounts AccountsPage GET
|
/accounts AccountsOnlyR GET
|
||||||
/journal AccountsJournalPage GET POST
|
/journal JournalR GET POST
|
||||||
/register AccountsRegisterPage GET POST
|
/register RegisterR GET POST
|
||||||
|]
|
|]
|
||||||
|
|
||||||
|
style_css = StaticRoute ["style.css"]
|
||||||
|
hledger_js = StaticRoute ["hledger.js"]
|
||||||
|
jquery_js = StaticRoute ["jquery.js"]
|
||||||
|
dhtmlxcommon_js = StaticRoute ["dhtmlxcommon.js"]
|
||||||
|
dhtmlxcombo_js = StaticRoute ["dhtmlxcombo.js"]
|
||||||
|
|
||||||
instance Yesod HledgerWebApp where approot = appRoot
|
instance Yesod HledgerWebApp where approot = appRoot
|
||||||
|
|
||||||
defaultpage = AccountsJournalPage
|
defaultroute = JournalR
|
||||||
|
|
||||||
-- | A bundle of useful data passed to templates.
|
-- | A bundle of useful data passed to templates.
|
||||||
data TemplateData = TD {
|
data TemplateData = TD {
|
||||||
@ -71,7 +79,7 @@ data TemplateData = TD {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mktd = TD {
|
mktd = TD {
|
||||||
here = IndexPage
|
here = IndexR
|
||||||
,title = "hledger"
|
,title = "hledger"
|
||||||
,msg = Nothing
|
,msg = Nothing
|
||||||
,a = ""
|
,a = ""
|
||||||
@ -83,8 +91,9 @@ mktd = TD {
|
|||||||
-- | The web command.
|
-- | The web command.
|
||||||
web :: [Opt] -> [String] -> Journal -> IO ()
|
web :: [Opt] -> [String] -> Journal -> IO ()
|
||||||
web opts args j = do
|
web opts args j = do
|
||||||
let baseurl = fromMaybe defbaseurl $ baseUrlFromOpts opts
|
let host = defhost
|
||||||
port = fromMaybe defport $ portFromOpts opts
|
port = fromMaybe defport $ portFromOpts opts
|
||||||
|
baseurl = fromMaybe (printf "http://%s:%d" host port) $ baseUrlFromOpts opts
|
||||||
unless (Debug `elem` opts) $ forkIO (browser baseurl) >> return ()
|
unless (Debug `elem` opts) $ forkIO (browser baseurl) >> return ()
|
||||||
server baseurl port opts args j
|
server baseurl port opts args j
|
||||||
|
|
||||||
@ -98,10 +107,11 @@ browser baseurl = do
|
|||||||
server :: String -> Int -> [Opt] -> [String] -> Journal -> IO ()
|
server :: String -> Int -> [Opt] -> [String] -> Journal -> IO ()
|
||||||
server baseurl port opts args j = do
|
server baseurl port opts args j = do
|
||||||
printf "starting web server on port %d with base url %s\n" port baseurl
|
printf "starting web server on port %d with base url %s\n" port baseurl
|
||||||
fp <- getDataFileName "web"
|
dir <- getDataFileName "web"
|
||||||
let app = HledgerWebApp{
|
let app = HledgerWebApp{
|
||||||
appRoot=baseurl
|
appRoot=baseurl
|
||||||
,appWebdir=fp
|
,appDir=dir
|
||||||
|
,appStatic=fileLookupDir (dir </> "static") $ typeByExt -- ++[("hamlet","text/plain")]
|
||||||
,appOpts=opts
|
,appOpts=opts
|
||||||
,appArgs=args
|
,appArgs=args
|
||||||
,appJournal=j
|
,appJournal=j
|
||||||
@ -156,22 +166,14 @@ getHandlerParameters = do
|
|||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
-- handlers & templates
|
-- handlers & templates
|
||||||
|
|
||||||
getStyleCss :: Handler HledgerWebApp ()
|
getIndexR :: Handler HledgerWebApp ()
|
||||||
getStyleCss = do
|
getIndexR = redirect RedirectTemporary defaultroute
|
||||||
app <- getYesod
|
|
||||||
let dir = appWebdir app
|
|
||||||
sendFile "text/css" $ dir </> "style.css"
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
|
|
||||||
getIndexPage :: Handler HledgerWebApp ()
|
|
||||||
getIndexPage = redirect RedirectTemporary defaultpage
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
-- | A combined accounts and journal view.
|
-- | A combined accounts and journal view.
|
||||||
getAccountsJournalPage :: Handler HledgerWebApp RepHtml
|
getJournalR :: Handler HledgerWebApp RepHtml
|
||||||
getAccountsJournalPage = do
|
getJournalR = do
|
||||||
(a, p, opts, fspec, j, msg, here) <- getHandlerParameters
|
(a, p, opts, fspec, j, msg, here) <- getHandlerParameters
|
||||||
today <- liftIO getCurrentDay
|
today <- liftIO getCurrentDay
|
||||||
-- app <- getYesod
|
-- app <- getYesod
|
||||||
@ -183,11 +185,10 @@ getAccountsJournalPage = do
|
|||||||
td = mktd{here=here, title="hledger", msg=msg, a=a, p=p, j=j, today=today}
|
td = mktd{here=here, title="hledger", msg=msg, a=a, p=p, j=j, today=today}
|
||||||
editform' = editform td $ jtext j
|
editform' = editform td $ jtext j
|
||||||
hamletToRepHtml $ pageLayout td [$hamlet|
|
hamletToRepHtml $ pageLayout td [$hamlet|
|
||||||
^scripts^
|
|
||||||
%div.ledger
|
%div.ledger
|
||||||
%div.accounts!style=float:left; ^br^
|
%div.accounts!style=float:left; ^br^
|
||||||
^navlinks.td^
|
^navlinks.td^
|
||||||
^addform^
|
^addform.td^
|
||||||
^editform'^
|
^editform'^
|
||||||
^importform^
|
^importform^
|
||||||
%div#transactions.journal
|
%div#transactions.journal
|
||||||
@ -195,14 +196,14 @@ getAccountsJournalPage = do
|
|||||||
^jr^
|
^jr^
|
||||||
|]
|
|]
|
||||||
|
|
||||||
postAccountsJournalPage :: Handler HledgerWebApp RepPlain
|
postJournalR :: Handler HledgerWebApp RepPlain
|
||||||
postAccountsJournalPage = postJournalOnlyPage
|
postJournalR = postJournalOnlyR
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
-- | A combined accounts and register view.
|
-- | A combined accounts and register view.
|
||||||
getAccountsRegisterPage :: Handler HledgerWebApp RepHtml
|
getRegisterR :: Handler HledgerWebApp RepHtml
|
||||||
getAccountsRegisterPage = do
|
getRegisterR = do
|
||||||
(a, p, opts, fspec, j, msg, here) <- getHandlerParameters
|
(a, p, opts, fspec, j, msg, here) <- getHandlerParameters
|
||||||
today <- liftIO getCurrentDay
|
today <- liftIO getCurrentDay
|
||||||
-- app <- getYesod
|
-- app <- getYesod
|
||||||
@ -215,11 +216,10 @@ getAccountsRegisterPage = do
|
|||||||
td = mktd{here=here, title="hledger", msg=msg, a=a, p=p, j=j, today=today}
|
td = mktd{here=here, title="hledger", msg=msg, a=a, p=p, j=j, today=today}
|
||||||
editform' = editform td $ jtext j
|
editform' = editform td $ jtext j
|
||||||
hamletToRepHtml $ pageLayout td [$hamlet|
|
hamletToRepHtml $ pageLayout td [$hamlet|
|
||||||
^scripts^
|
|
||||||
%div.ledger
|
%div.ledger
|
||||||
%div.accounts!style=float:left; ^br^
|
%div.accounts!style=float:left; ^br^
|
||||||
^navlinks.td^
|
^navlinks.td^
|
||||||
^addform^
|
^addform.td^
|
||||||
^editform'^
|
^editform'^
|
||||||
^importform^
|
^importform^
|
||||||
%div#transactions.register
|
%div#transactions.register
|
||||||
@ -227,14 +227,14 @@ getAccountsRegisterPage = do
|
|||||||
^rr^
|
^rr^
|
||||||
|]
|
|]
|
||||||
|
|
||||||
postAccountsRegisterPage :: Handler HledgerWebApp RepPlain
|
postRegisterR :: Handler HledgerWebApp RepPlain
|
||||||
postAccountsRegisterPage = postJournalOnlyPage
|
postRegisterR = postJournalOnlyR
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
-- | A simple accounts and balances view like hledger balance.
|
-- | A simple accounts and balances view like hledger balance.
|
||||||
getAccountsPage :: Handler HledgerWebApp RepHtml
|
getAccountsOnlyR :: Handler HledgerWebApp RepHtml
|
||||||
getAccountsPage = do
|
getAccountsOnlyR = do
|
||||||
(a, p, opts, fspec, j, msg, here) <- getHandlerParameters
|
(a, p, opts, fspec, j, msg, here) <- getHandlerParameters
|
||||||
today <- liftIO getCurrentDay
|
today <- liftIO getCurrentDay
|
||||||
let td = mktd{here=here, title="hledger", msg=msg, a=a, p=p, j=j, today=today}
|
let td = mktd{here=here, title="hledger", msg=msg, a=a, p=p, j=j, today=today}
|
||||||
@ -308,8 +308,8 @@ isAccountRegex s = take 1 s == "^" && (take 5 $ reverse s) == ")$|:("
|
|||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
-- | A basic journal view, like hledger print, with editing.
|
-- | A basic journal view, like hledger print, with editing.
|
||||||
getJournalOnlyPage :: Handler HledgerWebApp RepHtml
|
getJournalOnlyR :: Handler HledgerWebApp RepHtml
|
||||||
getJournalOnlyPage = do
|
getJournalOnlyR = do
|
||||||
(a, p, opts, fspec, j, msg, here) <- getHandlerParameters
|
(a, p, opts, fspec, j, msg, here) <- getHandlerParameters
|
||||||
today <- liftIO getCurrentDay
|
today <- liftIO getCurrentDay
|
||||||
let td = mktd{here=here, title="hledger", msg=msg, a=a, p=p, j=j, today=today}
|
let td = mktd{here=here, title="hledger", msg=msg, a=a, p=p, j=j, today=today}
|
||||||
@ -317,12 +317,11 @@ getJournalOnlyPage = do
|
|||||||
txns = journalReportAsHtml opts td $ journalReport opts fspec j
|
txns = journalReportAsHtml opts td $ journalReport opts fspec j
|
||||||
hamletToRepHtml $ pageLayout td [$hamlet|
|
hamletToRepHtml $ pageLayout td [$hamlet|
|
||||||
%div.journal
|
%div.journal
|
||||||
^scripts^
|
|
||||||
%div.nav2
|
%div.nav2
|
||||||
%a#addformlink!href!onclick="return addformToggle()" add one transaction
|
%a#addformlink!href!onclick="return addformToggle()" add one transaction
|
||||||
\ | $
|
\ | $
|
||||||
%a#editformlink!href!onclick="return editformToggle()" edit the whole journal
|
%a#editformlink!href!onclick="return editformToggle()" edit the whole journal
|
||||||
^addform^
|
^addform.td^
|
||||||
^editform'^
|
^editform'^
|
||||||
#transactions ^txns^
|
#transactions ^txns^
|
||||||
|]
|
|]
|
||||||
@ -346,9 +345,25 @@ journalReportAsHtml _ td items = [$hamlet|
|
|||||||
evenodd = if even n then "even" else "odd"
|
evenodd = if even n then "even" else "odd"
|
||||||
txn = trimnl $ showTransaction t where trimnl = reverse . dropWhile (=='\n') . reverse
|
txn = trimnl $ showTransaction t where trimnl = reverse . dropWhile (=='\n') . reverse
|
||||||
|
|
||||||
addform :: Hamlet HledgerWebAppRoute
|
addform :: TemplateData -> Hamlet HledgerWebAppRoute
|
||||||
addform = [$hamlet|
|
addform td = [$hamlet|
|
||||||
%form#addform!method=POST!style=display:none;
|
%script!type=text/javascript
|
||||||
|
$$(document).ready(function() {
|
||||||
|
/* dhtmlxcombo setup */
|
||||||
|
window.dhx_globalImgPath="../static/images/";
|
||||||
|
var desccombo = new dhtmlXCombo("description");
|
||||||
|
var acct1combo = new dhtmlXCombo("account1");
|
||||||
|
var acct2combo = new dhtmlXCombo("account2");
|
||||||
|
desccombo.enableFilteringMode(true);
|
||||||
|
acct1combo.enableFilteringMode(true);
|
||||||
|
acct2combo.enableFilteringMode(true);
|
||||||
|
desccombo.setSize(300);
|
||||||
|
acct1combo.setSize(300);
|
||||||
|
acct2combo.setSize(300);
|
||||||
|
/* desccombo.enableOptionAutoHeight(true, 20); */
|
||||||
|
/* desccombo.setOptionHeight(200); */
|
||||||
|
});
|
||||||
|
%form#addform!method=POST!style=display:none;
|
||||||
%table.form
|
%table.form
|
||||||
%tr
|
%tr
|
||||||
%td!colspan=4
|
%td!colspan=4
|
||||||
@ -361,7 +376,10 @@ addform = [$hamlet|
|
|||||||
%td!style=padding-left:1em;
|
%td!style=padding-left:1em;
|
||||||
Description:
|
Description:
|
||||||
%td
|
%td
|
||||||
%input.textinput!size=35!name=description!value=$desc$
|
%select!id=description!name=description
|
||||||
|
%option
|
||||||
|
$forall descriptions d
|
||||||
|
%option!value=$d$ $d$
|
||||||
%tr.helprow
|
%tr.helprow
|
||||||
%td
|
%td
|
||||||
%td
|
%td
|
||||||
@ -369,8 +387,7 @@ addform = [$hamlet|
|
|||||||
%td
|
%td
|
||||||
%td
|
%td
|
||||||
.help $deschelp$
|
.help $deschelp$
|
||||||
^transactionfields1^
|
^postingsfields.td^
|
||||||
^transactionfields2^
|
|
||||||
%tr#addbuttonrow
|
%tr#addbuttonrow
|
||||||
%td!colspan=4
|
%td!colspan=4
|
||||||
%input!type=hidden!name=action!value=add
|
%input!type=hidden!name=action!value=add
|
||||||
@ -378,20 +395,29 @@ addform = [$hamlet|
|
|||||||
|]
|
|]
|
||||||
where
|
where
|
||||||
-- datehelplink = helplink "dates" "..."
|
-- datehelplink = helplink "dates" "..."
|
||||||
datehelp = "eg: 7/20, 2010/1/1, "
|
datehelp = "eg: 2010/7/20"
|
||||||
deschelp = "eg: supermarket (optional)"
|
deschelp = "eg: supermarket (optional)"
|
||||||
date = "today"
|
date = "today"
|
||||||
desc = ""
|
descriptions = sort $ nub $ map tdescription $ jtxns $ j td
|
||||||
transactionfields1 = transactionfields 1
|
|
||||||
transactionfields2 = transactionfields 2
|
|
||||||
|
|
||||||
transactionfields :: Int -> Hamlet HledgerWebAppRoute
|
postingsfields :: TemplateData -> Hamlet HledgerWebAppRoute
|
||||||
transactionfields n = [$hamlet|
|
postingsfields td = [$hamlet|
|
||||||
|
^p1^
|
||||||
|
^p2^
|
||||||
|
|]
|
||||||
|
where
|
||||||
|
p1 = postingfields td 1
|
||||||
|
p2 = postingfields td 2
|
||||||
|
|
||||||
|
postingfields :: TemplateData -> Int -> Hamlet HledgerWebAppRoute
|
||||||
|
postingfields td n = [$hamlet|
|
||||||
%tr#postingrow
|
%tr#postingrow
|
||||||
%td!align=right
|
%td!align=right $acctlabel$:
|
||||||
$label$:
|
|
||||||
%td
|
%td
|
||||||
%input.textinput!size=35!name=$acctvar$!value=$acct$
|
%select!id=$acctvar$!name=$acctvar$
|
||||||
|
%option
|
||||||
|
$forall acctnames a
|
||||||
|
%option!value=$a$ $a$
|
||||||
^amtfield^
|
^amtfield^
|
||||||
%tr.helprow
|
%tr.helprow
|
||||||
%td
|
%td
|
||||||
@ -402,24 +428,26 @@ transactionfields n = [$hamlet|
|
|||||||
.help $amthelp$
|
.help $amthelp$
|
||||||
|]
|
|]
|
||||||
where
|
where
|
||||||
label | n == 1 = "To account"
|
numbered = (++ show n)
|
||||||
| otherwise = "From account"
|
acctvar = numbered "account"
|
||||||
accthelp | n == 1 = "eg: expenses:food"
|
amtvar = numbered "amount"
|
||||||
| otherwise = "eg: assets:bank:checking"
|
acctnames = sort $ journalAccountNamesUsed $ j td
|
||||||
amtfield | n == 1 = [$hamlet|
|
(acctlabel, accthelp, amtfield, amthelp)
|
||||||
|
| n == 1 = ("To account"
|
||||||
|
,"eg: expenses:food"
|
||||||
|
,[$hamlet|
|
||||||
%td!style=padding-left:1em;
|
%td!style=padding-left:1em;
|
||||||
Amount:
|
Amount:
|
||||||
%td
|
%td
|
||||||
%input.textinput!size=15!name=$amtvar$!value=$amt$
|
%input.textinput!size=15!name=$amtvar$!value=""
|
||||||
|]
|
|]
|
||||||
| otherwise = nulltemplate
|
,"eg: $6"
|
||||||
amthelp | n == 1 = "eg: 5, $6, €7.01"
|
)
|
||||||
| otherwise = ""
|
| otherwise = ("From account"
|
||||||
acct = ""
|
,"eg: assets:bank:checking"
|
||||||
amt = ""
|
,nulltemplate
|
||||||
numbered = (++ show n)
|
,""
|
||||||
acctvar = numbered "accountname"
|
)
|
||||||
amtvar = numbered "amount"
|
|
||||||
|
|
||||||
editform :: TemplateData -> String -> Hamlet HledgerWebAppRoute
|
editform :: TemplateData -> String -> Hamlet HledgerWebAppRoute
|
||||||
editform _ content = [$hamlet|
|
editform _ content = [$hamlet|
|
||||||
@ -455,142 +483,8 @@ importform = [$hamlet|
|
|||||||
%a!href!onclick="return importformToggle()" cancel
|
%a!href!onclick="return importformToggle()" cancel
|
||||||
|]
|
|]
|
||||||
|
|
||||||
scripts = [$hamlet|
|
postJournalOnlyR :: Handler HledgerWebApp RepPlain
|
||||||
<script type="text/javascript">
|
postJournalOnlyR = do
|
||||||
|
|
||||||
function filterformToggle() {
|
|
||||||
var a = document.getElementById('addform');
|
|
||||||
var e = document.getElementById('editform');
|
|
||||||
var f = document.getElementById('filterform');
|
|
||||||
var i = document.getElementById('importform');
|
|
||||||
var t = document.getElementById('transactions');
|
|
||||||
var alink = document.getElementById('addformlink');
|
|
||||||
var elink = document.getElementById('editformlink');
|
|
||||||
var flink = document.getElementById('filterformlink');
|
|
||||||
var ilink = document.getElementById('importformlink');
|
|
||||||
var jlink = document.getElementById('journallink');
|
|
||||||
var rlink = document.getElementById('registerlink');
|
|
||||||
|
|
||||||
if (f.style.display == 'none') {
|
|
||||||
flink.style['font-weight'] = 'bold';
|
|
||||||
f.style.display = 'block';
|
|
||||||
} else {
|
|
||||||
flink.style['font-weight'] = 'normal';
|
|
||||||
f.style.display = 'none';
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addformToggle() {
|
|
||||||
var a = document.getElementById('addform');
|
|
||||||
var e = document.getElementById('editform');
|
|
||||||
var f = document.getElementById('filterform');
|
|
||||||
var i = document.getElementById('importform');
|
|
||||||
var t = document.getElementById('transactions');
|
|
||||||
var alink = document.getElementById('addformlink');
|
|
||||||
var elink = document.getElementById('editformlink');
|
|
||||||
var flink = document.getElementById('filterformlink');
|
|
||||||
var ilink = document.getElementById('importformlink');
|
|
||||||
var jlink = document.getElementById('journallink');
|
|
||||||
var rlink = document.getElementById('registerlink');
|
|
||||||
|
|
||||||
if (a.style.display == 'none') {
|
|
||||||
alink.style['font-weight'] = 'bold';
|
|
||||||
elink.style['font-weight'] = 'normal';
|
|
||||||
ilink.style['font-weight'] = 'normal';
|
|
||||||
jlink.style['font-weight'] = 'normal';
|
|
||||||
rlink.style['font-weight'] = 'normal';
|
|
||||||
a.style.display = 'block';
|
|
||||||
e.style.display = 'none';
|
|
||||||
i.style.display = 'none';
|
|
||||||
t.style.display = 'none';
|
|
||||||
} else {
|
|
||||||
alink.style['font-weight'] = 'normal';
|
|
||||||
elink.style['font-weight'] = 'normal';
|
|
||||||
ilink.style['font-weight'] = 'normal';
|
|
||||||
a.style.display = 'none';
|
|
||||||
e.style.display = 'none';
|
|
||||||
i.style.display = 'none';
|
|
||||||
t.style.display = 'block';
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function editformToggle() {
|
|
||||||
var a = document.getElementById('addform');
|
|
||||||
var e = document.getElementById('editform');
|
|
||||||
var f = document.getElementById('filterform');
|
|
||||||
var i = document.getElementById('importform');
|
|
||||||
var t = document.getElementById('transactions');
|
|
||||||
var alink = document.getElementById('addformlink');
|
|
||||||
var elink = document.getElementById('editformlink');
|
|
||||||
var flink = document.getElementById('filterformlink');
|
|
||||||
var ilink = document.getElementById('importformlink');
|
|
||||||
var jlink = document.getElementById('journallink');
|
|
||||||
var rlink = document.getElementById('registerlink');
|
|
||||||
|
|
||||||
if (e.style.display == 'none') {
|
|
||||||
alink.style['font-weight'] = 'normal';
|
|
||||||
elink.style['font-weight'] = 'bold';
|
|
||||||
ilink.style['font-weight'] = 'normal';
|
|
||||||
jlink.style['font-weight'] = 'normal';
|
|
||||||
rlink.style['font-weight'] = 'normal';
|
|
||||||
a.style.display = 'none';
|
|
||||||
e.style.display = 'block';
|
|
||||||
i.style.display = 'none';
|
|
||||||
t.style.display = 'none';
|
|
||||||
} else {
|
|
||||||
alink.style['font-weight'] = 'normal';
|
|
||||||
elink.style['font-weight'] = 'normal';
|
|
||||||
ilink.style['font-weight'] = 'normal';
|
|
||||||
a.style.display = 'none';
|
|
||||||
e.style.display = 'none';
|
|
||||||
i.style.display = 'none';
|
|
||||||
t.style.display = 'block';
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function importformToggle() {
|
|
||||||
var a = document.getElementById('addform');
|
|
||||||
var e = document.getElementById('editform');
|
|
||||||
var f = document.getElementById('filterform');
|
|
||||||
var i = document.getElementById('importform');
|
|
||||||
var t = document.getElementById('transactions');
|
|
||||||
var alink = document.getElementById('addformlink');
|
|
||||||
var elink = document.getElementById('editformlink');
|
|
||||||
var flink = document.getElementById('filterformlink');
|
|
||||||
var ilink = document.getElementById('importformlink');
|
|
||||||
var jlink = document.getElementById('journallink');
|
|
||||||
var rlink = document.getElementById('registerlink');
|
|
||||||
|
|
||||||
if (i.style.display == 'none') {
|
|
||||||
alink.style['font-weight'] = 'normal';
|
|
||||||
elink.style['font-weight'] = 'normal';
|
|
||||||
ilink.style['font-weight'] = 'bold';
|
|
||||||
jlink.style['font-weight'] = 'normal';
|
|
||||||
rlink.style['font-weight'] = 'normal';
|
|
||||||
a.style.display = 'none';
|
|
||||||
e.style.display = 'none';
|
|
||||||
i.style.display = 'block';
|
|
||||||
t.style.display = 'none';
|
|
||||||
} else {
|
|
||||||
alink.style['font-weight'] = 'normal';
|
|
||||||
elink.style['font-weight'] = 'normal';
|
|
||||||
ilink.style['font-weight'] = 'normal';
|
|
||||||
a.style.display = 'none';
|
|
||||||
e.style.display = 'none';
|
|
||||||
i.style.display = 'none';
|
|
||||||
t.style.display = 'block';
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|]
|
|
||||||
|
|
||||||
postJournalOnlyPage :: Handler HledgerWebApp RepPlain
|
|
||||||
postJournalOnlyPage = do
|
|
||||||
action <- runFormPost' $ maybeStringInput "action"
|
action <- runFormPost' $ maybeStringInput "action"
|
||||||
case action of Just "edit" -> postEditForm
|
case action of Just "edit" -> postEditForm
|
||||||
Just "import" -> postImportForm
|
Just "import" -> postImportForm
|
||||||
@ -606,9 +500,9 @@ postAddForm = do
|
|||||||
$ (,,,,,)
|
$ (,,,,,)
|
||||||
<$> maybeStringInput "date"
|
<$> maybeStringInput "date"
|
||||||
<*> maybeStringInput "description"
|
<*> maybeStringInput "description"
|
||||||
<*> maybeStringInput "accountname1"
|
<*> maybeStringInput "account1"
|
||||||
<*> maybeStringInput "amount1"
|
<*> maybeStringInput "amount1"
|
||||||
<*> maybeStringInput "accountname2"
|
<*> maybeStringInput "account2"
|
||||||
<*> maybeStringInput "amount2"
|
<*> maybeStringInput "amount2"
|
||||||
-- supply defaults and parse date and amounts, or get errors.
|
-- supply defaults and parse date and amounts, or get errors.
|
||||||
let dateE = maybe (Left "date required") (either (\e -> Left $ showDateParseError e) Right . fixSmartDateStrEither today) dateM
|
let dateE = maybe (Left "date required") (either (\e -> Left $ showDateParseError e) Right . fixSmartDateStrEither today) dateM
|
||||||
@ -643,14 +537,14 @@ postAddForm = do
|
|||||||
Left errs -> do
|
Left errs -> do
|
||||||
-- save current form values in session
|
-- save current form values in session
|
||||||
setMessage $ string $ intercalate "; " errs
|
setMessage $ string $ intercalate "; " errs
|
||||||
redirect RedirectTemporary AccountsRegisterPage
|
redirect RedirectTemporary RegisterR
|
||||||
|
|
||||||
Right t -> do
|
Right t -> do
|
||||||
let t' = txnTieKnot t -- XXX move into balanceTransaction
|
let t' = txnTieKnot t -- XXX move into balanceTransaction
|
||||||
j <- liftIO $ fromJust `fmap` getValue "hledger" "journal"
|
j <- liftIO $ fromJust `fmap` getValue "hledger" "journal"
|
||||||
liftIO $ journalAddTransaction j opts t'
|
liftIO $ journalAddTransaction j opts t'
|
||||||
setMessage $ string $ printf "Added transaction:\n%s" (show t')
|
setMessage $ string $ printf "Added transaction:\n%s" (show t')
|
||||||
redirect RedirectTemporary AccountsRegisterPage
|
redirect RedirectTemporary RegisterR
|
||||||
|
|
||||||
-- | Handle a journal edit form post.
|
-- | Handle a journal edit form post.
|
||||||
postEditForm :: Handler HledgerWebApp RepPlain
|
postEditForm :: Handler HledgerWebApp RepPlain
|
||||||
@ -663,7 +557,7 @@ postEditForm = do
|
|||||||
Left errs -> do
|
Left errs -> do
|
||||||
-- XXX should save current form values in session
|
-- XXX should save current form values in session
|
||||||
setMessage $ string errs
|
setMessage $ string errs
|
||||||
redirect RedirectTemporary AccountsJournalPage
|
redirect RedirectTemporary JournalR
|
||||||
|
|
||||||
Right t' -> do
|
Right t' -> do
|
||||||
-- try to avoid unnecessary backups or saving invalid data
|
-- try to avoid unnecessary backups or saving invalid data
|
||||||
@ -677,24 +571,24 @@ postEditForm = do
|
|||||||
if not changed
|
if not changed
|
||||||
then do
|
then do
|
||||||
setMessage $ string $ "No change"
|
setMessage $ string $ "No change"
|
||||||
redirect RedirectTemporary AccountsJournalPage
|
redirect RedirectTemporary JournalR
|
||||||
else do
|
else do
|
||||||
jE <- liftIO $ journalFromPathAndString Nothing f tnew
|
jE <- liftIO $ journalFromPathAndString Nothing f tnew
|
||||||
either
|
either
|
||||||
(\e -> do
|
(\e -> do
|
||||||
setMessage $ string e
|
setMessage $ string e
|
||||||
redirect RedirectTemporary AccountsJournalPage)
|
redirect RedirectTemporary JournalR)
|
||||||
(const $ do
|
(const $ do
|
||||||
liftIO $ writeFileWithBackup f tnew
|
liftIO $ writeFileWithBackup f tnew
|
||||||
setMessage $ string $ printf "Saved journal %s\n" (show f)
|
setMessage $ string $ printf "Saved journal %s\n" (show f)
|
||||||
redirect RedirectTemporary AccountsJournalPage)
|
redirect RedirectTemporary JournalR)
|
||||||
jE
|
jE
|
||||||
|
|
||||||
-- | Handle an import page post.
|
-- | Handle an import page post.
|
||||||
postImportForm :: Handler HledgerWebApp RepPlain
|
postImportForm :: Handler HledgerWebApp RepPlain
|
||||||
postImportForm = do
|
postImportForm = do
|
||||||
setMessage $ string $ "can't handle file upload yet"
|
setMessage $ string $ "can't handle file upload yet"
|
||||||
redirect RedirectTemporary AccountsJournalPage
|
redirect RedirectTemporary JournalR
|
||||||
-- -- get form input values, or basic validation errors. E means an Either value.
|
-- -- get form input values, or basic validation errors. E means an Either value.
|
||||||
-- fileM <- runFormPost' $ maybeFileInput "file"
|
-- fileM <- runFormPost' $ maybeFileInput "file"
|
||||||
-- let fileE = maybe (Left "No file provided") Right fileM
|
-- let fileE = maybe (Left "No file provided") Right fileM
|
||||||
@ -702,17 +596,17 @@ postImportForm = do
|
|||||||
-- case fileE of
|
-- case fileE of
|
||||||
-- Left errs -> do
|
-- Left errs -> do
|
||||||
-- setMessage $ string errs
|
-- setMessage $ string errs
|
||||||
-- redirect RedirectTemporary AccountsJournalPage
|
-- redirect RedirectTemporary JournalR
|
||||||
|
|
||||||
-- Right s -> do
|
-- Right s -> do
|
||||||
-- setMessage $ string $ s
|
-- setMessage $ string $ s
|
||||||
-- redirect RedirectTemporary AccountsJournalPage
|
-- redirect RedirectTemporary JournalR
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
-- | A simple postings view like hledger register.
|
-- | A simple postings view like hledger register.
|
||||||
getRegisterOnlyPage :: Handler HledgerWebApp RepHtml
|
getRegisterOnlyR :: Handler HledgerWebApp RepHtml
|
||||||
getRegisterOnlyPage = do
|
getRegisterOnlyR = do
|
||||||
(a, p, opts, fspec, j, msg, here) <- getHandlerParameters
|
(a, p, opts, fspec, j, msg, here) <- getHandlerParameters
|
||||||
today <- liftIO getCurrentDay
|
today <- liftIO getCurrentDay
|
||||||
let td = mktd{here=here, title="hledger", msg=msg, a=a, p=p, j=j, today=today}
|
let td = mktd{here=here, title="hledger", msg=msg, a=a, p=p, j=j, today=today}
|
||||||
@ -753,8 +647,8 @@ mixedAmountAsHtml b = preEscapedString $ addclass $ intercalate "<br>" $ lines $
|
|||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
-- | A standalone journal edit form page.
|
-- | A standalone journal edit form page.
|
||||||
getEditPage :: Handler HledgerWebApp RepHtml
|
getEditR :: Handler HledgerWebApp RepHtml
|
||||||
getEditPage = do
|
getEditR = do
|
||||||
(a, p, _, _, _, msg, here) <- getHandlerParameters
|
(a, p, _, _, _, msg, here) <- getHandlerParameters
|
||||||
today <- liftIO getCurrentDay
|
today <- liftIO getCurrentDay
|
||||||
-- reload journal's text without parsing, if changed -- XXX are we doing this right ?
|
-- reload journal's text without parsing, if changed -- XXX are we doing this right ?
|
||||||
@ -774,7 +668,11 @@ pageLayout td@TD{title=title, msg=msg} content = [$hamlet|
|
|||||||
%head
|
%head
|
||||||
%title $title$
|
%title $title$
|
||||||
%meta!http-equiv=Content-Type!content=$metacontent$
|
%meta!http-equiv=Content-Type!content=$metacontent$
|
||||||
%link!rel=stylesheet!type=text/css!href=@StyleCss@!media=all
|
%script!type=text/javascript!src=@StaticR.jquery_js@
|
||||||
|
%script!type=text/javascript!src=@StaticR.dhtmlxcommon_js@
|
||||||
|
%script!type=text/javascript!src=@StaticR.dhtmlxcombo_js@
|
||||||
|
%script!type=text/javascript!src=@StaticR.hledger_js@
|
||||||
|
%link!rel=stylesheet!type=text/css!media=all!href=@StaticR.style_css@
|
||||||
%body
|
%body
|
||||||
^navbar.td^
|
^navbar.td^
|
||||||
#messages $m$
|
#messages $m$
|
||||||
@ -787,7 +685,7 @@ pageLayout td@TD{title=title, msg=msg} content = [$hamlet|
|
|||||||
navbar :: TemplateData -> Hamlet HledgerWebAppRoute
|
navbar :: TemplateData -> Hamlet HledgerWebAppRoute
|
||||||
navbar TD{p=p,j=j,today=today} = [$hamlet|
|
navbar TD{p=p,j=j,today=today} = [$hamlet|
|
||||||
#navbar
|
#navbar
|
||||||
%a.topleftlink!href=$hledgerurl$
|
%a.topleftlink!href=$hledgerorgurl$
|
||||||
hledger
|
hledger
|
||||||
<br />
|
<br />
|
||||||
$version$
|
$version$
|
||||||
@ -817,8 +715,8 @@ navlinks td = [$hamlet|
|
|||||||
|]
|
|]
|
||||||
-- \ | $
|
-- \ | $
|
||||||
where
|
where
|
||||||
accountsjournallink = navlink td "journal" AccountsJournalPage
|
accountsjournallink = navlink td "journal" JournalR
|
||||||
accountsregisterlink = navlink td "register" AccountsRegisterPage
|
accountsregisterlink = navlink td "register" RegisterR
|
||||||
|
|
||||||
navlink :: TemplateData -> String -> HledgerWebAppRoute -> Hamlet HledgerWebAppRoute
|
navlink :: TemplateData -> String -> HledgerWebAppRoute -> Hamlet HledgerWebAppRoute
|
||||||
navlink TD{here=here,a=a,p=p} s dest = [$hamlet|%a#$s$link.$style$!href=@?u@ $s$|]
|
navlink TD{here=here,a=a,p=p} s dest = [$hamlet|%a#$s$link.$style$!href=@?u@ $s$|]
|
||||||
|
|||||||
135
data/web/static/hledger.js
Normal file
135
data/web/static/hledger.js
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/* hledger web ui javascripts */
|
||||||
|
/* depends on jquery, other support libs, and additional js inserted inline */
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
function filterformToggle() {
|
||||||
|
var a = document.getElementById('addform');
|
||||||
|
var e = document.getElementById('editform');
|
||||||
|
var f = document.getElementById('filterform');
|
||||||
|
var i = document.getElementById('importform');
|
||||||
|
var t = document.getElementById('transactions');
|
||||||
|
var alink = document.getElementById('addformlink');
|
||||||
|
var elink = document.getElementById('editformlink');
|
||||||
|
var flink = document.getElementById('filterformlink');
|
||||||
|
var ilink = document.getElementById('importformlink');
|
||||||
|
var jlink = document.getElementById('journallink');
|
||||||
|
var rlink = document.getElementById('registerlink');
|
||||||
|
|
||||||
|
if (f.style.display == 'none') {
|
||||||
|
flink.style['font-weight'] = 'bold';
|
||||||
|
f.style.display = 'block';
|
||||||
|
} else {
|
||||||
|
flink.style['font-weight'] = 'normal';
|
||||||
|
f.style.display = 'none';
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addformToggle() {
|
||||||
|
var a = document.getElementById('addform');
|
||||||
|
var e = document.getElementById('editform');
|
||||||
|
var f = document.getElementById('filterform');
|
||||||
|
var i = document.getElementById('importform');
|
||||||
|
var t = document.getElementById('transactions');
|
||||||
|
var alink = document.getElementById('addformlink');
|
||||||
|
var elink = document.getElementById('editformlink');
|
||||||
|
var flink = document.getElementById('filterformlink');
|
||||||
|
var ilink = document.getElementById('importformlink');
|
||||||
|
var jlink = document.getElementById('journallink');
|
||||||
|
var rlink = document.getElementById('registerlink');
|
||||||
|
|
||||||
|
if (a.style.display == 'none') {
|
||||||
|
alink.style['font-weight'] = 'bold';
|
||||||
|
elink.style['font-weight'] = 'normal';
|
||||||
|
ilink.style['font-weight'] = 'normal';
|
||||||
|
jlink.style['font-weight'] = 'normal';
|
||||||
|
rlink.style['font-weight'] = 'normal';
|
||||||
|
a.style.display = 'block';
|
||||||
|
e.style.display = 'none';
|
||||||
|
i.style.display = 'none';
|
||||||
|
t.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
alink.style['font-weight'] = 'normal';
|
||||||
|
elink.style['font-weight'] = 'normal';
|
||||||
|
ilink.style['font-weight'] = 'normal';
|
||||||
|
a.style.display = 'none';
|
||||||
|
e.style.display = 'none';
|
||||||
|
i.style.display = 'none';
|
||||||
|
t.style.display = 'block';
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function editformToggle() {
|
||||||
|
var a = document.getElementById('addform');
|
||||||
|
var e = document.getElementById('editform');
|
||||||
|
var f = document.getElementById('filterform');
|
||||||
|
var i = document.getElementById('importform');
|
||||||
|
var t = document.getElementById('transactions');
|
||||||
|
var alink = document.getElementById('addformlink');
|
||||||
|
var elink = document.getElementById('editformlink');
|
||||||
|
var flink = document.getElementById('filterformlink');
|
||||||
|
var ilink = document.getElementById('importformlink');
|
||||||
|
var jlink = document.getElementById('journallink');
|
||||||
|
var rlink = document.getElementById('registerlink');
|
||||||
|
|
||||||
|
if (e.style.display == 'none') {
|
||||||
|
alink.style['font-weight'] = 'normal';
|
||||||
|
elink.style['font-weight'] = 'bold';
|
||||||
|
ilink.style['font-weight'] = 'normal';
|
||||||
|
jlink.style['font-weight'] = 'normal';
|
||||||
|
rlink.style['font-weight'] = 'normal';
|
||||||
|
a.style.display = 'none';
|
||||||
|
e.style.display = 'block';
|
||||||
|
i.style.display = 'none';
|
||||||
|
t.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
alink.style['font-weight'] = 'normal';
|
||||||
|
elink.style['font-weight'] = 'normal';
|
||||||
|
ilink.style['font-weight'] = 'normal';
|
||||||
|
a.style.display = 'none';
|
||||||
|
e.style.display = 'none';
|
||||||
|
i.style.display = 'none';
|
||||||
|
t.style.display = 'block';
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function importformToggle() {
|
||||||
|
var a = document.getElementById('addform');
|
||||||
|
var e = document.getElementById('editform');
|
||||||
|
var f = document.getElementById('filterform');
|
||||||
|
var i = document.getElementById('importform');
|
||||||
|
var t = document.getElementById('transactions');
|
||||||
|
var alink = document.getElementById('addformlink');
|
||||||
|
var elink = document.getElementById('editformlink');
|
||||||
|
var flink = document.getElementById('filterformlink');
|
||||||
|
var ilink = document.getElementById('importformlink');
|
||||||
|
var jlink = document.getElementById('journallink');
|
||||||
|
var rlink = document.getElementById('registerlink');
|
||||||
|
|
||||||
|
if (i.style.display == 'none') {
|
||||||
|
alink.style['font-weight'] = 'normal';
|
||||||
|
elink.style['font-weight'] = 'normal';
|
||||||
|
ilink.style['font-weight'] = 'bold';
|
||||||
|
jlink.style['font-weight'] = 'normal';
|
||||||
|
rlink.style['font-weight'] = 'normal';
|
||||||
|
a.style.display = 'none';
|
||||||
|
e.style.display = 'none';
|
||||||
|
i.style.display = 'block';
|
||||||
|
t.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
alink.style['font-weight'] = 'normal';
|
||||||
|
elink.style['font-weight'] = 'normal';
|
||||||
|
ilink.style['font-weight'] = 'normal';
|
||||||
|
a.style.display = 'none';
|
||||||
|
e.style.display = 'none';
|
||||||
|
i.style.display = 'none';
|
||||||
|
t.style.display = 'block';
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@ -4,7 +4,7 @@
|
|||||||
/* overspecified for cross-browser robustness */
|
/* overspecified for cross-browser robustness */
|
||||||
body { font-family:helvetica,arial,"sans serif"; }
|
body { font-family:helvetica,arial,"sans serif"; }
|
||||||
pre { font-family:courier,"courier new",monospace; }
|
pre { font-family:courier,"courier new",monospace; }
|
||||||
#addform input.textinput { font-family:courier,"courier new",monospace; font-size:small; }
|
input.textinput, .dhx_combo_input, .dhx_combo_list { font-size:small; }
|
||||||
#editform textarea { font-family:courier,"courier new",monospace; font-size:small; }
|
#editform textarea { font-family:courier,"courier new",monospace; font-size:small; }
|
||||||
.nav2 { font-size:small; }
|
.nav2 { font-size:small; }
|
||||||
#filterform { font-size:small; }
|
#filterform { font-size:small; }
|
||||||
@ -75,9 +75,152 @@ table.registerreport { border-spacing:0; }
|
|||||||
.firstposting td { }
|
.firstposting td { }
|
||||||
.registerreport .odd { background-color:#f0f0f0; }
|
.registerreport .odd { background-color:#f0f0f0; }
|
||||||
|
|
||||||
#addform input.textinput { background-color:#eee; padding:4px; }
|
#addform input.textinput, #addform .dhx_combo_input, .dhx_combo_list { background-color:#eee; padding:4px; }
|
||||||
#addform table { }
|
#addform table { }
|
||||||
#addform #addbuttonrow { text-align:right; }
|
#addform #addbuttonrow { text-align:right; }
|
||||||
/* #editform { width:95%; } */
|
/* #editform { width:95%; } */
|
||||||
#editform textarea { width:100%; background-color:#eee; padding:4px; }
|
#editform textarea { width:100%; background-color:#eee; padding:4px; }
|
||||||
#filterform table { border-spacing:0; padding-left:1em; }
|
#filterform table { border-spacing:0; padding-left:1em; }
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
.dhx_combo_input{
|
||||||
|
/* color:#333333; */
|
||||||
|
/* font-family: Arial; */
|
||||||
|
/* font-size: 9pt; */
|
||||||
|
/* border:0px; */
|
||||||
|
/* padding:2px 2px 2px 2px; */
|
||||||
|
/* position:absolute; */
|
||||||
|
/* top:0px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* table {border:thin solid red} */
|
||||||
|
/* div {border:thin solid yellow} */
|
||||||
|
|
||||||
|
.dhx_combo_box{
|
||||||
|
position:relative;
|
||||||
|
display:inline-block;
|
||||||
|
/* text-align:left; */
|
||||||
|
/* height:20px; */
|
||||||
|
/* _height:22px; */
|
||||||
|
/* overflow:hidden; */
|
||||||
|
/* background-color: white; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.dhx_combo_list{
|
||||||
|
position:absolute;
|
||||||
|
z-index:230;
|
||||||
|
overflow-y:auto;
|
||||||
|
overflow-x:hidden;
|
||||||
|
white-space:nowrap;
|
||||||
|
border:1px solid black;
|
||||||
|
height:50%;
|
||||||
|
/* background-color: white; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.dhx_combo_list div{
|
||||||
|
cursor:default;
|
||||||
|
padding:2px 2px 2px 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dhx_selected_option{
|
||||||
|
background-color:navy;
|
||||||
|
color:white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dhx_combo_img{
|
||||||
|
/* display:none; */
|
||||||
|
width:18px;
|
||||||
|
height:20px;
|
||||||
|
position:absolute;
|
||||||
|
top:12px;
|
||||||
|
right:-10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dhx_combo_option_img{
|
||||||
|
position:relative;
|
||||||
|
top:1px;
|
||||||
|
margin:0px;
|
||||||
|
margin-left:2px;
|
||||||
|
left:0px;
|
||||||
|
width:18px; height:18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .combo_dhx_sel{ */
|
||||||
|
/* .dhx_selected_option{ */
|
||||||
|
/* background-image: url("../static/images/bg_selection.gif") !important; */
|
||||||
|
/* background-position: bottom; */
|
||||||
|
/* background-repeat: repeat-x; */
|
||||||
|
/* color:black; */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* .dhx_combo_img_rtl{ */
|
||||||
|
/* position:absolute; */
|
||||||
|
/* top:0px; */
|
||||||
|
/* left:1px; */
|
||||||
|
/* width:17px; */
|
||||||
|
/* height:20px; */
|
||||||
|
/* } */
|
||||||
|
/* .dhx_combo_option_img_rtl{ */
|
||||||
|
/* float:right; */
|
||||||
|
/* margin-right :0px; */
|
||||||
|
/* width:18px; height:18px; */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
/* .dhx_combo_list_rtl{ */
|
||||||
|
/* direction: rtl; */
|
||||||
|
/* unicode-bidi : bidi-override; */
|
||||||
|
/* position:absolute; */
|
||||||
|
/* z-index:230; */
|
||||||
|
/* overflow-y:auto; */
|
||||||
|
/* overflow-x:hidden; */
|
||||||
|
/* border:1px solid black; */
|
||||||
|
/* height:100px; */
|
||||||
|
/* /\* font-family: Arial; *\/ */
|
||||||
|
/* font-size: 9pt; */
|
||||||
|
/* background-color: white; */
|
||||||
|
/* } */
|
||||||
|
/* .dhx_combo_list_rtl div{ */
|
||||||
|
/* direction: rtl; */
|
||||||
|
/* unicode-bidi : bidi-override; */
|
||||||
|
/* padding:2px 2px 2px 2px; */
|
||||||
|
/* } */
|
||||||
|
/* .dhx_combo_list_rtl div div{ */
|
||||||
|
/* float :right !important; */
|
||||||
|
/* cursor:default; */
|
||||||
|
/* } */
|
||||||
|
/* .dhx_combo_list_rtl div img{ */
|
||||||
|
/* float :right !important; */
|
||||||
|
/* } */
|
||||||
|
/* .dhx_combo_list_rtl div input{ */
|
||||||
|
/* float :right !important; */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
/* .dhx_combo_box.dhx_skyblue{ */
|
||||||
|
/* border:1px solid #a4bed4; */
|
||||||
|
/* } */
|
||||||
|
/* .dhx_combo_box.dhx_skyblue .dhx_combo_input { */
|
||||||
|
/* font-family:Tahoma; */
|
||||||
|
/* font-size: 11px; */
|
||||||
|
/* padding:3px; */
|
||||||
|
/* } */
|
||||||
|
/* .dhx_combo_list.dhx_skyblue_list{ */
|
||||||
|
/* background-color: #eaf2fb; */
|
||||||
|
/* border:1px solid #a4bed4; */
|
||||||
|
/* font-family:Tahoma; */
|
||||||
|
/* font-size: 11px; */
|
||||||
|
/* } */
|
||||||
|
/* .dhx_combo_list.dhx_skyblue_list div{ */
|
||||||
|
/* cursor:default; */
|
||||||
|
/* padding:3px 4px; */
|
||||||
|
/* } */
|
||||||
|
/* .dhx_combo_list_rtl.dhx_skyblue_list{ */
|
||||||
|
/* background-color: #eaf2fb; */
|
||||||
|
/* border:1px solid #a4bed4; */
|
||||||
|
/* font-family:Tahoma; */
|
||||||
|
/* font-size: 11px; */
|
||||||
|
/* } */
|
||||||
|
|
||||||
@ -23,7 +23,12 @@ cabal-version: >= 1.2
|
|||||||
build-type: Custom
|
build-type: Custom
|
||||||
data-dir: data
|
data-dir: data
|
||||||
data-files:
|
data-files:
|
||||||
web/style.css
|
web/static/style.css
|
||||||
|
web/static/hledger.js
|
||||||
|
web/static/jquery.js
|
||||||
|
web/static/dhtmlxcommon.js
|
||||||
|
web/static/dhtmlxcombo.js
|
||||||
|
web/static/images/combo_select.gif
|
||||||
extra-tmp-files:
|
extra-tmp-files:
|
||||||
extra-source-files:
|
extra-source-files:
|
||||||
README.rst
|
README.rst
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user