From dbfa58699c20afada7f6caeca106384b2cec2886 Mon Sep 17 00:00:00 2001
From: jordi fita mas
Date: Tue, 4 Apr 2023 14:39:55 +0200
Subject: [PATCH] Show the duplicate invoice form in a dialog
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Had to add a new hidden field to the form to know whether, when the
request is HTMx-triggered, to refresh the page, as i do when duplicating
from the index, or redirect the client to the new invoice’s view page,
but only if i was duplicating from that same page, not the index.
Since i now have to target main when redirecting to the view page, so
i had to add a location structure with the required json fields and all
that, when “refreshing” i actually tell HTMx to open the index page
again, which seems faster, now that i am used to boosted links.
---
pkg/htmx.go | 23 +++++++++++++++++++++++
pkg/invoices.go | 20 ++++++++++++++++++--
pkg/router.go | 4 ----
web/template/invoices/edit.gohtml | 1 +
web/template/invoices/index.gohtml | 4 +++-
web/template/invoices/new.gohtml | 1 +
web/template/invoices/products.gohtml | 1 +
web/template/invoices/view.gohtml | 3 ++-
8 files changed, 49 insertions(+), 8 deletions(-)
create mode 100644 pkg/htmx.go
diff --git a/pkg/htmx.go b/pkg/htmx.go
new file mode 100644
index 0000000..52ab070
--- /dev/null
+++ b/pkg/htmx.go
@@ -0,0 +1,23 @@
+package pkg
+
+import (
+ "encoding/json"
+ "net/http"
+)
+
+type HTMxLocation struct {
+ Path string `json:"path"`
+ Target string `json:"target"`
+}
+
+func IsHTMxRequest(r *http.Request) bool {
+ return r.Header.Get("HX-Request") == "true"
+}
+
+func MustMarshalHTMxLocation(location *HTMxLocation) string {
+ data, err := json.Marshal(location)
+ if err != nil {
+ panic(err)
+ }
+ return string(data)
+}
diff --git a/pkg/invoices.go b/pkg/invoices.go
index a3a630d..7855a36 100644
--- a/pkg/invoices.go
+++ b/pkg/invoices.go
@@ -217,6 +217,7 @@ func ServeInvoice(w http.ResponseWriter, r *http.Request, params httprouter.Para
if invoiceToDuplicate := r.URL.Query().Get("duplicate"); invoiceToDuplicate != "" {
form.MustFillFromDatabase(r.Context(), conn, invoiceToDuplicate)
form.InvoiceStatus.Selected = []string{"created"}
+ form.Location.Val = r.URL.Query().Get("location")
}
form.Date.Val = time.Now().Format("2006-01-02")
w.WriteHeader(http.StatusOK)
@@ -456,12 +457,21 @@ func HandleAddInvoice(w http.ResponseWriter, r *http.Request, _ httprouter.Param
return
}
slug := conn.MustGetText(r.Context(), "", "select add_invoice($1, $2, $3, $4, $5, $6, $7)", company.Id, form.Date, form.Customer, form.Notes, form.PaymentMethod, form.Tags, NewInvoiceProductArray(form.Products))
+ viewUrl := companyURI(company, "/invoices/"+slug)
if IsHTMxRequest(r) {
w.Header().Set("HX-Trigger", "closeModal")
- w.Header().Set("HX-Refresh", "true")
+ location := &HTMxLocation{
+ Target: "main",
+ }
+ if form.Location.Val == "view" {
+ location.Path = viewUrl
+ } else {
+ location.Path = companyURI(company, "/invoices")
+ }
+ w.Header().Set("HX-Location", MustMarshalHTMxLocation(location))
w.WriteHeader(http.StatusNoContent)
} else {
- http.Redirect(w, r, companyURI(company, "/invoices/"+slug), http.StatusSeeOther)
+ http.Redirect(w, r, viewUrl, http.StatusSeeOther)
}
}
@@ -529,6 +539,7 @@ type invoiceForm struct {
locale *Locale
company *Company
Number string
+ Location *InputField
InvoiceStatus *SelectField
Customer *SelectField
Date *InputField
@@ -542,6 +553,10 @@ func newInvoiceForm(ctx context.Context, conn *Conn, locale *Locale, company *Co
return &invoiceForm{
locale: locale,
company: company,
+ Location: &InputField{
+ Name: "redirect",
+ Type: "hidden",
+ },
InvoiceStatus: &SelectField{
Name: "invoice_status",
Required: true,
@@ -584,6 +599,7 @@ func (form *invoiceForm) Parse(r *http.Request) error {
if err := r.ParseForm(); err != nil {
return err
}
+ form.Location.FillValue(r)
form.InvoiceStatus.FillValue(r)
form.Customer.FillValue(r)
form.Date.FillValue(r)
diff --git a/pkg/router.go b/pkg/router.go
index d82bd56..39c28ff 100644
--- a/pkg/router.go
+++ b/pkg/router.go
@@ -87,7 +87,3 @@ func MethodOverrider(next http.Handler) http.Handler {
next.ServeHTTP(w, r)
})
}
-
-func IsHTMxRequest(r *http.Request) bool {
- return r.Header.Get("HX-Request") == "true"
-}
diff --git a/web/template/invoices/edit.gohtml b/web/template/invoices/edit.gohtml
index 0789e3f..bcab216 100644
--- a/web/template/invoices/edit.gohtml
+++ b/web/template/invoices/edit.gohtml
@@ -21,6 +21,7 @@
{{ csrfToken }}
{{ with .Form -}}
+ {{ template "hidden-field" .Location }}
{{ template "select-field" .Customer }}
{{ template "hidden-field" .Date }}
{{ template "tags-field" .Tags }}
diff --git a/web/template/invoices/index.gohtml b/web/template/invoices/index.gohtml
index 001c85a..0033f6d 100644
--- a/web/template/invoices/index.gohtml
+++ b/web/template/invoices/index.gohtml
@@ -113,7 +113,9 @@
-
+
{{( pgettext "Duplicate" "action" )}}
diff --git a/web/template/invoices/new.gohtml b/web/template/invoices/new.gohtml
index 2aec35e..118cdb2 100644
--- a/web/template/invoices/new.gohtml
+++ b/web/template/invoices/new.gohtml
@@ -21,6 +21,7 @@
{{ csrfToken }}
{{ with .Form -}}
+ {{ template "hidden-field" .Location }}
{{ template "hidden-select-field" .InvoiceStatus }}
{{ template "select-field" .Customer }}
{{ template "input-field" .Date }}
diff --git a/web/template/invoices/products.gohtml b/web/template/invoices/products.gohtml
index 66a799c..a560767 100644
--- a/web/template/invoices/products.gohtml
+++ b/web/template/invoices/products.gohtml
@@ -25,6 +25,7 @@
{{ csrfToken }}
{{- with .Form }}
+ {{ template "hidden-field" .Location }}
{{ template "hidden-select-field" .Customer }}
{{ template "hidden-field" .Date }}
{{ template "hidden-field" .Notes }}
diff --git a/web/template/invoices/view.gohtml b/web/template/invoices/view.gohtml
index 4b21247..3ce8bad 100644
--- a/web/template/invoices/view.gohtml
+++ b/web/template/invoices/view.gohtml
@@ -12,7 +12,8 @@
{{( pgettext "Duplicate" "action" )}}
+ data-hx-push-url="false" data-hx-swap="beforeend" data-hx-boost="true"
+ href="{{ companyURI "/invoices/new"}}?duplicate={{ .Slug }}&location=view">{{( pgettext "Duplicate" "action" )}}
{{( pgettext "Edit" "action" )}}