admin: convert variables page to htmx

This commit is contained in:
Chris Sexton 2023-08-17 15:43:27 -04:00
parent 3dc8c77505
commit c32738f444
6 changed files with 96 additions and 73 deletions

View File

@ -147,6 +147,8 @@ func (b *bot) setupHTTP() {
b.router.HandleFunc("/", b.serveRoot) b.router.HandleFunc("/", b.serveRoot)
b.router.HandleFunc("/nav", b.serveNav) b.router.HandleFunc("/nav", b.serveNav)
b.router.HandleFunc("/navHTML", b.serveNavHTML)
b.router.HandleFunc("/navHTML/{currentPage}", b.serveNavHTML)
} }
func (b *bot) ListenAndServe() { func (b *bot) ListenAndServe() {

22
bot/nav.html Normal file
View File

@ -0,0 +1,22 @@
<nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container-fluid">
<a class="navbar-brand" href="/">catbase</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
{{- $currentPage := .CurrentPage -}}
{{range .Items}}
<li class="nav-item">
{{ if (eq $currentPage .Name) }}
<a class="nav-link active" aria-current="page" href="{{.URL}}">{{.Name}}</a>
{{ else }}
<a class="nav-link" href="{{.URL}}">{{.Name}}</a>
{{ end }}
</li>
{{end}}
</ul>
</div>
</div>
</nav>

View File

@ -3,8 +3,12 @@ package bot
import ( import (
"embed" "embed"
"encoding/json" "encoding/json"
"fmt"
"github.com/go-chi/chi/v5"
"github.com/rs/zerolog/log"
"net/http" "net/http"
"strings" "strings"
"text/template"
) )
//go:embed *.html //go:embed *.html
@ -15,6 +19,19 @@ func (b *bot) serveRoot(w http.ResponseWriter, r *http.Request) {
w.Write(index) w.Write(index)
} }
func (b *bot) serveNavHTML(w http.ResponseWriter, r *http.Request) {
currentPage := chi.URLParam(r, "currentPage")
tpl := template.Must(template.ParseFS(embeddedFS, "nav.html"))
if err := tpl.Execute(w, struct {
CurrentPage string
Items []EndPoint
}{currentPage, b.GetWebNavigation()}); err != nil {
log.Error().Err(err).Msg("template error")
w.WriteHeader(500)
fmt.Fprint(w, "Error parsing nav template")
}
}
func (b *bot) serveNav(w http.ResponseWriter, r *http.Request) { func (b *bot) serveNav(w http.ResponseWriter, r *http.Request) {
enc := json.NewEncoder(w) enc := json.NewEncoder(w)
err := enc.Encode(b.GetWebNavigation()) err := enc.Encode(b.GetWebNavigation())

View File

@ -1,77 +1,36 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<!-- Load required Bootstrap and BootstrapVue CSS --> <meta charset="utf-8">
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css"/> <meta name="viewport" content="width=device-width, initial-scale=1">
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@^2/dist/bootstrap-vue.min.css"/> <title>vars</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous">
<!-- Load polyfills to support older browsers --> <script src="https://unpkg.com/htmx.org@1.9.4"></script>
<script src="//polyfill.io/v3/polyfill.min.js?features=es2015%2CMutationObserver"></script>
<!-- Load Vue followed by BootstrapVue -->
<script src="//unpkg.com/vue@^2/dist/vue.min.js"></script>
<script src="//unpkg.com/bootstrap-vue@^2/dist/bootstrap-vue.min.js"></script>
<script src="//unpkg.com/axios/dist/axios.min.js"></script>
<meta charset="UTF-8">
<title>Vars</title>
</head> </head>
<body> <body>
<div class="container">
<div hx-get="/navHTML/Variables" hx-trigger="load" hx-swap="outerHTML"></div>
<div id="app"> <table class="table table-striped">
<b-navbar> <thead>
<b-navbar-brand>Variables</b-navbar-brand> <tr>
<b-navbar-nav> <th>Key</th>
<b-nav-item v-for="item in nav" :href="item.url" :active="item.name === 'Variables'">{{ item.name }} <th>Value</th>
</b-nav-item> </tr>
</b-navbar-nav> </thead>
</b-navbar> <tbody>
<b-alert {{range .Items}}
dismissable <tr>
variant="error" <td>{{.Key}}</td><td>{{.Value}}</td>
v-if="err" </tr>
@dismissed="err = ''"> {{else}}
{{ err }} <tr>
</b-alert> <td colspan="2">No data</td>
<b-container> </tr>
<b-table {{end}}
fixed </tbody>
:items="vars" </table>
:sort-by.sync="sortBy" </div>
:fields="fields"></b-table> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-HwwvtgBNo3bZJJLYd8oVXjrBZt8cqVSpeBNS5n7C8IVInixGAoxmnlMuBnhbgrkm" crossorigin="anonymous"></script>
</b-container>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
err: '',
nav: [],
vars: [],
sortBy: 'key',
fields: [
{key: {sortable: true}},
'value'
]
},
mounted() {
this.getData();
axios.get('/nav')
.then(resp => {
this.nav = resp.data;
})
.catch(err => console.log(err))
},
methods: {
getData: function () {
axios.get('/vars/api')
.then(resp => {
this.vars = resp.data;
})
.catch(err => this.err = err);
}
}
})
</script>
</body> </body>
</html> </html>

View File

@ -6,6 +6,7 @@ import (
"embed" "embed"
"encoding/json" "encoding/json"
"fmt" "fmt"
"html/template"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"strings" "strings"
@ -166,9 +167,32 @@ func writeErr(w http.ResponseWriter, err error) {
fmt.Fprint(w, string(j)) fmt.Fprint(w, string(j))
} }
type configEntry struct {
Key string `json:"key"`
Value string `json:"value"`
}
func (p *AdminPlugin) handleVars(w http.ResponseWriter, r *http.Request) { func (p *AdminPlugin) handleVars(w http.ResponseWriter, r *http.Request) {
index, _ := embeddedFS.ReadFile("vars.html") tpl := template.Must(template.ParseFS(embeddedFS, "vars.html"))
w.Write(index) var configEntries []configEntry
q := `select key, value from config`
err := p.db.Select(&configEntries, q)
if err != nil {
log.Error().
Err(err).
Msg("Error getting config entries.")
w.WriteHeader(500)
fmt.Fprint(w, err)
return
}
if err := tpl.Execute(w, struct {
Items []configEntry
}{configEntries}); err != nil {
log.Error().Err(err).Msg("template error")
w.WriteHeader(500)
fmt.Fprint(w, "Error parsing template")
}
} }
func (p *AdminPlugin) handleVarsAPI(w http.ResponseWriter, r *http.Request) { func (p *AdminPlugin) handleVarsAPI(w http.ResponseWriter, r *http.Request) {

View File

@ -144,7 +144,6 @@ func (p *FactoidPlugin) findTrigger(fact string) (bool, *Factoid) {
f, err := GetSingleFact(p.db, fact) f, err := GetSingleFact(p.db, fact)
if err != nil { if err != nil {
log.Error().Err(err).Msg("GetSingleFact")
return findAlias(p.db, fact) return findAlias(p.db, fact)
} }
return true, f return true, f