Move back most dialogs to regular (but still boosted) pages

With Oriol agreed that adding or editing invoices, products, and
contacts is not just a “user interruption” but the main flow of the
program, and, as such, it is not correct to use dialogs for these.

More importantly, it was harder to concentrate, specially with the more
involved form of invoices, because of all the “noise” behind the dialog.
This commit is contained in:
jordi fita mas 2023-04-25 15:28:55 +02:00
parent c5fba3246e
commit f2a0cd7d94
14 changed files with 39 additions and 93 deletions

View File

@ -48,7 +48,7 @@ func GetContactForm(w http.ResponseWriter, r *http.Request, params httprouter.Pa
}
func mustRenderNewContactForm(w http.ResponseWriter, r *http.Request, form *contactForm) {
mustRenderModalTemplate(w, r, "contacts/new.gohtml", form)
mustRenderMainTemplate(w, r, "contacts/new.gohtml", form)
}
type editContactPage struct {
@ -63,7 +63,7 @@ func mustRenderEditContactForm(w http.ResponseWriter, r *http.Request, slug stri
ContactName: form.BusinessName.Val,
Form: form,
}
mustRenderModalTemplate(w, r, "contacts/edit.gohtml", page)
mustRenderMainTemplate(w, r, "contacts/edit.gohtml", page)
}
func HandleAddContact(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
@ -87,13 +87,7 @@ func HandleAddContact(w http.ResponseWriter, r *http.Request, _ httprouter.Param
}
company := mustGetCompany(r)
conn.MustExec(r.Context(), "select add_contact($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)", company.Id, form.BusinessName, form.VATIN, form.TradeName, form.Phone, form.Email, form.Web, form.Address, form.City, form.Province, form.PostalCode, form.Country, form.Tags)
if IsHTMxRequest(r) {
w.Header().Set(HxTrigger, "closeModal")
w.Header().Set(HxRefresh, "true")
w.WriteHeader(http.StatusNoContent)
} else {
http.Redirect(w, r, companyURI(company, "/contacts"), http.StatusSeeOther)
}
htmxRedirect(w, r, companyURI(company, "/contacts"))
}
func HandleUpdateContact(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
@ -116,13 +110,7 @@ func HandleUpdateContact(w http.ResponseWriter, r *http.Request, params httprout
if slug == "" {
http.NotFound(w, r)
}
if IsHTMxRequest(r) {
w.Header().Set(HxTrigger, "closeModal")
w.Header().Set(HxRefresh, "true")
w.WriteHeader(http.StatusNoContent)
} else {
http.Redirect(w, r, companyURI(mustGetCompany(r), "/contacts/"+slug), http.StatusSeeOther)
}
htmxRedirect(w, r, companyURI(mustGetCompany(r), "/contacts"))
}
func mustCollectContactEntries(ctx context.Context, conn *Conn, company *Company, tag string) []*ContactEntry {

View File

@ -229,7 +229,6 @@ 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)
@ -423,7 +422,7 @@ func mustRenderNewInvoiceForm(w http.ResponseWriter, r *http.Request, form *invo
locale := getLocale(r)
form.Customer.EmptyLabel = gettext("Select a customer to bill.", locale)
page := newNewInvoicePage(form, r)
mustRenderModalTemplate(w, r, "invoices/new.gohtml", page)
mustRenderMainTemplate(w, r, "invoices/new.gohtml", page)
}
func mustRenderNewInvoiceProductsForm(w http.ResponseWriter, r *http.Request, action string, form *invoiceForm) {
@ -434,7 +433,7 @@ func mustRenderNewInvoiceProductsForm(w http.ResponseWriter, r *http.Request, ac
Form: form,
Products: mustGetProductChoices(r.Context(), conn, company),
}
mustRenderModalTemplate(w, r, "invoices/products.gohtml", page)
mustRenderMainTemplate(w, r, "invoices/products.gohtml", page)
}
func mustGetProductChoices(ctx context.Context, conn *Conn, company *Company) []*productChoice {
@ -489,7 +488,7 @@ 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))
closeModalAndRedirect(w, r, form.Location.Val, "/invoices/"+slug, "/invoices")
htmxRedirect(w, r, companyURI(company, "/invoices/"+slug))
}
func HandleNewInvoiceAction(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
@ -556,7 +555,6 @@ type invoiceForm struct {
locale *Locale
company *Company
Number string
Location *InputField
InvoiceStatus *SelectField
Customer *SelectField
Date *InputField
@ -570,10 +568,6 @@ 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,
@ -616,7 +610,6 @@ 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)
@ -932,22 +925,10 @@ func HandleUpdateInvoice(w http.ResponseWriter, r *http.Request, params httprout
http.NotFound(w, r)
return
}
closeModalAndRedirect(w, r, form.Location.Val, "/invoices/"+slug, "/invoices")
htmxRedirect(w, r, companyURI(company, "/invoices/"+slug))
}
}
func closeModalAndRedirect(w http.ResponseWriter, r *http.Request, selector string, viewUri string, indexUri string) {
company := mustGetCompany(r)
nextUri := companyURI(company, indexUri)
if IsHTMxRequest(r) {
w.Header().Set(HxTrigger, "closeModal")
if selector == "view" {
nextUri = companyURI(company, viewUri)
}
}
htmxRedirect(w, r, nextUri)
}
func htmxRedirect(w http.ResponseWriter, r *http.Request, uri string) {
if IsHTMxRequest(r) {
w.Header().Set(HxLocation, MustMarshalHTMxLocation(&HTMxLocation{
@ -970,7 +951,6 @@ func ServeEditInvoice(w http.ResponseWriter, r *http.Request, params httprouter.
http.NotFound(w, r)
return
}
form.Location.Val = r.URL.Query().Get("location")
w.WriteHeader(http.StatusOK)
mustRenderEditInvoiceForm(w, r, slug, form)
}
@ -991,7 +971,7 @@ func newEditInvoicePage(slug string, form *invoiceForm, r *http.Request) *editIn
func mustRenderEditInvoiceForm(w http.ResponseWriter, r *http.Request, slug string, form *invoiceForm) {
page := newEditInvoicePage(slug, form, r)
mustRenderModalTemplate(w, r, "invoices/edit.gohtml", page)
mustRenderMainTemplate(w, r, "invoices/edit.gohtml", page)
}
func HandleEditInvoiceAction(w http.ResponseWriter, r *http.Request, params httprouter.Params) {

View File

@ -59,7 +59,7 @@ func GetProductForm(w http.ResponseWriter, r *http.Request, params httprouter.Pa
}
func mustRenderNewProductForm(w http.ResponseWriter, r *http.Request, form *productForm) {
mustRenderModalTemplate(w, r, "products/new.gohtml", form)
mustRenderMainTemplate(w, r, "products/new.gohtml", form)
}
type editProductPage struct {
@ -74,7 +74,7 @@ func mustRenderEditProductForm(w http.ResponseWriter, r *http.Request, slug stri
ProductName: form.Name.Val,
Form: form,
}
mustRenderModalTemplate(w, r, "products/edit.gohtml", page)
mustRenderMainTemplate(w, r, "products/edit.gohtml", page)
}
func HandleAddProduct(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
@ -99,13 +99,7 @@ func HandleAddProduct(w http.ResponseWriter, r *http.Request, _ httprouter.Param
}
taxes := mustSliceAtoi(form.Tax.Selected)
conn.MustExec(r.Context(), "select add_product($1, $2, $3, $4, $5, $6)", company.Id, form.Name, form.Description, form.Price, taxes, form.Tags)
if IsHTMxRequest(r) {
w.Header().Set(HxTrigger, "closeModal")
w.Header().Set(HxRefresh, "true")
w.WriteHeader(http.StatusNoContent)
} else {
http.Redirect(w, r, companyURI(company, "/products"), http.StatusSeeOther)
}
htmxRedirect(w, r, companyURI(company, "/products"))
}
func sliceAtoi(s []string) ([]int, error) {
@ -151,13 +145,7 @@ func HandleUpdateProduct(w http.ResponseWriter, r *http.Request, params httprout
if ok := conn.MustGetBool(r.Context(), "select edit_product($1, $2, $3, $4, $5, $6)", slug, form.Name, form.Description, form.Price, taxes, form.Tags); !ok {
http.NotFound(w, r)
}
if IsHTMxRequest(r) {
w.Header().Set(HxTrigger, "closeModal")
w.Header().Set(HxRefresh, "true")
w.WriteHeader(http.StatusNoContent)
} else {
http.Redirect(w, r, companyURI(company, "/products/"+slug), http.StatusSeeOther)
}
htmxRedirect(w, r, companyURI(company, "/products"))
}
type productFilterForm struct {

View File

@ -16,9 +16,9 @@
{{ define "content" }}
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.editContactPage*/ -}}
<section class="dialog-content" id="edit-contact-dialog-content" data-hx-target="this">
<section class="dialog-content" id="edit-contact-dialog-content" data-hx-target="main">
<h2>{{printf (pgettext "Edit Contact “%s”" "title") .ContactName }}</h2>
<form method="POST" action="{{ companyURI "/contacts/" }}{{ .Slug }}" data-hx-boost="true" data-hx-select="#edit-contact-dialog-content">
<form method="POST" action="{{ companyURI "/contacts/" }}{{ .Slug }}" data-hx-boost="true">
{{ csrfToken }}
{{ putMethod }}

View File

@ -4,14 +4,13 @@
{{ define "breadcrumbs" -}}
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.ContactsIndexPage*/ -}}
<nav data-hx-boost="true">
<p data-hx-target="main">
<nav data-hx-boost="true" data-hx-target="main">
<p>
<a href="{{ companyURI "/" }}">{{( pgettext "Home" "title" )}}</a> /
<a>{{( pgettext "Contacts" "title" )}}</a>
</p>
<p>
<a class="primary button"
data-hx-push-url="false" data-hx-swap="beforeend"
href="{{ companyURI "/contacts/new" }}">{{( pgettext "New contact" "action" )}}</a>
</p>
</nav>
@ -34,7 +33,7 @@
{{- range $contact := . }}
<tr>
<td></td>
<td><a href="{{ companyURI "/contacts/"}}{{ .Slug }}" data-hx-push-url="false" data-hx-swap="beforeend" data-hx-boost="true">{{ .Name }}</a></td>
<td><a href="{{ companyURI "/contacts/"}}{{ .Slug }}" data-hx-target="main" data-hx-boost="true">{{ .Name }}</a></td>
<td><a href="mailto:{{ .Email }}">{{ .Email }}</a></td>
<td><a href="tel:{{ .Phone }}">{{ .Phone }}</a></td>
<td>

View File

@ -15,9 +15,9 @@
{{ define "content" }}
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.contactForm*/ -}}
<section class="dialog-content" id="new-contact-dialog-content" data-hx-target="this">
<section class="dialog-content" id="new-contact-dialog-content" data-hx-target="main">
<h2>{{(pgettext "New Contact" "title")}}</h2>
<form method="POST" action="{{ companyURI "/contacts" }}" data-hx-boost="true" data-hx-select="#new-contact-dialog-content">
<form method="POST" action="{{ companyURI "/contacts" }}" data-hx-boost="true">
{{ csrfToken }}
{{ template "input-field" .BusinessName | addInputAttr "autofocus" }}
{{ template "input-field" .VATIN }}

View File

@ -15,13 +15,12 @@
{{ define "content" }}
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.editInvoicePage*/ -}}
<section class="dialog-content" id="invoice-dialog-content" data-hx-target="this">
<section class="dialog-content" id="invoice-dialog-content" data-hx-target="main">
<h2>{{ printf (pgettext "Edit Invoice “%s”" "title") .Number }}</h2>
<form method="POST" action="{{ companyURI "/invoices/" }}{{ .Slug }}" data-hx-boost="true" data-hx-select="#invoice-dialog-content">
<form method="POST" action="{{ companyURI "/invoices/" }}{{ .Slug }}" data-hx-boost="true">
{{ csrfToken }}
{{ with .Form -}}
{{ template "hidden-field" .Location }}
{{ template "select-field" .Customer }}
{{ template "hidden-field" .Date }}
{{ template "tags-field" .Tags }}

