Allow optional select with empty label

This is not yet necessary, but the empty label is because i do not want
to select a default tax for products—at least, not without a setting for
it.

Since i need to add the required attribute now to select, because
otherwise the browser would allow sending that empty value, i did not
want to do it unconditionally, just in case.
This commit is contained in:
jordi fita mas 2023-02-05 14:06:33 +01:00
parent 60f9792e58
commit ae1949024b
9 changed files with 100 additions and 79 deletions

View File

@ -88,6 +88,7 @@ func newTaxDetailsForm(ctx context.Context, conn *Conn, locale *Locale) *taxDeta
Name: "currency",
Label: pgettext("input", "Currency", locale),
Options: MustGetOptions(ctx, conn, "select currency_code, currency_symbol from currency order by currency_code"),
Required: true,
Selected: "EUR",
},
}

View File

@ -224,6 +224,7 @@ func newContactForm(ctx context.Context, conn *Conn, locale *Locale) *contactFor
Name: "country",
Label: pgettext("input", "Tax", locale),
Options: mustGetCountryOptions(ctx, conn, locale),
Required: true,
Selected: "ES",
Attributes: []template.HTMLAttr{
`autocomplete="country"`,

View File

@ -61,6 +61,8 @@ type SelectField struct {
Selected string
Options []*SelectOption
Attributes []template.HTMLAttr
Required bool
EmptyLabel string
Errors []error
}

View File

@ -36,6 +36,7 @@ func GetProductForm(w http.ResponseWriter, r *http.Request, params httprouter.Pa
form := newProductForm(r.Context(), conn, locale, company)
slug := params[0].Value
if slug == "new" {
form.Tax.EmptyLabel = gettext("Select a tax for this product.", locale)
w.WriteHeader(http.StatusOK)
mustRenderNewProductForm(w, r, form)
return
@ -164,9 +165,10 @@ func newProductForm(ctx context.Context, conn *Conn, locale *Locale, company *Co
},
},
Tax: &SelectField{
Name: "tax",
Label: pgettext("input", "Tax", locale),
Options: MustGetOptions(ctx, conn, "select tax_id::text, name from tax where company_id = $1 order by name", company.Id),
Name: "tax",
Label: pgettext("input", "Tax", locale),
Required: true,
Options: MustGetOptions(ctx, conn, "select tax_id::text, name from tax where company_id = $1 order by name", company.Id),
},
}
}

View File

@ -61,9 +61,10 @@ func newProfileForm(ctx context.Context, conn *Conn, locale *Locale) *profileFor
},
},
Language: &SelectField{
Name: "language",
Label: pgettext("input", "Language", locale),
Options: languages,
Name: "language",
Label: pgettext("input", "Language", locale),
Options: languages,
Required: true,
Attributes: []template.HTMLAttr{
`autocomplete="language"`,
},

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: numerus\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2023-02-04 11:24+0100\n"
"POT-Creation-Date: 2023-02-05 14:04+0100\n"
"PO-Revision-Date: 2023-01-18 17:08+0100\n"
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
"Language-Team: Catalan <ca@dodds.net>\n"
@ -238,11 +238,11 @@ msgctxt "input"
msgid "Password"
msgstr "Contrasenya"
#: pkg/login.go:69 pkg/profile.go:88 pkg/contacts.go:262
#: pkg/login.go:69 pkg/profile.go:89 pkg/contacts.go:263
msgid "Email can not be empty."
msgstr "No podeu deixar el correu-e en blanc."
#: pkg/login.go:70 pkg/profile.go:89 pkg/contacts.go:263
#: pkg/login.go:70 pkg/profile.go:90 pkg/contacts.go:264
msgid "This value is not a valid email. It should be like name@domain.com."
msgstr "Aquest valor no és un correu-e vàlid. Hauria de ser similar a nom@domini.cat."
@ -254,70 +254,74 @@ msgstr "No podeu deixar la contrasenya en blanc."
msgid "Invalid user or password."
msgstr "Nom dusuari o contrasenya incorrectes."
#: pkg/products.go:144
#: pkg/products.go:39
msgid "Select a tax for this product."
msgstr "Escolliu un impost per aquest producte."
#: pkg/products.go:148
msgctxt "input"
msgid "Name"
msgstr "Nom"
#: pkg/products.go:150
#: pkg/products.go:154
msgctxt "input"
msgid "Description"
msgstr "Descripció"
#: pkg/products.go:155
#: pkg/products.go:159
msgctxt "input"
msgid "Price"
msgstr "Preu"
#: pkg/products.go:164 pkg/contacts.go:225
#: pkg/products.go:169 pkg/contacts.go:225
msgctxt "input"
msgid "Tax"
msgstr "Impost"
#: pkg/products.go:183 pkg/profile.go:91
#: pkg/products.go:189 pkg/profile.go:92
msgid "Name can not be empty."
msgstr "No podeu deixar el nom en blanc."
#: pkg/products.go:184
#: pkg/products.go:190
msgid "Price can not be empty."
msgstr "No podeu deixar el preu en blanc."
#: pkg/products.go:185
#: pkg/products.go:191
msgid "Price must be a number greater than zero."
msgstr "El preu ha de ser un número major a zero."
#: pkg/products.go:187
#: pkg/products.go:193
msgid "Selected tax is not valid."
msgstr "Heu seleccionat un impost que no és vàlid."
#: pkg/company.go:78
#: pkg/company.go:89
msgctxt "input"
msgid "Currency"
msgstr "Moneda"
#: pkg/company.go:95
#: pkg/company.go:107
msgid "Selected currency is not valid."
msgstr "Heu seleccionat una moneda que no és vàlida."
#: pkg/company.go:217
#: pkg/company.go:229
msgctxt "input"
msgid "Tax name"
msgstr "Nom impost"
#: pkg/company.go:223
#: pkg/company.go:235
msgctxt "input"
msgid "Rate (%)"
msgstr "Percentatge"
#: pkg/company.go:245
#: pkg/company.go:257
msgid "Tax name can not be empty."
msgstr "No podeu deixar el nom de limpost en blanc."
#: pkg/company.go:246
#: pkg/company.go:258
msgid "Tax rate can not be empty."
msgstr "No podeu deixar percentatge en blanc."
#: pkg/company.go:247
#: pkg/company.go:259
msgid "Tax rate must be an integer between -99 and 99."
msgstr "El percentatge ha de ser entre -99 i 99."
@ -341,11 +345,11 @@ msgctxt "input"
msgid "Language"
msgstr "Idioma"
#: pkg/profile.go:92
#: pkg/profile.go:93
msgid "Confirmation does not match password."
msgstr "La confirmació no és igual a la contrasenya."
#: pkg/profile.go:93
#: pkg/profile.go:94
msgid "Selected language is not valid."
msgstr "Heu seleccionat un idioma que no és vàlid."
@ -394,51 +398,51 @@ msgctxt "input"
msgid "Postal code"
msgstr "Codi postal"
#: pkg/contacts.go:255
#: pkg/contacts.go:256
msgid "Business name can not be empty."
msgstr "No podeu deixar el nom i els cognoms en blanc."
#: pkg/contacts.go:256
#: pkg/contacts.go:257
msgid "VAT number can not be empty."
msgstr "No podeu deixar el DNI o NIF en blanc."
#: pkg/contacts.go:257
#: pkg/contacts.go:258
msgid "This value is not a valid VAT number."
msgstr "Aquest valor no és un DNI o NIF vàlid."
#: pkg/contacts.go:259
#: pkg/contacts.go:260
msgid "Phone can not be empty."
msgstr "No podeu deixar el telèfon en blanc."
#: pkg/contacts.go:260
#: pkg/contacts.go:261
msgid "This value is not a valid phone number."
msgstr "Aquest valor no és un telèfon vàlid."
#: pkg/contacts.go:266
#: pkg/contacts.go:267
msgid "This value is not a valid web address. It should be like https://domain.com/."
msgstr "Aquest valor no és una adreça web vàlida. Hauria de ser similar a https://domini.cat/."
#: pkg/contacts.go:268
#: pkg/contacts.go:269
msgid "Address can not be empty."
msgstr "No podeu deixar ladreça en blanc."
#: pkg/contacts.go:269
#: pkg/contacts.go:270
msgid "City can not be empty."
msgstr "No podeu deixar la població en blanc."
#: pkg/contacts.go:270
#: pkg/contacts.go:271
msgid "Province can not be empty."
msgstr "No podeu deixar la província en blanc."
#: pkg/contacts.go:271
#: pkg/contacts.go:272
msgid "Postal code can not be empty."
msgstr "No podeu deixar el codi postal en blanc."
#: pkg/contacts.go:272
#: pkg/contacts.go:273
msgid "This value is not a valid postal code."
msgstr "Aquest valor no és un codi postal vàlid."
#: pkg/contacts.go:274
#: pkg/contacts.go:275
msgid "Selected country is not valid."
msgstr "Heu seleccionat un país que no és vàlid."

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: numerus\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2023-02-04 11:24+0100\n"
"POT-Creation-Date: 2023-02-05 14:04+0100\n"
"PO-Revision-Date: 2023-01-18 17:45+0100\n"
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
"Language-Team: Spanish <es@tp.org.es>\n"
@ -238,11 +238,11 @@ msgctxt "input"
msgid "Password"
msgstr "Contraseña"
#: pkg/login.go:69 pkg/profile.go:88 pkg/contacts.go:262
#: pkg/login.go:69 pkg/profile.go:89 pkg/contacts.go:263
msgid "Email can not be empty."
msgstr "No podéis dejar el correo-e en blanco."
#: pkg/login.go:70 pkg/profile.go:89 pkg/contacts.go:263
#: pkg/login.go:70 pkg/profile.go:90 pkg/contacts.go:264
msgid "This value is not a valid email. It should be like name@domain.com."
msgstr "Este valor no es un correo-e válido. Tiene que ser parecido a nombre@dominio.es."
@ -254,70 +254,74 @@ msgstr "No podéis dejar la contraseña en blanco."
msgid "Invalid user or password."
msgstr "Nombre de usuario o contraseña inválido."
#: pkg/products.go:144
#: pkg/products.go:39
msgid "Select a tax for this product."
msgstr "Escoged un impuesto para este producto."
#: pkg/products.go:148
msgctxt "input"
msgid "Name"
msgstr "Nombre"
#: pkg/products.go:150
#: pkg/products.go:154
msgctxt "input"
msgid "Description"
msgstr "Descripción"
#: pkg/products.go:155
#: pkg/products.go:159
msgctxt "input"
msgid "Price"
msgstr "Precio"
#: pkg/products.go:164 pkg/contacts.go:225
#: pkg/products.go:169 pkg/contacts.go:225
msgctxt "input"
msgid "Tax"
msgstr "Impuesto"
#: pkg/products.go:183 pkg/profile.go:91
#: pkg/products.go:189 pkg/profile.go:92
msgid "Name can not be empty."
msgstr "No podéis dejar el nombre en blanco."
#: pkg/products.go:184
#: pkg/products.go:190
msgid "Price can not be empty."
msgstr "No podéis dejar el precio en blanco."
#: pkg/products.go:185
#: pkg/products.go:191
msgid "Price must be a number greater than zero."
msgstr "El precio tiene que ser un número mayor a cero."
#: pkg/products.go:187
#: pkg/products.go:193
msgid "Selected tax is not valid."
msgstr "Habéis escogido un impuesto que no es válido."
#: pkg/company.go:78
#: pkg/company.go:89
msgctxt "input"
msgid "Currency"
msgstr "Moneda"
#: pkg/company.go:95
#: pkg/company.go:107
msgid "Selected currency is not valid."
msgstr "Habéis escogido una moneda que no es válida."
#: pkg/company.go:217
#: pkg/company.go:229
msgctxt "input"
msgid "Tax name"
msgstr "Nombre impuesto"
#: pkg/company.go:223
#: pkg/company.go:235
msgctxt "input"
msgid "Rate (%)"
msgstr "Porcentaje"
#: pkg/company.go:245
#: pkg/company.go:257
msgid "Tax name can not be empty."
msgstr "No podéis dejar el nombre del impuesto en blanco."
#: pkg/company.go:246
#: pkg/company.go:258
msgid "Tax rate can not be empty."
msgstr "No podéis dejar el porcentaje en blanco."
#: pkg/company.go:247
#: pkg/company.go:259
msgid "Tax rate must be an integer between -99 and 99."
msgstr "El porcentaje tiene que estar entre -99 y 99."
@ -341,11 +345,11 @@ msgctxt "input"
msgid "Language"
msgstr "Idioma"
#: pkg/profile.go:92
#: pkg/profile.go:93
msgid "Confirmation does not match password."
msgstr "La confirmación no corresponde con la contraseña."
#: pkg/profile.go:93
#: pkg/profile.go:94
msgid "Selected language is not valid."
msgstr "Habéis escogido un idioma que no es válido."
@ -394,51 +398,51 @@ msgctxt "input"
msgid "Postal code"
msgstr "Código postal"
#: pkg/contacts.go:255
#: pkg/contacts.go:256
msgid "Business name can not be empty."
msgstr "No podéis dejar el nombre y los apellidos en blanco."
#: pkg/contacts.go:256
#: pkg/contacts.go:257
msgid "VAT number can not be empty."
msgstr "No podéis dejar el DNI o NIF en blanco."
#: pkg/contacts.go:257
#: pkg/contacts.go:258
msgid "This value is not a valid VAT number."
msgstr "Este valor no es un DNI o NIF válido."
#: pkg/contacts.go:259
#: pkg/contacts.go:260
msgid "Phone can not be empty."
msgstr "No podéis dejar el teléfono en blanco."
#: pkg/contacts.go:260
#: pkg/contacts.go:261
msgid "This value is not a valid phone number."
msgstr "Este valor no es un teléfono válido."
#: pkg/contacts.go:266
#: pkg/contacts.go:267
msgid "This value is not a valid web address. It should be like https://domain.com/."
msgstr "Este valor no es una dirección web válida. Tiene que ser parecida a https://dominio.es/."
#: pkg/contacts.go:268
#: pkg/contacts.go:269
msgid "Address can not be empty."
msgstr "No podéis dejar la dirección en blanco."
#: pkg/contacts.go:269
#: pkg/contacts.go:270
msgid "City can not be empty."
msgstr "No podéis dejar la población en blanco."
#: pkg/contacts.go:270
#: pkg/contacts.go:271
msgid "Province can not be empty."
msgstr "No podéis dejar la provincia en blanco."
#: pkg/contacts.go:271
#: pkg/contacts.go:272
msgid "Postal code can not be empty."
msgstr "No podéis dejar el código postal en blanco."
#: pkg/contacts.go:272
#: pkg/contacts.go:273
msgid "This value is not a valid postal code."
msgstr "Este valor no es un código postal válido válido."
#: pkg/contacts.go:274
#: pkg/contacts.go:275
msgid "Selected country is not valid."
msgstr "Habéis escogido un país que no es válido."

View File

@ -342,11 +342,13 @@ input.width-2x {
color: var(--numerus--color--red);
}
[lang="en"] input:not([required]) + label::after {
[lang="en"] input:not([required]) + label::after,
[lang="en"] select:not([required]) + label::after {
content: " (optional)"
}
[lang="ca"] input:not([required]) + label::after, [lang="es"] input:not([required]) + label::after {
[lang="ca"] input:not([required]) + label::after, [lang="es"] input:not([required]) + label::after,
[lang="ca"] select:not([required]) + label::after, [lang="es"] select:not([required]) + label::after {
content: " (opcional)"
}

View File

@ -1,8 +1,8 @@
{{ define "input-field" -}}
<div class="input {{ if .Errors }}has-errors{{ end }}">
<input type="{{ .Type }}" name="{{ .Name }}" id="{{ .Name }}-field"
{{- range $attribute := .Attributes }} {{$attribute}} {{ end }}
{{ if .Required }}required="required"{{ end }} value="{{ .Val }}" placeholder="{{ .Label }}">
{{- range $attribute := .Attributes }} {{$attribute}} {{ end }}
{{ if .Required }}required="required"{{ end }} value="{{ .Val }}" placeholder="{{ .Label }}">
<label for="{{ .Name }}-field">{{ .Label }}</label>
{{- if .Errors }}
<ul>
@ -17,12 +17,16 @@
{{ define "select-field" -}}
<div class="input {{ if .Errors }}has-errors{{ end }}">
<select id="{{ .Name }}-field" name="{{ .Name }}"
{{- range $attribute := .Attributes }} {{$attribute}} {{ end -}}
{{- range $attribute := .Attributes }} {{$attribute}} {{ end -}}
{{ if .Required }}required="required"{{ end }}
>
{{- range $option := .Options }}
<option value="{{ .Value }}"
{{- if eq .Value $.Selected }} selected="selected"{{ end }}>{{ .Label }}</option>
{{- end }}
{{- with .EmptyLabel }}
<option value="">{{ . }}</option>
{{- end}}
{{- range $option := .Options }}
<option value="{{ .Value }}"
{{- if eq .Value $.Selected }} selected="selected"{{ end }}>{{ .Label }}</option>
{{- end }}
</select>
<label for="{{ .Name }}-field">{{ .Label }}</label>
{{- if .Errors }}