From 7df46e03e01600e9fcf50020dae80d7aa161e663 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Thu, 8 Dec 2022 16:44:17 +0100 Subject: [PATCH] Create a basic HTML page to permit usage of non-JS devices --- app.go | 1 + ui/nojs.go | 139 ++++++++++++++++++++++++++++++++ ui/nojs_templates/error.tmpl | 4 + ui/nojs_templates/index.tmpl | 73 +++++++++++++++++ ui/nojs_templates/single.tmpl | 18 +++++ ui/src/app.html | 1 + ui/src/routes/nojs/+page.svelte | 0 7 files changed, 236 insertions(+) create mode 100644 ui/nojs.go create mode 100644 ui/nojs_templates/error.tmpl create mode 100644 ui/nojs_templates/index.tmpl create mode 100644 ui/nojs_templates/single.tmpl create mode 100644 ui/src/routes/nojs/+page.svelte diff --git a/app.go b/app.go index 0867a7e..e2b5973 100644 --- a/app.go +++ b/app.go @@ -49,6 +49,7 @@ func NewApp(cfg *config.Config) *App { // Register routes ui.DeclareRoutes(router, cfg) + ui.DeclareNoJSRoutes(router, cfg, db, app.ResetTimer) api.DeclareRoutes(router, cfg, db, app.ResetTimer) router.GET("/api/version", func(c *gin.Context) { diff --git a/ui/nojs.go b/ui/nojs.go new file mode 100644 index 0000000..51b0299 --- /dev/null +++ b/ui/nojs.go @@ -0,0 +1,139 @@ +package ui + +import ( + "embed" + "fmt" + "html/template" + "net/http" + "strconv" + "strings" + "time" + + "github.com/gin-gonic/gin" + + "git.nemunai.re/nemunaire/reveil/config" + "git.nemunai.re/nemunaire/reveil/model" + "git.nemunai.re/nemunaire/reveil/player" +) + +//go:embed nojs_templates/* +var nojs_tpl embed.FS + +func DeclareNoJSRoutes(router *gin.Engine, cfg *config.Config, db *reveil.LevelDBStorage, resetTimer func()) { + templ := template.Must(template.New("").ParseFS(nojs_tpl, "nojs_templates/*.tmpl")) + router.SetHTMLTemplate(templ) + + router.GET("/nojs.html", func(c *gin.Context) { + alarm, err := reveil.GetNextAlarm(cfg, db) + if err != nil { + c.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{"errmsg": err.Error()}) + return + } + + nCycles := int(time.Until(*alarm) / (90 * time.Minute)) + nDays := int(time.Until(*alarm) / (24 * time.Hour)) + nMinutes := int((time.Until(*alarm) / time.Minute) % 90) + + c.HTML(http.StatusOK, "index.tmpl", gin.H{ + "nextAlarmDate": alarm.Format("Mon 2"), + "nextAlarmTime": alarm.Format("15:04"), + "sameDay": time.Now().Day() == alarm.Day(), + "nCycles": nCycles, + "nDays": nDays, + "nMinutes": nMinutes, + "isPlaying": player.CommonPlayer != nil, + }) + }) + + router.POST("/nojs.html", func(c *gin.Context) { + var form struct { + Action string `form:"action"` + Time *string `form:"time"` + } + c.Bind(&form) + + switch form.Action { + case "new": + if form.Time == nil { + c.HTML(http.StatusBadRequest, "error.tmpl", gin.H{"errmsg": "This time is invalid."}) + return + } + + alarm := time.Now() + + if len(*form.Time) == 2 && (*form.Time)[1] == 'c' { + n, err := strconv.Atoi((*form.Time)[:1]) + if err != nil { + c.HTML(http.StatusBadRequest, "error.tmpl", gin.H{"errmsg": fmt.Sprintf("This number of cycle is invalid: %s", err.Error())}) + return + } + + alarm = alarm.Add((time.Duration(90*n) + 10) * time.Minute) + } else { + tmp := strings.Split(*form.Time, ":") + if len(tmp) != 2 { + c.HTML(http.StatusBadRequest, "error.tmpl", gin.H{"errmsg": "This time is invalid."}) + return + } + + duration, err := time.ParseDuration(fmt.Sprintf("%sh%sm", tmp[0], tmp[1])) + if err != nil { + c.HTML(http.StatusBadRequest, "error.tmpl", gin.H{"errmsg": fmt.Sprintf("This time is invalid: %s", err.Error())}) + return + } + + _, offset := alarm.Zone() + alarm = alarm.Truncate(24 * time.Hour).Add(-time.Duration(offset)*time.Second + duration) + } + + if time.Now().After(alarm) { + alarm = alarm.Add(24 * time.Hour) + } + + if err := reveil.PutAlarmSingle(db, &reveil.AlarmSingle{ + Time: alarm, + }); err != nil { + c.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{"errmsg": err.Error()}) + return + } + + resetTimer() + + case "cancel": + err := reveil.DropNextAlarm(cfg, db) + if err != nil { + c.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{"errmsg": err.Error()}) + return + } + resetTimer() + + case "start": + if player.CommonPlayer == nil { + err := player.WakeUp(cfg) + if err != nil { + c.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{"errmsg": err.Error()}) + return + } + } else { + c.HTML(http.StatusBadRequest, "error.tmpl", gin.H{"errmsg": "Player already running"}) + return + } + + case "nexttrack": + if player.CommonPlayer != nil { + player.CommonPlayer.NextTrack() + } + + case "stop": + if player.CommonPlayer != nil { + err := player.CommonPlayer.Stop() + if err != nil { + c.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{"errmsg": err.Error()}) + return + } + } + } + + c.Redirect(http.StatusFound, "/nojs.html") + }) +} diff --git a/ui/nojs_templates/error.tmpl b/ui/nojs_templates/error.tmpl new file mode 100644 index 0000000..98fa1cc --- /dev/null +++ b/ui/nojs_templates/error.tmpl @@ -0,0 +1,4 @@ +

+ Une erreur inattendue s'est produite : + {{ .errmsg }} +

\ No newline at end of file diff --git a/ui/nojs_templates/index.tmpl b/ui/nojs_templates/index.tmpl new file mode 100644 index 0000000..09334e9 --- /dev/null +++ b/ui/nojs_templates/index.tmpl @@ -0,0 +1,73 @@ +

+ Prochain réveil le : + {{ if .sameDay }} + aujourd'hui + {{ else if lt .nCycles 16 }} + demain + {{ else }} + {{ .nextAlarmDate }} + {{ end }} + à {{ .nextAlarmTime }} +

+

+ {{ if gt .nDays 2 }}(dans {{ .nDays }} jours){{ else }}(dans {{ .nCycles }} cycles + {{ .nMinutes }} min){{ end }} +

+ +
+
+ + +
+ +{{ if .isPlaying }} +
+ + +
+ +
+ + +
+{{ else }} +
+ + +
+{{ end }} +
+ +

Programmer une nouvelle alarme

+
+
+ + + +
+ +
+ + + +
+ +
+ + + +
+
diff --git a/ui/nojs_templates/single.tmpl b/ui/nojs_templates/single.tmpl new file mode 100644 index 0000000..2ea56ed --- /dev/null +++ b/ui/nojs_templates/single.tmpl @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + +
%sveltekit.body%
+ + diff --git a/ui/src/app.html b/ui/src/app.html index cb871a8..2de989a 100644 --- a/ui/src/app.html +++ b/ui/src/app.html @@ -14,6 +14,7 @@ %sveltekit.head% +
%sveltekit.body%
diff --git a/ui/src/routes/nojs/+page.svelte b/ui/src/routes/nojs/+page.svelte new file mode 100644 index 0000000..e69de29