templating: Remove unused lazy code
This commit is contained in:
parent
1c68893a02
commit
46b16e5700
4 changed files with 30 additions and 110 deletions
|
|
@ -3,7 +3,6 @@ package templating
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
@ -14,7 +13,6 @@ import (
|
||||||
"github.com/gorilla/csrf"
|
"github.com/gorilla/csrf"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/tkw1536/pkglib/httpx"
|
"github.com/tkw1536/pkglib/httpx"
|
||||||
"github.com/tkw1536/pkglib/timex"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed "src/base.html"
|
//go:embed "src/base.html"
|
||||||
|
|
@ -32,17 +30,10 @@ func (tpl *Template[C]) Template() *template.Template {
|
||||||
return baseTemplate
|
return baseTemplate
|
||||||
}
|
}
|
||||||
|
|
||||||
// LazyContext is like the lazy context
|
|
||||||
func (tpl *Template[C]) LazyContext(r *http.Request, f func() (C, error), funcs ...FlagFunc) (ctx *tContext[C]) {
|
|
||||||
ctx = tpl.context(r, funcs...)
|
|
||||||
ctx.startLazy(f)
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
// Context generates the context to pass to an instance of the template returned by Template.
|
// Context generates the context to pass to an instance of the template returned by Template.
|
||||||
func (tpl *Template[C]) Context(r *http.Request, c C, funcs ...FlagFunc) (ctx *tContext[C]) {
|
func (tpl *Template[C]) Context(r *http.Request, c C, funcs ...FlagFunc) (ctx *tContext[C]) {
|
||||||
ctx = tpl.context(r, funcs...)
|
ctx = tpl.context(r, funcs...)
|
||||||
ctx.start(c, nil) // setup the request
|
ctx.cMain = c
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,27 +84,22 @@ func FormTemplateContext(tw *Template[FormContext]) func(ctx httpx.FormContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hander returns a function that returns a context for the given template
|
// HandlerWithFlags returns a function that, given a request, generates context and error to pass to the generated template.
|
||||||
|
// The worker implements the actual buisness logic, it takes a request, and returns the content for the main template, and any error.
|
||||||
|
// See also HandlerWithFlags.
|
||||||
func (tw *Template[C]) Handler(f func(r *http.Request) (C, error)) func(r *http.Request) (any, error) {
|
func (tw *Template[C]) Handler(f func(r *http.Request) (C, error)) func(r *http.Request) (any, error) {
|
||||||
// TODO: Should this one be removed?
|
|
||||||
return tw.HandlerWithFlags(func(r *http.Request) (C, []FlagFunc, error) {
|
return tw.HandlerWithFlags(func(r *http.Request) (C, []FlagFunc, error) {
|
||||||
c, err := f(r)
|
c, err := f(r)
|
||||||
return c, nil, err
|
return c, nil, err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTMLHandler returns a new HTMLHandler for this request
|
// HandlerWithFlags returns a function that, given a request, generates context and error to pass to the generated template.
|
||||||
func (tw *Template[C]) HTMLHandler(f func(r *http.Request) (C, error)) httpx.HTMLHandler[any] {
|
// The worker implements the actual buisness logic, it takes a request, and returns the content for the main template, flag functions and error.
|
||||||
return httpx.HTMLHandler[any]{
|
// See also Handler.
|
||||||
Handler: tw.Handler(f),
|
func (tw *Template[C]) HandlerWithFlags(worker func(r *http.Request) (C, []FlagFunc, error)) func(r *http.Request) (any, error) {
|
||||||
Template: tw.Template(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandlerWithFlags works like handler, but additionally receive funcs to generate flags
|
|
||||||
func (tw *Template[C]) HandlerWithFlags(f func(r *http.Request) (C, []FlagFunc, error)) func(r *http.Request) (any, error) {
|
|
||||||
return func(r *http.Request) (any, error) {
|
return func(r *http.Request) (any, error) {
|
||||||
c, funcs, err := f(r)
|
c, funcs, err := worker(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -122,9 +108,20 @@ func (tw *Template[C]) HandlerWithFlags(f func(r *http.Request) (C, []FlagFunc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tw *Template[C]) HTMLHandlerWithFlags(f func(r *http.Request) (C, []FlagFunc, error)) httpx.HTMLHandler[any] {
|
// HTMLHandler creates a new httpx.HTMLHandler that calls tw.Handler(worker) and tw.Template.
|
||||||
|
// See also Handler.
|
||||||
|
func (tw *Template[C]) HTMLHandler(worker func(r *http.Request) (C, error)) httpx.HTMLHandler[any] {
|
||||||
return httpx.HTMLHandler[any]{
|
return httpx.HTMLHandler[any]{
|
||||||
Handler: tw.HandlerWithFlags(f),
|
Handler: tw.Handler(worker),
|
||||||
|
Template: tw.Template(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTMLHandlerWithFlags creates a new httpx.HTMLHandler that calls tw.HandlerWithFlags(worker) and tw.Template.
|
||||||
|
// See also HandlerWithFlags.
|
||||||
|
func (tw *Template[C]) HTMLHandlerWithFlags(worker func(r *http.Request) (C, []FlagFunc, error)) httpx.HTMLHandler[any] {
|
||||||
|
return httpx.HTMLHandler[any]{
|
||||||
|
Handler: tw.HandlerWithFlags(worker),
|
||||||
Template: tw.Template(),
|
Template: tw.Template(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -140,8 +137,6 @@ type tContext[C any] struct {
|
||||||
ctx context.Context // underlying context for render
|
ctx context.Context // underlying context for render
|
||||||
|
|
||||||
// the main template and context
|
// the main template and context
|
||||||
eMain chan error // are we done?
|
|
||||||
cWaiting bool
|
|
||||||
tMain *template.Template
|
tMain *template.Template
|
||||||
cMain C
|
cMain C
|
||||||
|
|
||||||
|
|
@ -150,64 +145,8 @@ type tContext[C any] struct {
|
||||||
cFooter RuntimeFlags
|
cFooter RuntimeFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *tContext[C]) start(c C, err error) {
|
|
||||||
ctx.cMain = c
|
|
||||||
ctx.eMain = make(chan error, 1)
|
|
||||||
ctx.eMain <- err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *tContext[C]) startLazy(f func() (C, error)) {
|
|
||||||
ctx.eMain = make(chan error, 1)
|
|
||||||
go func() {
|
|
||||||
defer close(ctx.eMain)
|
|
||||||
|
|
||||||
// compute the result, storing the error
|
|
||||||
var err error
|
|
||||||
ctx.cMain, err = f()
|
|
||||||
ctx.eMain <- err
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
const mainDelay = time.Second
|
|
||||||
|
|
||||||
// Main renders the main template.
|
// Main renders the main template.
|
||||||
func (ctx *tContext[C]) Main() (template.HTML, error) {
|
func (ctx *tContext[C]) Main() (template.HTML, error) {
|
||||||
timer := timex.NewTimer()
|
|
||||||
defer timex.ReleaseTimer(timer)
|
|
||||||
|
|
||||||
timer.Reset(mainDelay)
|
|
||||||
select {
|
|
||||||
|
|
||||||
case err := <-ctx.eMain:
|
|
||||||
// we received the result within the given time
|
|
||||||
// so we can render it immediatly
|
|
||||||
ctx.cWaiting = false
|
|
||||||
return ctx.doMain(err)
|
|
||||||
|
|
||||||
case <-timer.C:
|
|
||||||
// the template is taking longer than expected.
|
|
||||||
// we should display a spinner, and do something later
|
|
||||||
ctx.cWaiting = true
|
|
||||||
return timeWait, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Footer renders the footer template
|
|
||||||
func (ctx *tContext[C]) Footer() (template.HTML, error) {
|
|
||||||
return ctx.renderSafe("footer", ctx.tFooter, ctx.cFooter)
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
timeWait = "Loading"
|
|
||||||
errUnknown = "An unknown error occured, see the server log for details. "
|
|
||||||
)
|
|
||||||
|
|
||||||
func (ctx *tContext[C]) doMain(err error) (template.HTML, error) {
|
|
||||||
if err != nil {
|
|
||||||
zerolog.Ctx(ctx.ctx).Err(err).Msg("error lazy loading template")
|
|
||||||
return errUnknown, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the context has a runtime flags embed, then set the field properly
|
// if the context has a runtime flags embed, then set the field properly
|
||||||
if ctx.updateEmbedded {
|
if ctx.updateEmbedded {
|
||||||
reflect.ValueOf(&ctx.cMain).Elem().
|
reflect.ValueOf(&ctx.cMain).Elem().
|
||||||
|
|
@ -218,34 +157,16 @@ func (ctx *tContext[C]) doMain(err error) (template.HTML, error) {
|
||||||
return ctx.renderSafe("main", ctx.tMain, ctx.cMain)
|
return ctx.renderSafe("main", ctx.tMain, ctx.cMain)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *tContext[C]) AfterBody() (template.HTML, error) {
|
// Footer renders the footer template
|
||||||
// everything was done already
|
func (ctx *tContext[C]) Footer() (template.HTML, error) {
|
||||||
if !ctx.cWaiting {
|
return ctx.renderSafe("footer", ctx.tFooter, ctx.cFooter)
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for the result to appear
|
|
||||||
res, err := ctx.doMain(<-ctx.eMain)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
str, err := json.Marshal(string(res))
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
fix := "<script>document.getElementById('main').innerHTML=" + string(str) + "</script>"
|
|
||||||
|
|
||||||
// hook that is called after the body is complete
|
|
||||||
return template.HTML(fix), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderSafeError = "Error displaying page. See server log for details. "
|
const renderSafeError = "Error displaying page. See server log for details. "
|
||||||
|
|
||||||
func (ctx *tContext[C]) renderSafe(name string, t *template.Template, c any) (template.HTML, error) {
|
func (ctx *tContext[C]) renderSafe(name string, t *template.Template, c any) (template.HTML, error) {
|
||||||
|
|
||||||
// already done
|
// already done with context => return
|
||||||
if err := ctx.ctx.Err(); err != nil {
|
if err := ctx.ctx.Err(); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ type RuntimeFlags struct {
|
||||||
CSRF template.HTML // csrf data (if any)
|
CSRF template.HTML // csrf data (if any)
|
||||||
}
|
}
|
||||||
|
|
||||||
var runtimeFlagsName = reflectx.TypeOf[RuntimeFlags]().Name()
|
var runtimeFlagsName = reflectx.MakeType[RuntimeFlags]().Name()
|
||||||
|
|
||||||
// Clone clones this flags
|
// Clone clones this flags
|
||||||
func (flags Flags) Clone() Flags {
|
func (flags Flags) Clone() Flags {
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ type Parsed[C any] struct {
|
||||||
// If base is not nil, every template associated with the base template is copied into the given template.
|
// If base is not nil, every template associated with the base template is copied into the given template.
|
||||||
// Functions will be applied on creation time to represent the context for the given template.
|
// Functions will be applied on creation time to represent the context for the given template.
|
||||||
func Parse[C any](name string, source []byte, base *template.Template, funcs ...FlagFunc) Parsed[C] {
|
func Parse[C any](name string, source []byte, base *template.Template, funcs ...FlagFunc) Parsed[C] {
|
||||||
tp := reflectx.TypeOf[C]()
|
tp := reflectx.MakeType[C]()
|
||||||
|
|
||||||
// determine if we have an embedded field in the struct
|
// determine if we have an embedded field in the struct
|
||||||
var hasEmbed bool
|
var hasEmbed bool
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,6 @@
|
||||||
{{ .Footer }}
|
{{ .Footer }}
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
{{ .AfterBody }}
|
|
||||||
{{ .Runtime.Flags.Assets.Scripts }}
|
{{ .Runtime.Flags.Assets.Scripts }}
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue