view current month of logs
This commit is contained in:
parent
ca39609fef
commit
9e070d269b
@ -1,6 +1,7 @@
|
||||
package archive
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"time"
|
||||
@ -48,3 +49,17 @@ func NewArchiveServer(cfg *Config) (*ArchiveServer, error) {
|
||||
rxSearchRx: regexp.MustCompile(`^/([^/]+)/rx/(.*)$`),
|
||||
}, nil
|
||||
}
|
||||
|
||||
var ErrNoLogForMonth = errors.New("No logs for the selected month.")
|
||||
|
||||
func (this *ArchiveServer) LogFile(ls *LogSource, ym YearMonth) (string, error) {
|
||||
ymIndex := ym.Index()
|
||||
|
||||
for _, fl := range ls.FileLocation {
|
||||
if fl.StartMonth.Index() <= ymIndex && (fl.EndMonth == nil || fl.EndMonth.Index() >= ymIndex) {
|
||||
return time.Date(ym.Year, ym.Month, 1, 0, 0, 0, 0, this.timezone).Format(fl.LogFilePath), nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", ErrNoLogForMonth
|
||||
}
|
||||
|
@ -3,7 +3,14 @@ package archive
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
pageNotSet int = -1
|
||||
)
|
||||
|
||||
type ArchiveState struct {
|
||||
@ -18,18 +25,60 @@ type ArchiveState struct {
|
||||
}
|
||||
|
||||
func NewArchiveState(svr *ArchiveServer) *ArchiveState {
|
||||
return &ArchiveState{svr: svr}
|
||||
}
|
||||
|
||||
func (this *ArchiveState) selectSource(log *LogSource) error {
|
||||
logBestSlug, err := this.svr.bestSlugFor(log)
|
||||
if err != nil {
|
||||
return err
|
||||
return &ArchiveState{
|
||||
svr: svr,
|
||||
page: pageNotSet,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ArchiveState) selectSource(log *LogSource, slug string) {
|
||||
this.log = log
|
||||
this.logBestSlug = logBestSlug
|
||||
return nil
|
||||
this.logBestSlug = slug
|
||||
}
|
||||
|
||||
// renderView renders a single page of log entries.
|
||||
// - Mandatory: log, ym
|
||||
// - Optional: page
|
||||
func (this *ArchiveState) renderView(w http.ResponseWriter) {
|
||||
if this.log == nil {
|
||||
this.renderError(w, "Invalid log source selected")
|
||||
return
|
||||
}
|
||||
|
||||
fname, err := this.svr.LogFile(this.log, this.ym)
|
||||
if err != nil {
|
||||
this.renderError(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
fc, err := ioutil.ReadFile(fname)
|
||||
if err != nil {
|
||||
this.renderError(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
lines := strings.Split(string(fc), "\n")
|
||||
|
||||
this.highestPage = int(math.Ceil(float64(len(lines))/float64(this.svr.cfg.LinesPerPage))) - 1
|
||||
if this.page == pageNotSet || this.page > this.highestPage {
|
||||
this.page = this.highestPage
|
||||
}
|
||||
if this.page < 0 {
|
||||
this.page = 0
|
||||
}
|
||||
|
||||
startLine := this.svr.cfg.LinesPerPage * this.page
|
||||
endLine := this.svr.cfg.LinesPerPage * (this.page + 1)
|
||||
if endLine > len(lines) {
|
||||
endLine = len(lines)
|
||||
}
|
||||
|
||||
output := ""
|
||||
for i := startLine; i < endLine; i += 1 {
|
||||
output += template.HTMLEscapeString(lines[i]) + "<br>\n"
|
||||
}
|
||||
|
||||
this.renderTemplate(w, []byte(output))
|
||||
}
|
||||
|
||||
func (this *ArchiveState) renderError(w http.ResponseWriter, msg string) {
|
||||
@ -105,12 +154,13 @@ func (this *ArchiveState) renderTemplateHead(w http.ResponseWriter) {
|
||||
// Generate month dropdown options
|
||||
|
||||
lastY := -1
|
||||
for ympair := this.log.EarliestDate(); !ympair.Equals(this.log.LatestDate()); ympair = ympair.Next() {
|
||||
limit := this.log.LatestDate().Next() // one off the end
|
||||
for ympair := this.log.EarliestDate(); !ympair.Equals(limit); ympair = ympair.Next() {
|
||||
if ympair.Year != lastY {
|
||||
if lastY != -1 {
|
||||
w.Write([]byte(`</optgroup>`))
|
||||
}
|
||||
w.Write([]byte(`<optgroup label="` + fmt.Sprintf("%s", ympair.Year) + `">`))
|
||||
w.Write([]byte(`<optgroup label="` + fmt.Sprintf("%d", ympair.Year) + `">`))
|
||||
lastY = ympair.Year
|
||||
}
|
||||
|
||||
|
14
Router.go
14
Router.go
@ -7,6 +7,7 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (this *ArchiveServer) lookupSourceByNumericString(slug string) *LogSource {
|
||||
@ -92,8 +93,17 @@ func (this *ArchiveServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
} else if r.URL.Path == `/download` {
|
||||
arc.renderError(w, "Not implemented.") // FIXME
|
||||
|
||||
} else if this.rxViewRoot.MatchString(r.URL.Path) {
|
||||
arc.renderError(w, "Not implemented.") // FIXME
|
||||
} else if matches := this.rxViewRoot.FindStringSubmatch(r.URL.Path); len(matches) > 0 {
|
||||
if ls := this.lookupSource(matches[1]); ls != nil {
|
||||
arc.selectSource(ls, matches[1])
|
||||
y, _ := strconv.Atoi(matches[2])
|
||||
m, _ := strconv.Atoi(matches[3])
|
||||
arc.ym = YearMonth{Year: y, Month: time.Month(m)} // 1-based months
|
||||
arc.renderView(w)
|
||||
|
||||
} else {
|
||||
arc.renderError(w, fmt.Sprintf("Unknown source '%s'", matches[1]))
|
||||
}
|
||||
|
||||
} else if this.rxViewPage.MatchString(r.URL.Path) {
|
||||
arc.renderError(w, "Not implemented.") // FIXME
|
||||
|
@ -26,3 +26,9 @@ func (ym YearMonth) Next() YearMonth {
|
||||
return YearMonth{Year: ym.Year, Month: ym.Month + 1}
|
||||
}
|
||||
}
|
||||
|
||||
// Index returns a single int that can be used to compare this YearMonth with
|
||||
// other YearMonth objects.
|
||||
func (ym YearMonth) Index() int {
|
||||
return (ym.Year * 12) + (int(ym.Month) - 1)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user