chore(webui): improve the states id page

This commit is contained in:
Julien Dessaux 2025-04-21 23:49:24 +02:00
parent 9bf75bfd37
commit 6fb2db436d
Signed by: adyxax
GPG key ID: F92E51B86E07177E
4 changed files with 106 additions and 45 deletions

View file

@ -45,7 +45,7 @@
</span>
{{ end }}
<div style="align-self:stretch; display:flex; justify-content:flex-end;">
<button class="primary" type="submit" value="submit">Upload and Create State</button>
<button type="submit" value="submit">Upload and Create State</button>
</div>
</fieldset>
</form>

View file

@ -1,5 +1,6 @@
{{ define "main" }}
<h1>State</h1>
<h1>{{ .State.Path }}</h1>
<h2>Status</h2>
<p>
The state at path
<strong>{{ .State.Path }}</strong>
@ -18,8 +19,54 @@
</span>
{{ end }}
</strong>
Use this page to manage the state or inspect the current and past state versions.
</p>
<p>Use this page to inspect the existing versions.</p>
<h2>Operations</h2>
<div class="flex-row">
<form action="/states/{{ .State.Id }}" method="post">
<fieldset>
<legend>Edit State</legend>
<div class="flex-row">
<label for="path">Path</label>
<input {{ if or .PathDuplicate .PathError }}class="error"{{ end }}
id="path"
name="path"
required
type="text"
value="{{ if eq .Path "" }}{{ .State.Path }}{{ else }}{{ .Path }}{{ end }}">
<button name="action" type="submit" value="edit">Edit State</button>
</div>
{{ if .PathDuplicate }}
<span class="error">This path already exist.</span>
{{ else if .PathError }}
<span class="error">
Path needs to be a valid
<span class="tooltip">
absolute
<span class="tooltip-text">
URL path is considered absolute when it starts with a <code>/</code> character.
</span>
</span>
and
<span class="tooltip">
clean
<span class="tooltip-text">
A URL path is considered clean when it has no relative path elements like <code>../</code>, repeated <code>//</code> and when it does not end with a <code>/</code>.
</span>
</span>
URL path.
</span>
{{ end }}
</fieldset>
</form>
<form action="/states/{{ .State.Id }}" method="post">
<fieldset>
<legend>Danger Zone</legend>
<button action="delete" type="submit" value="delete">Delete State</button>
</fieldset>
</form>
</div>
<h2>Versions</h2>
<article>
<table style="width:100%;">
<thead>

View file

@ -10,7 +10,6 @@ import (
"git.adyxax.org/adyxax/tfstated/pkg/database"
"git.adyxax.org/adyxax/tfstated/pkg/model"
"go.n16f.net/uuid"
)
type StatesPage struct {
@ -23,7 +22,6 @@ type StatesPage struct {
}
var statesTemplates = template.Must(template.ParseFS(htmlFS, "html/base.html", "html/states.html"))
var statesIdTemplate = template.Must(template.ParseFS(htmlFS, "html/base.html", "html/statesId.html"))
func handleStatesGET(db *database.DB) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@ -95,43 +93,3 @@ func handleStatesPOST(db *database.DB) http.Handler {
http.Redirect(w, r, destination, http.StatusFound)
})
}
func handleStatesIdGET(db *database.DB) http.Handler {
type StatesData struct {
Page *Page
State *model.State
Usernames map[string]string
Versions []model.Version
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var stateId uuid.UUID
if err := stateId.Parse(r.PathValue("id")); err != nil {
errorResponse(w, r, http.StatusBadRequest, err)
return
}
state, err := db.LoadStateById(stateId)
if err != nil {
errorResponse(w, r, http.StatusInternalServerError, err)
return
}
versions, err := db.LoadVersionsByState(state)
if err != nil {
errorResponse(w, r, http.StatusInternalServerError, err)
return
}
usernames, err := db.LoadAccountUsernames()
if err != nil {
errorResponse(w, r, http.StatusInternalServerError, err)
return
}
render(w, statesIdTemplate, http.StatusOK, StatesData{
Page: makePage(r, &Page{
Section: "states",
Title: state.Path,
}),
State: state,
Usernames: usernames,
Versions: versions,
})
})
}

56
pkg/webui/statesId.go Normal file
View file

@ -0,0 +1,56 @@
package webui
import (
"html/template"
"net/http"
"git.adyxax.org/adyxax/tfstated/pkg/database"
"git.adyxax.org/adyxax/tfstated/pkg/model"
"go.n16f.net/uuid"
)
type StatesIdPage struct {
Page *Page
Path string
PathError bool
PathDuplicate bool
State *model.State
Usernames map[string]string
Versions []model.Version
}
var statesIdTemplate = template.Must(template.ParseFS(htmlFS, "html/base.html", "html/statesId.html"))
func handleStatesIdGET(db *database.DB) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var stateId uuid.UUID
if err := stateId.Parse(r.PathValue("id")); err != nil {
errorResponse(w, r, http.StatusBadRequest, err)
return
}
state, err := db.LoadStateById(stateId)
if err != nil {
errorResponse(w, r, http.StatusInternalServerError, err)
return
}
versions, err := db.LoadVersionsByState(state)
if err != nil {
errorResponse(w, r, http.StatusInternalServerError, err)
return
}
usernames, err := db.LoadAccountUsernames()
if err != nil {
errorResponse(w, r, http.StatusInternalServerError, err)
return
}
render(w, statesIdTemplate, http.StatusOK, StatesIdPage{
Page: makePage(r, &Page{
Section: "states",
Title: state.Path,
}),
State: state,
Usernames: usernames,
Versions: versions,
})
})
}