detached d0a3ac0

WIP

commit
d0a3ac029c6cdce17c554fdf68bea15cbeff7608
author
bnema · · 2023-09-07 14:17 UTC
parent
7456be8
signature
unsigned
3 files · +37 -3
M internal/http/handlers/htmx-installer.go +33 -2
@@ -1,14 +1,20 @@
11 package handlers
22
33 import (
4+ "fmt"
5+ "net/http"
6+
47 "github.com/labstack/echo/v4"
58 "gogs.bnema.dev/gordon-echo/internal/app"
69 "gogs.bnema.dev/gordon-echo/pkg/scripts"
710 )
811
12+var eventsChan = make(chan string)
13+
914 // TraefikInstallerHandler handles the installation of Traefik
1015 func TraefikInstallerHandler(c echo.Context, a *app.App) error {
1116 logger := a.AppLogger
17+ eventsChan <- "Starting Traefik installation..."
1218 // Retrieve the logger from the context
1319 // Reject POST requests if they are not allowed with the RejectPOSTPolicy function
1420 if err := RejectPOSTPolicy(c); err != nil {
@@ -36,9 +42,34 @@ func TraefikInstallerHandler(c echo.Context, a *app.App) error {
3642 logger.Error().Msg("Failed to install Traefik")
3743 return err
3844 } else {
39- logger.Info().Msg("Traefik installed successfully")
45+ eventsChan <- "Traefik installation completed!"
4046 return c.String(200, "Traefik installed successfully")
4147 }
4248 }
4349
44-// use the handler at the route /admin/install/traefik
50+func TraefikInstallerSSEHandler(c echo.Context, a *app.App) error {
51+ w := c.Response().Writer
52+ flusher, ok := w.(http.Flusher)
53+ if !ok {
54+ return c.String(http.StatusInternalServerError, "Streaming unsupported!")
55+ }
56+
57+ c.Response().Header().Set("Content-Type", "text/event-stream")
58+ c.Response().Header().Set("Cache-Control", "no-cache")
59+ c.Response().Header().Set("Connection", "keep-alive")
60+
61+ for {
62+ // Listen for a new message to be sent to the client
63+ msg, open := <-eventsChan
64+ if !open {
65+ fmt.Println("Connection closed")
66+ break
67+ }
68+ _, err := fmt.Fprintf(w, "data: %s\n\n", msg)
69+ if err != nil {
70+ return err
71+ }
72+ flusher.Flush()
73+ }
74+ return nil
75+}
@@ -1,14 +1,20 @@
1 package handlers1 package handlers
2 2
3 import (3 import (
4+ "fmt"
5+ "net/http"
6+
4 "github.com/labstack/echo/v4"7 "github.com/labstack/echo/v4"
5 "gogs.bnema.dev/gordon-echo/internal/app"8 "gogs.bnema.dev/gordon-echo/internal/app"
6 "gogs.bnema.dev/gordon-echo/pkg/scripts"9 "gogs.bnema.dev/gordon-echo/pkg/scripts"
7 )10 )
8 11
12+var eventsChan = make(chan string)
13+
9 // TraefikInstallerHandler handles the installation of Traefik14 // TraefikInstallerHandler handles the installation of Traefik
10 func TraefikInstallerHandler(c echo.Context, a *app.App) error {15 func TraefikInstallerHandler(c echo.Context, a *app.App) error {
11 logger := a.AppLogger16 logger := a.AppLogger
17+ eventsChan <- "Starting Traefik installation..."
12 // Retrieve the logger from the context18 // Retrieve the logger from the context
13 // Reject POST requests if they are not allowed with the RejectPOSTPolicy function19 // Reject POST requests if they are not allowed with the RejectPOSTPolicy function
14 if err := RejectPOSTPolicy(c); err != nil {20 if err := RejectPOSTPolicy(c); err != nil {
@@ -36,9 +42,34 @@ func TraefikInstallerHandler(c echo.Context, a *app.App) error {
36 logger.Error().Msg("Failed to install Traefik")42 logger.Error().Msg("Failed to install Traefik")
37 return err43 return err
38 } else {44 } else {
39- logger.Info().Msg("Traefik installed successfully")45+ eventsChan <- "Traefik installation completed!"
40 return c.String(200, "Traefik installed successfully")46 return c.String(200, "Traefik installed successfully")
41 }47 }
42 }48 }
43 49
44-// use the handler at the route /admin/install/traefik50+func TraefikInstallerSSEHandler(c echo.Context, a *app.App) error {
51+ w := c.Response().Writer
52+ flusher, ok := w.(http.Flusher)
53+ if !ok {
54+ return c.String(http.StatusInternalServerError, "Streaming unsupported!")
55+ }
56+
57+ c.Response().Header().Set("Content-Type", "text/event-stream")
58+ c.Response().Header().Set("Cache-Control", "no-cache")
59+ c.Response().Header().Set("Connection", "keep-alive")
60+
61+ for {
62+ // Listen for a new message to be sent to the client
63+ msg, open := <-eventsChan
64+ if !open {
65+ fmt.Println("Connection closed")
66+ break
67+ }
68+ _, err := fmt.Fprintf(w, "data: %s\n\n", msg)
69+ if err != nil {
70+ return err
71+ }
72+ flusher.Flush()
73+ }
74+ return nil
75+}
M internal/http/routes/router.go +3 -0
@@ -36,6 +36,9 @@ func bindAdminRoutes(e *echo.Echo, a *app.App, ac *app.Config) *echo.Echo {
3636 e.POST("/admin/install/traefik", func(c echo.Context) error {
3737 return handlers.TraefikInstallerHandler(c, a)
3838 })
39+ e.GET("/admin/install/traefik/sse", func(c echo.Context) error {
40+ return handlers.TraefikInstallerSSEHandler(c, a)
41+ })
3942 return e
4043 }
4144
@@ -36,6 +36,9 @@ func bindAdminRoutes(e *echo.Echo, a *app.App, ac *app.Config) *echo.Echo {
36 e.POST("/admin/install/traefik", func(c echo.Context) error {36 e.POST("/admin/install/traefik", func(c echo.Context) error {
37 return handlers.TraefikInstallerHandler(c, a)37 return handlers.TraefikInstallerHandler(c, a)
38 })38 })
39+ e.GET("/admin/install/traefik/sse", func(c echo.Context) error {
40+ return handlers.TraefikInstallerSSEHandler(c, a)
41+ })
39 return e42 return e
40 }43 }
41 44
M internal/ui/templates/install.gohtml +1 -1
@@ -100,7 +100,7 @@
100100 <div
101101 class="flex flex-col space-y-2"
102102 hx-ext="sse"
103- sse-connect="/install/traefik/sse"
103+ sse-connect="/admin/install/traefik/sse"
104104 >
105105 <!-- One item -->
106106 <div class="flex flex-row items-center">
@@ -100,7 +100,7 @@
100 <div100 <div
101 class="flex flex-col space-y-2"101 class="flex flex-col space-y-2"
102 hx-ext="sse"102 hx-ext="sse"
103- sse-connect="/install/traefik/sse"103+ sse-connect="/admin/install/traefik/sse"
104 >104 >
105 <!-- One item -->105 <!-- One item -->
106 <div class="flex flex-row items-center">106 <div class="flex flex-row items-center">

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close