diff --git a/framework-ui/ui/button.go b/framework-ui/ui/button.go index 1cad240..669e1f3 100644 --- a/framework-ui/ui/button.go +++ b/framework-ui/ui/button.go @@ -28,17 +28,17 @@ func Button(props ButtonProps) h.Ren { text := h.Text(props.Text) lifecycle := h.NewLifeCycle(). - BeforeRequest( + HxBeforeRequest( h.AddAttribute("disabled", "true"), h.SetText("Loading..."), h.AddClass("bg-gray-400"), ). - AfterRequest( + HxAfterRequest( h.RemoveAttribute("disabled"), h.RemoveClass("bg-gray-400"), h.SetText(props.Text), ). - OnMutationError( + HxOnMutationError( h.SetText("failed"), h.AddClass("bg-red-400"), h.RemoveAttribute("disabled"), diff --git a/framework/h/app.go b/framework/h/app.go index effd666..29f4f33 100644 --- a/framework/h/app.go +++ b/framework/h/app.go @@ -3,9 +3,9 @@ package h import ( "fmt" "github.com/labstack/echo/v4" - "github.com/maddalax/htmgo/framework/htmgo/service" "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" "time" ) @@ -82,7 +82,7 @@ func (a App) start() { } }) - if a.Opts.LiveReload { + if a.Opts.LiveReload && IsDevelopment() { AddLiveReloadHandler("/dev/livereload", a.Echo) } diff --git a/framework/h/lifecycle.go b/framework/h/lifecycle.go index dfbb086..2901885 100644 --- a/framework/h/lifecycle.go +++ b/framework/h/lifecycle.go @@ -51,23 +51,23 @@ func (l *LifeCycle) OnEvent(event hx.Event, cmd ...Command) *LifeCycle { 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...) return l } -func OnLoad(cmd ...Command) *LifeCycle { +func HxOnLoad(cmd ...Command) *LifeCycle { return NewLifeCycle().OnEvent(hx.LoadEvent, cmd...) } -func OnAfterSwap(cmd ...Command) *LifeCycle { +func HxOnAfterSwap(cmd ...Command) *LifeCycle { 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 { return NewLifeCycle().OnEvent(hx.ClickEvent, cmd...) } @@ -76,24 +76,24 @@ func OnEvent(event hx.Event, cmd ...Command) *LifeCycle { return NewLifeCycle().OnEvent(event, cmd...) } -func BeforeRequest(cmd ...Command) *LifeCycle { - return NewLifeCycle().BeforeRequest(cmd...) +func HxBeforeRequest(cmd ...Command) *LifeCycle { + return NewLifeCycle().HxBeforeRequest(cmd...) } -func AfterRequest(cmd ...Command) *LifeCycle { - return NewLifeCycle().AfterRequest(cmd...) +func HxAfterRequest(cmd ...Command) *LifeCycle { + return NewLifeCycle().HxAfterRequest(cmd...) } -func OnMutationError(cmd ...Command) *LifeCycle { - return NewLifeCycle().OnMutationError(cmd...) +func HxOnMutationError(cmd ...Command) *LifeCycle { + return NewLifeCycle().HxOnMutationError(cmd...) } -func (l *LifeCycle) AfterRequest(cmd ...Command) *LifeCycle { +func (l *LifeCycle) HxAfterRequest(cmd ...Command) *LifeCycle { l.OnEvent(hx.AfterRequestEvent, cmd...) return l } -func (l *LifeCycle) OnMutationError(cmd ...Command) *LifeCycle { +func (l *LifeCycle) HxOnMutationError(cmd ...Command) *LifeCycle { l.OnEvent(hx.OnMutationErrorEvent, cmd...) return l } @@ -109,6 +109,11 @@ type ComplexJsCommand struct { 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 { // language=JavaScript return SimpleJsCommand{Command: fmt.Sprintf("this.innerText = '%s'", text)} @@ -177,18 +182,17 @@ func Alert(text string) SimpleJsCommand { } func EvalJs(js string) ComplexJsCommand { - name := fmt.Sprintf("__eval_%s", util.RandSeq(6)) - return ComplexJsCommand{Command: js, TempFuncName: name} + return NewComplexJsCommand(js) } func InjectScript(src string) ComplexJsCommand { // language=JavaScript - return ComplexJsCommand{Command: fmt.Sprintf(` + return NewComplexJsCommand(fmt.Sprintf(` var script = document.createElement('script'); script.src = '%s'; - src.async = true; + script.async = true; document.head.appendChild(script); - `, src)} + `, src)) } func InjectScriptIfNotExist(src string) ComplexJsCommand { diff --git a/framework/h/render_test.go b/framework/h/render_test.go index 0e78d03..9492002 100644 --- a/framework/h/render_test.go +++ b/framework/h/render_test.go @@ -13,10 +13,10 @@ func TestRender(t *testing.T) { "data-attr-3": "value", "data-attr-4": "value", }), - BeforeRequest( + HxBeforeRequest( SetText("before request"), ), - AfterRequest( + HxAfterRequest( SetText("after request"), ), Children( diff --git a/framework/h/util.go b/framework/h/serialize.go similarity index 75% rename from framework/h/util.go rename to framework/h/serialize.go index 3533737..eb35418 100644 --- a/framework/h/util.go +++ b/framework/h/serialize.go @@ -4,7 +4,7 @@ import ( "encoding/json" ) -func JsonSerialize(data any) string { +func JsonSerializeOrEmpty(data any) string { serialized, err := json.Marshal(data) if err != nil { return "" diff --git a/framework/h/xhr.go b/framework/h/xhr.go index 1350b9f..f732d6c 100644 --- a/framework/h/xhr.go +++ b/framework/h/xhr.go @@ -30,6 +30,10 @@ func Post(url string, trigger ...string) *AttributeMap { 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 { return Post(url, hx.ClickEvent) } diff --git a/framework/util/process/process.go b/framework/internal/process/process.go similarity index 100% rename from framework/util/process/process.go rename to framework/internal/process/process.go diff --git a/framework/js/commands.go b/framework/js/commands.go new file mode 100644 index 0000000..2722014 --- /dev/null +++ b/framework/js/commands.go @@ -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 diff --git a/framework/htmgo/service/locator.go b/framework/service/locator.go similarity index 100% rename from framework/htmgo/service/locator.go rename to framework/service/locator.go diff --git a/framework/util/httpjson/http.go b/framework/util/httpjson/http.go deleted file mode 100644 index c86cff9..0000000 --- a/framework/util/httpjson/http.go +++ /dev/null @@ -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 -} diff --git a/htmgo-site/main.go b/htmgo-site/main.go index ba8e2fe..c9d3a6c 100644 --- a/htmgo-site/main.go +++ b/htmgo-site/main.go @@ -4,7 +4,7 @@ import ( "embed" "github.com/labstack/echo/v4" "github.com/maddalax/htmgo/framework/h" - "github.com/maddalax/htmgo/framework/htmgo/service" + "github.com/maddalax/htmgo/framework/service" _ "github.com/mattn/go-sqlite3" "htmgo-site/internal/markdown" "htmgo-site/pages" diff --git a/htmgo-site/pages/markdown.go b/htmgo-site/pages/markdown.go index bc1dfd1..79a5b6c 100644 --- a/htmgo-site/pages/markdown.go +++ b/htmgo-site/pages/markdown.go @@ -3,7 +3,7 @@ package pages import ( "embed" "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/pages/base" ) diff --git a/starter-template/pages/index.go b/starter-template/pages/index.go index 7f75508..dd818bf 100644 --- a/starter-template/pages/index.go +++ b/starter-template/pages/index.go @@ -30,7 +30,7 @@ func IndexPage(c echo.Context) *h.Page { func Button() h.Ren { return h.Button(h.Class("btn bg-green-500 p-4 rounded text-white"), h.Text("my button"), - h.AfterRequest( + h.HxAfterRequest( h.SetDisabled(true), h.RemoveClass("bg-red-600"), h.AddClass("bg-gray-500"), diff --git a/todo-list/internal/tasks/service.go b/todo-list/internal/tasks/service.go index f560c97..5b47d8c 100644 --- a/todo-list/internal/tasks/service.go +++ b/todo-list/internal/tasks/service.go @@ -3,7 +3,7 @@ package tasks import ( "context" "github.com/google/uuid" - "github.com/maddalax/htmgo/framework/htmgo/service" + "github.com/maddalax/htmgo/framework/service" "time" "todolist/ent" "todolist/ent/predicate" diff --git a/todo-list/main.go b/todo-list/main.go index 8e40b4a..0188341 100644 --- a/todo-list/main.go +++ b/todo-list/main.go @@ -3,7 +3,7 @@ package main import ( "github.com/labstack/echo/v4" "github.com/maddalax/htmgo/framework/h" - "github.com/maddalax/htmgo/framework/htmgo/service" + "github.com/maddalax/htmgo/framework/service" _ "github.com/mattn/go-sqlite3" "todolist/ent" "todolist/infrastructure/db" diff --git a/todo-list/pages/index.go b/todo-list/pages/index.go index 65b5cac..81d3622 100644 --- a/todo-list/pages/index.go +++ b/todo-list/pages/index.go @@ -1,6 +1,7 @@ package pages import ( + "github.com/maddalax/htmgo/framework/js" "todolist/pages/base" "todolist/partials/task" @@ -19,6 +20,12 @@ func TaskListPage(ctx *h.RequestContext) *h.Page { h.Div( h.Class("flex flex-col gap-6 p-4 items-center max-w-xl mx-auto pb-12"), title, + h.Button( + h.Text("Add Task"), + h.OnClick( + js.InjectScript("https://htmgo.dev"), + ), + ), task.Card(ctx), h.Children( h.Div(h.Text("Double-click to edit a todo")),