view current month of logs
This commit is contained in:
parent
ca39609fef
commit
9e070d269b
@ -1,6 +1,7 @@
|
|||||||
package archive
|
package archive
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"time"
|
"time"
|
||||||
@ -48,3 +49,17 @@ func NewArchiveServer(cfg *Config) (*ArchiveServer, error) {
|
|||||||
rxSearchRx: regexp.MustCompile(`^/([^/]+)/rx/(.*)$`),
|
rxSearchRx: regexp.MustCompile(`^/([^/]+)/rx/(.*)$`),
|
||||||
}, nil
|
}, 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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
"io/ioutil"
|
||||||
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
pageNotSet int = -1
|
||||||
)
|
)
|
||||||
|
|
||||||
type ArchiveState struct {
|
type ArchiveState struct {
|
||||||
@ -18,18 +25,60 @@ type ArchiveState struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewArchiveState(svr *ArchiveServer) *ArchiveState {
|
func NewArchiveState(svr *ArchiveServer) *ArchiveState {
|
||||||
return &ArchiveState{svr: svr}
|
return &ArchiveState{
|
||||||
}
|
svr: svr,
|
||||||
|
page: pageNotSet,
|
||||||
func (this *ArchiveState) selectSource(log *LogSource) error {
|
}
|
||||||
logBestSlug, err := this.svr.bestSlugFor(log)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *ArchiveState) selectSource(log *LogSource, slug string) {
|
||||||
this.log = log
|
this.log = log
|
||||||
this.logBestSlug = logBestSlug
|
this.logBestSlug = slug
|
||||||
return nil
|
}
|
||||||
|
|
||||||
|
// 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) {
|
func (this *ArchiveState) renderError(w http.ResponseWriter, msg string) {
|
||||||
@ -105,12 +154,13 @@ func (this *ArchiveState) renderTemplateHead(w http.ResponseWriter) {
|
|||||||
// Generate month dropdown options
|
// Generate month dropdown options
|
||||||
|
|
||||||
lastY := -1
|
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 ympair.Year != lastY {
|
||||||
if lastY != -1 {
|
if lastY != -1 {
|
||||||
w.Write([]byte(`</optgroup>`))
|
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
|
lastY = ympair.Year
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
Router.go
14
Router.go
@ -7,6 +7,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (this *ArchiveServer) lookupSourceByNumericString(slug string) *LogSource {
|
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` {
|
} else if r.URL.Path == `/download` {
|
||||||
arc.renderError(w, "Not implemented.") // FIXME
|
arc.renderError(w, "Not implemented.") // FIXME
|
||||||
|
|
||||||
} else if this.rxViewRoot.MatchString(r.URL.Path) {
|
} else if matches := this.rxViewRoot.FindStringSubmatch(r.URL.Path); len(matches) > 0 {
|
||||||
arc.renderError(w, "Not implemented.") // FIXME
|
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) {
|
} else if this.rxViewPage.MatchString(r.URL.Path) {
|
||||||
arc.renderError(w, "Not implemented.") // FIXME
|
arc.renderError(w, "Not implemented.") // FIXME
|
||||||
|
@ -26,3 +26,9 @@ func (ym YearMonth) Next() YearMonth {
|
|||||||
return YearMonth{Year: ym.Year, Month: ym.Month + 1}
|
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