View File

@ -4,8 +4,8 @@
{{ define "breadcrumbs" -}}
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.InvoicesIndexPage*/ -}}
<nav>
<p data-hx-target="main" data-hx-boost="true">
<nav data-hx-target="main" data-hx-boost="true">
<p>
<a href="{{ companyURI "/" }}">{{( pgettext "Home" "title" )}}</a> /
<a>{{( pgettext "Invoices" "title" )}}</a>
</p>
@ -17,7 +17,6 @@
name="action" value="download"
>{{( pgettext "Download invoices" "action" )}}</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>
</p>
</form>
@ -111,7 +110,7 @@
<ul role="menu" class="action-menu">
<li role="presentation">
<a role="menuitem" href="{{ companyURI "/invoices"}}/{{ .Slug }}/edit"
data-hx-push-url="false" data-hx-swap="beforeend" data-hx-boost="true"
data-hx-target="main" data-hx-boost="true"
>
<i class="ri-edit-line"></i>
{{( pgettext "Edit" "action" )}}
@ -119,7 +118,7 @@
</li>
<li role="presentation">
<a role="menuitem" href="{{ companyURI "/invoices/new"}}?duplicate={{ .Slug }}"
data-hx-push-url="false" data-hx-swap="beforeend" data-hx-boost="true"
data-hx-target="main" data-hx-boost="true"
>
<i class="ri-file-copy-line"></i>
{{( pgettext "Duplicate" "action" )}}

