Rendering status as HTML tables.
This commit is contained in:
parent
638dffd143
commit
d6fc2e4118
@ -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,
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
@ -27,7 +27,5 @@ spec:
|
||||
- name: CONVERGE_PASSWORD
|
||||
# change this password in your final deployment
|
||||
value: "abc123"
|
||||
- name: TZ
|
||||
value: Europe/Amsterdam
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user