Implémenter page web de scan de présence
Voir diff pour détails
This commit is contained in:
parent
c6f3a52f91
commit
c218860e33
10 changed files with 139 additions and 10 deletions
|
@ -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
|
||||||
|
}
|
||||||
|
|
12
cmd/web.go
12
cmd/web.go
|
@ -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))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 }}
|
||||||
|
|
3
webcontent/html/scan.html
Normal file
3
webcontent/html/scan.html
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{{ define "scan-html" }}
|
||||||
|
<h3>{{ .Message }}</h3>
|
||||||
|
{{ end }}
|
1
webcontent/js/htmx.min.js
vendored
Normal file
1
webcontent/js/htmx.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
14
webcontent/js/membreid-selected-and-cleared.js
Normal file
14
webcontent/js/membreid-selected-and-cleared.js
Normal 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);
|
||||||
|
};
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue