Rendering status as HTML tables.
This commit is contained in:
parent
885b7790d7
commit
4c52fb0f12
@ -140,7 +140,11 @@ func main() {
|
|||||||
Handler: func(w http.ResponseWriter, r *http.Request, conn net.Conn) {
|
Handler: func(w http.ResponseWriter, r *http.Request, conn net.Conn) {
|
||||||
websession := websessions.NewSession(conn)
|
websession := websessions.NewSession(conn)
|
||||||
defer websessions.SessionClosed(websession)
|
defer websessions.SessionClosed(websession)
|
||||||
websession.WriteNotifications()
|
location, err := converge.GetUserLocation(r)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
websession.WriteNotifications(location)
|
||||||
},
|
},
|
||||||
Text: true,
|
Text: true,
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"converge/pkg/server/converge"
|
||||||
templates2 "converge/pkg/server/templates"
|
templates2 "converge/pkg/server/templates"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@ -24,6 +25,11 @@ func pageHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
username, _ := os.LookupEnv("CONVERGE_USERNAME")
|
username, _ := os.LookupEnv("CONVERGE_USERNAME")
|
||||||
|
|
||||||
|
location, err := converge.GetUserLocation(r)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
switch r.URL.Path {
|
switch r.URL.Path {
|
||||||
case "":
|
case "":
|
||||||
fallthrough
|
fallthrough
|
||||||
@ -36,7 +42,7 @@ func pageHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
case "downloads.html":
|
case "downloads.html":
|
||||||
templates2.DownloadsTab().Render(r.Context(), w)
|
templates2.DownloadsTab().Render(r.Context(), w)
|
||||||
case "sessions.html":
|
case "sessions.html":
|
||||||
templates2.SessionsTab().Render(r.Context(), w)
|
templates2.SessionsTab(nil, location).Render(r.Context(), w)
|
||||||
default:
|
default:
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,14 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"converge/pkg/comms"
|
||||||
|
"converge/pkg/models"
|
||||||
templates2 "converge/pkg/server/templates"
|
templates2 "converge/pkg/server/templates"
|
||||||
"github.com/a-h/templ"
|
"github.com/a-h/templ"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RenderFunc func() templ.Component
|
type RenderFunc func() templ.Component
|
||||||
@ -29,6 +32,11 @@ func render(dir string, name string, render RenderFunc) {
|
|||||||
func main() {
|
func main() {
|
||||||
dir := "html/docs"
|
dir := "html/docs"
|
||||||
|
|
||||||
|
netherlands, err := time.LoadLocation("Europe/Amsterdam")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
fullindex := func() templ.Component {
|
fullindex := func() templ.Component {
|
||||||
return templates2.Index("s", "example.com", "converge")
|
return templates2.Index("s", "example.com", "converge")
|
||||||
}
|
}
|
||||||
@ -41,5 +49,37 @@ func main() {
|
|||||||
render(dir, "usage.html", usage)
|
render(dir, "usage.html", usage)
|
||||||
render(dir, "downloads.html", templates2.Downloads)
|
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
|
- name: CONVERGE_PASSWORD
|
||||||
# change this password in your final deployment
|
# change this password in your final deployment
|
||||||
value: "abc123"
|
value: "abc123"
|
||||||
- name: TZ
|
|
||||||
value: Europe/Amsterdam
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"converge/pkg/server/templates"
|
"converge/pkg/server/templates"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -57,7 +58,25 @@ func (sessions *WebSessions) NewSession(wsConnection net.Conn) *WebSession {
|
|||||||
return session
|
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)
|
timer := time.NewTicker(10 * time.Second)
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
for {
|
for {
|
||||||
@ -66,8 +85,8 @@ func (session *WebSession) WriteNotifications() {
|
|||||||
if !ok {
|
if !ok {
|
||||||
log.Println("channel closed")
|
log.Println("channel closed")
|
||||||
}
|
}
|
||||||
log.Println("Got notification: ", notification.Ascii)
|
//log.Println("Got notification: ", notification)
|
||||||
err := templates.State(notification).Render(context.Background(), session.conn)
|
err := templates.State(notification, location).Render(context.Background(), session.conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("WS connection closed: %v", err)
|
log.Printf("WS connection closed: %v", err)
|
||||||
return
|
return
|
||||||
|
@ -1,34 +1,94 @@
|
|||||||
package templates
|
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">
|
<div hx-ext="ws" ws-connect="/ws/sessions">
|
||||||
<h1>sessions</h1>
|
<h1>sessions</h1>
|
||||||
|
|
||||||
<div id="status">
|
<div id="status">
|
||||||
if state != nil {
|
if state != nil {
|
||||||
@State(state)
|
@State(state, loc)
|
||||||
} else {
|
} else {
|
||||||
"Loading..."
|
Loading...
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
templ State(state *models.State) {
|
templ State(state *models.State, location *time.Location) {
|
||||||
<div id="status">
|
<div id="status">
|
||||||
<pre>
|
|
||||||
{ state.Ascii }
|
<h3>agents</h3>
|
||||||
</pre>
|
|
||||||
|
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>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
templ SessionsTab() {
|
templ SessionsTab(state *models.State, loc *time.Location) {
|
||||||
@BasePage(4) {
|
@BasePage(4) {
|
||||||
@Sessions(nil)
|
@Sessions(state, loc)
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user