diff --git a/go.mod b/go.mod
index 1aad9a0..f9a45dd 100644
--- a/go.mod
+++ b/go.mod
@@ -14,6 +14,7 @@ require (
github.com/mattn/go-sqlite3 v1.14.22 // indirect
github.com/mergestat/timediff v0.0.3 // 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/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
@@ -31,6 +32,7 @@ require (
require (
github.com/go-chi/chi v1.5.5
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/joho/godotenv v1.5.1 // indirect
github.com/uptrace/bun v1.2.1
diff --git a/go.sum b/go.sum
index ad9da2b..4caf0a5 100644
--- a/go.sum
+++ b/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/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
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/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
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/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
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/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
diff --git a/main.go b/main.go
index adb03bb..8612543 100644
--- a/main.go
+++ b/main.go
@@ -28,23 +28,47 @@ func main() {
}
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)
- scanner, err := services.NewScanner(persistence, time.Second*10, doneChan)
+ scanner, err := services.NewScanner(persistence, cachedProvider, time.Second*10, doneChan)
if err != nil {
log.Fatal(err)
}
go scanner.Scan()
- router.Use(routes.PathMiddleware)
+ router.Use(routes.PathMiddleware, routes.AuthMiddleware)
router.Handle("/*", public())
router.Get("/health", routes.Make(server.HandleHealth))
+ router.Get("/server/status", routes.Make(server.HandleServerStatus))
router.Get("/captures/{captureID}", routes.Make(server.HandleCapture))
- router.Delete("/captures/{captureID}", routes.Make(server.HandleCaptureDelete))
- router.Get("/new/capture", routes.Make(server.HandleCaptureForm))
- router.Post("/new/capture", routes.Make(server.HandleCaptureCreate))
+ router.Get("/captures/{captureID}/table", routes.Make(server.HandleCaptureTable))
+ router.Get("/login", routes.Make(server.HandleLogin))
+ 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))
listenAddr := os.Getenv("LISTEN_ADDR")
diff --git a/models/cod4cache.go b/models/cod4cache.go
new file mode 100644
index 0000000..fa4e924
--- /dev/null
+++ b/models/cod4cache.go
@@ -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)
+}
diff --git a/models/cod4server.go b/models/cod4server.go
index 1c70052..637f0f5 100644
--- a/models/cod4server.go
+++ b/models/cod4server.go
@@ -12,38 +12,44 @@ import (
"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 {
- server string
- port string
- protocol string
- timeout time.Duration
+ server string
+ port string
+ timeout time.Duration
}
type CoD4ServerStatus struct {
raw string
serverData map[string]string
+ Name string
MapStartTime time.Time
MapName string
+ MaxPlayers int
Score []Score
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 == "" {
return nil, errors.New("server or port is empty")
}
- return &CoD4Server{
- server: server,
- port: port,
- protocol: "udp",
- timeout: timeout,
- }, nil
-}
+ c := &CoD4Server{
+ server: server,
+ port: port,
+ timeout: timeout,
+ }
-func (c *CoD4Server) GetServerStatus() (*CoD4ServerStatus, error) {
data, err := c.receiveData()
if err != nil {
return nil, err
@@ -54,7 +60,7 @@ func (c *CoD4Server) GetServerStatus() (*CoD4ServerStatus, error) {
func (c *CoD4Server) receiveData() (string, error) {
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 {
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]
}
+ 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.Name = c.serverData["sv_hostname"]
c.serverData["_Maps"] = strings.Join(strings.Split(c.serverData["_Maps"], "-"), ",")
c.MapName = c.serverData["mapname"]
-
- startTime, err := time.ParseInLocation(timeLayout, c.serverData["g_mapStartTime"], time.Local)
+ c.MaxPlayers, err = strconv.Atoi(c.serverData["sv_maxclients"])
if err != nil {
return nil, err
}
@@ -159,9 +170,19 @@ func colorCode(str string) string {
"9": "#6E3C3C",
}
- re := regexp.MustCompile(`\^(\d)(.*?)\^`)
- return re.ReplaceAllStringFunc(str, func(m string) string {
- matches := re.FindStringSubmatch(m)
- return fmt.Sprintf(`%s^`, colorMap[matches[1]], matches[2])
+ re := regexp.MustCompile(`\^(\d)`)
+ str = re.ReplaceAllStringFunc(str, func(m string) string {
+ code := string(m[1])
+ if color, ok := colorMap[code]; ok {
+ return fmt.Sprintf(``, color)
+ }
+ return m
})
+
+ // Close open span tags
+ str += "^"
+ reClose := regexp.MustCompile(`\^(.*?)\^`)
+ str = reClose.ReplaceAllString(str, "$1")
+
+ return str[:len(str)-1]
}
diff --git a/models/persistence.go b/models/persistence.go
index 08159bc..4acfa46 100644
--- a/models/persistence.go
+++ b/models/persistence.go
@@ -12,6 +12,7 @@ import (
type Persistence interface {
CreateCapture(context.Context, *Capture) error
+ UpdateCapture(context.Context, *Capture) error
GetCaptures(context.Context) ([]Capture, error)
GetCapturesByID(context.Context, int64) (*Capture, error)
DeleteCapture(context.Context, int64) error
@@ -68,6 +69,12 @@ func (s *SQLitePersistence) GetCapturesByID(ctx context.Context, id int64) (*Cap
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 {
capture := Capture{
ID: id,
diff --git a/routes/auth.go b/routes/auth.go
new file mode 100644
index 0000000..5f3efa4
--- /dev/null
+++ b/routes/auth.go
@@ -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, "/")
+}
diff --git a/routes/auth_middleware.go b/routes/auth_middleware.go
new file mode 100644
index 0000000..3efa66f
--- /dev/null
+++ b/routes/auth_middleware.go
@@ -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
+}
diff --git a/routes/capture.go b/routes/capture.go
index 50cfe2f..8366365 100644
--- a/routes/capture.go
+++ b/routes/capture.go
@@ -7,6 +7,7 @@ import (
"gitea.henriburau.de/haw-lan/cod4watcher/models"
"gitea.henriburau.de/haw-lan/cod4watcher/views/capture"
+ "gitea.henriburau.de/haw-lan/cod4watcher/views/components"
"github.com/go-chi/chi"
)
@@ -22,7 +23,52 @@ func (s *Server) HandleCapture(w http.ResponseWriter, r *http.Request) error {
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 {
@@ -58,7 +104,7 @@ func (s *Server) HandleCaptureCreate(w http.ResponseWriter, r *http.Request) err
Start: time.Now(),
}
- _, err := s.cs.GetServerStatus(r.Context(), newCapture)
+ _, err := s.c4s.GetServerStatus(newCapture.Host, newCapture.Port)
if err != nil {
errors["host"] = err.Error()
errors["port"] = err.Error()
diff --git a/routes/cod4server.go b/routes/cod4server.go
new file mode 100644
index 0000000..841c3b1
--- /dev/null
+++ b/routes/cod4server.go
@@ -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))
+}
diff --git a/routes/home.go b/routes/home.go
index b4f62ee..12938d2 100644
--- a/routes/home.go
+++ b/routes/home.go
@@ -3,17 +3,24 @@ package routes
import (
"net/http"
+ "gitea.henriburau.de/haw-lan/cod4watcher/models"
+ "gitea.henriburau.de/haw-lan/cod4watcher/views"
"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 {
- 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 {
return err
}
- spew.Dump(r.Context())
-
return Render(w, r, home.Index(captureList))
}
diff --git a/routes/routes.go b/routes/routes.go
index 7a38687..412e1f1 100644
--- a/routes/routes.go
+++ b/routes/routes.go
@@ -19,12 +19,13 @@ func Make(h HTTPHandler) http.HandlerFunc {
}
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{
- cs,
+ cs, c4s,
}
}
diff --git a/services/authorization.go b/services/authorization.go
new file mode 100644
index 0000000..1e4c717
--- /dev/null
+++ b/services/authorization.go
@@ -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")
+ }
+}
diff --git a/services/capture.go b/services/capture.go
index 6c4e879..9aa1848 100644
--- a/services/capture.go
+++ b/services/capture.go
@@ -2,7 +2,6 @@ package services
import (
"context"
- "time"
"gitea.henriburau.de/haw-lan/cod4watcher/models"
)
@@ -40,14 +39,30 @@ func (cs *CaptureService) GetActiveCapures(ctx context.Context) ([]models.Captur
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) {
- server, err := models.NewCOD4ServerStatus(capture.Host, capture.Port, time.Second)
+func (cs *CaptureService) StartCapture(ctx context.Context, id int64) error {
+ capture, err := cs.p.GetCapturesByID(ctx, id)
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) {
diff --git a/services/cod4server.go b/services/cod4server.go
new file mode 100644
index 0000000..569c067
--- /dev/null
+++ b/services/cod4server.go
@@ -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)
+}
diff --git a/services/scanner.go b/services/scanner.go
index 0a96b47..40736ac 100644
--- a/services/scanner.go
+++ b/services/scanner.go
@@ -10,13 +10,14 @@ import (
type Scanner struct {
p models.Persistence
+ c4s models.StatusProvider
done chan bool
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{
- p, done, interval,
+ p, c4s, done, interval,
}, nil
}
@@ -52,12 +53,7 @@ func (s *Scanner) Scan() {
}
func (s *Scanner) fetchInformation(ctx context.Context, capture models.Capture) error {
- server, err := models.NewCOD4ServerStatus(capture.Host, capture.Port, time.Second)
- if err != nil {
- return err
- }
-
- status, err := server.GetServerStatus()
+ status, err := s.c4s.GetServerStatus(capture.Host, capture.Port, time.Second)
if err != nil {
return err
}
diff --git a/views/auth/login_form.templ b/views/auth/login_form.templ
new file mode 100644
index 0000000..7f18aaf
--- /dev/null
+++ b/views/auth/login_form.templ
@@ -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",
+ }) {
+
+
+ @components.Input(components.InputProps{
+ Name: "username",
+ Value: formValues.Username,
+ Error: errors["username"],
+ Placeholder: "Your username",
+ })
+
+
+
+ @components.Input(components.InputProps{
+ Name: "password",
+ Value: formValues.Password,
+ Error: errors["password"],
+ Placeholder: "Your password",
+ })
+
+ }
+ }
+}
diff --git a/views/auth/login_form_templ.go b/views/auth/login_form_templ.go
new file mode 100644
index 0000000..38ce4b2
--- /dev/null
+++ b/views/auth/login_form_templ.go
@@ -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("")
+ 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("
")
+ 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("
")
+ 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
+ })
+}
diff --git a/views/capture/capture.templ b/views/capture/capture.templ
index 3ed9628..b9a263d 100644
--- a/views/capture/capture.templ
+++ b/views/capture/capture.templ
@@ -3,17 +3,50 @@ package capture
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/components"
+import "fmt"
+import "net/url"
-templ Capture(capture *models.Capture) {
+templ Capture(capture *models.Capture, table models.ResultTable) {
@layouts.Base() {
-
- { capture.Name }
+
+
+
+ { capture.Name }
+
+ @components.ServerAddress(capture.Host, capture.Port)
+
+ Loading Server status...
+
+
+
+ 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")
+ }
+
-
- { capture.Host }:{ capture.Port }
+
+ @components.CaptureTable(table)
- @components.CaptureTable(*capture.MapScores.BuildTable())
}
}
+
+templ Medal(placement, name, color string) {
+
+
+
+ { placement } { name }
+
+
+}
diff --git a/views/capture/capture_form.templ b/views/capture/capture_form.templ
index 207e329..0b84c56 100644
--- a/views/capture/capture_form.templ
+++ b/views/capture/capture_form.templ
@@ -1,50 +1,53 @@
package capture
-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/layouts"
+ "gitea.henriburau.de/haw-lan/cod4watcher/views/components"
+)
type CaptureFormValues struct {
Host string
Port string
Name string
+ Active bool
+ ValidateServer bool
}
templ CaptureForm(formValues CaptureFormValues, errors map[string]string) {
@layouts.Base() {
-
+ @components.Form(components.FormProps{
+ Title: "Create new capture",
+ Action: "/new/capture",
+ Method: "post",
+ SubmitText: "Create capture",
+ }) {
+
+
+ @components.Input(components.InputProps{
+ Name: "name",
+ Value: formValues.Name,
+ Error: errors["name"],
+ Placeholder: "Name for the capture",
+ })
+
+
+
+ @components.Input(components.InputProps{
+ Name: "host",
+ Value: formValues.Host,
+ Error: errors["host"],
+ Placeholder: "Host-Address of the capture",
+ })
+
+
+
+ @components.Input(components.InputProps{
+ Name: "port",
+ Value: formValues.Port,
+ Error: errors["port"],
+ Placeholder: "Port for the capture",
+ })
+
+ }
}
}
diff --git a/views/capture/capture_form_templ.go b/views/capture/capture_form_templ.go
index cab5598..cb38435 100644
--- a/views/capture/capture_form_templ.go
+++ b/views/capture/capture_form_templ.go
@@ -10,13 +10,17 @@ import "context"
import "io"
import "bytes"
-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"
+ "gitea.henriburau.de/haw-lan/cod4watcher/views/layouts"
+)
type CaptureFormValues struct {
- Host string
- Port string
- Name string
+ Host string
+ Port string
+ Name string
+ Active bool
+ ValidateServer bool
}
func CaptureForm(formValues CaptureFormValues, errors map[string]string) templ.Component {
@@ -38,46 +42,66 @@ func CaptureForm(formValues CaptureFormValues, errors map[string]string) templ.C
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
")
+ })
+ 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 {
return templ_7745c5c3_Err
}
diff --git a/views/capture/capture_templ.go b/views/capture/capture_templ.go
index 812e5ec..5f7e65f 100644
--- a/views/capture/capture_templ.go
+++ b/views/capture/capture_templ.go
@@ -13,8 +13,10 @@ import "bytes"
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/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) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
@@ -33,54 +35,84 @@ func Capture(capture *models.Capture) templ.Component {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
")
+ _, 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(capture.Name)
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))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
")
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
")
+ 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("
Loading Server status...
")
+ 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("
")
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" hx-trigger=\"every 10s\">")
if templ_7745c5c3_Err != nil {
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 {
return templ_7745c5c3_Err
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
")
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -99,3 +131,75 @@ func Capture(capture *models.Capture) templ.Component {
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("
")
+ 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(" ")
+ 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("
")
+ 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
+ })
+}
diff --git a/views/cod4server/server_status.templ b/views/cod4server/server_status.templ
new file mode 100644
index 0000000..a4f51b5
--- /dev/null
+++ b/views/cod4server/server_status.templ
@@ -0,0 +1,16 @@
+package cod4server
+
+import "gitea.henriburau.de/haw-lan/cod4watcher/models"
+import "fmt"
+
+templ ServerStatus(status *models.CoD4ServerStatus) {
+
+
+ { status.MapName }
+
+ { fmt.Sprintf("%d/%d",len(status.Score), status.MaxPlayers) }
+
+
+ @templ.Raw(status.Name)
+
+}
diff --git a/views/cod4server/server_status_templ.go b/views/cod4server/server_status_templ.go
new file mode 100644
index 0000000..9b9dec5
--- /dev/null
+++ b/views/cod4server/server_status_templ.go
@@ -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("
")
+ 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(" ")
+ 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("
")
+ 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("
")
+ 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
+ })
+}
diff --git a/views/components/button.templ b/views/components/button.templ
new file mode 100644
index 0000000..dfbc610
--- /dev/null
+++ b/views/components/button.templ
@@ -0,0 +1,25 @@
+package components
+
+templ Button() {
+
+}
+
+templ SubmitButton() {
+
+}
+
+templ IconButton(icon, url string) {
+
+
+
+}
+
+templ IconButtonRed(icon, url string) {
+
+
+
+}
diff --git a/views/components/button_templ.go b/views/components/button_templ.go
new file mode 100644
index 0000000..6a4c306
--- /dev/null
+++ b/views/components/button_templ.go
@@ -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("
")
+ 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("
")
+ 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("
")
+ 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("")
+ 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("
")
+ 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("")
+ 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
+ })
+}
diff --git a/views/components/capture_card.templ b/views/components/capture_card.templ
index 0a3a576..6d9c9b0 100644
--- a/views/components/capture_card.templ
+++ b/views/components/capture_card.templ
@@ -1,15 +1,31 @@
package components
import "gitea.henriburau.de/haw-lan/cod4watcher/models"
-import "github.com/mergestat/timediff"
+import "gitea.henriburau.de/haw-lan/cod4watcher/views"
import "fmt"
+import "net/url"
templ CaptureCard(capture models.Capture) {
-
+
{ capture.Name }
-
{ timediff.TimeDiff(capture.Start) }
-
+
{ capture.Host }:{ capture.Port }
+
+ Loading Server status...
+
+ if views.Username(ctx) != "" {
+
+ @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))
+ }
+
+ }
}
diff --git a/views/components/capture_card_templ.go b/views/components/capture_card_templ.go
index 04c8d71..e80bfda 100644
--- a/views/components/capture_card_templ.go
+++ b/views/components/capture_card_templ.go
@@ -11,8 +11,9 @@ import "io"
import "bytes"
import "gitea.henriburau.de/haw-lan/cod4watcher/models"
-import "github.com/mergestat/timediff"
+import "gitea.henriburau.de/haw-lan/cod4watcher/views"
import "fmt"
+import "net/url"
func CaptureCard(capture models.Capture) templ.Component {
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
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(capture.Name)
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))
if templ_7745c5c3_Err != nil {
@@ -54,28 +55,70 @@ func CaptureCard(capture models.Capture) templ.Component {
return templ_7745c5c3_Err
}
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 {
- 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))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
")
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Loading Server status...
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if views.Username(ctx) != "" {
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
")
+ 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("
")
+ 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
}
diff --git a/views/components/capture_table.templ b/views/components/capture_table.templ
index 7420467..6a5f7b2 100644
--- a/views/components/capture_table.templ
+++ b/views/components/capture_table.templ
@@ -4,8 +4,8 @@ import "gitea.henriburau.de/haw-lan/cod4watcher/models"
import "strconv"
templ CaptureTable(table models.ResultTable) {
-
-
+
+
for _, header := range table.Header {
@@ -20,7 +20,7 @@ templ CaptureTable(table models.ResultTable) {
}
-
+
for _, row := range table.Rows {
diff --git a/views/components/capture_table_templ.go b/views/components/capture_table_templ.go
index 01c525a..9c53193 100644
--- a/views/components/capture_table_templ.go
+++ b/views/components/capture_table_templ.go
@@ -26,7 +26,7 @@ func CaptureTable(table models.ResultTable) templ.Component {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("")
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -62,7 +62,7 @@ func CaptureTable(table models.ResultTable) templ.Component {
return templ_7745c5c3_Err
}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
diff --git a/views/components/form.templ b/views/components/form.templ
new file mode 100644
index 0000000..97b9060
--- /dev/null
+++ b/views/components/form.templ
@@ -0,0 +1,20 @@
+package components
+
+type FormProps struct {
+ Title string
+ Method string
+ Action string
+ SubmitText string
+}
+
+templ Form(props FormProps) {
+
+
+
+}
\ No newline at end of file
diff --git a/views/components/form_templ.go b/views/components/form_templ.go
new file mode 100644
index 0000000..43de612
--- /dev/null
+++ b/views/components/form_templ.go
@@ -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("")
+ 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
+ })
+}
diff --git a/views/components/navbar.templ b/views/components/navbar.templ
index fa697f7..2753ba6 100644
--- a/views/components/navbar.templ
+++ b/views/components/navbar.templ
@@ -1,6 +1,7 @@
package components
import "gitea.henriburau.de/haw-lan/cod4watcher/views"
+import "strings"
templ Nagivation() {
diff --git a/views/components/navbar_templ.go b/views/components/navbar_templ.go
index cb05ec9..1fcfccc 100644
--- a/views/components/navbar_templ.go
+++ b/views/components/navbar_templ.go
@@ -11,6 +11,7 @@ import "io"
import "bytes"
import "gitea.henriburau.de/haw-lan/cod4watcher/views"
+import "strings"
func Nagivation() templ.Component {
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
}
if ctx.Value(views.PathContext) == "" || ctx.Value(views.PathContext) == "/" {
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Dashboard About")
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Dashboard")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Dashboard About")
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Dashboard")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("")
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
diff --git a/views/components/server_address.templ b/views/components/server_address.templ
new file mode 100644
index 0000000..0b750e2
--- /dev/null
+++ b/views/components/server_address.templ
@@ -0,0 +1,17 @@
+package components
+
+import "fmt"
+
+templ ServerAddress(host, port string) {
+
+
+ { host }:{ port }
+
+
+
+
+
+
+
+
+}
diff --git a/views/components/server_address_templ.go b/views/components/server_address_templ.go
new file mode 100644
index 0000000..f20fa34
--- /dev/null
+++ b/views/components/server_address_templ.go
@@ -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("")
+ 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(" ")
+ 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
+ })
+}
diff --git a/views/context.go b/views/context.go
index 1c711b4..806e700 100644
--- a/views/context.go
+++ b/views/context.go
@@ -1,5 +1,14 @@
package views
+import "context"
+
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)
+}
diff --git a/views/home/index.templ b/views/home/index.templ
index 8bf0eb8..4b6c596 100644
--- a/views/home/index.templ
+++ b/views/home/index.templ
@@ -3,11 +3,22 @@ package home
import "gitea.henriburau.de/haw-lan/cod4watcher/views/layouts"
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"
templ Index(captures []models.Capture) {
@layouts.Base() {
- for _, capture := range captures {
- @components.CaptureCard(capture)
+ if views.Username(ctx) != "" {
+
+ @components.Button() {
+ Create new Capture
+ }
+
}
+
+
+ for _, capture := range captures {
+ @components.CaptureCard(capture)
+ }
+
}
}
diff --git a/views/home/index_templ.go b/views/home/index_templ.go
index 51c7f99..2d036a7 100644
--- a/views/home/index_templ.go
+++ b/views/home/index_templ.go
@@ -13,6 +13,7 @@ import "bytes"
import "gitea.henriburau.de/haw-lan/cod4watcher/views/layouts"
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"
func Index(captures []models.Capture) templ.Component {
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()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
+ if views.Username(ctx) != "" {
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("")
+ 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("")
+ 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
+ }
for _, capture := range captures {
templ_7745c5c3_Err = components.CaptureCard(capture).Render(ctx, templ_7745c5c3_Buffer)
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
+ }
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
}
diff --git a/views/layouts/base.templ b/views/layouts/base.templ
index 80708e1..20cfef3 100644
--- a/views/layouts/base.templ
+++ b/views/layouts/base.templ
@@ -15,7 +15,7 @@ templ Base() {
@components.Nagivation()
-
+
{ children... }
diff --git a/views/layouts/base_templ.go b/views/layouts/base_templ.go
index 0ba53c9..fa87ba1 100644
--- a/views/layouts/base_templ.go
+++ b/views/layouts/base_templ.go
@@ -33,7 +33,7 @@ func Base() templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
|