mirror of https://github.com/velour/catbase.git
web: add a menu and redo index
We can add arbitrary links now with the `bot.links` config
This commit is contained in:
parent
f407da6128
commit
9ea45f0ad3
51
bot/bot.go
51
bot/bot.go
|
@ -3,7 +3,6 @@
|
|||
package bot
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
@ -38,7 +37,7 @@ type bot struct {
|
|||
version string
|
||||
|
||||
// The entries to the bot's HTTP interface
|
||||
httpEndPoints map[string]string
|
||||
httpEndPoints []EndPoint
|
||||
|
||||
// filters registered by plugins
|
||||
filters map[string]func(string) string
|
||||
|
@ -46,6 +45,10 @@ type bot struct {
|
|||
callbacks CallbackMap
|
||||
}
|
||||
|
||||
type EndPoint struct {
|
||||
Name, URL string
|
||||
}
|
||||
|
||||
// Variable represents a $var replacement
|
||||
type Variable struct {
|
||||
Variable, Value string
|
||||
|
@ -73,7 +76,7 @@ func New(config *config.Config, connector Connector) Bot {
|
|||
me: users[0],
|
||||
logIn: logIn,
|
||||
logOut: logOut,
|
||||
httpEndPoints: make(map[string]string),
|
||||
httpEndPoints: make([]EndPoint, 0),
|
||||
filters: make(map[string]func(string) string),
|
||||
callbacks: make(CallbackMap),
|
||||
}
|
||||
|
@ -133,46 +136,6 @@ func (b *bot) Who(channel string) []user.User {
|
|||
return users
|
||||
}
|
||||
|
||||
var rootIndex = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Factoids</title>
|
||||
<link rel="stylesheet" href="https://unpkg.com/purecss@1.0.0/build/pure-min.css" integrity="sha384-nn4HPE8lTHyVtfCBi5yW9d20FjT8BJwUXyWZT9InLYax14RDjBj46LmSztkmNP9w" crossorigin="anonymous">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
{{if .EndPoints}}
|
||||
<div style="padding-top: 1em;">
|
||||
<table class="pure-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Plugin</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{{range $key, $value := .EndPoints}}
|
||||
<tr>
|
||||
<td><a href="{{$value}}">{{$key}}</a></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{end}}
|
||||
</html>
|
||||
`
|
||||
|
||||
func (b *bot) serveRoot(w http.ResponseWriter, r *http.Request) {
|
||||
context := make(map[string]interface{})
|
||||
context["EndPoints"] = b.httpEndPoints
|
||||
t, err := template.New("rootIndex").Parse(rootIndex)
|
||||
if err != nil {
|
||||
log.Error().Err(err)
|
||||
}
|
||||
t.Execute(w, context)
|
||||
}
|
||||
|
||||
// IsCmd checks if message is a command and returns its curtailed version
|
||||
func IsCmd(c *config.Config, message string) (bool, string) {
|
||||
cmdcs := c.GetArray("CommandChar", []string{"!"})
|
||||
|
@ -266,5 +229,5 @@ func (b *bot) Register(p Plugin, kind Kind, cb Callback) {
|
|||
}
|
||||
|
||||
func (b *bot) RegisterWeb(root, name string) {
|
||||
b.httpEndPoints[name] = root
|
||||
b.httpEndPoints = append(b.httpEndPoints, EndPoint{name, root})
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@ type Bot interface {
|
|||
RegisterFilter(string, func(string) string)
|
||||
RegisterWeb(string, string)
|
||||
DefaultConnector() Connector
|
||||
GetWebNavigation() []EndPoint
|
||||
}
|
||||
|
||||
// Connector represents a server connection to a chat service
|
||||
|
|
|
@ -52,6 +52,7 @@ func (mb *MockBot) Send(c Connector, kind Kind, args ...interface{}) (string, er
|
|||
func (mb *MockBot) AddPlugin(f Plugin) {}
|
||||
func (mb *MockBot) Register(p Plugin, kind Kind, cb Callback) {}
|
||||
func (mb *MockBot) RegisterWeb(_, _ string) {}
|
||||
func (mb *MockBot) GetWebNavigation() []EndPoint { return nil }
|
||||
func (mb *MockBot) Receive(c Connector, kind Kind, msg msg.Message, args ...interface{}) bool {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
package bot
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (b *bot) serveRoot(w http.ResponseWriter, r *http.Request) {
|
||||
context := make(map[string]interface{})
|
||||
context["Nav"] = b.GetWebNavigation()
|
||||
t := template.Must(template.New("rootIndex").Parse(rootIndex))
|
||||
t.Execute(w, context)
|
||||
}
|
||||
|
||||
// GetWebNavigation returns a list of bootstrap-vue <b-nav-item> links
|
||||
// The parent <nav> is not included so each page may display it as
|
||||
// best fits
|
||||
func (b *bot) GetWebNavigation() []EndPoint {
|
||||
endpoints := b.httpEndPoints
|
||||
moreEndpoints := b.config.GetArray("bot.links", []string{})
|
||||
for _, e := range moreEndpoints {
|
||||
link := strings.Split(e, ":")
|
||||
if len(link) != 2 {
|
||||
continue
|
||||
}
|
||||
endpoints = append(endpoints, EndPoint{link[0], link[1]})
|
||||
}
|
||||
return endpoints
|
||||
}
|
||||
|
||||
var rootIndex = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Load required Bootstrap and BootstrapVue CSS -->
|
||||
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
|
||||
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.css" />
|
||||
|
||||
<!-- Load polyfills to support older browsers -->
|
||||
<script src="//polyfill.io/v3/polyfill.min.js?features=es2015%2CMutationObserver"></script>
|
||||
|
||||
<!-- Load Vue followed by BootstrapVue -->
|
||||
<script src="//unpkg.com/vue@latest/dist/vue.min.js"></script>
|
||||
<script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>
|
||||
<script src="https://unpkg.com/vue-router"></script>
|
||||
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
|
||||
<meta charset="UTF-8">
|
||||
<title>Factoids</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="app">
|
||||
<b-container>
|
||||
<h1>catbase</h1>
|
||||
<b-nav vertical class="w-25">
|
||||
<b-nav-item v-for="item in nav" :href="item.URL">{{ "{{ item.Name }}" }}</b-nav-item>
|
||||
</b-nav>
|
||||
</b-container>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data: {
|
||||
err: '',
|
||||
nav: {{ .Nav }},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`
|
|
@ -5,6 +5,7 @@ package admin
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -160,8 +161,10 @@ func (p *AdminPlugin) registerWeb() {
|
|||
p.bot.RegisterWeb("/vars", "Variables")
|
||||
}
|
||||
|
||||
var tpl = template.Must(template.New("factoidIndex").Parse(varIndex))
|
||||
|
||||
func (p *AdminPlugin) handleWeb(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, varIndex)
|
||||
tpl.Execute(w, struct{ Nav []bot.EndPoint }{p.bot.GetWebNavigation()})
|
||||
}
|
||||
|
||||
func (p *AdminPlugin) handleWebAPI(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -21,13 +21,18 @@ var varIndex = `
|
|||
<body>
|
||||
|
||||
<div id="app">
|
||||
<h1>Vars</h1>
|
||||
<b-navbar>
|
||||
<b-navbar-brand>Variables</b-navbar-brand>
|
||||
<b-navbar-nav>
|
||||
<b-nav-item v-for="item in nav" :href="item.URL" :active="item.Name === 'Variables'">{{ "{{ item.Name }}" }}</b-nav-item>
|
||||
</b-navbar-nav>
|
||||
</b-navbar>
|
||||
<b-alert
|
||||
dismissable
|
||||
variant="error"
|
||||
v-if="err"
|
||||
@dismissed="err = ''">
|
||||
{{ err }}
|
||||
{{ "{{ err }}" }}
|
||||
</b-alert>
|
||||
<b-container>
|
||||
<b-table
|
||||
|
@ -42,8 +47,9 @@ var varIndex = `
|
|||
var app = new Vue({
|
||||
el: '#app',
|
||||
data: {
|
||||
vars: [],
|
||||
err: '',
|
||||
nav: {{ .Nav }},
|
||||
vars: [],
|
||||
sortBy: 'key',
|
||||
fields: [
|
||||
{ key: { sortable: true } },
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/velour/catbase/bot"
|
||||
"github.com/velour/catbase/bot/msg"
|
||||
"github.com/velour/catbase/bot/user"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
@ -81,8 +82,10 @@ func (p *CliPlugin) handleWebAPI(w http.ResponseWriter, r *http.Request) {
|
|||
w.Write(data)
|
||||
}
|
||||
|
||||
var tpl = template.Must(template.New("factoidIndex").Parse(indexHTML))
|
||||
|
||||
func (p *CliPlugin) handleWeb(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, indexHTML)
|
||||
tpl.Execute(w, struct{ Nav []bot.EndPoint }{p.bot.GetWebNavigation()})
|
||||
}
|
||||
|
||||
// Completing the Connector interface, but will not actually be a connector
|
||||
|
|
|
@ -21,13 +21,18 @@ var indexHTML = `
|
|||
<body>
|
||||
|
||||
<div id="app">
|
||||
<h1>CLI</h1>
|
||||
<b-navbar>
|
||||
<b-navbar-brand>CLI</b-navbar-brand>
|
||||
<b-navbar-nav>
|
||||
<b-nav-item v-for="item in nav" :href="item.URL" :active="item.Name === 'CLI'">{{ "{{ item.Name }}" }}</b-nav-item>
|
||||
</b-navbar-nav>
|
||||
</b-navbar>
|
||||
<b-alert
|
||||
dismissable
|
||||
variant="error"
|
||||
v-if="err"
|
||||
@dismissed="err = ''">
|
||||
{{ err }}
|
||||
{{ "{{ err }}" }}
|
||||
</b-alert>
|
||||
<b-container>
|
||||
<b-row>
|
||||
|
@ -80,12 +85,13 @@ var indexHTML = `
|
|||
var app = new Vue({
|
||||
el: '#app',
|
||||
data: {
|
||||
err: '',
|
||||
nav: {{ .Nav }},
|
||||
answer: '',
|
||||
correct: 0,
|
||||
textarea: [],
|
||||
user: '',
|
||||
input: '',
|
||||
err: '',
|
||||
},
|
||||
computed: {
|
||||
authenticated: function() {
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
// © 2013 the CatBase Authors under the WTFPL. See AUTHORS for the list of authors.
|
||||
|
||||
package counter
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"regexp"
|
||||
|
@ -558,8 +557,10 @@ func (p *CounterPlugin) registerWeb() {
|
|||
p.Bot.RegisterWeb("/counter", "Counter")
|
||||
}
|
||||
|
||||
var tpl = template.Must(template.New("factoidIndex").Parse(html))
|
||||
|
||||
func (p *CounterPlugin) handleCounter(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, html)
|
||||
tpl.Execute(w, struct{ Nav []bot.EndPoint }{p.Bot.GetWebNavigation()})
|
||||
}
|
||||
|
||||
func (p *CounterPlugin) handleCounterAPI(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -19,28 +19,33 @@ var html = `
|
|||
<body>
|
||||
|
||||
<div id="app">
|
||||
<h1>Counters</h1>
|
||||
<b-navbar>
|
||||
<b-navbar-brand>Counters</b-navbar-brand>
|
||||
<b-navbar-nav>
|
||||
<b-nav-item v-for="item in nav" :href="item.URL" :active="item.Name === 'Counter'">{{ "{{ item.Name }}" }}</b-nav-item>
|
||||
</b-navbar-nav>
|
||||
</b-navbar>
|
||||
<b-alert
|
||||
dismissable
|
||||
variant="error"
|
||||
v-if="err"
|
||||
@dismissed="err = ''">
|
||||
{{ err }}
|
||||
{{ "{{ err }}" }}
|
||||
</b-alert>
|
||||
<b-container>
|
||||
<b-row>
|
||||
<b-col cols="5">Human test: What is {{ equation }}?</b-col>
|
||||
<b-col cols="5">Human test: What is {{ "{{ equation }}" }}?</b-col>
|
||||
<b-col><b-input v-model="answer"></b-col>
|
||||
</b-row>
|
||||
<b-row v-for="(counter, user) in counters">
|
||||
{{ user }}:
|
||||
{{ "{{ user }}" }}:
|
||||
<b-container>
|
||||
<b-row v-for="(count, thing) in counter">
|
||||
<b-col offset="1">
|
||||
{{ thing }}:
|
||||
{{ "{{ thing }}" }}:
|
||||
</b-col>
|
||||
<b-col>
|
||||
{{ count }}
|
||||
{{ "{{ count }}" }}
|
||||
</b-col>
|
||||
<b-col cols="2">
|
||||
<button :disabled="!authenticated" @click="subtract(user,thing,count)">-</button>
|
||||
|
@ -67,9 +72,10 @@ var html = `
|
|||
var app = new Vue({
|
||||
el: '#app',
|
||||
data: {
|
||||
err: '',
|
||||
nav: {{ .Nav }},
|
||||
answer: '',
|
||||
correct: 0,
|
||||
err: '',
|
||||
counters: {
|
||||
stk5: {
|
||||
beer: 12,
|
||||
|
|
|
@ -807,6 +807,8 @@ func (p *FactoidPlugin) serveAPI(w http.ResponseWriter, r *http.Request) {
|
|||
w.Write(data)
|
||||
}
|
||||
|
||||
var tpl = template.Must(template.New("factoidIndex").Parse(factoidIndex))
|
||||
|
||||
func (p *FactoidPlugin) serveQuery(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, factoidIndex)
|
||||
tpl.Execute(w, struct{ Nav []bot.EndPoint }{p.Bot.GetWebNavigation()})
|
||||
}
|
||||
|
|
|
@ -29,13 +29,18 @@ var factoidIndex = `
|
|||
<body>
|
||||
|
||||
<div id="app">
|
||||
<h1>Factoids</h1>
|
||||
<b-navbar>
|
||||
<b-navbar-brand>Factoids</b-navbar-brand>
|
||||
<b-navbar-nav>
|
||||
<b-nav-item v-for="item in nav" :href="item.URL" :active="item.Name === 'Factoid'">{{ "{{ item.Name }}" }}</b-nav-item>
|
||||
</b-navbar-nav>
|
||||
</b-navbar>
|
||||
<b-alert
|
||||
dismissable
|
||||
variant="error"
|
||||
v-if="err"
|
||||
@dismissed="err = ''">
|
||||
{{ err }}
|
||||
{{ "{{ err }}" }}
|
||||
</b-alert>
|
||||
<b-form @submit="runQuery">
|
||||
<b-container>
|
||||
|
@ -69,6 +74,7 @@ var factoidIndex = `
|
|||
router,
|
||||
data: {
|
||||
err: '',
|
||||
nav: {{ .Nav }},
|
||||
query: '',
|
||||
results: [],
|
||||
fields: [
|
||||
|
|
Loading…
Reference in New Issue