some cleanup, alias funcs in js package to know which commands can be used with lifecycle
This commit is contained in:
parent
94f7d53a0d
commit
a58cb051e8
16 changed files with 74 additions and 97 deletions
|
|
@ -28,17 +28,17 @@ func Button(props ButtonProps) h.Ren {
|
||||||
text := h.Text(props.Text)
|
text := h.Text(props.Text)
|
||||||
|
|
||||||
lifecycle := h.NewLifeCycle().
|
lifecycle := h.NewLifeCycle().
|
||||||
BeforeRequest(
|
HxBeforeRequest(
|
||||||
h.AddAttribute("disabled", "true"),
|
h.AddAttribute("disabled", "true"),
|
||||||
h.SetText("Loading..."),
|
h.SetText("Loading..."),
|
||||||
h.AddClass("bg-gray-400"),
|
h.AddClass("bg-gray-400"),
|
||||||
).
|
).
|
||||||
AfterRequest(
|
HxAfterRequest(
|
||||||
h.RemoveAttribute("disabled"),
|
h.RemoveAttribute("disabled"),
|
||||||
h.RemoveClass("bg-gray-400"),
|
h.RemoveClass("bg-gray-400"),
|
||||||
h.SetText(props.Text),
|
h.SetText(props.Text),
|
||||||
).
|
).
|
||||||
OnMutationError(
|
HxOnMutationError(
|
||||||
h.SetText("failed"),
|
h.SetText("failed"),
|
||||||
h.AddClass("bg-red-400"),
|
h.AddClass("bg-red-400"),
|
||||||
h.RemoveAttribute("disabled"),
|
h.RemoveAttribute("disabled"),
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@ package h
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/maddalax/htmgo/framework/htmgo/service"
|
|
||||||
"github.com/maddalax/htmgo/framework/hx"
|
"github.com/maddalax/htmgo/framework/hx"
|
||||||
"github.com/maddalax/htmgo/framework/util/process"
|
"github.com/maddalax/htmgo/framework/internal/process"
|
||||||
|
"github.com/maddalax/htmgo/framework/service"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
@ -82,7 +82,7 @@ func (a App) start() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if a.Opts.LiveReload {
|
if a.Opts.LiveReload && IsDevelopment() {
|
||||||
AddLiveReloadHandler("/dev/livereload", a.Echo)
|
AddLiveReloadHandler("/dev/livereload", a.Echo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,23 +51,23 @@ func (l *LifeCycle) OnEvent(event hx.Event, cmd ...Command) *LifeCycle {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LifeCycle) BeforeRequest(cmd ...Command) *LifeCycle {
|
func OnLoad(cmd ...Command) *LifeCycle {
|
||||||
|
return NewLifeCycle().OnEvent(hx.LoadDomEvent, cmd...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LifeCycle) HxBeforeRequest(cmd ...Command) *LifeCycle {
|
||||||
l.OnEvent(hx.BeforeRequestEvent, cmd...)
|
l.OnEvent(hx.BeforeRequestEvent, cmd...)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func OnLoad(cmd ...Command) *LifeCycle {
|
func HxOnLoad(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().OnEvent(hx.LoadEvent, cmd...)
|
return NewLifeCycle().OnEvent(hx.LoadEvent, cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func OnAfterSwap(cmd ...Command) *LifeCycle {
|
func HxOnAfterSwap(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().OnEvent(hx.AfterSwapEvent, cmd...)
|
return NewLifeCycle().OnEvent(hx.AfterSwapEvent, cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func OnTrigger(trigger string, cmd ...Command) *LifeCycle {
|
|
||||||
return NewLifeCycle().OnEvent(hx.NewStringTrigger(trigger).ToString(), cmd...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func OnClick(cmd ...Command) *LifeCycle {
|
func OnClick(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().OnEvent(hx.ClickEvent, cmd...)
|
return NewLifeCycle().OnEvent(hx.ClickEvent, cmd...)
|
||||||
}
|
}
|
||||||
|
|
@ -76,24 +76,24 @@ func OnEvent(event hx.Event, cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().OnEvent(event, cmd...)
|
return NewLifeCycle().OnEvent(event, cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BeforeRequest(cmd ...Command) *LifeCycle {
|
func HxBeforeRequest(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().BeforeRequest(cmd...)
|
return NewLifeCycle().HxBeforeRequest(cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func AfterRequest(cmd ...Command) *LifeCycle {
|
func HxAfterRequest(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().AfterRequest(cmd...)
|
return NewLifeCycle().HxAfterRequest(cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func OnMutationError(cmd ...Command) *LifeCycle {
|
func HxOnMutationError(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().OnMutationError(cmd...)
|
return NewLifeCycle().HxOnMutationError(cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LifeCycle) AfterRequest(cmd ...Command) *LifeCycle {
|
func (l *LifeCycle) HxAfterRequest(cmd ...Command) *LifeCycle {
|
||||||
l.OnEvent(hx.AfterRequestEvent, cmd...)
|
l.OnEvent(hx.AfterRequestEvent, cmd...)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LifeCycle) OnMutationError(cmd ...Command) *LifeCycle {
|
func (l *LifeCycle) HxOnMutationError(cmd ...Command) *LifeCycle {
|
||||||
l.OnEvent(hx.OnMutationErrorEvent, cmd...)
|
l.OnEvent(hx.OnMutationErrorEvent, cmd...)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
@ -109,6 +109,11 @@ type ComplexJsCommand struct {
|
||||||
TempFuncName string
|
TempFuncName string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewComplexJsCommand(command string) ComplexJsCommand {
|
||||||
|
name := fmt.Sprintf("__eval_%s", util.RandSeq(6))
|
||||||
|
return ComplexJsCommand{Command: command, TempFuncName: name}
|
||||||
|
}
|
||||||
|
|
||||||
func SetText(text string) SimpleJsCommand {
|
func SetText(text string) SimpleJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return SimpleJsCommand{Command: fmt.Sprintf("this.innerText = '%s'", text)}
|
return SimpleJsCommand{Command: fmt.Sprintf("this.innerText = '%s'", text)}
|
||||||
|
|
@ -177,18 +182,17 @@ func Alert(text string) SimpleJsCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
func EvalJs(js string) ComplexJsCommand {
|
func EvalJs(js string) ComplexJsCommand {
|
||||||
name := fmt.Sprintf("__eval_%s", util.RandSeq(6))
|
return NewComplexJsCommand(js)
|
||||||
return ComplexJsCommand{Command: js, TempFuncName: name}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func InjectScript(src string) ComplexJsCommand {
|
func InjectScript(src string) ComplexJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return ComplexJsCommand{Command: fmt.Sprintf(`
|
return NewComplexJsCommand(fmt.Sprintf(`
|
||||||
var script = document.createElement('script');
|
var script = document.createElement('script');
|
||||||
script.src = '%s';
|
script.src = '%s';
|
||||||
src.async = true;
|
script.async = true;
|
||||||
document.head.appendChild(script);
|
document.head.appendChild(script);
|
||||||
`, src)}
|
`, src))
|
||||||
}
|
}
|
||||||
|
|
||||||
func InjectScriptIfNotExist(src string) ComplexJsCommand {
|
func InjectScriptIfNotExist(src string) ComplexJsCommand {
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,10 @@ func TestRender(t *testing.T) {
|
||||||
"data-attr-3": "value",
|
"data-attr-3": "value",
|
||||||
"data-attr-4": "value",
|
"data-attr-4": "value",
|
||||||
}),
|
}),
|
||||||
BeforeRequest(
|
HxBeforeRequest(
|
||||||
SetText("before request"),
|
SetText("before request"),
|
||||||
),
|
),
|
||||||
AfterRequest(
|
HxAfterRequest(
|
||||||
SetText("after request"),
|
SetText("after request"),
|
||||||
),
|
),
|
||||||
Children(
|
Children(
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
func JsonSerialize(data any) string {
|
func JsonSerializeOrEmpty(data any) string {
|
||||||
serialized, err := json.Marshal(data)
|
serialized, err := json.Marshal(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
|
|
@ -30,6 +30,10 @@ func Post(url string, trigger ...string) *AttributeMap {
|
||||||
return AttributeList(Attribute(hx.PostAttr, url), TriggerString(trigger...))
|
return AttributeList(Attribute(hx.PostAttr, url), TriggerString(trigger...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PostWithQs(url string, qs *Qs, trigger string) *AttributeMap {
|
||||||
|
return Post(SetQueryParams(url, qs), trigger)
|
||||||
|
}
|
||||||
|
|
||||||
func PostOnClick(url string) *AttributeMap {
|
func PostOnClick(url string) *AttributeMap {
|
||||||
return Post(url, hx.ClickEvent)
|
return Post(url, hx.ClickEvent)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
25
framework/js/commands.go
Normal file
25
framework/js/commands.go
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
package js
|
||||||
|
|
||||||
|
import "github.com/maddalax/htmgo/framework/h"
|
||||||
|
|
||||||
|
var AddAttribute = h.AddAttribute
|
||||||
|
var RemoveAttribute = h.RemoveAttribute
|
||||||
|
var AddClass = h.AddClass
|
||||||
|
var SetText = h.SetText
|
||||||
|
var Increment = h.Increment
|
||||||
|
var SetInnerHtml = h.SetInnerHtml
|
||||||
|
var SetOuterHtml = h.SetOuterHtml
|
||||||
|
var SetDisabled = h.SetDisabled
|
||||||
|
var RemoveClass = h.RemoveClass
|
||||||
|
var Alert = h.Alert
|
||||||
|
var EvalJs = h.EvalJs
|
||||||
|
var InjectScript = h.InjectScript
|
||||||
|
var InjectScriptIfNotExist = h.InjectScriptIfNotExist
|
||||||
|
var GetPartial = h.GetPartial
|
||||||
|
var GetPartialWithQs = h.GetPartialWithQs
|
||||||
|
var PostPartial = h.PostPartial
|
||||||
|
var PostPartialWithQs = h.PostPartialWithQs
|
||||||
|
var GetWithQs = h.GetWithQs
|
||||||
|
var PostWithQs = h.PostWithQs
|
||||||
|
var ToggleClass = h.ToggleClass
|
||||||
|
var ToggleClassOnElement = h.ToggleClassOnElement
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
package httpjson
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var client *http.Client
|
|
||||||
var once sync.Once
|
|
||||||
|
|
||||||
func getClient() *http.Client {
|
|
||||||
once.Do(func() {
|
|
||||||
tr := &http.Transport{
|
|
||||||
MaxIdleConns: 10,
|
|
||||||
IdleConnTimeout: 15 * time.Second,
|
|
||||||
ResponseHeaderTimeout: 15 * time.Second,
|
|
||||||
DisableKeepAlives: false,
|
|
||||||
}
|
|
||||||
httpClient := &http.Client{
|
|
||||||
Transport: tr,
|
|
||||||
}
|
|
||||||
client = httpClient
|
|
||||||
})
|
|
||||||
|
|
||||||
return client
|
|
||||||
}
|
|
||||||
|
|
||||||
func Get[T any](url string) (T, error) {
|
|
||||||
resp, err := getClient().Get(url)
|
|
||||||
if err != nil {
|
|
||||||
return *new(T), err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
io.Copy(io.Discard, resp.Body)
|
|
||||||
resp.Body.Close()
|
|
||||||
}()
|
|
||||||
|
|
||||||
if resp.StatusCode > 299 {
|
|
||||||
return *new(T), errors.New(fmt.Sprintf("get to %s failed with %d code", url, resp.StatusCode))
|
|
||||||
}
|
|
||||||
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return *new(T), err
|
|
||||||
}
|
|
||||||
d := new(T)
|
|
||||||
err = json.Unmarshal(body, &d)
|
|
||||||
if err != nil {
|
|
||||||
return *new(T), err
|
|
||||||
}
|
|
||||||
|
|
||||||
if d == nil {
|
|
||||||
return *new(T), errors.New("failed to create T")
|
|
||||||
}
|
|
||||||
|
|
||||||
return *d, nil
|
|
||||||
}
|
|
||||||
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"embed"
|
"embed"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/maddalax/htmgo/framework/h"
|
"github.com/maddalax/htmgo/framework/h"
|
||||||
"github.com/maddalax/htmgo/framework/htmgo/service"
|
"github.com/maddalax/htmgo/framework/service"
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
"htmgo-site/internal/markdown"
|
"htmgo-site/internal/markdown"
|
||||||
"htmgo-site/pages"
|
"htmgo-site/pages"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package pages
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
"github.com/maddalax/htmgo/framework/h"
|
"github.com/maddalax/htmgo/framework/h"
|
||||||
"github.com/maddalax/htmgo/framework/htmgo/service"
|
"github.com/maddalax/htmgo/framework/service"
|
||||||
"htmgo-site/internal/markdown"
|
"htmgo-site/internal/markdown"
|
||||||
"htmgo-site/pages/base"
|
"htmgo-site/pages/base"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ func IndexPage(c echo.Context) *h.Page {
|
||||||
func Button() h.Ren {
|
func Button() h.Ren {
|
||||||
return h.Button(h.Class("btn bg-green-500 p-4 rounded text-white"),
|
return h.Button(h.Class("btn bg-green-500 p-4 rounded text-white"),
|
||||||
h.Text("my button"),
|
h.Text("my button"),
|
||||||
h.AfterRequest(
|
h.HxAfterRequest(
|
||||||
h.SetDisabled(true),
|
h.SetDisabled(true),
|
||||||
h.RemoveClass("bg-red-600"),
|
h.RemoveClass("bg-red-600"),
|
||||||
h.AddClass("bg-gray-500"),
|
h.AddClass("bg-gray-500"),
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package tasks
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/maddalax/htmgo/framework/htmgo/service"
|
"github.com/maddalax/htmgo/framework/service"
|
||||||
"time"
|
"time"
|
||||||
"todolist/ent"
|
"todolist/ent"
|
||||||
"todolist/ent/predicate"
|
"todolist/ent/predicate"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/maddalax/htmgo/framework/h"
|
"github.com/maddalax/htmgo/framework/h"
|
||||||
"github.com/maddalax/htmgo/framework/htmgo/service"
|
"github.com/maddalax/htmgo/framework/service"
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
"todolist/ent"
|
"todolist/ent"
|
||||||
"todolist/infrastructure/db"
|
"todolist/infrastructure/db"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package pages
|
package pages
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/maddalax/htmgo/framework/js"
|
||||||
"todolist/pages/base"
|
"todolist/pages/base"
|
||||||
"todolist/partials/task"
|
"todolist/partials/task"
|
||||||
|
|
||||||
|
|
@ -19,6 +20,12 @@ func TaskListPage(ctx *h.RequestContext) *h.Page {
|
||||||
h.Div(
|
h.Div(
|
||||||
h.Class("flex flex-col gap-6 p-4 items-center max-w-xl mx-auto pb-12"),
|
h.Class("flex flex-col gap-6 p-4 items-center max-w-xl mx-auto pb-12"),
|
||||||
title,
|
title,
|
||||||
|
h.Button(
|
||||||
|
h.Text("Add Task"),
|
||||||
|
h.OnClick(
|
||||||
|
js.InjectScript("https://htmgo.dev"),
|
||||||
|
),
|
||||||
|
),
|
||||||
task.Card(ctx),
|
task.Card(ctx),
|
||||||
h.Children(
|
h.Children(
|
||||||
h.Div(h.Text("Double-click to edit a todo")),
|
h.Div(h.Text("Double-click to edit a todo")),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue