Skip to content

Commit

Permalink
Add responsive reports (pie chart)
Browse files Browse the repository at this point in the history
  • Loading branch information
howeyc committed Oct 6, 2015
1 parent 2e64f91 commit a9a22df
Show file tree
Hide file tree
Showing 52 changed files with 6,380 additions and 11 deletions.
13 changes: 11 additions & 2 deletions src/cmd/lweb/handler_accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ func AccountsHandler(w http.ResponseWriter, r *http.Request) {

balances := ledger.GetBalances(trans, []string{})

err = t.Execute(w, balances)
var pData pageData
pData.Reports = reportConfigData.Reports
pData.Accounts = balances
pData.Transactions = trans

err = t.Execute(w, pData)
if err != nil {
http.Error(w, err.Error(), 500)
}
Expand Down Expand Up @@ -64,7 +69,11 @@ func AccountHandler(w http.ResponseWriter, r *http.Request, params martini.Param
}
}

err = t.Execute(w, pageTrans)
var pData pageData
pData.Reports = reportConfigData.Reports
pData.Transactions = pageTrans

err = t.Execute(w, pData)
if err != nil {
http.Error(w, err.Error(), 500)
}
Expand Down
6 changes: 5 additions & 1 deletion src/cmd/lweb/handler_ledger.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ func LedgerHandler(w http.ResponseWriter, r *http.Request) {
return
}

err = t.Execute(w, trans)
var pData pageData
pData.Reports = reportConfigData.Reports
pData.Transactions = trans

err = t.Execute(w, pData)
if err != nil {
http.Error(w, err.Error(), 500)
}
Expand Down
146 changes: 146 additions & 0 deletions src/cmd/lweb/handler_report.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package main

import (
"bytes"
"fmt"
"html/template"
"net/http"
"strings"
"time"

"ledger"

"github.com/go-martini/martini"
"github.com/studiofrenetic/period"
)

func getReportPeriod(currentTime time.Time, duration string) period.Period {
var per period.Period
switch duration {
case "YTD":
per, _ = period.CreateFromYear(currentTime.Year())
case "Previous Year":
per, _ = period.CreateFromYear(currentTime.Year() - 1)
case "Current Month":
per, _ = period.CreateFromMonth(currentTime.Year(), int(currentTime.Month()))
case "Previous Month":
per, _ = period.CreateFromMonth(currentTime.Year(), int(currentTime.Month())-1)
}

return per
}

func ReportHandler(w http.ResponseWriter, r *http.Request, params martini.Params) {
reportName := params["reportName"]

ledgerFileReader := bytes.NewReader(ledgerBuffer.Bytes())

trans, terr := ledger.ParseLedger(ledgerFileReader)
if terr != nil {
http.Error(w, terr.Error(), 500)
return
}

var rConf reportConfig
for _, reportConf := range reportConfigData.Reports {
if reportConf.Name == reportName {
rConf = reportConf
}
}
reportPeriod := getReportPeriod(time.Now(), rConf.DateRange)

timeStartIndex, timeEndIndex := 0, 0
for idx := 0; idx < len(trans); idx++ {
if reportPeriod.Contains(trans[idx].Date) {
timeStartIndex = idx
break
}
}
for idx := len(trans) - 1; idx >= 0; idx-- {
if !reportPeriod.Contains(trans[idx].Date) {
timeEndIndex = idx
break
}
}
trans = trans[timeStartIndex : timeEndIndex+1]

accountName := rConf.Accounts[0]

balances := ledger.GetBalances(trans, []string{accountName})

skipCount := 0
for _, account := range balances {
if !strings.HasPrefix(account.Name, accountName) {
skipCount++
}
if account.Name == accountName {
skipCount++
}
}

accStartLen := len(accountName)

type reportAccount struct {
Name string
Balance float64
Color string
Highlight string
}

values := make([]reportAccount, 0)

type reportColor struct {
Color string
Highlight string
}

colorlist := []reportColor{{"#F7464A", "#FF5A5E"},
{"#46BFBD", "#5AD3D1"},
{"#FDB45C", "#FFC870"},
{"#B48EAD", "#C69CBE"},
{"#949FB1", "#A8B3C5"},
{"#4D5360", "#616774"},
{"#23A1A3", "#34B3b5"},
{"#bf9005", "#D1A216"},
{"#1742d1", "#2954e2"},
{"#E228BA", "#E24FC2"}}

colorIdx := 0
for _, account := range balances[skipCount:] {
accName := account.Name[accStartLen+1:]
value, _ := account.Balance.Float64()

if !strings.Contains(accName, ":") {
values = append(values, reportAccount{Name: accName, Balance: value,
Color: colorlist[colorIdx].Color,
Highlight: colorlist[colorIdx].Highlight})
colorIdx++
}
}

switch rConf.Chart {
case "pie":
type piePageData struct {
pageData
ChartAccounts []reportAccount
}

var pData piePageData
pData.Reports = reportConfigData.Reports
pData.Transactions = trans
pData.ChartAccounts = values

t, err := template.ParseFiles("templates/template.piechart.html", "templates/template.nav.html")
if err != nil {
http.Error(w, err.Error(), 500)
return
}

err = t.Execute(w, pData)
if err != nil {
http.Error(w, err.Error(), 500)
}
default:
fmt.Fprint(w, "Unsupported chart type.")
}
}
31 changes: 30 additions & 1 deletion src/cmd/lweb/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,55 @@ import (
"net/http"
"os"

"ledger"

"github.com/BurntSushi/toml"
"github.com/go-martini/martini"
)

