Rendering status as HTML tables.

This commit is contained in:
Erik Brakkee 2024-07-31 21:12:09 +02:00
parent 638dffd143
commit d6fc2e4118
6 changed files with 145 additions and 18 deletions

View File

@ -140,7 +140,11 @@ func main() {
Handler: func(w http.ResponseWriter, r *http.Request, conn net.Conn) {
websession := websessions.NewSession(conn)
defer websessions.SessionClosed(websession)
websession.WriteNotifications()
location, err := converge.GetUserLocation(r)
if err != nil {
panic(err)
}
websession.WriteNotifications(location)
},
Text: true,
}

View File

@ -1,6 +1,7 @@
package main
import (
"converge/pkg/server/converge"
templates2 "converge/pkg/server/templates"
"net/http"
"os"
@ -24,6 +25,11 @@ func pageHandler(w http.ResponseWriter, r *http.Request) {
}
username, _ := os.LookupEnv("CONVERGE_USERNAME")
location, err := converge.GetUserLocation(r)
if err != nil {
panic(err)
}
switch r.URL.Path {
case "":
fallthrough
@ -36,7 +42,7 @@ func pageHandler(w http.ResponseWriter, r *http.Request) {
case "downloads.html":
templates2.DownloadsTab().Render(r.Context(), w)
case "sessions.html":
templates2.SessionsTab().Render(r.Context(), w)
templates2.SessionsTab(nil, location).Render(r.Context(), w)
default:
http.NotFound(w, r)
}

View File

@ -2,11 +2,14 @@ package main
import (
"context"
"converge/pkg/comms"
"converge/pkg/models"
templates2 "converge/pkg/server/templates"
"github.com/a-h/templ"
"log"
"os"
"path/filepath"
"time"
)
type RenderFunc func() templ.Component
@ -29,6 +32,11 @@ func render(dir string, name string, render RenderFunc) {
func main() {
dir := "html/docs"
netherlands, err := time.LoadLocation("Europe/Amsterdam")
if err != nil {
panic(err)
}
fullindex := func() templ.Component {
return templates2.Index("s", "example.com", "converge")
}
@ -41,5 +49,37 @@ func main() {
render(dir, "usage.html", usage)
render(dir, "downloads.html", templates2.Downloads)
render(dir, "sessions.html", templates2.SessionsTab)
render(dir, "sessions-none.html", func() templ.Component {
return templates2.SessionsTab(nil, netherlands)
})
render(dir, "sessions.html", func() templ.Component {
japan, err := time.LoadLocation("Asia/Tokyo")
if err != nil {
panic(err)
}
state := models.State{}
agent := models.Agent{
PublicId: "id",
StartTime: time.Now().In(japan),
AgentInfo: comms.AgentInfo{
Username: "ci",
Hostname: "container123",
Pwd: "/home/ci",
OS: "linux",
Shell: "/bin/bash",
},
ExpiryTime: time.Now().In(japan).Add(10 * time.Minute),
}
state.Agents = append(state.Agents, agent)
client := models.Client{
PublicId: "c1",
ClientId: 3,
StartTime: time.Now().In(japan),
SessionType: "sftp",
}
state.Clients = append(state.Clients, client)
return templates2.SessionsTab(&state, netherlands)
})
}

View File

@ -27,7 +27,5 @@ spec:
- name: CONVERGE_PASSWORD
# change this password in your final deployment
value: "abc123"
- name: TZ
value: Europe/Amsterdam

View File

@ -6,6 +6,7 @@ import (
"converge/pkg/server/templates"
"log"
"net"
"net/http"
"sync"
"time"
)
@ -57,7 +58,25 @@ func (sessions *WebSessions) NewSession(wsConnection net.Conn) *WebSession {
return session
}
func (session *WebSession) WriteNotifications() {
func GetUserLocation(r *http.Request) (*time.Location, error) {
// Try to get timezone from a custom header
tzName := r.Header.Get("X-Timezone")
// If not found in header, try to get from query parameter
if tzName == "" {
tzName = r.URL.Query().Get("tz")
}
// If still not found, default to UTC
if tzName == "" {
tzName = "UTC"
}
// Load the location
return time.LoadLocation(tzName)
}
func (session *WebSession) WriteNotifications(location *time.Location) {
timer := time.NewTicker(10 * time.Second)
defer timer.Stop()
for {
@ -66,8 +85,8 @@ func (session *WebSession) WriteNotifications() {
if !ok {
log.Println("channel closed")
}
log.Println("Got notification: ", notification.Ascii)
err := templates.State(notification).Render(context.Background(), session.conn)
//log.Println("Got notification: ", notification)
err := templates.State(notification, location).Render(context.Background(), session.conn)
if err != nil {
log.Printf("WS connection closed: %v", err)
return

View File

@ -1,34 +1,94 @@
package templates
import "converge/pkg/models"
import (
"converge/pkg/models"
"strconv"
"time"
_ "time/tzdata"
)
templ Sessions(state *models.State) {
templ Sessions(state *models.State, loc *time.Location) {
<div hx-ext="ws" ws-connect="/ws/sessions">
<h1>sessions</h1>
<div id="status">
if state != nil {
@State(state)
@State(state, loc)
} else {
"Loading..."
Loading...
}
</div>
</div>
}
templ State(state *models.State) {
templ State(state *models.State, location *time.Location) {
<div id="status">
<pre>
{ state.Ascii }
</pre>
<h3>agents</h3>
if len(state.Agents) == 0 {
<p>-</p>
} else {
<table class="table">
<thead>
<tr>
<th>id</th>
<th>start time</th>
<th>expiry time</th>
<th>username</th>
<th>host</th>
<th>OS</th>
<th>shell</th>
</tr>
</thead>
for _, agent := range state.Agents {
<tr>
<td>{agent.PublicId}</td>
<td>{agent.StartTime.In(location).Format(time.DateTime)}</td>
<td>{agent.ExpiryTime.In(location).Format(time.DateTime)}</td>
<td>{agent.AgentInfo.Username}</td>
<td>{agent.AgentInfo.Hostname}</td>
<td>{agent.AgentInfo.OS}</td>
<td>{agent.AgentInfo.Shell}</td>
</tr>
}
</table>
}
<h3>clients</h3>
if len(state.Clients) == 0 {
<p>-</p>
} else {
<table class="table">
<thead>
<tr>
<th>agent id</th>
<th>id</th>
<th>start time</th>
<th>session type</th>
</tr>
</thead>
for _, client := range state.Clients {
<tr>
<td>{client.PublicId}</td>
<td>{strconv.Itoa(client.ClientId)}</td>
<td>{client.StartTime.In(location).Format(time.DateTime)}</td>
<td>{client.SessionType}</td>
</tr>
}
</table>
}
</div>
}
templ SessionsTab() {
templ SessionsTab(state *models.State, loc *time.Location) {
@BasePage(4) {
@Sessions(nil)
@Sessions(state, loc)
}
}