Basic functionality
This commit is contained in:
parent
17f878f088
commit
72dce76e2b
2
go.mod
2
go.mod
|
@ -14,6 +14,7 @@ require (
|
||||||
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
||||||
github.com/mergestat/timediff v0.0.3 // indirect
|
github.com/mergestat/timediff v0.0.3 // indirect
|
||||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||||
|
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
|
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
|
||||||
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
|
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
|
||||||
|
@ -31,6 +32,7 @@ require (
|
||||||
require (
|
require (
|
||||||
github.com/go-chi/chi v1.5.5
|
github.com/go-chi/chi v1.5.5
|
||||||
github.com/go-chi/chi/v5 v5.0.12 // indirect
|
github.com/go-chi/chi/v5 v5.0.12 // indirect
|
||||||
|
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||||
github.com/gorcon/rcon v1.3.5 // indirect
|
github.com/gorcon/rcon v1.3.5 // indirect
|
||||||
github.com/joho/godotenv v1.5.1 // indirect
|
github.com/joho/godotenv v1.5.1 // indirect
|
||||||
github.com/uptrace/bun v1.2.1
|
github.com/uptrace/bun v1.2.1
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -8,6 +8,8 @@ github.com/go-chi/chi v1.5.5 h1:vOB/HbEMt9QqBqErz07QehcOKHaWFtuj87tTDVz2qXE=
|
||||||
github.com/go-chi/chi v1.5.5/go.mod h1:C9JqLr3tIYjDOZpzn+BCuxY8z8vmca43EeMgyZt7irw=
|
github.com/go-chi/chi v1.5.5/go.mod h1:C9JqLr3tIYjDOZpzn+BCuxY8z8vmca43EeMgyZt7irw=
|
||||||
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
|
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
|
||||||
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||||
|
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||||
|
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorcon/rcon v1.3.5 h1:YE/Vrw6R99uEP08wp0EjdPAP3Jwz/ys3J8qxI1nYoeU=
|
github.com/gorcon/rcon v1.3.5 h1:YE/Vrw6R99uEP08wp0EjdPAP3Jwz/ys3J8qxI1nYoeU=
|
||||||
|
@ -26,6 +28,8 @@ github.com/mergestat/timediff v0.0.3 h1:ucCNh4/ZrTPjFZ081PccNbhx9spymCJkFxSzgVuP
|
||||||
github.com/mergestat/timediff v0.0.3/go.mod h1:yvMUaRu2oetc+9IbPLYBJviz6sA7xz8OXMDfhBl7YSI=
|
github.com/mergestat/timediff v0.0.3/go.mod h1:yvMUaRu2oetc+9IbPLYBJviz6sA7xz8OXMDfhBl7YSI=
|
||||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||||
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||||
|
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||||
|
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
|
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
|
||||||
|
|
36
main.go
36
main.go
|
@ -28,23 +28,47 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
cs := services.NewCaptureService(persistence)
|
cs := services.NewCaptureService(persistence)
|
||||||
server := routes.NewServer(cs)
|
|
||||||
|
cod4StatusProvider := &models.CoD4UdpClient{}
|
||||||
|
|
||||||
|
cachedProvider, err := models.NewCachedProvider(cod4StatusProvider)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cod4Service, err := services.NewCoD4Server(cachedProvider)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
server := routes.NewServer(cs, cod4Service)
|
||||||
|
|
||||||
doneChan := make(chan bool)
|
doneChan := make(chan bool)
|
||||||
scanner, err := services.NewScanner(persistence, time.Second*10, doneChan)
|
scanner, err := services.NewScanner(persistence, cachedProvider, time.Second*10, doneChan)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
go scanner.Scan()
|
go scanner.Scan()
|
||||||
|
|
||||||
router.Use(routes.PathMiddleware)
|
router.Use(routes.PathMiddleware, routes.AuthMiddleware)
|
||||||
router.Handle("/*", public())
|
router.Handle("/*", public())
|
||||||
router.Get("/health", routes.Make(server.HandleHealth))
|
router.Get("/health", routes.Make(server.HandleHealth))
|
||||||
|
router.Get("/server/status", routes.Make(server.HandleServerStatus))
|
||||||
router.Get("/captures/{captureID}", routes.Make(server.HandleCapture))
|
router.Get("/captures/{captureID}", routes.Make(server.HandleCapture))
|
||||||
router.Delete("/captures/{captureID}", routes.Make(server.HandleCaptureDelete))
|
router.Get("/captures/{captureID}/table", routes.Make(server.HandleCaptureTable))
|
||||||
router.Get("/new/capture", routes.Make(server.HandleCaptureForm))
|
router.Get("/login", routes.Make(server.HandleLogin))
|
||||||
router.Post("/new/capture", routes.Make(server.HandleCaptureCreate))
|
router.Get("/logout", routes.Make(server.HandleLogout))
|
||||||
|
router.Group(func(r chi.Router) {
|
||||||
|
r.Use(routes.OnlyAuthenticatedMiddleware)
|
||||||
|
|
||||||
|
r.Delete("/captures/{captureID}", routes.Make(server.HandleCaptureDelete))
|
||||||
|
r.Get("/captures/{captureID}/start", routes.Make(server.HandleCaptureStart))
|
||||||
|
r.Get("/captures/{captureID}/stop", routes.Make(server.HandleCaptureStop))
|
||||||
|
r.Post("/new/capture", routes.Make(server.HandleCaptureCreate))
|
||||||
|
r.Get("/new/capture", routes.Make(server.HandleCaptureForm))
|
||||||
|
})
|
||||||
|
router.Post("/signin", routes.Make(server.HandleSignin))
|
||||||
router.Get("/", routes.Make(server.HandleHome))
|
router.Get("/", routes.Make(server.HandleHome))
|
||||||
|
|
||||||
listenAddr := os.Getenv("LISTEN_ADDR")
|
listenAddr := os.Getenv("LISTEN_ADDR")
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/patrickmn/go-cache"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CachedProvider struct {
|
||||||
|
provider StatusProvider
|
||||||
|
cache *cache.Cache
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCachedProvider(provider StatusProvider) (*CachedProvider, error) {
|
||||||
|
c := cache.New(10*time.Second, 20*time.Second)
|
||||||
|
|
||||||
|
return &CachedProvider{
|
||||||
|
provider: provider,
|
||||||
|
cache: c,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CachedProvider) GetServerStatus(host, port string, timeout time.Duration) (*CoD4ServerStatus, error) {
|
||||||
|
status, found := c.cache.Get(ID(host, port))
|
||||||
|
if found {
|
||||||
|
return status.(*CoD4ServerStatus), nil
|
||||||
|
} else {
|
||||||
|
status, err := c.provider.GetServerStatus(host, port, timeout)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.cache.Set(ID(host, port), status, cache.DefaultExpiration)
|
||||||
|
|
||||||
|
return status, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ID(host, port string) string {
|
||||||
|
return fmt.Sprintf("%s:%s", host, port)
|
||||||
|
}
|
|
@ -12,38 +12,44 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var timeLayout = "Mon Jan 2 15:04:05 2006"
|
var (
|
||||||
|
timeLayout = "Mon Jan 2 15:04:05 2006"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StatusProvider interface {
|
||||||
|
GetServerStatus(string, string, time.Duration) (*CoD4ServerStatus, error)
|
||||||
|
}
|
||||||
|
|
||||||
type CoD4Server struct {
|
type CoD4Server struct {
|
||||||
server string
|
server string
|
||||||
port string
|
port string
|
||||||
protocol string
|
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
type CoD4ServerStatus struct {
|
type CoD4ServerStatus struct {
|
||||||
raw string
|
raw string
|
||||||
serverData map[string]string
|
serverData map[string]string
|
||||||
|
Name string
|
||||||
MapStartTime time.Time
|
MapStartTime time.Time
|
||||||
MapName string
|
MapName string
|
||||||
|
MaxPlayers int
|
||||||
Score []Score
|
Score []Score
|
||||||
meta map[string]interface{}
|
meta map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCOD4ServerStatus(server, port string, timeout time.Duration) (*CoD4Server, error) {
|
type CoD4UdpClient struct{}
|
||||||
|
|
||||||
|
func (CoD4UdpClient) GetServerStatus(server, port string, timeout time.Duration) (*CoD4ServerStatus, error) {
|
||||||
if server == "" || port == "" {
|
if server == "" || port == "" {
|
||||||
return nil, errors.New("server or port is empty")
|
return nil, errors.New("server or port is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &CoD4Server{
|
c := &CoD4Server{
|
||||||
server: server,
|
server: server,
|
||||||
port: port,
|
port: port,
|
||||||
protocol: "udp",
|
|
||||||
timeout: timeout,
|
timeout: timeout,
|
||||||
}, nil
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (c *CoD4Server) GetServerStatus() (*CoD4ServerStatus, error) {
|
|
||||||
data, err := c.receiveData()
|
data, err := c.receiveData()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -54,7 +60,7 @@ func (c *CoD4Server) GetServerStatus() (*CoD4ServerStatus, error) {
|
||||||
|
|
||||||
func (c *CoD4Server) receiveData() (string, error) {
|
func (c *CoD4Server) receiveData() (string, error) {
|
||||||
address := fmt.Sprintf("%s:%s", c.server, c.port)
|
address := fmt.Sprintf("%s:%s", c.server, c.port)
|
||||||
conn, err := net.DialTimeout(c.protocol, address, c.timeout)
|
conn, err := net.DialTimeout("udp", address, c.timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("could not connect to server: %s", err)
|
return "", fmt.Errorf("could not connect to server: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -105,11 +111,16 @@ func parseServerData(data string) (*CoD4ServerStatus, error) {
|
||||||
c.serverData[tempData[i]] = tempData[i+1]
|
c.serverData[tempData[i]] = tempData[i+1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startTime, err := time.ParseInLocation(timeLayout, c.serverData["g_mapStartTime"], time.Local)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
c.serverData["sv_hostname"] = colorCode(c.serverData["sv_hostname"])
|
c.serverData["sv_hostname"] = colorCode(c.serverData["sv_hostname"])
|
||||||
|
c.Name = c.serverData["sv_hostname"]
|
||||||
c.serverData["_Maps"] = strings.Join(strings.Split(c.serverData["_Maps"], "-"), ",")
|
c.serverData["_Maps"] = strings.Join(strings.Split(c.serverData["_Maps"], "-"), ",")
|
||||||
c.MapName = c.serverData["mapname"]
|
c.MapName = c.serverData["mapname"]
|
||||||
|
c.MaxPlayers, err = strconv.Atoi(c.serverData["sv_maxclients"])
|
||||||
startTime, err := time.ParseInLocation(timeLayout, c.serverData["g_mapStartTime"], time.Local)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -159,9 +170,19 @@ func colorCode(str string) string {
|
||||||
"9": "#6E3C3C",
|
"9": "#6E3C3C",
|
||||||
}
|
}
|
||||||
|
|
||||||
re := regexp.MustCompile(`\^(\d)(.*?)\^`)
|
re := regexp.MustCompile(`\^(\d)`)
|
||||||
return re.ReplaceAllStringFunc(str, func(m string) string {
|
str = re.ReplaceAllStringFunc(str, func(m string) string {
|
||||||
matches := re.FindStringSubmatch(m)
|
code := string(m[1])
|
||||||
return fmt.Sprintf(`<span style="color:%s;">%s</span>^`, colorMap[matches[1]], matches[2])
|
if color, ok := colorMap[code]; ok {
|
||||||
|
return fmt.Sprintf(`<span style="color:%s;">`, color)
|
||||||
|
}
|
||||||
|
return m
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Close open span tags
|
||||||
|
str += "^"
|
||||||
|
reClose := regexp.MustCompile(`\^(.*?)\^`)
|
||||||
|
str = reClose.ReplaceAllString(str, "$1</span>")
|
||||||
|
|
||||||
|
return str[:len(str)-1]
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
|
|
||||||
type Persistence interface {
|
type Persistence interface {
|
||||||
CreateCapture(context.Context, *Capture) error
|
CreateCapture(context.Context, *Capture) error
|
||||||
|
UpdateCapture(context.Context, *Capture) error
|
||||||
GetCaptures(context.Context) ([]Capture, error)
|
GetCaptures(context.Context) ([]Capture, error)
|
||||||
GetCapturesByID(context.Context, int64) (*Capture, error)
|
GetCapturesByID(context.Context, int64) (*Capture, error)
|
||||||
DeleteCapture(context.Context, int64) error
|
DeleteCapture(context.Context, int64) error
|
||||||
|
@ -68,6 +69,12 @@ func (s *SQLitePersistence) GetCapturesByID(ctx context.Context, id int64) (*Cap
|
||||||
return &capture, err
|
return &capture, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SQLitePersistence) UpdateCapture(ctx context.Context, capture *Capture) error {
|
||||||
|
_, err := s.db.NewUpdate().Model(capture).WherePK().Exec(ctx)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (s *SQLitePersistence) DeleteCapture(ctx context.Context, id int64) error {
|
func (s *SQLitePersistence) DeleteCapture(ctx context.Context, id int64) error {
|
||||||
capture := Capture{
|
capture := Capture{
|
||||||
ID: id,
|
ID: id,
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
package routes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gitea.henriburau.de/haw-lan/cod4watcher/services"
|
||||||
|
"gitea.henriburau.de/haw-lan/cod4watcher/views/auth"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) HandleLogin(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
return Render(w, r, auth.LoginForm(auth.LoginFormValues{}, map[string]string{}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) HandleSignin(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
r.ParseForm()
|
||||||
|
|
||||||
|
creds := services.Credentials{
|
||||||
|
Username: r.FormValue("username"),
|
||||||
|
Password: r.FormValue("password"),
|
||||||
|
}
|
||||||
|
|
||||||
|
token, expiresIn, err := services.Signin(creds)
|
||||||
|
if err != nil {
|
||||||
|
errors := map[string]string{
|
||||||
|
"username": "username or password incorrect" + err.Error(),
|
||||||
|
"password": "username or password incorrect" + err.Error(),
|
||||||
|
}
|
||||||
|
return Render(w, r, auth.LoginForm(auth.LoginFormValues{
|
||||||
|
Username: creds.Username,
|
||||||
|
Password: creds.Password,
|
||||||
|
}, errors))
|
||||||
|
}
|
||||||
|
|
||||||
|
http.SetCookie(w, &http.Cookie{
|
||||||
|
Name: "session_token",
|
||||||
|
Value: token,
|
||||||
|
Expires: expiresIn,
|
||||||
|
})
|
||||||
|
|
||||||
|
return hxRedirect(w, r, "/")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) HandleLogout(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
http.SetCookie(w, &http.Cookie{
|
||||||
|
Name: "session_token",
|
||||||
|
Value: "",
|
||||||
|
Expires: time.Time{},
|
||||||
|
})
|
||||||
|
|
||||||
|
return hxRedirect(w, r, "/")
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package routes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"log/slog"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"gitea.henriburau.de/haw-lan/cod4watcher/services"
|
||||||
|
"gitea.henriburau.de/haw-lan/cod4watcher/views"
|
||||||
|
)
|
||||||
|
|
||||||
|
func OnlyAuthenticatedMiddleware(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
session, err := getSession(r)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("failed to optain session", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if session != nil {
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func AuthMiddleware(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
session, err := getSession(r)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("error getting token", "err", err)
|
||||||
|
}
|
||||||
|
username := ""
|
||||||
|
if session != nil {
|
||||||
|
username = session.Username
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := context.WithValue(r.Context(), views.AuthContext, username)
|
||||||
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSession(r *http.Request) (*services.Session, error) {
|
||||||
|
c, err := r.Cookie("session_token")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionToken := c.Value
|
||||||
|
|
||||||
|
session, err := services.GetSession(sessionToken)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if session.IsExpired() {
|
||||||
|
services.RemoveSession(sessionToken)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return session, nil
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import (
|
||||||
|
|
||||||
"gitea.henriburau.de/haw-lan/cod4watcher/models"
|
"gitea.henriburau.de/haw-lan/cod4watcher/models"
|
||||||
"gitea.henriburau.de/haw-lan/cod4watcher/views/capture"
|
"gitea.henriburau.de/haw-lan/cod4watcher/views/capture"
|
||||||
|
"gitea.henriburau.de/haw-lan/cod4watcher/views/components"
|
||||||
"github.com/go-chi/chi"
|
"github.com/go-chi/chi"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -22,7 +23,52 @@ func (s *Server) HandleCapture(w http.ResponseWriter, r *http.Request) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return Render(w, r, capture.Capture(foundCapture))
|
return Render(w, r, capture.Capture(foundCapture, *foundCapture.MapScores.BuildTable()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) HandleCaptureTable(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
captureString := chi.URLParam(r, "captureID")
|
||||||
|
captureID, err := strconv.ParseInt(captureString, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
foundCapture, err := s.cs.GetCaptureById(r.Context(), captureID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return Render(w, r, components.CaptureTable(*foundCapture.MapScores.BuildTable()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) HandleCaptureStart(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
captureString := chi.URLParam(r, "captureID")
|
||||||
|
captureID, err := strconv.ParseInt(captureString, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.cs.StartCapture(r.Context(), captureID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return hxRedirect(w, r, "/")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) HandleCaptureStop(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
captureString := chi.URLParam(r, "captureID")
|
||||||
|
captureID, err := strconv.ParseInt(captureString, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.cs.StopCapture(r.Context(), captureID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return hxRedirect(w, r, "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) HandleCaptureDelete(w http.ResponseWriter, r *http.Request) error {
|
func (s *Server) HandleCaptureDelete(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
@ -58,7 +104,7 @@ func (s *Server) HandleCaptureCreate(w http.ResponseWriter, r *http.Request) err
|
||||||
Start: time.Now(),
|
Start: time.Now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := s.cs.GetServerStatus(r.Context(), newCapture)
|
_, err := s.c4s.GetServerStatus(newCapture.Host, newCapture.Port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors["host"] = err.Error()
|
errors["host"] = err.Error()
|
||||||
errors["port"] = err.Error()
|
errors["port"] = err.Error()
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package routes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"gitea.henriburau.de/haw-lan/cod4watcher/views/cod4server"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) HandleServerStatus(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
status, err := s.c4s.GetServerStatus(r.URL.Query().Get("host"), r.URL.Query().Get("port"))
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return Render(w, r, cod4server.ServerStatus(status))
|
||||||
|
}
|
|
@ -3,17 +3,24 @@ package routes
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"gitea.henriburau.de/haw-lan/cod4watcher/models"
|
||||||
|
"gitea.henriburau.de/haw-lan/cod4watcher/views"
|
||||||
"gitea.henriburau.de/haw-lan/cod4watcher/views/home"
|
"gitea.henriburau.de/haw-lan/cod4watcher/views/home"
|
||||||
"github.com/davecgh/go-spew/spew"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) HandleHome(w http.ResponseWriter, r *http.Request) error {
|
func (s *Server) HandleHome(w http.ResponseWriter, r *http.Request) error {
|
||||||
captureList, err := s.cs.GetActiveCapures(r.Context())
|
|
||||||
|
var captureList []models.Capture
|
||||||
|
var err error
|
||||||
|
if views.Username(r.Context()) != "" {
|
||||||
|
captureList, err = s.cs.GetCaptures(r.Context())
|
||||||
|
} else {
|
||||||
|
captureList, err = s.cs.GetActiveCapures(r.Context())
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
spew.Dump(r.Context())
|
|
||||||
|
|
||||||
return Render(w, r, home.Index(captureList))
|
return Render(w, r, home.Index(captureList))
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,12 @@ func Make(h HTTPHandler) http.HandlerFunc {
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
cs *services.CaptureService
|
cs *services.CaptureService
|
||||||
|
c4s *services.CoD4Service
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(cs *services.CaptureService) *Server {
|
func NewServer(cs *services.CaptureService, c4s *services.CoD4Service) *Server {
|
||||||
return &Server{
|
return &Server{
|
||||||
cs,
|
cs, c4s,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/golang-jwt/jwt"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
users = map[string]string{
|
||||||
|
"henri": "henri123",
|
||||||
|
}
|
||||||
|
secret = []byte("mein-secret")
|
||||||
|
)
|
||||||
|
|
||||||
|
type Session struct {
|
||||||
|
Username string
|
||||||
|
Expiry time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type Credentials struct {
|
||||||
|
Password string
|
||||||
|
Username string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Session) IsExpired() bool {
|
||||||
|
return s.Expiry.Before(time.Now())
|
||||||
|
}
|
||||||
|
|
||||||
|
func Signin(cred Credentials) (string, time.Time, error) {
|
||||||
|
expectedPassword, ok := users[cred.Username]
|
||||||
|
if !ok || expectedPassword != cred.Password {
|
||||||
|
return "", time.Time{}, errors.New("wrong password")
|
||||||
|
}
|
||||||
|
|
||||||
|
expiresAt := time.Now().Add(2 * time.Hour)
|
||||||
|
|
||||||
|
sessionToken, err := tokenFromSession(Session{
|
||||||
|
Username: cred.Username,
|
||||||
|
Expiry: expiresAt,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", time.Time{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return sessionToken, expiresAt, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSession(sessionToken string) (*Session, error) {
|
||||||
|
return sessionFromToken(sessionToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RemoveSession(sessionID string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func tokenFromSession(session Session) (string, error) {
|
||||||
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256,
|
||||||
|
jwt.MapClaims{
|
||||||
|
"username": session.Username,
|
||||||
|
"exp": session.Expiry.Unix(),
|
||||||
|
})
|
||||||
|
|
||||||
|
return token.SignedString(secret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sessionFromToken(tokenString string) (*Session, error) {
|
||||||
|
sessionToken, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
return secret, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !sessionToken.Valid {
|
||||||
|
return nil, errors.New("invalid token")
|
||||||
|
}
|
||||||
|
|
||||||
|
if claims, ok := sessionToken.Claims.(jwt.MapClaims); ok {
|
||||||
|
expiresAt := time.Unix(int64(claims["exp"].(float64)), 0)
|
||||||
|
return &Session{
|
||||||
|
Username: claims["username"].(string),
|
||||||
|
Expiry: expiresAt,
|
||||||
|
}, nil
|
||||||
|
} else {
|
||||||
|
return nil, errors.New("cannot read claims")
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,6 @@ package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
"gitea.henriburau.de/haw-lan/cod4watcher/models"
|
"gitea.henriburau.de/haw-lan/cod4watcher/models"
|
||||||
)
|
)
|
||||||
|
@ -40,14 +39,30 @@ func (cs *CaptureService) GetActiveCapures(ctx context.Context) ([]models.Captur
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
func (cs *CaptureService) GetCaptures(ctx context.Context) ([]models.Capture, error) {
|
||||||
|
return cs.p.GetCaptures(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
func (cs *CaptureService) GetServerStatus(ctx context.Context, capture *models.Capture) (*models.CoD4ServerStatus, error) {
|
func (cs *CaptureService) StartCapture(ctx context.Context, id int64) error {
|
||||||
server, err := models.NewCOD4ServerStatus(capture.Host, capture.Port, time.Second)
|
capture, err := cs.p.GetCapturesByID(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return server.GetServerStatus()
|
capture.Active = true
|
||||||
|
|
||||||
|
return cs.p.UpdateCapture(ctx, capture)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cs *CaptureService) StopCapture(ctx context.Context, id int64) error {
|
||||||
|
capture, err := cs.p.GetCapturesByID(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
capture.Active = false
|
||||||
|
|
||||||
|
return cs.p.UpdateCapture(ctx, capture)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *CaptureService) GetCaptureById(ctx context.Context, id int64) (*models.Capture, error) {
|
func (cs *CaptureService) GetCaptureById(ctx context.Context, id int64) (*models.Capture, error) {
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gitea.henriburau.de/haw-lan/cod4watcher/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CoD4Service struct {
|
||||||
|
p models.StatusProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCoD4Server(p models.StatusProvider) (*CoD4Service, error) {
|
||||||
|
return &CoD4Service{
|
||||||
|
p,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CoD4Service) GetServerStatus(host, port string) (*models.CoD4ServerStatus, error) {
|
||||||
|
return s.p.GetServerStatus(host, port, time.Second)
|
||||||
|
}
|
|
@ -10,13 +10,14 @@ import (
|
||||||
|
|
||||||
type Scanner struct {
|
type Scanner struct {
|
||||||
p models.Persistence
|
p models.Persistence
|
||||||
|
c4s models.StatusProvider
|
||||||
done chan bool
|
done chan bool
|
||||||
interval time.Duration
|
interval time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewScanner(p models.Persistence, interval time.Duration, done chan bool) (*Scanner, error) {
|
func NewScanner(p models.Persistence, c4s models.StatusProvider, interval time.Duration, done chan bool) (*Scanner, error) {
|
||||||
return &Scanner{
|
return &Scanner{
|
||||||
p, done, interval,
|
p, c4s, done, interval,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,12 +53,7 @@ func (s *Scanner) Scan() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Scanner) fetchInformation(ctx context.Context, capture models.Capture) error {
|
func (s *Scanner) fetchInformation(ctx context.Context, capture models.Capture) error {
|
||||||
server, err := models.NewCOD4ServerStatus(capture.Host, capture.Port, time.Second)
|
status, err := s.c4s.GetServerStatus(capture.Host, capture.Port, time.Second)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
status, err := server.GetServerStatus()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gitea.henriburau.de/haw-lan/cod4watcher/views/layouts"
|
||||||
|
"gitea.henriburau.de/haw-lan/cod4watcher/views/components"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LoginFormValues struct {
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
|
||||||
|
templ LoginForm(formValues LoginFormValues, errors map[string]string) {
|
||||||
|
@layouts.Base() {
|
||||||
|
@components.Form(components.FormProps{
|
||||||
|
Title: "Log into your account",
|
||||||
|
Action: "/signin",
|
||||||
|
Method: "post",
|
||||||
|
SubmitText: "Login",
|
||||||
|
}) {
|
||||||
|
<div>
|
||||||
|
<label for="username" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Username</label>
|
||||||
|
@components.Input(components.InputProps{
|
||||||
|
Name: "username",
|
||||||
|
Value: formValues.Username,
|
||||||
|
Error: errors["username"],
|
||||||
|
Placeholder: "Your username",
|
||||||
|
})
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="password" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Password</label>
|
||||||
|
@components.Input(components.InputProps{
|
||||||
|
Name: "password",
|
||||||
|
Value: formValues.Password,
|
||||||
|
Error: errors["password"],
|
||||||
|
Placeholder: "Your password",
|
||||||
|
})
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
// Code generated by templ - DO NOT EDIT.
|
||||||
|
|
||||||
|
// templ: version: v0.2.707
|
||||||
|
package auth
|
||||||
|
|
||||||
|
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||||
|
|
||||||
|
import "github.com/a-h/templ"
|
||||||
|
import "context"
|
||||||
|
import "io"
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gitea.henriburau.de/haw-lan/cod4watcher/views/components"
|
||||||
|
"gitea.henriburau.de/haw-lan/cod4watcher/views/layouts"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LoginFormValues struct {
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoginForm(formValues LoginFormValues, errors map[string]string) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var1 == nil {
|
||||||
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
templ_7745c5c3_Var2 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var3 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div><label for=\"username\" class=\"block mb-2 text-sm font-medium text-gray-900 dark:text-white\">Username</label>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = components.Input(components.InputProps{
|
||||||
|
Name: "username",
|
||||||
|
Value: formValues.Username,
|
||||||
|
Error: errors["username"],
|
||||||
|
Placeholder: "Your username",
|
||||||
|
}).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div><label for=\"password\" class=\"block mb-2 text-sm font-medium text-gray-900 dark:text-white\">Password</label>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = components.Input(components.InputProps{
|
||||||
|
Name: "password",
|
||||||
|
Value: formValues.Password,
|
||||||
|
Error: errors["password"],
|
||||||
|
Placeholder: "Your password",
|
||||||
|
}).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
templ_7745c5c3_Err = components.Form(components.FormProps{
|
||||||
|
Title: "Log into your account",
|
||||||
|
Action: "/signin",
|
||||||
|
Method: "post",
|
||||||
|
SubmitText: "Login",
|
||||||
|
}).Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
templ_7745c5c3_Err = layouts.Base().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
|
@ -3,17 +3,50 @@ package capture
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/models"
|
import "gitea.henriburau.de/haw-lan/cod4watcher/models"
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/views/layouts"
|
import "gitea.henriburau.de/haw-lan/cod4watcher/views/layouts"
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/views/components"
|
import "gitea.henriburau.de/haw-lan/cod4watcher/views/components"
|
||||||
|
import "fmt"
|
||||||
|
import "net/url"
|
||||||
|
|
||||||
templ Capture(capture *models.Capture) {
|
templ Capture(capture *models.Capture, table models.ResultTable) {
|
||||||
@layouts.Base() {
|
@layouts.Base() {
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
|
<div class="flex">
|
||||||
|
<div>
|
||||||
<div class="block font-bold text-lg">
|
<div class="block font-bold text-lg">
|
||||||
{ capture.Name }
|
{ capture.Name }
|
||||||
</div>
|
</div>
|
||||||
<div class="block">
|
@components.ServerAddress(capture.Host, capture.Port)
|
||||||
{ capture.Host }:{ capture.Port }
|
<div
|
||||||
|
class="my-3 w-60"
|
||||||
|
hx-get={ fmt.Sprintf("/server/status?host=%s&port=%s", url.QueryEscape(capture.Host), url.QueryEscape(capture.Port)) }
|
||||||
|
hx-trigger="load, every 20s"
|
||||||
|
>
|
||||||
|
Loading Server status...
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex w-full justify-around items-center gap-5">
|
||||||
|
if len(table.Rows) >= 1 {
|
||||||
|
@Medal("1. Platz", table.Rows[0].Name, "text-yellow-600")
|
||||||
|
}
|
||||||
|
if len(table.Rows) >= 2 {
|
||||||
|
@Medal("2. Platz", table.Rows[1].Name, "text-gray-500")
|
||||||
|
}
|
||||||
|
if len(table.Rows) >= 3 {
|
||||||
|
@Medal("3. Platz", table.Rows[2].Name, "text-amber-700")
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div hx-get={ fmt.Sprintf("/captures/%d/table", capture.ID) } hx-trigger="every 10s">
|
||||||
|
@components.CaptureTable(table)
|
||||||
</div>
|
</div>
|
||||||
@components.CaptureTable(*capture.MapScores.BuildTable())
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
templ Medal(placement, name, color string) {
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<i class={ "fa-solid", "fa-medal","text-3xl", color }></i>
|
||||||
|
<span>
|
||||||
|
{ placement } { name }
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
|
@ -1,19 +1,26 @@
|
||||||
package capture
|
package capture
|
||||||
|
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/views/layouts"
|
import (
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/views/components"
|
"gitea.henriburau.de/haw-lan/cod4watcher/views/layouts"
|
||||||
|
"gitea.henriburau.de/haw-lan/cod4watcher/views/components"
|
||||||
|
)
|
||||||
|
|
||||||
type CaptureFormValues struct {
|
type CaptureFormValues struct {
|
||||||
Host string
|
Host string
|
||||||
Port string
|
Port string
|
||||||
Name string
|
Name string
|
||||||
|
Active bool
|
||||||
|
ValidateServer bool
|
||||||
}
|
}
|
||||||
|
|
||||||
templ CaptureForm(formValues CaptureFormValues, errors map[string]string) {
|
templ CaptureForm(formValues CaptureFormValues, errors map[string]string) {
|
||||||
@layouts.Base() {
|
@layouts.Base() {
|
||||||
<div class="w-full mx-auto max-w-96 p-4 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700">
|
@components.Form(components.FormProps{
|
||||||
<form class="space-y-6" action="/new/capture" method="post">
|
Title: "Create new capture",
|
||||||
<h5 class="text-xl font-medium text-gray-900 dark:text-white">Create new capture</h5>
|
Action: "/new/capture",
|
||||||
|
Method: "post",
|
||||||
|
SubmitText: "Create capture",
|
||||||
|
}) {
|
||||||
<div>
|
<div>
|
||||||
<label for="name" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Name</label>
|
<label for="name" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Name</label>
|
||||||
@components.Input(components.InputProps{
|
@components.Input(components.InputProps{
|
||||||
|
@ -41,10 +48,6 @@ templ CaptureForm(formValues CaptureFormValues, errors map[string]string) {
|
||||||
Placeholder: "Port for the capture",
|
Placeholder: "Port for the capture",
|
||||||
})
|
})
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" method="post" class="w-full text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
|
}
|
||||||
Create capture
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,13 +10,17 @@ import "context"
|
||||||
import "io"
|
import "io"
|
||||||
import "bytes"
|
import "bytes"
|
||||||
|
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/views/layouts"
|
import (
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/views/components"
|
"gitea.henriburau.de/haw-lan/cod4watcher/views/components"
|
||||||
|
"gitea.henriburau.de/haw-lan/cod4watcher/views/layouts"
|
||||||
|
)
|
||||||
|
|
||||||
type CaptureFormValues struct {
|
type CaptureFormValues struct {
|
||||||
Host string
|
Host string
|
||||||
Port string
|
Port string
|
||||||
Name string
|
Name string
|
||||||
|
Active bool
|
||||||
|
ValidateServer bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func CaptureForm(formValues CaptureFormValues, errors map[string]string) templ.Component {
|
func CaptureForm(formValues CaptureFormValues, errors map[string]string) templ.Component {
|
||||||
|
@ -38,7 +42,13 @@ func CaptureForm(formValues CaptureFormValues, errors map[string]string) templ.C
|
||||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"w-full mx-auto max-w-96 p-4 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700\"><form class=\"space-y-6\" action=\"/new/capture\" method=\"post\"><h5 class=\"text-xl font-medium text-gray-900 dark:text-white\">Create new capture</h5><div><label for=\"name\" class=\"block mb-2 text-sm font-medium text-gray-900 dark:text-white\">Name</label>")
|
templ_7745c5c3_Var3 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div><label for=\"name\" class=\"block mb-2 text-sm font-medium text-gray-900 dark:text-white\">Name</label>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
@ -77,7 +87,21 @@ func CaptureForm(formValues CaptureFormValues, errors map[string]string) templ.C
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><button type=\"submit\" method=\"post\" class=\"w-full text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800\">Create capture</button></form></div>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
templ_7745c5c3_Err = components.Form(components.FormProps{
|
||||||
|
Title: "Create new capture",
|
||||||
|
Action: "/new/capture",
|
||||||
|
Method: "post",
|
||||||
|
SubmitText: "Create capture",
|
||||||
|
}).Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,10 @@ import "bytes"
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/models"
|
import "gitea.henriburau.de/haw-lan/cod4watcher/models"
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/views/layouts"
|
import "gitea.henriburau.de/haw-lan/cod4watcher/views/layouts"
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/views/components"
|
import "gitea.henriburau.de/haw-lan/cod4watcher/views/components"
|
||||||
|
import "fmt"
|
||||||
|
import "net/url"
|
||||||
|
|
||||||
func Capture(capture *models.Capture) templ.Component {
|
func Capture(capture *models.Capture, table models.ResultTable) templ.Component {
|
||||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
@ -33,54 +35,84 @@ func Capture(capture *models.Capture) templ.Component {
|
||||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex flex-col\"><div class=\"block font-bold text-lg\">")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex flex-col\"><div class=\"flex\"><div><div class=\"block font-bold text-lg\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var3 string
|
var templ_7745c5c3_Var3 string
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(capture.Name)
|
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(capture.Name)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/capture/capture.templ`, Line: 11, Col: 18}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/capture/capture.templ`, Line: 15, Col: 20}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"block\">")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = components.ServerAddress(capture.Host, capture.Port).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"my-3 w-60\" hx-get=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var4 string
|
var templ_7745c5c3_Var4 string
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(capture.Host)
|
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/server/status?host=%s&port=%s", url.QueryEscape(capture.Host), url.QueryEscape(capture.Port)))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/capture/capture.templ`, Line: 14, Col: 18}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/capture/capture.templ`, Line: 20, Col: 122}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(":")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" hx-trigger=\"load, every 20s\">Loading Server status...</div></div><div class=\"flex w-full justify-around items-center gap-5\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if len(table.Rows) >= 1 {
|
||||||
|
templ_7745c5c3_Err = Medal("1. Platz", table.Rows[0].Name, "text-yellow-600").Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(table.Rows) >= 2 {
|
||||||
|
templ_7745c5c3_Err = Medal("2. Platz", table.Rows[1].Name, "text-gray-500").Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(table.Rows) >= 3 {
|
||||||
|
templ_7745c5c3_Err = Medal("3. Platz", table.Rows[2].Name, "text-amber-700").Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div><div hx-get=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var5 string
|
var templ_7745c5c3_Var5 string
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(capture.Port)
|
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/captures/%d/table", capture.ID))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/capture/capture.templ`, Line: 14, Col: 35}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/capture/capture.templ`, Line: 38, Col: 62}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" hx-trigger=\"every 10s\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = components.CaptureTable(*capture.MapScores.BuildTable()).Render(ctx, templ_7745c5c3_Buffer)
|
templ_7745c5c3_Err = components.CaptureTable(table).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
@ -99,3 +131,75 @@ func Capture(capture *models.Capture) templ.Component {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Medal(placement, name, color string) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var6 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var6 == nil {
|
||||||
|
templ_7745c5c3_Var6 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex flex-col gap-2\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var7 = []any{"fa-solid", "fa-medal", "text-3xl", color}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var7...)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<i class=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var8 string
|
||||||
|
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var7).String())
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/capture/capture.templ`, Line: 1, Col: 0}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"></i> <span>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var9 string
|
||||||
|
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(placement)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/capture/capture.templ`, Line: 49, Col: 14}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var10 string
|
||||||
|
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(name)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/capture/capture.templ`, Line: 49, Col: 23}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span></div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package cod4server
|
||||||
|
|
||||||
|
import "gitea.henriburau.de/haw-lan/cod4watcher/models"
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
templ ServerStatus(status *models.CoD4ServerStatus) {
|
||||||
|
<div class="flex items-center gap-1 font-normal text-gray-700 dark:text-gray-400">
|
||||||
|
<i class="fa-solid fa-map"></i>
|
||||||
|
<span>{ status.MapName }</span>
|
||||||
|
<i class="fa-solid fa-user"></i>
|
||||||
|
<span>{ fmt.Sprintf("%d/%d",len(status.Score), status.MaxPlayers) }</span>
|
||||||
|
</div>
|
||||||
|
<div class="p-1 rounded-md bg-slate-800">
|
||||||
|
@templ.Raw(status.Name)
|
||||||
|
</div>
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
// Code generated by templ - DO NOT EDIT.
|
||||||
|
|
||||||
|
// templ: version: v0.2.707
|
||||||
|
package cod4server
|
||||||
|
|
||||||
|
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||||
|
|
||||||
|
import "github.com/a-h/templ"
|
||||||
|
import "context"
|
||||||
|
import "io"
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
|
import "gitea.henriburau.de/haw-lan/cod4watcher/models"
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func ServerStatus(status *models.CoD4ServerStatus) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var1 == nil {
|
||||||
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex items-center gap-1 font-normal text-gray-700 dark:text-gray-400\"><i class=\"fa-solid fa-map\"></i> <span>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var2 string
|
||||||
|
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(status.MapName)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/cod4server/server_status.templ`, Line: 9, Col: 24}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span> <i class=\"fa-solid fa-user\"></i> <span>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var3 string
|
||||||
|
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d/%d", len(status.Score), status.MaxPlayers))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/cod4server/server_status.templ`, Line: 11, Col: 67}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span></div><div class=\"p-1 rounded-md bg-slate-800\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templ.Raw(status.Name).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package components
|
||||||
|
|
||||||
|
templ Button() {
|
||||||
|
<button class="w-full text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
|
||||||
|
{ children... }
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ SubmitButton() {
|
||||||
|
<button type="submit" class="w-full text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
|
||||||
|
{ children... }
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ IconButton(icon, url string) {
|
||||||
|
<a href={ templ.SafeURL(url) } class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-full text-sm p-2.5 text-center inline-flex items-center me-2 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
|
||||||
|
<i class={ icon }></i>
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ IconButtonRed(icon, url string) {
|
||||||
|
<a hx-delete={ url } class="text-white bg-red-700 hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-full text-sm p-2.5 text-center inline-flex items-center me-2 dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-800">
|
||||||
|
<i class={ icon }></i>
|
||||||
|
</a>
|
||||||
|
}
|
|
@ -0,0 +1,189 @@
|
||||||
|
// Code generated by templ - DO NOT EDIT.
|
||||||
|
|
||||||
|
// templ: version: v0.2.707
|
||||||
|
package components
|
||||||
|
|
||||||
|
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||||
|
|
||||||
|
import "github.com/a-h/templ"
|
||||||
|
import "context"
|
||||||
|
import "io"
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
|
func Button() templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var1 == nil {
|
||||||
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<button class=\"w-full text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</button>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func SubmitButton() templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var2 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var2 == nil {
|
||||||
|
templ_7745c5c3_Var2 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<button type=\"submit\" class=\"w-full text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templ_7745c5c3_Var2.Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</button>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func IconButton(icon, url string) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var3 == nil {
|
||||||
|
templ_7745c5c3_Var3 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a href=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var4 templ.SafeURL = templ.SafeURL(url)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4)))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" class=\"text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-full text-sm p-2.5 text-center inline-flex items-center me-2 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var5 = []any{icon}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<i class=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var6 string
|
||||||
|
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var5).String())
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/components/button.templ`, Line: 1, Col: 0}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"></i></a>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func IconButtonRed(icon, url string) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var7 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var7 == nil {
|
||||||
|
templ_7745c5c3_Var7 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a hx-delete=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var8 string
|
||||||
|
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(url)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/components/button.templ`, Line: 22, Col: 19}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" class=\"text-white bg-red-700 hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-full text-sm p-2.5 text-center inline-flex items-center me-2 dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-800\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var9 = []any{icon}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var9...)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<i class=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var10 string
|
||||||
|
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var9).String())
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/components/button.templ`, Line: 1, Col: 0}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"></i></a>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,15 +1,31 @@
|
||||||
package components
|
package components
|
||||||
|
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/models"
|
import "gitea.henriburau.de/haw-lan/cod4watcher/models"
|
||||||
import "github.com/mergestat/timediff"
|
import "gitea.henriburau.de/haw-lan/cod4watcher/views"
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
import "net/url"
|
||||||
|
|
||||||
templ CaptureCard(capture models.Capture) {
|
templ CaptureCard(capture models.Capture) {
|
||||||
<div class="block max-w-sm p-6 bg-white border border-gray-200 rounded-lg shadow hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">
|
<div class="block max-w-sm p-6 bg-white border border-gray-200 rounded-lg shadow hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">
|
||||||
<a href={ templ.URL(fmt.Sprintf("/captures/%d", capture.ID)) } >
|
<a href={ templ.URL(fmt.Sprintf("/captures/%d", capture.ID)) }>
|
||||||
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">{ capture.Name }</h5>
|
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">{ capture.Name }</h5>
|
||||||
</a>
|
</a>
|
||||||
<p class="font-normal text-gray-700 dark:text-gray-400">{ timediff.TimeDiff(capture.Start) }</p>
|
<p class="font-normal text-gray-700 dark:text-gray-400">{ capture.Host }:{ capture.Port }</p>
|
||||||
<button type="button" hx-delete={ fmt.Sprintf("/captures/%d", capture.ID) } class="mt-10 py-1 px-2 bg-red-500 text-white rounded-xl">Delete</button>
|
<div
|
||||||
|
hx-get={ fmt.Sprintf("/server/status?host=%s&port=%s", url.QueryEscape(capture.Host), url.QueryEscape(capture.Port)) }
|
||||||
|
hx-trigger="load, every 20s"
|
||||||
|
>
|
||||||
|
Loading Server status...
|
||||||
|
</div>
|
||||||
|
if views.Username(ctx) != "" {
|
||||||
|
<div class="mt-4">
|
||||||
|
@IconButtonRed("fa-solid fa-trash", fmt.Sprintf("/captures/%d", capture.ID))
|
||||||
|
if capture.Active {
|
||||||
|
@IconButton("fa-solid fa-stop", fmt.Sprintf("/captures/%d/stop", capture.ID))
|
||||||
|
} else {
|
||||||
|
@IconButton("fa-solid fa-play", fmt.Sprintf("/captures/%d/start", capture.ID))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,9 @@ import "io"
|
||||||
import "bytes"
|
import "bytes"
|
||||||
|
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/models"
|
import "gitea.henriburau.de/haw-lan/cod4watcher/models"
|
||||||
import "github.com/mergestat/timediff"
|
import "gitea.henriburau.de/haw-lan/cod4watcher/views"
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
import "net/url"
|
||||||
|
|
||||||
func CaptureCard(capture models.Capture) templ.Component {
|
func CaptureCard(capture models.Capture) templ.Component {
|
||||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
@ -43,7 +44,7 @@ func CaptureCard(capture models.Capture) templ.Component {
|
||||||
var templ_7745c5c3_Var3 string
|
var templ_7745c5c3_Var3 string
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(capture.Name)
|
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(capture.Name)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/components/capture_card.templ`, Line: 10, Col: 98}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/components/capture_card.templ`, Line: 11, Col: 98}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
|
@ -54,28 +55,70 @@ func CaptureCard(capture models.Capture) templ.Component {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var4 string
|
var templ_7745c5c3_Var4 string
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(timediff.TimeDiff(capture.Start))
|
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(capture.Host)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/components/capture_card.templ`, Line: 12, Col: 92}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/components/capture_card.templ`, Line: 13, Col: 72}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p><button type=\"button\" hx-delete=\"")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(":")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var5 string
|
var templ_7745c5c3_Var5 string
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/captures/%d", capture.ID))
|
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(capture.Port)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/components/capture_card.templ`, Line: 13, Col: 75}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/components/capture_card.templ`, Line: 13, Col: 89}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" class=\"mt-10 py-1 px-2 bg-red-500 text-white rounded-xl\">Delete</button></div>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p><div hx-get=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var6 string
|
||||||
|
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/server/status?host=%s&port=%s", url.QueryEscape(capture.Host), url.QueryEscape(capture.Port)))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/components/capture_card.templ`, Line: 15, Col: 119}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" hx-trigger=\"load, every 20s\">Loading Server status...</div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if views.Username(ctx) != "" {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"mt-4\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = IconButtonRed("fa-solid fa-trash", fmt.Sprintf("/captures/%d", capture.ID)).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if capture.Active {
|
||||||
|
templ_7745c5c3_Err = IconButton("fa-solid fa-stop", fmt.Sprintf("/captures/%d/stop", capture.ID)).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
templ_7745c5c3_Err = IconButton("fa-solid fa-play", fmt.Sprintf("/captures/%d/start", capture.ID)).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ import "gitea.henriburau.de/haw-lan/cod4watcher/models"
|
||||||
import "strconv"
|
import "strconv"
|
||||||
|
|
||||||
templ CaptureTable(table models.ResultTable) {
|
templ CaptureTable(table models.ResultTable) {
|
||||||
<div class="relative overflow-x-auto">
|
<div class="relative overflow-x-auto" style="height: 50vh;">
|
||||||
<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
|
<table class="w-full overflow-scroll text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
|
||||||
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
|
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
|
||||||
<tr>
|
<tr>
|
||||||
for _, header := range table.Header {
|
for _, header := range table.Header {
|
||||||
|
@ -20,7 +20,7 @@ templ CaptureTable(table models.ResultTable) {
|
||||||
}
|
}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody class="overflow-y-scroll">
|
||||||
for _, row := range table.Rows {
|
for _, row := range table.Rows {
|
||||||
<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
|
<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
|
||||||
<th scope="row" class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
|
<th scope="row" class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
|
||||||
|
|
|
@ -26,7 +26,7 @@ func CaptureTable(table models.ResultTable) templ.Component {
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"relative overflow-x-auto\"><table class=\"w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400\"><thead class=\"text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400\"><tr>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"relative overflow-x-auto\" style=\"height: 50vh;\"><table class=\"w-full overflow-scroll text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400\"><thead class=\"text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400\"><tr>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ func CaptureTable(table models.ResultTable) templ.Component {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</tr></thead> <tbody>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</tr></thead> <tbody class=\"overflow-y-scroll\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package components
|
||||||
|
|
||||||
|
type FormProps struct {
|
||||||
|
Title string
|
||||||
|
Method string
|
||||||
|
Action string
|
||||||
|
SubmitText string
|
||||||
|
}
|
||||||
|
|
||||||
|
templ Form(props FormProps) {
|
||||||
|
<div class="w-full mx-auto max-w-96 p-4 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700">
|
||||||
|
<form class="space-y-6" action={ templ.SafeURL(props.Action) } method={ props.Method }>
|
||||||
|
<h5 class="text-xl font-medium text-gray-900 dark:text-white">{ props.Title }</h5>
|
||||||
|
{ children... }
|
||||||
|
@SubmitButton() {
|
||||||
|
{ props.SubmitText }
|
||||||
|
}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
// Code generated by templ - DO NOT EDIT.
|
||||||
|
|
||||||
|
// templ: version: v0.2.707
|
||||||
|
package components
|
||||||
|
|
||||||
|
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||||
|
|
||||||
|
import "github.com/a-h/templ"
|
||||||
|
import "context"
|
||||||
|
import "io"
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
|
type FormProps struct {
|
||||||
|
Title string
|
||||||
|
Method string
|
||||||
|
Action string
|
||||||
|
SubmitText string
|
||||||
|
}
|
||||||
|
|
||||||
|
func Form(props FormProps) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var1 == nil {
|
||||||
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"w-full mx-auto max-w-96 p-4 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700\"><form class=\"space-y-6\" action=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var2 templ.SafeURL = templ.SafeURL(props.Action)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var2)))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" method=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var3 string
|
||||||
|
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(props.Method)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/components/form.templ`, Line: 12, Col: 87}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><h5 class=\"text-xl font-medium text-gray-900 dark:text-white\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var4 string
|
||||||
|
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(props.Title)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/components/form.templ`, Line: 13, Col: 79}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h5>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var5 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var6 string
|
||||||
|
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(props.SubmitText)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/components/form.templ`, Line: 16, Col: 35}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
templ_7745c5c3_Err = SubmitButton().Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</form></div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package components
|
package components
|
||||||
|
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/views"
|
import "gitea.henriburau.de/haw-lan/cod4watcher/views"
|
||||||
|
import "strings"
|
||||||
|
|
||||||
templ Nagivation() {
|
templ Nagivation() {
|
||||||
<nav class="bg-gray-800">
|
<nav class="bg-gray-800">
|
||||||
|
@ -16,16 +17,23 @@ templ Nagivation() {
|
||||||
<!-- Current: "bg-gray-900 text-white", Default: "text-gray-300 hover:bg-gray-700 hover:text-white" -->
|
<!-- Current: "bg-gray-900 text-white", Default: "text-gray-300 hover:bg-gray-700 hover:text-white" -->
|
||||||
if ctx.Value(views.PathContext) == "" || ctx.Value(views.PathContext) == "/" {
|
if ctx.Value(views.PathContext) == "" || ctx.Value(views.PathContext) == "/" {
|
||||||
<a href="/" class="bg-gray-900 text-white rounded-md px-3 py-2 text-sm font-medium" aria-current="page">Dashboard</a>
|
<a href="/" class="bg-gray-900 text-white rounded-md px-3 py-2 text-sm font-medium" aria-current="page">Dashboard</a>
|
||||||
<a href="/about" class="text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium">About</a>
|
|
||||||
} else {
|
} else {
|
||||||
<a href="/" class="text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium">Dashboard</a>
|
<a href="/" class="text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium">Dashboard</a>
|
||||||
|
}
|
||||||
|
<!--
|
||||||
<a href="/about" class="text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium">About</a>
|
<a href="/about" class="text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium">About</a>
|
||||||
|
-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0">
|
||||||
|
if views.Username(ctx) != "" {
|
||||||
|
<a href="/logout" class="text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium">{ strings.ToUpper(views.Username(ctx)) }</a>
|
||||||
|
} else {
|
||||||
|
<a href="/login" class="text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium">Login</a>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
</nav>
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import "io"
|
||||||
import "bytes"
|
import "bytes"
|
||||||
|
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/views"
|
import "gitea.henriburau.de/haw-lan/cod4watcher/views"
|
||||||
|
import "strings"
|
||||||
|
|
||||||
func Nagivation() templ.Component {
|
func Nagivation() templ.Component {
|
||||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
@ -30,17 +31,45 @@ func Nagivation() templ.Component {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
if ctx.Value(views.PathContext) == "" || ctx.Value(views.PathContext) == "/" {
|
if ctx.Value(views.PathContext) == "" || ctx.Value(views.PathContext) == "/" {
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a href=\"/\" class=\"bg-gray-900 text-white rounded-md px-3 py-2 text-sm font-medium\" aria-current=\"page\">Dashboard</a> <a href=\"/about\" class=\"text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium\">About</a>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a href=\"/\" class=\"bg-gray-900 text-white rounded-md px-3 py-2 text-sm font-medium\" aria-current=\"page\">Dashboard</a>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a href=\"/\" class=\"text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium\">Dashboard</a> <a href=\"/about\" class=\"text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium\">About</a>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a href=\"/\" class=\"text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium\">Dashboard</a>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div></div><div class=\"absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0\"></div></div></div></nav>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<!-- \n\t\t\t\t\t\t\t\t<a href=\"/about\" class=\"text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium\">About</a>\n\t\t\t\t\t\t\t--></div></div></div><div class=\"absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if views.Username(ctx) != "" {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a href=\"/logout\" class=\"text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var2 string
|
||||||
|
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(strings.ToUpper(views.Username(ctx)))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/components/navbar.templ`, Line: 31, Col: 160}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a href=\"/login\" class=\"text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium\">Login</a>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div></div></nav>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package components
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
templ ServerAddress(host, port string) {
|
||||||
|
<div class="my-2 flex gap-4 items-center">
|
||||||
|
<span class="block">
|
||||||
|
{ host }:{ port }
|
||||||
|
</span>
|
||||||
|
<a class="block" href="#">
|
||||||
|
<i class="fa-regular fa-clipboard"></i>
|
||||||
|
</a>
|
||||||
|
<a class="block" href={ templ.SafeURL(fmt.Sprintf("cod4://%s:%s", host, port)) }>
|
||||||
|
<i class="block fa-solid fa-play"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
// Code generated by templ - DO NOT EDIT.
|
||||||
|
|
||||||
|
// templ: version: v0.2.707
|
||||||
|
package components
|
||||||
|
|
||||||
|
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||||
|
|
||||||
|
import "github.com/a-h/templ"
|
||||||
|
import "context"
|
||||||
|
import "io"
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func ServerAddress(host, port string) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var1 == nil {
|
||||||
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"my-2 flex gap-4 items-center\"><span class=\"block\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var2 string
|
||||||
|
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(host)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/components/server_address.templ`, Line: 8, Col: 9}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(":")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var3 string
|
||||||
|
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(port)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/components/server_address.templ`, Line: 8, Col: 18}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span> <a class=\"block\" href=\"#\"><i class=\"fa-regular fa-clipboard\"></i></a> <a class=\"block\" href=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var4 templ.SafeURL = templ.SafeURL(fmt.Sprintf("cod4://%s:%s", host, port))
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4)))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><i class=\"block fa-solid fa-play\"></i></a></div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,5 +1,14 @@
|
||||||
package views
|
package views
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
type contextKey string
|
type contextKey string
|
||||||
|
|
||||||
var PathContext = contextKey("path")
|
var (
|
||||||
|
PathContext = contextKey("path")
|
||||||
|
AuthContext = contextKey("auth")
|
||||||
|
)
|
||||||
|
|
||||||
|
func Username(ctx context.Context) string {
|
||||||
|
return ctx.Value(AuthContext).(string)
|
||||||
|
}
|
||||||
|
|
|
@ -3,11 +3,22 @@ package home
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/views/layouts"
|
import "gitea.henriburau.de/haw-lan/cod4watcher/views/layouts"
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/models"
|
import "gitea.henriburau.de/haw-lan/cod4watcher/models"
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/views/components"
|
import "gitea.henriburau.de/haw-lan/cod4watcher/views/components"
|
||||||
|
import "gitea.henriburau.de/haw-lan/cod4watcher/views"
|
||||||
|
|
||||||
templ Index(captures []models.Capture) {
|
templ Index(captures []models.Capture) {
|
||||||
@layouts.Base() {
|
@layouts.Base() {
|
||||||
|
if views.Username(ctx) != "" {
|
||||||
|
<a href="/new/capture" class="mb-8 block">
|
||||||
|
@components.Button() {
|
||||||
|
Create new Capture
|
||||||
|
}
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
|
||||||
|
<div class="flex gap-3 flex-wrap">
|
||||||
for _, capture := range captures {
|
for _, capture := range captures {
|
||||||
@components.CaptureCard(capture)
|
@components.CaptureCard(capture)
|
||||||
}
|
}
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import "bytes"
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/views/layouts"
|
import "gitea.henriburau.de/haw-lan/cod4watcher/views/layouts"
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/models"
|
import "gitea.henriburau.de/haw-lan/cod4watcher/models"
|
||||||
import "gitea.henriburau.de/haw-lan/cod4watcher/views/components"
|
import "gitea.henriburau.de/haw-lan/cod4watcher/views/components"
|
||||||
|
import "gitea.henriburau.de/haw-lan/cod4watcher/views"
|
||||||
|
|
||||||
func Index(captures []models.Capture) templ.Component {
|
func Index(captures []models.Capture) templ.Component {
|
||||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
@ -33,12 +34,49 @@ func Index(captures []models.Capture) templ.Component {
|
||||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
}
|
}
|
||||||
|
if views.Username(ctx) != "" {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a href=\"/new/capture\" class=\"mb-8 block\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Var3 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Create new Capture")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
templ_7745c5c3_Err = components.Button().Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <div class=\"flex gap-3 flex-wrap\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
for _, capture := range captures {
|
for _, capture := range captures {
|
||||||
templ_7745c5c3_Err = components.CaptureCard(capture).Render(ctx, templ_7745c5c3_Buffer)
|
templ_7745c5c3_Err = components.CaptureCard(capture).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
|
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ templ Base() {
|
||||||
</head>
|
</head>
|
||||||
<body class="antialiased">
|
<body class="antialiased">
|
||||||
@components.Nagivation()
|
@components.Nagivation()
|
||||||
<div class="mx-auto max-w-7xl mt-10 flex gap-3 flex-wrap">
|
<div class="mx-auto max-w-7xl mt-10">
|
||||||
{ children... }
|
{ children... }
|
||||||
</div>
|
</div>
|
||||||
<script src="/assets/index.js"></script>
|
<script src="/assets/index.js"></script>
|
||||||
|
|
|
@ -33,7 +33,7 @@ func Base() templ.Component {
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"mx-auto max-w-7xl mt-10 flex gap-3 flex-wrap\">")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"mx-auto max-w-7xl mt-10\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue