You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
2.8 KiB
137 lines
2.8 KiB
package web
|
|
|
|
import (
|
|
"html/template"
|
|
"net/http"
|
|
"sort"
|
|
"time"
|
|
|
|
"github.com/domagojzecevic/cammonitor/internal/auth"
|
|
"github.com/domagojzecevic/cammonitor/internal/footage"
|
|
webtemplates "github.com/domagojzecevic/cammonitor/internal/web/templates"
|
|
"github.com/go-chi/chi/v5"
|
|
)
|
|
|
|
type Handler struct {
|
|
index *footage.Index
|
|
}
|
|
|
|
type ShellData struct {
|
|
Title string
|
|
User *auth.User
|
|
Months []MonthGroup
|
|
CurrentDate string
|
|
ActiveTab string
|
|
Content any
|
|
}
|
|
|
|
type MonthGroup struct {
|
|
Label string
|
|
Days []string
|
|
}
|
|
|
|
type DayPageData struct {
|
|
Date string
|
|
ImageCount int
|
|
VideoCount int
|
|
}
|
|
|
|
func NewHandler(index *footage.Index) *Handler {
|
|
return &Handler{index: index}
|
|
}
|
|
|
|
func (h *Handler) Index(w http.ResponseWriter, r *http.Request) {
|
|
days := h.dayList()
|
|
if len(days) == 0 {
|
|
h.render(w, r, ShellData{
|
|
Title: "CamMonitor",
|
|
Content: DayPageData{
|
|
Date: "No footage",
|
|
},
|
|
})
|
|
return
|
|
}
|
|
|
|
http.Redirect(w, r, "/day/"+days[0]+"/images", http.StatusFound)
|
|
}
|
|
|
|
func (h *Handler) DayOverview(w http.ResponseWriter, r *http.Request) {
|
|
date := chi.URLParam(r, "date")
|
|
day, ok := h.day(date)
|
|
if !ok {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
|
|
h.render(w, r, ShellData{
|
|
Title: "CamMonitor " + date,
|
|
CurrentDate: date,
|
|
Content: DayPageData{
|
|
Date: date,
|
|
ImageCount: len(day.Images),
|
|
VideoCount: len(day.Videos),
|
|
},
|
|
})
|
|
}
|
|
|
|
func (h *Handler) render(w http.ResponseWriter, r *http.Request, data ShellData) {
|
|
data.User, _ = auth.UserFromContext(r.Context())
|
|
data.Months = groupDaysByMonth(h.dayList())
|
|
|
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
if err := shellTemplate.ExecuteTemplate(w, "base", data); err != nil {
|
|
http.Error(w, "render page failed", http.StatusInternalServerError)
|
|
}
|
|
}
|
|
|
|
func (h *Handler) dayList() []string {
|
|
if h.index == nil {
|
|
return nil
|
|
}
|
|
return h.index.DayList()
|
|
}
|
|
|
|
func (h *Handler) day(date string) (*footage.DayEntry, bool) {
|
|
if h.index == nil {
|
|
return nil, false
|
|
}
|
|
return h.index.Day(date)
|
|
}
|
|
|
|
func groupDaysByMonth(days []string) []MonthGroup {
|
|
groups := make(map[string][]string)
|
|
labels := make([]string, 0)
|
|
|
|
for _, day := range days {
|
|
if len(day) != len("20060102") {
|
|
continue
|
|
}
|
|
|
|
parsed, err := time.Parse("20060102", day)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
label := parsed.Format("2006-01")
|
|
if _, ok := groups[label]; !ok {
|
|
labels = append(labels, label)
|
|
}
|
|
groups[label] = append(groups[label], day)
|
|
}
|
|
|
|
sort.Sort(sort.Reverse(sort.StringSlice(labels)))
|
|
monthGroups := make([]MonthGroup, 0, len(labels))
|
|
for _, label := range labels {
|
|
monthGroups = append(monthGroups, MonthGroup{
|
|
Label: label,
|
|
Days: groups[label],
|
|
})
|
|
}
|
|
return monthGroups
|
|
}
|
|
|
|
var shellTemplate = template.Must(template.ParseFS(
|
|
webtemplates.FS,
|
|
webtemplates.Base,
|
|
webtemplates.Day,
|
|
))
|
|
|