aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJP Appel <jeanpierre.appel01@gmail.com>2024-10-02 17:26:41 -0400
committerJP Appel <jeanpierre.appel01@gmail.com>2024-10-02 17:27:46 -0400
commit50df0f7b61462a6bfad9e74f7c7917c6b19d4b92 (patch)
tree50f478d0cacfcb57acdc8edd0f357db304b249ae
parente8d9040688925304edad469d92518da84e1b8d96 (diff)
Add first pass at dashboard
-rw-r--r--Makefile2
-rw-r--r--api/api.go37
-rw-r--r--dashboard/dashboard.go48
-rw-r--r--nonsense-time.go6
-rw-r--r--static/styles.css10
-rw-r--r--templates/base.html12
-rw-r--r--templates/dashboard/dashboard.html7
-rw-r--r--templates/dashboard/server_logs.html0
-rw-r--r--templates/dashboard/server_status.html15
9 files changed, 120 insertions, 17 deletions
diff --git a/Makefile b/Makefile
index b6980df..6867614 100644
--- a/Makefile
+++ b/Makefile
@@ -20,5 +20,5 @@ info:
@echo "BIN: $(BIN)"
@echo "SERVICE: $(SERVICE)"
-nonsense-time: nonsense-time.go
+nonsense-time: nonsense-time.go $(wildcard api/*.go) $(wildcard dashboard/*.go)
go build .
diff --git a/api/api.go b/api/api.go
index 3e0dc27..8f7d76d 100644
--- a/api/api.go
+++ b/api/api.go
@@ -6,13 +6,21 @@ import (
"log/slog"
"net/http"
"os"
+ "time"
)
+type ServerStatus struct {
+ Online bool `json:"online"`
+ Site string `json:"url"`
+ Timestamp time.Time `json:"timestamp"`
+}
+
var Logger *slog.Logger
const VTT_URL string = "http://73.188.175.49:30000"
-func remoteOnline(ctx context.Context, url string) bool {
+func remoteOnline(ctx context.Context, url string) ServerStatus {
+ status := ServerStatus{Site: url, Timestamp: time.Now()}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
panic(err)
@@ -20,19 +28,16 @@ func remoteOnline(ctx context.Context, url string) bool {
_, err = http.DefaultClient.Do(req)
if err != nil {
- return false
+ status.Online = false
+ } else {
+ status.Online = true
}
- return true
+ return status
}
-func respondOnline(w http.ResponseWriter, url string, isOnline bool) {
- data := struct {
- Online bool `json:"online"`
- Site string `json:"url"`
- }{isOnline, url}
-
- jsonData, err := json.Marshal(data)
+func respondOnline(w http.ResponseWriter, status ServerStatus) {
+ jsonData, err := json.Marshal(status)
if err != nil {
http.Error(w, "Error constructing response", http.StatusInternalServerError)
Logger.Error("Error marshalling site status data")
@@ -44,12 +49,12 @@ func respondOnline(w http.ResponseWriter, url string, isOnline bool) {
}
func VttOnline(w http.ResponseWriter, req *http.Request) {
- isOnline := remoteOnline(req.Context(), VTT_URL)
+ status := remoteOnline(req.Context(), VTT_URL)
- if !isOnline {
+ if !status.Online {
Logger.DebugContext(req.Context(), "Foundry VTT is offline")
}
- respondOnline(w, VTT_URL, isOnline)
+ respondOnline(w, status)
}
func VttRedirect(w http.ResponseWriter, req *http.Request) {
@@ -59,12 +64,12 @@ func VttRedirect(w http.ResponseWriter, req *http.Request) {
func SiteOnline(w http.ResponseWriter, req *http.Request) {
const URL string = "https://dnd.jpappel.xyz"
- isOnline := remoteOnline(req.Context(), URL)
- if !isOnline {
+ status := remoteOnline(req.Context(), URL)
+ if !status.Online {
Logger.DebugContext(req.Context(), "Campaign Website is offline")
}
- respondOnline(w, URL, isOnline)
+ respondOnline(w, status)
}
func init() {
diff --git a/dashboard/dashboard.go b/dashboard/dashboard.go
new file mode 100644
index 0000000..c3839f2
--- /dev/null
+++ b/dashboard/dashboard.go
@@ -0,0 +1,48 @@
+package dashboard
+
+import (
+ "html/template"
+ "log/slog"
+ "net/http"
+ "nonsense-time/api"
+ "path/filepath"
+)
+
+var Logger *slog.Logger
+var templates map[string]*template.Template
+
+func Index(w http.ResponseWriter, req *http.Request) {
+ t, ok := templates["dashboard"]
+
+ if !ok {
+ panic(t)
+ }
+
+ // TODO: poll database
+ data := struct {
+ ServerStatus api.ServerStatus
+ }{
+ ServerStatus: api.ServerStatus{},
+ }
+
+ err := t.Execute(w, data)
+ if err != nil {
+ Logger.Error("Unable to execute template", slog.Any("err", err))
+ http.Error(w, "Internal Server Error", http.StatusInternalServerError)
+ return
+ }
+}
+
+func StaticHandler(w http.ResponseWriter, req *http.Request) {
+ http.StripPrefix("/static", http.FileServer(http.Dir("static"))).ServeHTTP(w, req)
+}
+
+func init() {
+ Logger = slog.Default()
+ templates = make(map[string]*template.Template)
+ templates["dashboard"] = template.Must(template.New("base.html").ParseFiles(
+ filepath.Join("templates", "base.html"),
+ filepath.Join("templates", "dashboard", "dashboard.html"),
+ filepath.Join("templates", "dashboard", "server_status.html"),
+ ))
+}
diff --git a/nonsense-time.go b/nonsense-time.go
index f9901e6..94c0a30 100644
--- a/nonsense-time.go
+++ b/nonsense-time.go
@@ -7,6 +7,7 @@ import (
"log/slog"
"net/http"
"nonsense-time/api"
+ "nonsense-time/dashboard"
"os"
"time"
)
@@ -51,12 +52,15 @@ func main() {
loggerOpts.Level = slog.LevelDebug
case "error":
loggerOpts.Level = slog.LevelError
+ default:
+ panic(fmt.Sprintf("Unkown log level %s", *logLevel))
}
addr := fmt.Sprintf("%s:%d", *bindAddr, *port)
logger = slog.New(slog.NewTextHandler(os.Stdout, loggerOpts))
api.Logger = logger
+ dashboard.Logger = logger
vtt := timeoutMiddleware(http.HandlerFunc(api.VttOnline), *waitTime)
site := timeoutMiddleware(http.HandlerFunc(api.SiteOnline), *waitTime)
@@ -64,6 +68,8 @@ func main() {
mux.Handle("GET /vtt/status", vtt)
mux.HandleFunc("GET /vtt", api.VttRedirect)
mux.Handle("GET /site/status", site)
+ mux.HandleFunc("GET /", dashboard.Index)
+ mux.HandleFunc("GET /static/", dashboard.StaticHandler)
logger.Info(fmt.Sprint("Listening on ", addr))
logger.Info(http.ListenAndServe(addr, mux).Error())
diff --git a/static/styles.css b/static/styles.css
new file mode 100644
index 0000000..497cf2c
--- /dev/null
+++ b/static/styles.css
@@ -0,0 +1,10 @@
+main {
+ display: flex;
+ margin: 1em;
+ flex-direction: column;
+}
+
+section.server-status {
+ padding: 0 1em 0.75em;
+ border: 0.25em solid black;
+}
diff --git a/templates/base.html b/templates/base.html
new file mode 100644
index 0000000..768d7eb
--- /dev/null
+++ b/templates/base.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang=en>
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ {{ block "head" . }}<title>Nonsense Time Dashboard</title>{{ end }}
+ <link rel="stylesheet" href="/static/styles.css">
+</head>
+<body>
+ {{ block "body" . }}{{ end }}
+</body>
+</html>
diff --git a/templates/dashboard/dashboard.html b/templates/dashboard/dashboard.html
new file mode 100644
index 0000000..29a852e
--- /dev/null
+++ b/templates/dashboard/dashboard.html
@@ -0,0 +1,7 @@
+{{ define "body" }}
+<h1>Dashboard Home</h1>
+<p>Welcome to the Dashboard! It is still under construction so please be patient :) </p>
+<main>
+ {{template "server_status" . }}
+</main>
+{{ end }}
diff --git a/templates/dashboard/server_logs.html b/templates/dashboard/server_logs.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/templates/dashboard/server_logs.html
diff --git a/templates/dashboard/server_status.html b/templates/dashboard/server_status.html
new file mode 100644
index 0000000..8019659
--- /dev/null
+++ b/templates/dashboard/server_status.html
@@ -0,0 +1,15 @@
+{{define "server_status"}}
+<section class="server-status">
+ <h2>Server Status</h2>
+ <div id=uptime>
+ <dl>
+ <dt>Url</dt>
+ <dd>{{ .ServerStatus.Site }}</dd>
+ <dt>Online</dt>
+ <dd>{{ .ServerStatus.Online }}</dd>
+ <dt>Timestamp</dt>
+ <dd>{{ .ServerStatus.Timestamp }}</dd>
+ </dl>
+ </div>
+</section>
+{{end}}