Implémenter page web de scan de présence

Voir diff pour détails
This commit is contained in:
Victor Lacasse-Beaudoin 2023-09-17 16:32:40 -04:00
parent c6f3a52f91
commit c218860e33
10 changed files with 139 additions and 10 deletions

View file

@ -17,8 +17,8 @@ type APIClient struct {
Protocol string Protocol string
} }
func New(key, host, protocol string, port int) APIClient { func New(key, host, protocol string, port int) *APIClient {
return APIClient{ return &APIClient{
Key: key, Key: key,
Host: host, Host: host,
Port: port, Port: port,
@ -83,3 +83,11 @@ func (a *APIClient) Call(method, route string, requestBody io.Reader, useKey boo
return response, nil return response, nil
} }
func (a *APIClient) Scan(membreID string) (response apiresponse.ScanPOST, err error) {
//TODO implement api key
//err = a.CallResponder(http.MethodPost, "/v0/scan", &buf, true, &response)
err = a.CallResponder(http.MethodPost, fmt.Sprintf("/v0/scan/%s", membreID), nil, false, &response)
return
}

View file

@ -6,7 +6,9 @@ package cmd
import ( import (
"fmt" "fmt"
"log" "log"
"net/http"
"git.agecem.com/agecem/bottin-ag/apiclient"
"git.agecem.com/agecem/bottin-ag/config" "git.agecem.com/agecem/bottin-ag/config"
"git.agecem.com/agecem/bottin-ag/webcontent" "git.agecem.com/agecem/bottin-ag/webcontent"
"git.agecem.com/agecem/bottin-ag/webhandler" "git.agecem.com/agecem/bottin-ag/webhandler"
@ -31,10 +33,18 @@ var webCmd = &cobra.Command{
e.Pre(middleware.AddTrailingSlash()) e.Pre(middleware.AddTrailingSlash())
handler := webhandler.New() apiClient := apiclient.New(cfg.Web.API.Key, cfg.Web.API.Host, cfg.Web.API.Protocol, cfg.Web.API.Port)
handler := webhandler.New(apiClient)
webhandler.DeclareRoutes(e, &handler) webhandler.DeclareRoutes(e, &handler)
publicGroup := e.Group("/public/*")
publicGroup.Use(middleware.StaticWithConfig(middleware.StaticConfig{
Root: "/",
Filesystem: http.FS(webcontent.PublicFS()),
}))
e.Start(fmt.Sprintf(":%d", cfg.Web.Port)) e.Start(fmt.Sprintf(":%d", cfg.Web.Port))
}, },
} }

View file

@ -17,6 +17,7 @@ type Config struct {
} }
type APIConfig struct { type APIConfig struct {
Key string
Port int Port int
} }
@ -39,6 +40,12 @@ type DBConfig struct {
} }
type WebConfig struct { type WebConfig struct {
API struct {
Host string
Key string
Port int
Protocol string
}
Port int Port int
} }
@ -87,6 +94,12 @@ func RegisterFlags(cmd *cobra.Command) error {
return err return err
} }
// api.key ; --api-key
if err := RegisterString(cmd, true,
"api.key", "api-key", "API server key", "bottinag"); err != nil {
return err
}
// bottin.api.host // bottin.api.host
if err := RegisterString(cmd, true, if err := RegisterString(cmd, true,
"bottin.api.host", "bottin-api-host", "Bottin API server host", "localhost"); err != nil { "bottin.api.host", "bottin-api-host", "Bottin API server host", "localhost"); err != nil {
@ -147,6 +160,30 @@ func RegisterFlags(cmd *cobra.Command) error {
return err return err
} }
// web.api.host
if err := RegisterString(cmd, true,
"web.api.host", "web-api-host", "Webserver API client host", "localhost"); err != nil {
return err
}
// web.api.key
if err := RegisterString(cmd, true,
"web.api.key", "web-api-key", "Webserver API client key", "bottinag"); err != nil {
return err
}
// web.api.port
if err := RegisterInt(cmd, true,
"web.api.port", "web-api-port", "Webserver API client port", 3182); err != nil {
return err
}
// web.api.protocol
if err := RegisterString(cmd, true,
"web.api.protocol", "web-api-protocol", "Webserver API client protocol", "http"); err != nil {
return err
}
// web.port ; --web-port // web.port ; --web-port
cmd.PersistentFlags().Int("web-port", 3183, "Webserver port") cmd.PersistentFlags().Int("web-port", 3183, "Webserver port")
if err := viper.BindPFlag("web.port", cmd.PersistentFlags().Lookup("web-port")); err != nil { if err := viper.BindPFlag("web.port", cmd.PersistentFlags().Lookup("web-port")); err != nil {

View file

@ -1,7 +1,25 @@
{{ define "index-html" }} {{ define "index-html" }}
<h2>agecem/bottin-ag</h2> <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>AGECEM | Assemblée Générale</title>
<script src="/public/js/htmx.min.js"></script>
<script src="/public/js/membreid-selected-and-cleared.js"></script>
</head>
<body>
<h2>Présences en Assemblée Générale</h2>
<h3>StatusCode: {{ .StatusCode }}</h3> {{ if .Error }}<h3>Error: {{ .Error }}</h3>{{ end }}
<h3>Message: {{ .Message }}</h3>
<h3>Error: {{ .Error }}</h3> <form action="" hx-post="/scan" hx-target="#app-content">
<label for="membre_id">Numéro étudiant:</label>
<input id="membre_id" name="membre_id" value="" required />
<button type="submit">enregistrer</button>
</form>
<div id="app-content">
</div>
</body>
</html>
{{ end }} {{ end }}

View file

@ -0,0 +1,3 @@
{{ define "scan-html" }}
<h3>{{ .Message }}</h3>
{{ end }}

1
webcontent/js/htmx.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,14 @@
function clearInput(inputId) {
document.getElementById(inputId).value = '';
};
function focusInput(inputId) {
document.getElementById(inputId).focus();
};
window.onload = function() {
inputId = "membre_id";
clearInput(inputId);
focusInput(inputId);
};

View file

@ -12,13 +12,20 @@ import (
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
) )
//go:embed html/*html //go:embed html/*.html
var htmlFS embed.FS var htmlFS embed.FS
//go:embed js/*.js
var publicFS embed.FS
func HTMLFS() embed.FS { func HTMLFS() embed.FS {
return htmlFS return htmlFS
} }
func PublicFS() embed.FS {
return publicFS
}
type Template struct { type Template struct {
templates *template.Template templates *template.Template
} }

View file

@ -2,21 +2,27 @@
package webhandler package webhandler
import ( import (
"log"
"net/http" "net/http"
"git.agecem.com/agecem/bottin-ag/apiclient"
"git.agecem.com/agecem/bottin-ag/webresponse" "git.agecem.com/agecem/bottin-ag/webresponse"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
) )
func DeclareRoutes(e *echo.Echo, h *WebHandler) { func DeclareRoutes(e *echo.Echo, h *WebHandler) {
e.GET("/", h.IndexGET) e.GET("/", h.IndexGET)
e.POST("/scan/", h.ScanPOST)
} }
type WebHandler struct { type WebHandler struct {
APIClient *apiclient.APIClient
} }
func New() WebHandler { func New(apiClient *apiclient.APIClient) WebHandler {
return WebHandler{} return WebHandler{
APIClient: apiClient,
}
} }
func (w *WebHandler) IndexGET(c echo.Context) error { func (w *WebHandler) IndexGET(c echo.Context) error {
@ -27,3 +33,24 @@ func (w *WebHandler) IndexGET(c echo.Context) error {
return c.Render(r.StatusCode, "index-html", r) return c.Render(r.StatusCode, "index-html", r)
} }
func (w *WebHandler) ScanPOST(c echo.Context) error {
var r webresponse.ScanPOST
membreID := c.FormValue("membre_id")
//TODO
log.Println("membreID:", membreID)
r.StatusCode = http.StatusOK
scanResponse, err := w.APIClient.Scan(membreID)
r.Error = scanResponse.Error
if err != nil {
r.Error = err.Error()
}
r.Message = scanResponse.Message
return c.Render(r.StatusCode, "scan-html", r)
}

View file

@ -5,3 +5,7 @@ import "git.agecem.com/agecem/bottin-ag/apiresponse"
type IndexGET struct { type IndexGET struct {
apiresponse.Response apiresponse.Response
} }
type ScanPOST struct {
apiresponse.Response
}