show loading status in user interface
This commit is contained in:
parent
ae51e9d1b9
commit
ec6016062b
5 changed files with 108 additions and 17 deletions
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/cncd/queue"
|
"github.com/cncd/queue"
|
||||||
"github.com/dimfeld/httptreemux"
|
"github.com/dimfeld/httptreemux"
|
||||||
|
@ -176,11 +177,10 @@ func setupCoding(c *cli.Context) (remote.Remote, error) {
|
||||||
|
|
||||||
func setupTree(c *cli.Context) *httptreemux.ContextMux {
|
func setupTree(c *cli.Context) *httptreemux.ContextMux {
|
||||||
tree := httptreemux.NewContextMux()
|
tree := httptreemux.NewContextMux()
|
||||||
if path := c.String("www"); path == "" {
|
web.New(
|
||||||
web.New().Register(tree)
|
web.WithDir(c.String("www")),
|
||||||
} else {
|
web.WithSync(time.Hour*72),
|
||||||
web.FromPath(path).Register(tree)
|
).Register(tree)
|
||||||
}
|
|
||||||
return tree
|
return tree
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
37
server/web/opts.go
Normal file
37
server/web/opts.go
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
package web
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// Options defines website handler options.
|
||||||
|
type Options struct {
|
||||||
|
sync time.Duration
|
||||||
|
path string
|
||||||
|
docs string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option configures the website handler.
|
||||||
|
type Option func(*Options)
|
||||||
|
|
||||||
|
// WithSync configures the website hanlder with the duration value
|
||||||
|
// used to determine if the user account requires synchronization.
|
||||||
|
func WithSync(d time.Duration) Option {
|
||||||
|
return func(o *Options) {
|
||||||
|
o.sync = d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDir configures the website hanlder with the directory value
|
||||||
|
// used to serve the website from the local filesystem.
|
||||||
|
func WithDir(s string) Option {
|
||||||
|
return func(o *Options) {
|
||||||
|
o.path = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDocs configures the website hanlder with the documentation
|
||||||
|
// website address, which should be included in the user interface.
|
||||||
|
func WithDocs(s string) Option {
|
||||||
|
return func(o *Options) {
|
||||||
|
o.docs = s
|
||||||
|
}
|
||||||
|
}
|
30
server/web/opts_test.go
Normal file
30
server/web/opts_test.go
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package web
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWithSync(t *testing.T) {
|
||||||
|
opts := new(Options)
|
||||||
|
WithSync(time.Minute)(opts)
|
||||||
|
if got, want := opts.sync, time.Minute; got != want {
|
||||||
|
t.Errorf("Want sync duration %v, got %v", want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithDir(t *testing.T) {
|
||||||
|
opts := new(Options)
|
||||||
|
WithDir("/tmp/www")(opts)
|
||||||
|
if got, want := opts.path, "/tmp/www"; got != want {
|
||||||
|
t.Errorf("Want www directory %q, got %q", want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithDocs(t *testing.T) {
|
||||||
|
opts := new(Options)
|
||||||
|
WithDocs("http://docs.drone.io")(opts)
|
||||||
|
if got, want := opts.docs, "http://docs.drone.io"; got != want {
|
||||||
|
t.Errorf("Want documentation url %q, got %q", want, got)
|
||||||
|
}
|
||||||
|
}
|
|
@ -68,6 +68,7 @@ const partials = `
|
||||||
{{ if .user }}
|
{{ if .user }}
|
||||||
<script>
|
<script>
|
||||||
window.DRONE_USER = {{ json .user }};
|
window.DRONE_USER = {{ json .user }};
|
||||||
|
window.DRONE_SYNC = {{ .syncing }};
|
||||||
</script>
|
</script>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -83,4 +84,12 @@ const partials = `
|
||||||
{{define "version"}}
|
{{define "version"}}
|
||||||
<meta name="version" content="{{ .version }}">
|
<meta name="version" content="{{ .version }}">
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
{{define "docs"}}
|
||||||
|
{{ if .docs -}}
|
||||||
|
<script>
|
||||||
|
window.DRONE_DOCS = "{{ .docs }}"
|
||||||
|
</script>
|
||||||
|
{{- end }}
|
||||||
|
{{end}}
|
||||||
`
|
`
|
||||||
|
|
|
@ -25,32 +25,42 @@ type Endpoint interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns the default website endpoint.
|
// New returns the default website endpoint.
|
||||||
func New() Endpoint {
|
func New(opt ...Option) Endpoint {
|
||||||
|
opts := new(Options)
|
||||||
|
for _, f := range opt {
|
||||||
|
f(opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.path != "" {
|
||||||
|
return fromPath(opts)
|
||||||
|
}
|
||||||
|
|
||||||
return &website{
|
return &website{
|
||||||
fs: dist.New(),
|
fs: dist.New(),
|
||||||
templ: mustCreateTemplate(
|
opts: opts,
|
||||||
|
tmpl: mustCreateTemplate(
|
||||||
string(dist.MustLookup("/index.html")),
|
string(dist.MustLookup("/index.html")),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromPath returns the website endpoint that
|
func fromPath(opts *Options) *website {
|
||||||
// serves the webpage form disk at path p.
|
f := filepath.Join(opts.path, "index.html")
|
||||||
func FromPath(p string) Endpoint {
|
|
||||||
f := filepath.Join(p, "index.html")
|
|
||||||
b, err := ioutil.ReadFile(f)
|
b, err := ioutil.ReadFile(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return &website{
|
return &website{
|
||||||
fs: http.Dir(p),
|
fs: http.Dir(opts.path),
|
||||||
templ: mustCreateTemplate(string(b)),
|
tmpl: mustCreateTemplate(string(b)),
|
||||||
|
opts: opts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type website struct {
|
type website struct {
|
||||||
fs http.FileSystem
|
opts *Options
|
||||||
templ *template.Template
|
fs http.FileSystem
|
||||||
|
tmpl *template.Template
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *website) Register(mux *httptreemux.ContextMux) {
|
func (w *website) Register(mux *httptreemux.ContextMux) {
|
||||||
|
@ -72,14 +82,19 @@ func (w *website) handleIndex(rw http.ResponseWriter, r *http.Request) {
|
||||||
user.Login,
|
user.Login,
|
||||||
).Sign(user.Hash)
|
).Sign(user.Hash)
|
||||||
}
|
}
|
||||||
|
var syncing bool
|
||||||
|
if user != nil {
|
||||||
|
syncing = time.Unix(user.Synced, 0).Add(w.opts.sync).Before(time.Now())
|
||||||
|
}
|
||||||
params := map[string]interface{}{
|
params := map[string]interface{}{
|
||||||
"user": user,
|
"user": user,
|
||||||
"csrf": csrf,
|
"csrf": csrf,
|
||||||
|
"syncing": syncing,
|
||||||
"version": version.Version.String(),
|
"version": version.Version.String(),
|
||||||
}
|
}
|
||||||
rw.Header().Set("Content-Type", "text/html; charset=UTF-8")
|
rw.Header().Set("Content-Type", "text/html; charset=UTF-8")
|
||||||
|
|
||||||
w.templ.Execute(rw, params)
|
w.tmpl.Execute(rw, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupCache(h http.Handler) http.Handler {
|
func setupCache(h http.Handler) http.Handler {
|
||||||
|
|
Loading…
Reference in a new issue