var ledgerBuffer bytes.Buffer

type reportConfig struct {
Name string
Chart string
DateRange string `toml:"date_range"`
DateFreq string `toml:"date_freq"`
Accounts []string
}

var reportConfigData struct {
Reports []reportConfig `toml:"report"`
}

type pageData struct {
Reports []reportConfig
Transactions []*ledger.Transaction
Accounts []*ledger.Account
}

func main() {
var ledgerFileName string
var reportConfigFileName string
var serverPort int
var localhost bool

flag.StringVar(&ledgerFileName, "f", "", "Ledger file name (*Required).")
flag.StringVar(&reportConfigFileName, "r", "", "Report config file name (*Required).")
flag.IntVar(&serverPort, "port", 8056, "Port to listen on.")
flag.BoolVar(&localhost, "localhost", false, "Listen on localhost only.")

flag.Parse()

if len(ledgerFileName) == 0 {
if len(ledgerFileName) == 0 || len(reportConfigFileName) == 0 {
flag.Usage()
return
}

_, derr := toml.DecodeFile(reportConfigFileName, &reportConfigData)
if derr != nil {
fmt.Println(derr)
}

ledgerFileReader, err := os.Open(ledgerFileName)
if err != nil {
fmt.Println(err)
Expand All @@ -41,6 +69,7 @@ func main() {
m.Get("/ledger", LedgerHandler)
m.Get("/accounts", AccountsHandler)
m.Get("/account/:accountName", AccountHandler)
m.Get("/report/:reportName", ReportHandler)

fmt.Println("Listening on port", serverPort)
listenAddress := ""
Expand Down
11 changes: 11 additions & 0 deletions src/cmd/lweb/public/Chart.min.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/cmd/lweb/templates/template.account.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

<body>

{{template "nav" .}}
{{template "nav" .Reports}}

<div class="container">
<div class="content-header">
Expand All @@ -47,7 +47,7 @@ <h1>Account</h1>
</tr>
</thead>
<tbody>
{{range .}}
{{range .Transactions}}
<tr>
<td>{{.Date.Format "2006-01-02"}}</td>
<td>{{.Payee}}</td>
Expand Down
4 changes: 2 additions & 2 deletions src/cmd/lweb/templates/template.accounts.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

<body>

{{template "nav" .}}
{{template "nav" .Reports}}

<div class="container">
<div class="content-header">
Expand All @@ -46,7 +46,7 @@ <h1>Account List</h1>
</tr>
</thead>
<tbody>
{{range .}}
{{range .Accounts}}
<tr>
<td><a href="/account/{{.Name}}">{{.Name}}</a></td>
<td align="right">{{.Balance.FloatString 2}}</td>
Expand Down
4 changes: 2 additions & 2 deletions src/cmd/lweb/templates/template.ledger.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

<body>

{{template "nav" .}}
{{template "nav" .Reports}}

<div class="container">
<div class="content-header">
Expand All @@ -52,7 +52,7 @@ <h1>Ledger</h1>
</tr>
</thead>
<tbody>
{{range .}}
{{range .Transactions}}
<tr>
<td>{{.Date.Format "2006-01-02"}}</td>
<td>{{.Payee}}</td>
Expand Down
9 changes: 8 additions & 1 deletion src/cmd/lweb/templates/template.nav.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@
<ul class="nav navbar-nav">
<li><a href="/ledger">General Ledger</a></li>
<li><a href="/accounts">Accounts</a></li>
<li><a href="/report.html">Report</a></li>
<li class="dropdown">
<a href="#" class="dropdown toggle" data-toggle="dropdown">Reports <span class="caret"></span></a>
<ul class="dropdown-menu">
{{range .}}
<li><a href="/report/{{.Name}}">{{.Name}}</a></li>
{{end}}
</ul>
</li>
</ul>
</div><!--/.nav-collapse -->
</div>
Expand Down
Loading

0 comments on commit a9a22df

Please sign in to comment.