diff --git a/cmd/drone-server/setup.go b/cmd/drone-server/setup.go
index 041016660..fabc6fac8 100644
--- a/cmd/drone-server/setup.go
+++ b/cmd/drone-server/setup.go
@@ -2,6 +2,7 @@ package main
import (
"fmt"
+ "time"
"github.com/cncd/queue"
"github.com/dimfeld/httptreemux"
@@ -176,11 +177,10 @@ func setupCoding(c *cli.Context) (remote.Remote, error) {
func setupTree(c *cli.Context) *httptreemux.ContextMux {
tree := httptreemux.NewContextMux()
- if path := c.String("www"); path == "" {
- web.New().Register(tree)
- } else {
- web.FromPath(path).Register(tree)
- }
+ web.New(
+ web.WithDir(c.String("www")),
+ web.WithSync(time.Hour*72),
+ ).Register(tree)
return tree
}
diff --git a/server/web/opts.go b/server/web/opts.go
new file mode 100644
index 000000000..d3e70b052
--- /dev/null
+++ b/server/web/opts.go
@@ -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
+ }
+}
diff --git a/server/web/opts_test.go b/server/web/opts_test.go
new file mode 100644
index 000000000..188ec09da
--- /dev/null
+++ b/server/web/opts_test.go
@@ -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)
+ }
+}
diff --git a/server/web/template.go b/server/web/template.go
index 8d9e4a1b9..dd93a74a0 100644
--- a/server/web/template.go
+++ b/server/web/template.go
@@ -68,6 +68,7 @@ const partials = `
{{ if .user }}
{{ end }}
{{end}}
@@ -83,4 +84,12 @@ const partials = `
{{define "version"}}
{{end}}
+
+{{define "docs"}}
+{{ if .docs -}}
+
+{{- end }}
+{{end}}
`
diff --git a/server/web/web.go b/server/web/web.go
index 5f4d508d2..58cb5dcee 100644
--- a/server/web/web.go
+++ b/server/web/web.go
@@ -25,32 +25,42 @@ type Endpoint interface {
}
// 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{
- fs: dist.New(),
- templ: mustCreateTemplate(
+ fs: dist.New(),
+ opts: opts,
+ tmpl: mustCreateTemplate(
string(dist.MustLookup("/index.html")),
),
}
}
-// FromPath returns the website endpoint that
-// serves the webpage form disk at path p.
-func FromPath(p string) Endpoint {
- f := filepath.Join(p, "index.html")
+func fromPath(opts *Options) *website {
+ f := filepath.Join(opts.path, "index.html")
b, err := ioutil.ReadFile(f)
if err != nil {
panic(err)
}
return &website{
- fs: http.Dir(p),
- templ: mustCreateTemplate(string(b)),
+ fs: http.Dir(opts.path),
+ tmpl: mustCreateTemplate(string(b)),
+ opts: opts,
}
}
type website struct {
- fs http.FileSystem
- templ *template.Template
+ opts *Options
+ fs http.FileSystem
+ tmpl *template.Template
}
func (w *website) Register(mux *httptreemux.ContextMux) {
@@ -72,14 +82,19 @@ func (w *website) handleIndex(rw http.ResponseWriter, r *http.Request) {
user.Login,
).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{}{
"user": user,
"csrf": csrf,
+ "syncing": syncing,
"version": version.Version.String(),
}
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 {