Show the duplicate invoice form in a dialog
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.
This commit is contained in:
parent
b6668e72ef
commit
dbfa58699c
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
{{ csrfToken }}
|
||||
|
||||
{{ with .Form -}}
|
||||
{{ template "hidden-field" .Location }}
|
||||
{{ template "select-field" .Customer }}
|
||||
{{ template "hidden-field" .Date }}
|
||||
{{ template "tags-field" .Tags }}
|
||||
|
|
|
@ -113,7 +113,9 @@
|
|||
</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a role="menuitem" href="{{ companyURI "/invoices/new"}}?duplicate={{ .Slug }}">
|
||||
<a role="menuitem" href="{{ companyURI "/invoices/new"}}?duplicate={{ .Slug }}"
|
||||
data-hx-push-url="false" data-hx-swap="beforeend" data-hx-boost="true"
|
||||
>
|
||||
<i class="ri-file-copy-line"></i>
|
||||
{{( pgettext "Duplicate" "action" )}}
|
||||
</a>
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
{{ csrfToken }}
|
||||
|
||||
{{ with .Form -}}
|
||||
{{ template "hidden-field" .Location }}
|
||||
{{ template "hidden-select-field" .InvoiceStatus }}
|
||||
{{ template "select-field" .Customer }}
|
||||
{{ template "input-field" .Date }}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
{{ csrfToken }}
|
||||
|
||||
{{- with .Form }}
|
||||
{{ template "hidden-field" .Location }}
|
||||
{{ template "hidden-select-field" .Customer }}
|
||||
{{ template "hidden-field" .Date }}
|
||||
{{ template "hidden-field" .Notes }}
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
</p>
|
||||
<p>
|
||||
<a class="button primary"
|
||||
href="{{ companyURI "/invoices/new"}}?duplicate={{ .Slug }}">{{( pgettext "Duplicate" "action" )}}</a>
|
||||
data-hx-push-url="false" data-hx-swap="beforeend" data-hx-boost="true"
|
||||
href="{{ companyURI "/invoices/new"}}?duplicate={{ .Slug }}&location=view">{{( pgettext "Duplicate" "action" )}}</a>
|
||||
<a class="button primary"
|
||||
data-hx-push-url="false" data-hx-swap="beforeend" data-hx-boost="true"
|
||||
href="{{ companyURI "/invoices/"}}{{ .Slug }}/edit">{{( pgettext "Edit" "action" )}}</a>
|
||||
|
|
Loading…
Reference in New Issue