Compare commits

...

2 Commits

Author SHA1 Message Date
jordi fita mas f2a0cd7d94 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.
2023-04-25 15:28:55 +02:00
jordi fita mas c5fba3246e Fix label for products’ name filter 2023-04-25 15:21:34 +02:00
14 changed files with 40 additions and 94 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 {
@ -170,7 +158,7 @@ func newProductFilterForm(locale *Locale) *productFilterForm {
return &productFilterForm{
Name: &InputField{
Name: "number",
Label: pgettext("input", "Invoice Number", locale),
Label: pgettext("input", "Name", locale),
Type: "search",
},
Tags: &TagsField{

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" }}