mirror of https://github.com/velour/catbase.git
admin: convert variables page to htmx
This commit is contained in:
parent
3dc8c77505
commit
c32738f444
|
@ -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() {
|
||||||
|
|
|
@ -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>
|
17
bot/web.go
17
bot/web.go
|
@ -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())
|
||||||
|
|
|
@ -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>
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue