Put new invoice and edit invoice forms into a dialog
In this case i have to use the same id for the dialog content in all pages because, for now, there are a couple of forms that need to replace it on submit—the new/edit form and the product selection form. Unfortunately, HTMx does not have support for `formaction` attribute at this point, so i had to use the workaround described in [0]. [0] https://github.com/bigskysoftware/htmx/issues/623
This commit is contained in:
parent
d1852a9703
commit
5717a5b9ed
|
@ -393,7 +393,7 @@ func mustRenderNewInvoiceForm(w http.ResponseWriter, r *http.Request, form *invo
|
||||||
locale := getLocale(r)
|
locale := getLocale(r)
|
||||||
form.Customer.EmptyLabel = gettext("Select a customer to bill.", locale)
|
form.Customer.EmptyLabel = gettext("Select a customer to bill.", locale)
|
||||||
page := newNewInvoicePage(form, r)
|
page := newNewInvoicePage(form, r)
|
||||||
mustRenderAppTemplate(w, r, "invoices/new.gohtml", page)
|
mustRenderModalTemplate(w, r, "invoices/new.gohtml", page)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustRenderNewInvoiceProductsForm(w http.ResponseWriter, r *http.Request, action string, form *invoiceForm) {
|
func mustRenderNewInvoiceProductsForm(w http.ResponseWriter, r *http.Request, action string, form *invoiceForm) {
|
||||||
|
@ -404,7 +404,7 @@ func mustRenderNewInvoiceProductsForm(w http.ResponseWriter, r *http.Request, ac
|
||||||
Form: form,
|
Form: form,
|
||||||
Products: mustGetProductChoices(r.Context(), conn, company),
|
Products: mustGetProductChoices(r.Context(), conn, company),
|
||||||
}
|
}
|
||||||
mustRenderAppTemplate(w, r, "invoices/products.gohtml", page)
|
mustRenderModalTemplate(w, r, "invoices/products.gohtml", page)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustGetProductChoices(ctx context.Context, conn *Conn, company *Company) []*productChoice {
|
func mustGetProductChoices(ctx context.Context, conn *Conn, company *Company) []*productChoice {
|
||||||
|
@ -457,7 +457,13 @@ func HandleAddInvoice(w http.ResponseWriter, r *http.Request, _ httprouter.Param
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
slug := conn.MustGetText(r.Context(), "", "select add_invoice($1, $2, $3, $4, $5, $6, $7, $8)", company.Id, form.Number, form.Date, form.Customer, form.Notes, form.PaymentMethod, form.Tags, NewInvoiceProductArray(form.Products))
|
slug := conn.MustGetText(r.Context(), "", "select add_invoice($1, $2, $3, $4, $5, $6, $7, $8)", company.Id, form.Number, form.Date, form.Customer, form.Notes, form.PaymentMethod, form.Tags, NewInvoiceProductArray(form.Products))
|
||||||
http.Redirect(w, r, companyURI(company, "/invoices/"+slug), http.StatusSeeOther)
|
if IsHTMxRequest(r) {
|
||||||
|
w.Header().Set("HX-Trigger", "closeModal")
|
||||||
|
w.Header().Set("HX-Refresh", "true")
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
} else {
|
||||||
|
http.Redirect(w, r, companyURI(company, "/invoices/"+slug), http.StatusSeeOther)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleNewInvoiceAction(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
func HandleNewInvoiceAction(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
||||||
|
@ -832,7 +838,12 @@ func HandleUpdateInvoice(w http.ResponseWriter, r *http.Request, params httprout
|
||||||
if slug == "" {
|
if slug == "" {
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
}
|
}
|
||||||
http.Redirect(w, r, companyURI(mustGetCompany(r), "/invoices"), http.StatusSeeOther)
|
if IsHTMxRequest(r) {
|
||||||
|
w.Header().Set("HX-Refresh", "true")
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
} else {
|
||||||
|
http.Redirect(w, r, companyURI(mustGetCompany(r), "/invoices"), http.StatusSeeOther)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
slug := params[0].Value
|
slug := params[0].Value
|
||||||
if !form.Validate() {
|
if !form.Validate() {
|
||||||
|
@ -845,7 +856,13 @@ func HandleUpdateInvoice(w http.ResponseWriter, r *http.Request, params httprout
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
http.Redirect(w, r, companyURI(company, "/invoices/"+slug), http.StatusSeeOther)
|
if IsHTMxRequest(r) {
|
||||||
|
w.Header().Set("HX-Trigger", "closeModal")
|
||||||
|
w.Header().Set("HX-Refresh", "true")
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
} else {
|
||||||
|
http.Redirect(w, r, companyURI(company, "/invoices/"+slug), http.StatusSeeOther)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -879,7 +896,7 @@ func newEditInvoicePage(slug string, form *invoiceForm, r *http.Request) *editIn
|
||||||
|
|
||||||
func mustRenderEditInvoiceForm(w http.ResponseWriter, r *http.Request, slug string, form *invoiceForm) {
|
func mustRenderEditInvoiceForm(w http.ResponseWriter, r *http.Request, slug string, form *invoiceForm) {
|
||||||
page := newEditInvoicePage(slug, form, r)
|
page := newEditInvoicePage(slug, form, r)
|
||||||
mustRenderAppTemplate(w, r, "invoices/edit.gohtml", page)
|
mustRenderModalTemplate(w, r, "invoices/edit.gohtml", page)
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleEditInvoiceAction(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
func HandleEditInvoiceAction(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
||||||
|
|
|
@ -421,6 +421,19 @@ htmx.onLoad((target) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
htmx.on('htmx:configRequest', function(e) {
|
||||||
|
const element = e.detail.elt;
|
||||||
|
if (element && element.nodeName === 'FORM') {
|
||||||
|
let submitter = e.detail.triggeringEvent.submitter;
|
||||||
|
if (submitter) {
|
||||||
|
const action = submitter.attributes['formaction'];
|
||||||
|
if (action && action.value) {
|
||||||
|
e.detail.path = action.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
htmx.on('closeModal', () => {
|
htmx.on('closeModal', () => {
|
||||||
const openDialog = document.querySelector('dialog[open]');
|
const openDialog = document.querySelector('dialog[open]');
|
||||||
if (!openDialog) {
|
if (!openDialog) {
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
|
|
||||||
{{ define "content" }}
|
{{ define "content" }}
|
||||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.editInvoicePage*/ -}}
|
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.editInvoicePage*/ -}}
|
||||||
<section class="dialog-content">
|
<section class="dialog-content" id="invoice-dialog-content" data-hx-target="this">
|
||||||
<h2>{{ printf (pgettext "Edit Invoice “%s”" "title") .Number }}</h2>
|
<h2>{{ printf (pgettext "Edit Invoice “%s”" "title") .Number }}</h2>
|
||||||
<form method="POST" action="{{ companyURI "/invoices/" }}{{ .Slug }}">
|
<form method="POST" action="{{ companyURI "/invoices/" }}{{ .Slug }}" data-hx-boost="true" data-hx-select="#invoice-dialog-content">
|
||||||
{{ csrfToken }}
|
{{ csrfToken }}
|
||||||
|
|
||||||
{{ with .Form -}}
|
{{ with .Form -}}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
name="action" value="download"
|
name="action" value="download"
|
||||||
>{{( pgettext "Download invoices" "action" )}}</button>
|
>{{( pgettext "Download invoices" "action" )}}</button>
|
||||||
<a class="primary button"
|
<a class="primary button"
|
||||||
|
data-hx-push-url="false" data-hx-swap="beforeend" data-hx-boost="true"
|
||||||
href="{{ companyURI "/invoices/new" }}">{{( pgettext "New invoice" "action" )}}</a>
|
href="{{ companyURI "/invoices/new" }}">{{( pgettext "New invoice" "action" )}}</a>
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
|
@ -68,7 +69,7 @@
|
||||||
<td>
|
<td>
|
||||||
<details class="invoice-status menu">
|
<details class="invoice-status menu">
|
||||||
<summary class="invoice-status-{{ .Status }}">{{ .StatusLabel }}</summary>
|
<summary class="invoice-status-{{ .Status }}">{{ .StatusLabel }}</summary>
|
||||||
<form action="{{companyURI "/invoices/"}}{{ .Slug }}" method="POST">
|
<form action="{{companyURI "/invoices/"}}{{ .Slug }}" method="POST" data-hx-boost="true">
|
||||||
{{ csrfToken }}
|
{{ csrfToken }}
|
||||||
{{ putMethod }}
|
{{ putMethod }}
|
||||||
<input type="hidden" name="quick" value="status">
|
<input type="hidden" name="quick" value="status">
|
||||||
|
@ -104,7 +105,9 @@
|
||||||
<summary><i class="ri-more-line"></i></summary>
|
<summary><i class="ri-more-line"></i></summary>
|
||||||
<ul role="menu" class="action-menu">
|
<ul role="menu" class="action-menu">
|
||||||
<li role="presentation">
|
<li role="presentation">
|
||||||
<a role="menuitem" href="{{ companyURI "/invoices"}}/{{ .Slug }}/edit">
|
<a role="menuitem" href="{{ companyURI "/invoices"}}/{{ .Slug }}/edit"
|
||||||
|
data-hx-push-url="false" data-hx-swap="beforeend" data-hx-boost="true"
|
||||||
|
>
|
||||||
<i class="ri-edit-line"></i>
|
<i class="ri-edit-line"></i>
|
||||||
{{( pgettext "Edit" "action" )}}
|
{{( pgettext "Edit" "action" )}}
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
|
|
||||||
{{ define "content" }}
|
{{ define "content" }}
|
||||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.newInvoicePage*/ -}}
|
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.newInvoicePage*/ -}}
|
||||||
<section class="dialog-content">
|
<section class="dialog-content" id="invoice-dialog-content" data-hx-target="this">
|
||||||
<h2>{{(pgettext "New Invoice" "title")}}</h2>
|
<h2>{{(pgettext "New Invoice" "title")}}</h2>
|
||||||
<form method="POST" action="{{ companyURI "/invoices" }}">
|
<form method="POST" action="{{ companyURI "/invoices" }}" data-hx-boost="true" data-hx-select="#invoice-dialog-content">
|
||||||
{{ csrfToken }}
|
{{ csrfToken }}
|
||||||
|
|
||||||
{{ with .Form -}}
|
{{ with .Form -}}
|
||||||
|
|
|
@ -19,9 +19,9 @@
|
||||||
|
|
||||||
{{ define "content" }}
|
{{ define "content" }}
|
||||||
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.newInvoiceProductsPage*/ -}}
|
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.newInvoiceProductsPage*/ -}}
|
||||||
<section class="dialog-content">
|
<section class="dialog-content" id="invoice-dialog-content" data-hx-target="this">
|
||||||
<h2>{{(pgettext "Add Products to Invoice" "title")}}</h2>
|
<h2>{{(pgettext "Add Products to Invoice" "title")}}</h2>
|
||||||
<form method="POST" action="{{ .Action }}">
|
<form method="POST" action="{{ .Action }}" data-hx-boost="true" data-hx-select="#invoice-dialog-content">
|
||||||
{{ csrfToken }}
|
{{ csrfToken }}
|
||||||
|
|
||||||
{{- with .Form }}
|
{{- with .Form }}
|
||||||
|
|
Loading…
Reference in New Issue