add embedded UI

This commit is contained in:
Alexander Baryshnikov 2020-10-06 15:03:07 +08:00
parent d46c2011a1
commit 30c9fc7e31
5 changed files with 730 additions and 13 deletions

14
_docs/ui.md Normal file
View File

@ -0,0 +1,14 @@
# UI
UI available by default at port 8989, browser will be automatically redirected to `/ui/`.
Disable ui by `disable_ui: yes` flag in the config.
If UI directory (from `ui_directory`, default `ui`), embedded UI will be used.
UI directory supports static files under `static` directory under `/static` prefix.
All *.html files scanned under `ui_directory` directory as [Go HTML template](https://golang.org/pkg/html/template/)
with additional functions from [Sprig](http://masterminds.github.io/sprig/). Recursive scanning not supported.
UI embedded by [go-bindata](https://github.com/go-bindata/go-bindata).

View File

@ -15,7 +15,7 @@ type serverCmd struct {
}
type serverInitCmd struct {
Directory string `short:"d" long:"directory" env:"DIRECTORY" description:"Target directory" default:"server"`
Directory string `short:"d" long:"directory" env:"DIRECTORY" description:"Target directory" default:"."`
ConfigFile string `long:"config-file" env:"CONFIG_FILE" description:"Config file name" default:"server.yaml"`
NoSample bool `long:"no-sample" env:"NO_SAMPLE" description:"Do not create same file"`
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,6 +2,7 @@ package runner
import (
"context"
"html/template"
"io/ioutil"
"log"
"net/http"
@ -14,16 +15,22 @@ import (
"gopkg.in/yaml.v2"
"nano-run/server"
embedded_static "nano-run/server/runner/embedded/static"
embedded_templates "nano-run/server/runner/embedded/templates"
"nano-run/server/ui"
"nano-run/worker"
)
//go:generate go-bindata -pkg templates -o embedded/templates/bindata.go -nometadata -prefix ../../templates/ ../../templates/
//go:generate go-bindata -fs -pkg static -o embedded/static/bindata.go -prefix ../../templates/static/ ../../templates/static/...
type Config struct {
UIDirectory string `yaml:"ui_directory"`
WorkingDirectory string `yaml:"working_directory"`
ConfigDirectory string `yaml:"config_directory"`
Bind string `yaml:"bind"`
GracefulShutdown time.Duration `yaml:"graceful_shutdown"`
DisableUI bool `yaml:"disable_ui"`
Auth ui.Authorization `yaml:"auth,omitempty"`
TLS struct {
Enable bool `yaml:"enable"`
@ -92,18 +99,7 @@ func (cfg Config) Create(global context.Context) (*Server, error) {
}
ctx, cancel := context.WithCancel(global)
router := gin.Default()
router.SetFuncMap(sprig.HtmlFuncMap())
uiPath := filepath.Join(cfg.UIDirectory, "*.html")
if v, err := filepath.Glob(uiPath); err == nil && len(v) > 0 {
// little hack to prevent panic on empty UI
router.LoadHTMLGlob(uiPath)
}
router.GET("/", func(gctx *gin.Context) {
gctx.Redirect(http.StatusTemporaryRedirect, "ui")
})
uiGroup := router.Group("/ui/")
ui.Attach(uiGroup, units, workers, cfg.Auth)
uiGroup.Static("/static/", filepath.Join(cfg.UIDirectory, "static"))
cfg.installUI(router, units, workers)
server.Attach(router.Group("/api/"), units, workers)
srv := &Server{
@ -153,6 +149,42 @@ func (cfg Config) Run(global context.Context) error {
return err
}
func (cfg Config) installUI(router *gin.Engine, units []server.Unit, workers []*worker.Worker) {
if cfg.DisableUI {
log.Println("ui disabled")
return
}
uiPath := filepath.Join(cfg.UIDirectory, "*.html")
uiGroup := router.Group("/ui/")
if v, err := filepath.Glob(uiPath); err == nil && len(v) > 0 {
cfg.useDirectoryUI(router, uiGroup)
} else {
log.Println("using embedded UI")
cfg.useEmbeddedUI(router, uiGroup)
}
router.GET("/", func(gctx *gin.Context) {
gctx.Redirect(http.StatusTemporaryRedirect, "ui")
})
ui.Attach(uiGroup, units, workers, cfg.Auth)
}
func (cfg Config) useDirectoryUI(router *gin.Engine, uiGroup gin.IRouter) {
uiPath := filepath.Join(cfg.UIDirectory, "*.html")
router.SetFuncMap(sprig.HtmlFuncMap())
router.LoadHTMLGlob(uiPath)
uiGroup.Static("/static/", filepath.Join(cfg.UIDirectory, "static"))
}
func (cfg Config) useEmbeddedUI(router *gin.Engine, uiGroup gin.IRouter) {
root := template.New("").Funcs(sprig.HtmlFuncMap())
for _, src := range embedded_templates.AssetNames() {
_, _ = root.New(src).Parse(string(embedded_templates.MustAsset(src)))
}
router.SetHTMLTemplate(root)
uiGroup.StaticFS("/static/", embedded_static.AssetFile())
}
type Server struct {
http.Handler
workers []*worker.Worker