add basic UI
This commit is contained in:
parent
48094464eb
commit
4698e52dca
@ -15,6 +15,7 @@ import (
|
|||||||
|
|
||||||
type runCmd struct {
|
type runCmd struct {
|
||||||
Directory string `long:"directory" short:"d" env:"DIRECTORY" description:"Data directory" default:"run"`
|
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"`
|
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"`
|
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"`
|
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 := runner.DefaultConfig()
|
||||||
srv.Bind = cfg.Bind
|
srv.Bind = cfg.Bind
|
||||||
srv.WorkingDirectory = cfg.Directory
|
srv.WorkingDirectory = cfg.Directory
|
||||||
|
srv.UIDirectory = cfg.UI
|
||||||
srv.ConfigDirectory = tmpDir
|
srv.ConfigDirectory = tmpDir
|
||||||
|
|
||||||
unit := server.DefaultUnit()
|
unit := server.DefaultUnit()
|
||||||
|
@ -91,14 +91,13 @@ func (cfg Config) Create(global context.Context) (*Server, error) {
|
|||||||
ctx, cancel := context.WithCancel(global)
|
ctx, cancel := context.WithCancel(global)
|
||||||
|
|
||||||
router := gin.Default()
|
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)
|
server.Attach(router.Group("/api/"), units, workers)
|
||||||
ui.Attach(router.Group("/ui/"), units, cfg.UIDirectory)
|
ui.Attach(router.Group("/ui/"), units)
|
||||||
router.Group("/", func(gctx *gin.Context) {
|
router.GET("/", func(gctx *gin.Context) {
|
||||||
gctx.Redirect(http.StatusTemporaryRedirect, "ui")
|
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{
|
srv := &Server{
|
||||||
Handler: router,
|
Handler: router,
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"html/template"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/Masterminds/sprig"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
"nano-run/server"
|
"nano-run/server"
|
||||||
@ -13,21 +11,23 @@ import (
|
|||||||
|
|
||||||
func Expose(units []server.Unit, uiDir string) http.Handler {
|
func Expose(units []server.Unit, uiDir string) http.Handler {
|
||||||
router := gin.New()
|
router := gin.New()
|
||||||
Attach(router, units, uiDir)
|
router.LoadHTMLGlob(filepath.Join(uiDir, "*.html"))
|
||||||
|
Attach(router, units)
|
||||||
return router
|
return router
|
||||||
}
|
}
|
||||||
|
|
||||||
func Attach(router gin.IRouter, units []server.Unit, uiDir string) {
|
func Attach(router gin.IRouter, units []server.Unit) {
|
||||||
ui := &uiRouter{
|
ui := &uiRouter{
|
||||||
dir: uiDir,
|
|
||||||
units: units,
|
units: units,
|
||||||
}
|
}
|
||||||
|
router.GET("", func(gctx *gin.Context) {
|
||||||
|
gctx.Redirect(http.StatusTemporaryRedirect, "units")
|
||||||
|
})
|
||||||
router.GET("/units", ui.listUnits)
|
router.GET("/units", ui.listUnits)
|
||||||
router.GET("/unit/:name", ui.unitInfo)
|
router.GET("/unit/:name", ui.unitInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
type uiRouter struct {
|
type uiRouter struct {
|
||||||
dir string
|
|
||||||
units []server.Unit
|
units []server.Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,15 +58,3 @@ func (ui *uiRouter) listUnits(gctx *gin.Context) {
|
|||||||
reply.Units = ui.units
|
reply.Units = ui.units
|
||||||
gctx.HTML(http.StatusOK, "units-list.html", reply)
|
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
|
|
||||||
}
|
|
||||||
|
@ -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>
|
<body>
|
||||||
<div>
|
<main>
|
||||||
<a href="unit/{{.Unit.Name}}">
|
<section>
|
||||||
<h2>{{.Unit.Name}}</h2>
|
<header>
|
||||||
{{if .Unit.Secured}}
|
<h2><a href="../units">Units</a> :: {{.Unit.Name}}</h2>
|
||||||
secured
|
<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}}
|
{{end}}
|
||||||
</a>
|
</section>
|
||||||
<p>
|
</main>
|
||||||
<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>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -1,17 +1,78 @@
|
|||||||
<html>
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/mvp.css">
|
||||||
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{{range .Units}}
|
<header>
|
||||||
<div>
|
<nav>
|
||||||
<a href="unit/{{.Name}}">
|
</nav>
|
||||||
<h2>{{.Name}}</h2>
|
<h1> Units </h1>
|
||||||
</a>
|
</header>
|
||||||
<p>
|
<main>
|
||||||
<span class="unit-mode unit-mode-{{.Mode}}">{{.Mode}}</span>,
|
<section>
|
||||||
<span class="unit-mode unit-mode-workers">{{.Workers}}</span>,
|
<table>
|
||||||
<span class="unit-mode unit-mode-interval">{{.Interval}}</span>,
|
<thead>
|
||||||
<span class="unit-mode unit-mode-timeout">{{.Timeout}}</span>,
|
<tr>
|
||||||
</p>
|
<th>Name</th>
|
||||||
</div>
|
<th>Mode</th>
|
||||||
{{end}}
|
<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>
|
</body>
|
||||||
</html>
|
</html>
|
Loading…
x
Reference in New Issue
Block a user