View File

@ -15,13 +15,12 @@
{{ define "content" }}
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.newInvoicePage*/ -}}
<section class="dialog-content" id="invoice-dialog-content" data-hx-target="this">
<section class="dialog-content" id="invoice-dialog-content" data-hx-target="main">
<h2>{{(pgettext "New Invoice" "title")}}</h2>
<form method="POST" action="{{ companyURI "/invoices" }}" data-hx-boost="true" data-hx-select="#invoice-dialog-content">
<form method="POST" action="{{ companyURI "/invoices" }}" data-hx-boost="true">
{{ csrfToken }}
{{ with .Form -}}
{{ template "hidden-field" .Location }}
{{ template "hidden-select-field" .InvoiceStatus }}
{{ template "select-field" .Customer }}
{{ template "input-field" .Date }}

View File

@ -25,7 +25,6 @@
{{ csrfToken }}
{{- with .Form }}
{{ template "hidden-field" .Location }}
{{ template "hidden-select-field" .Customer }}
{{ template "hidden-field" .Date }}
{{ template "hidden-field" .Notes }}

View File

@ -12,11 +12,11 @@
</p>
<p>
<a class="button primary"
data-hx-push-url="false" data-hx-swap="beforeend" data-hx-boost="true"
href="{{ companyURI "/invoices/new"}}?duplicate={{ .Slug }}&amp;location=view">{{( pgettext "Duplicate" "action" )}}</a>
data-hx-target="main" data-hx-boost="true"
href="{{ companyURI "/invoices/new"}}?duplicate={{ .Slug }}">{{( 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?location=view">{{( pgettext "Edit" "action" )}}</a>
data-hx-target="main" data-hx-boost="true"
href="{{ companyURI "/invoices/"}}{{ .Slug }}/edit">{{( pgettext "Edit" "action" )}}</a>
<a class="primary button"
href="{{ companyURI "/invoices/" }}{{ .Slug }}.pdf"
download="{{ .Number}}.pdf">{{( pgettext "Download invoice" "action" )}}</a>

View File

@ -16,11 +16,9 @@
{{ define "content" }}
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.editProductPage*/ -}}
<section class="dialog-content" id="edit-product-dialog-content" data-hx-target="this">
<section class="dialog-content" id="edit-product-dialog-content" data-hx-target="main">
<h2>{{printf (pgettext "Edit Product “%s”" "title") .ProductName }}</h2>
<form method="POST" action="{{ companyURI "/products/" }}{{ .Slug }}"
data-hx-boost="true" data-hx-select="#edit-product-dialog-content"
>
<form method="POST" action="{{ companyURI "/products/" }}{{ .Slug }}" data-hx-boost="true">
{{ csrfToken }}
{{ putMethod }}

View File

@ -4,14 +4,13 @@
{{ define "breadcrumbs" -}}
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.productsIndexPage*/ -}}
<nav data-hx-boost="true">
<p data-hx-target="main">
<nav data-hx-boost="true" data-hx-target="main">
<p>
<a href="{{ companyURI "/" }}">{{( pgettext "Home" "title" )}}</a> /
<a>{{( pgettext "Products" "title" )}}</a>
</p>
<p>
<a class="primary button"
data-hx-push-url="false" data-hx-swap="beforeend"
href="{{ companyURI "/products/new" }}">{{( pgettext "New product" "action" )}}</a>
</p>
</nav>
@ -47,7 +46,7 @@
{{- range $product := . }}
<tr>
<td></td>
<td><a href="{{ companyURI "/products/"}}{{ .Slug }}" data-hx-push-url="false" data-hx-swap="beforeend" data-hx-boost="true">{{ .Name }}</a></td>
<td><a href="{{ companyURI "/products/"}}{{ .Slug }}" data-hx-target="main" data-hx-boost="true">{{ .Name }}</a></td>
<td>
{{- range $index, $tag := .Tags }}
{{- if gt $index 0 }}, {{ end -}}

View File

@ -15,11 +15,9 @@
{{ define "content" }}
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.productForm*/ -}}
<section class="dialog-content" id="new-product-dialog-content" data-hx-target="this">
<section class="dialog-content" id="new-product-dialog-content" data-hx-target="main">
<h2>{{(pgettext "New Product" "title")}}</h2>
<form method="POST" action="{{ companyURI "/products" }}"
data-hx-boost="true" data-hx-select="#new-product-dialog-content"
>
<form method="POST" action="{{ companyURI "/products" }}" data-hx-boost="true">
{{ csrfToken }}
{{ template "input-field" .Name | addInputAttr "autofocus" }}