diff --git a/ArchiveServer.go b/ArchiveServer.go
index 2e7e717..cd69bf3 100644
--- a/ArchiveServer.go
+++ b/ArchiveServer.go
@@ -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
+}
diff --git a/ArchiveState.go b/ArchiveState.go
index a477345..4838cfd 100644
--- a/ArchiveState.go
+++ b/ArchiveState.go
@@ -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}
+ 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.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
}
- this.log = log
- this.logBestSlug = logBestSlug
- return nil
+ 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]) + "
\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(``))
}
- w.Write([]byte(`