Use HTMX fragements on the fitness dashboard
This commit is contained in:
+61
-2
@@ -34,13 +34,42 @@ func (f *fitnessHandler) handle(root, fsPath, urlPath string, r *http.Request) *
|
||||
if s == nil || s.Type != "fitness" {
|
||||
return nil
|
||||
}
|
||||
q := r.URL.Query()
|
||||
weightView, weeklyView := fitnessViews(r.URL.Query())
|
||||
return &specialPage{
|
||||
Content: renderFitnessDashboard(fsPath, chartViewFrom(q, "weight", "3m"), chartViewFrom(q, "weekly", "1y")),
|
||||
Content: renderFitnessDashboard(fsPath, weightView, weeklyView),
|
||||
SuppressTOC: true,
|
||||
}
|
||||
}
|
||||
|
||||
// serveFragment answers a chart's controls (htmx GET ?chart=<param> with
|
||||
// every chart's view state) with just that chart, and points the address bar
|
||||
// at the canonical dashboard URL so the view stays bookmarkable.
|
||||
func (f *fitnessHandler) serveFragment(w http.ResponseWriter, r *http.Request, root, fsPath, urlPath string) bool {
|
||||
q := r.URL.Query()
|
||||
param := q.Get("chart")
|
||||
if param == "" {
|
||||
return false
|
||||
}
|
||||
if s := readPageSettings(fsPath); s == nil || s.Type != "fitness" {
|
||||
return false
|
||||
}
|
||||
weightView, weeklyView := fitnessViews(q)
|
||||
dash := buildFitnessDash(fsPath, weightView, weeklyView, time.Now())
|
||||
for _, c := range dash.Charts {
|
||||
if c.Param != param {
|
||||
continue
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
w.Header().Set("HX-Replace-Url", fitnessURL(urlPath, weightView, weeklyView))
|
||||
if err := fitnessTmpl.ExecuteTemplate(w, "fitnessChart", c); err != nil {
|
||||
log.Printf("fitness template: %v", err)
|
||||
}
|
||||
return true
|
||||
}
|
||||
http.Error(w, "Unknown chart: "+param, http.StatusNotFound)
|
||||
return true
|
||||
}
|
||||
|
||||
// === Time ranges ===
|
||||
|
||||
type fitnessRange struct {
|
||||
@@ -79,6 +108,36 @@ func chartViewFrom(q url.Values, param, fallback string) fitnessView {
|
||||
}
|
||||
}
|
||||
|
||||
// Default ranges of the two charts.
|
||||
const (
|
||||
weightDefaultRange = "3m"
|
||||
weeklyDefaultRange = "1y"
|
||||
)
|
||||
|
||||
func fitnessViews(q url.Values) (weight, weekly fitnessView) {
|
||||
return chartViewFrom(q, "weight", weightDefaultRange), chartViewFrom(q, "weekly", weeklyDefaultRange)
|
||||
}
|
||||
|
||||
// fitnessURL is the dashboard URL for the given views; defaults are left out.
|
||||
func fitnessURL(urlPath string, weight, weekly fitnessView) string {
|
||||
q := url.Values{}
|
||||
add := func(param, fallback string, v fitnessView) {
|
||||
if v.Range != fallback {
|
||||
q.Set(param, v.Range)
|
||||
}
|
||||
if v.Absolute {
|
||||
q.Set(param+"-absolute", "1")
|
||||
}
|
||||
}
|
||||
add("weight", weightDefaultRange, weight)
|
||||
add("weekly", weeklyDefaultRange, weekly)
|
||||
target := pageURL(urlPath)
|
||||
if len(q) > 0 {
|
||||
target += "?" + q.Encode()
|
||||
}
|
||||
return target
|
||||
}
|
||||
|
||||
func rangeMonths(v string) int {
|
||||
for _, r := range fitnessRanges {
|
||||
if r.Value == v {
|
||||
|
||||
Reference in New Issue
Block a user