add basic UI

This commit is contained in:
Alexander Baryshnikov 2020-09-28 23:12:57 +08:00
parent 48094464eb
commit 4698e52dca
5 changed files with 188 additions and 50 deletions

View File

@ -15,6 +15,7 @@ import (
type runCmd struct {
Directory string `long:"directory" short:"d" env:"DIRECTORY" description:"Data directory" default:"run"`
UI string `long:"ui" env:"UI" description:"Path to UI directory" default:"templates"`
Interval time.Duration `long:"interval" short:"i" env:"INTERVAL" description:"Requeue interval" default:"3s"`
Attempts int `long:"attempts" short:"a" env:"ATTEMPTS" description:"Max number of attempts" default:"5"`
Concurrency int `long:"concurrency" short:"c" env:"CONCURRENCY" description:"Number of parallel worker (0 - mean number of CPU)" default:"0"`
@ -35,6 +36,7 @@ func (cfg *runCmd) Execute([]string) error {
srv := runner.DefaultConfig()
srv.Bind = cfg.Bind
srv.WorkingDirectory = cfg.Directory
srv.UIDirectory = cfg.UI
srv.ConfigDirectory = tmpDir
unit := server.DefaultUnit()

View File

@ -91,14 +91,13 @@ func (cfg Config) Create(global context.Context) (*Server, error) {
ctx, cancel := context.WithCancel(global)
router := gin.Default()
router.LoadHTMLGlob(filepath.Join(cfg.UIDirectory, "*.html"))
router.Static("/static", filepath.Join(cfg.UIDirectory, "static"))
server.Attach(router.Group("/api/"), units, workers)
ui.Attach(router.Group("/ui/"), units, cfg.UIDirectory)
router.Group("/", func(gctx *gin.Context) {
ui.Attach(router.Group("/ui/"), units)
router.GET("/", func(gctx *gin.Context) {
gctx.Redirect(http.StatusTemporaryRedirect, "ui")
})
//router.Path("/").Methods("GET").HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
// http.Redirect(writer, request, "ui", http.StatusTemporaryRedirect)
//})
srv := &Server{
Handler: router,

View File

@ -1,11 +1,9 @@
package ui
import (
"html/template"
"net/http"
"path/filepath"
"github.com/Masterminds/sprig"
"github.com/gin-gonic/gin"
"nano-run/server"
@ -13,21 +11,23 @@ import (
func Expose(units []server.Unit, uiDir string) http.Handler {
router := gin.New()
Attach(router, units, uiDir)
router.LoadHTMLGlob(filepath.Join(uiDir, "*.html"))
Attach(router, units)
return router
}
func Attach(router gin.IRouter, units []server.Unit, uiDir string) {
func Attach(router gin.IRouter, units []server.Unit) {
ui := &uiRouter{
dir: uiDir,
units: units,
}
router.GET("", func(gctx *gin.Context) {
gctx.Redirect(http.StatusTemporaryRedirect, "units")
})
router.GET("/units", ui.listUnits)
router.GET("/unit/:name", ui.unitInfo)
}
type uiRouter struct {
dir string
units []server.Unit
}
@ -58,15 +58,3 @@ func (ui *uiRouter) listUnits(gctx *gin.Context) {
reply.Units = ui.units
gctx.HTML(http.StatusOK, "units-list.html", reply)
}
func (ui *uiRouter) getTemplate(name string) *template.Template {
t, err := template.New("").Funcs(sprig.HtmlFuncMap()).ParseFiles(filepath.Join(ui.dir, name))
if err == nil {
return t
}
t, err = template.New("").Parse("<html><body>Ooops... Page not found</body></html>")
if err != nil {
panic(err)
}
return t
}

View File

@ -1,18 +1,106 @@
<html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/mvp.css">
</head>
<body>
<div>
<a href="unit/{{.Unit.Name}}">
<h2>{{.Unit.Name}}</h2>
{{if .Unit.Secured}}
secured
<main>
<section>
<header>
<h2><a href="../units">Units</a> :: {{.Unit.Name}}</h2>
<h4>
<code><script>document.write((new URL("../../api/{{.Unit.Name}}/", window.location).href))</script></code>
</h4>
</header>
<aside>
<h3>Configuration</h3>
<ul>
{{with .Unit}}
<li>
<b>Mode: </b>{{.Mode}}
</li>
<li>
<b>Concurrency: </b>{{.Workers}}
</li>
<li>
<b>Attempts: </b>{{.Attempts}}
</li>
<li>
<b>Interval: </b>{{.Interval}}
</li>
<li>
<b>Timeout: </b>
{{with .Timeout}}
{{.}}
{{else}}
{{end}}
</li>
<li>
<b>Max request size: </b>
{{with .MaxRequest}}
{{.}}
{{else}}
{{end}}
</li>
<li>
<b>Working directory: </b>
{{with .WorkDir}}
<sup>static</sup>
<span style="overflow-x: auto; word-break: break-all">{{.}}</span>
{{else}}
<i>dynamic</i>
{{end}}
</li>
{{end}}
</ul>
</aside>
<aside>
<h3>Environment</h3>
<table>
<thead>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
</thead>
<tbody>
{{range $k,$v := .Unit.Environment}}
<tr>
<td>
<pre>{{$k}}</pre>
</td>
<td>{{$v}}</td>
</tr>
{{end}}
</tbody>
</table>
</aside>
{{with .Unit.Authorization}}
<aside>
<h3>Authorization{{if not $.Unit.Secured}} ⚠️{{end}}</h3>
<table>
<tr>
<th>JWT</th>
<td>{{if .JWT.Enable}}✅{{else}}❌{{end}}</td>
</tr>
<tr>
<th>Token in query</th>
<td>{{if .QueryToken.Enable}}✅{{else}}❌{{end}}</td>
</tr>
<tr>
<th>Token in header</th>
<td>{{if .HeaderToken.Enable}}✅{{else}}❌{{end}}</td>
</tr>
<tr>
<th>Basic auth</th>
<td>{{if .Basic.Enable}}✅{{else}}❌{{end}}</td>
</tr>
</table>
</aside>
{{end}}
</a>
<p>
<span class="unit-mode unit-mode-{{.Unit.Mode}}">{{.Unit.Mode}}</span>,
<span class="unit-mode unit-mode-workers">{{.Unit.Workers}}</span>,
<span class="unit-mode unit-mode-interval">{{.Unit.Interval}}</span>,
<span class="unit-mode unit-mode-timeout">{{.Unit.Timeout}}</span>,
</p>
</div>
</section>
</main>
</body>
</html>

View File

@ -1,17 +1,78 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/mvp.css">
</head>
<body>
{{range .Units}}
<div>
<a href="unit/{{.Name}}">
<h2>{{.Name}}</h2>
</a>
<p>
<span class="unit-mode unit-mode-{{.Mode}}">{{.Mode}}</span>,
<span class="unit-mode unit-mode-workers">{{.Workers}}</span>,
<span class="unit-mode unit-mode-interval">{{.Interval}}</span>,
<span class="unit-mode unit-mode-timeout">{{.Timeout}}</span>,
</p>
</div>
{{end}}
<header>
<nav>
</nav>
<h1> Units </h1>
</header>
<main>
<section>
<table>
<thead>
<tr>
<th>Name</th>
<th>Mode</th>
<th>Concurrency</th>
<th>Attempts</th>
<th>Interval</th>
<th>Timeout</th>
<th>Max request size</th>
<th>Working directory</th>
</tr>
</thead>
<tbody>
{{range .Units}}
<tr>
<td>
<a href="unit/{{.Name}}">
{{.Name}}{{if .Secured}} (secured){{end}}
</a>
</td>
<td>
<span class="unit-mode unit-mode-{{.Mode}}">{{.Mode}}</span>
</td>
<td>
<span class="unit-mode unit-mode-workers">{{.Workers}}</span>
</td>
<td>
{{.Attempts}}
</td>
<td>
<span class="unit-mode unit-mode-interval">{{.Interval}}</span>
</td>
<td>
{{with .Timeout}}
{{.}}
{{else}}
{{end}}
</td>
<td>
{{with .MaxRequest}}
{{.}}
{{else}}
{{end}}
</td>
<td>
{{with .WorkDir}}
<details>
<summary>static</summary>
<p>{{.}}</p>
</details>
{{else}}
<i>dynamic</i>
{{end}}
</td>
</tr>
{{end}}
</tbody>
</table>
</section>
</main>
</body>
</html>