diff --git a/assets/styles/main.css b/assets/styles/main.css index 47eddb6..3f4c7c3 100644 --- a/assets/styles/main.css +++ b/assets/styles/main.css @@ -206,9 +206,46 @@ textarea { .form-input { display: flex; flex-direction: column; - gap: .5rem; - flex-grow: 1; margin-top: 1rem; + + label { + margin-bottom: .5rem; + } + + .error { + background-color: #a20000; + color: #fff; + margin: 0; + margin-top: .15rem; + padding: .25rem; + display: inline-block; + } + + .error::before { + content: ''; + width: 1em; + height: 1em; + background-color: #fff; + mask-image: url("data:image/svg+xml,"); + display: inline-block; + mask-repeat: no-repeat; + mask-position: center; + mask-size: cover; + margin-right: .25rem; + margin-bottom: -.05em; + } + + .help { + margin: 0; + margin-bottom: .15rem; + font-style: oblique; + } + + input, + textarea { + padding: .25rem; + margin: 0; + } } .form-row { @@ -220,6 +257,7 @@ textarea { .form-input { margin-top: 0; + flex: 1; } } diff --git a/locales/en/main.ftl b/locales/en/main.ftl index 4a1fd88..932a9fa 100644 --- a/locales/en/main.ftl +++ b/locales/en/main.ftl @@ -43,11 +43,18 @@ record-input-name = button-create-record-next-step = Next step +record-input-ttl = + .input-label = Duration in cache (TTL), in seconds + .help = Optional, default to 1 hour (3600 secondes) + .error-input-type_error = The duration in cache must be a positif integer number. + .error-record-parse-number = The duration in cache must be a positif integer number. + record-input-addresses = .input-label = IP address #{ $index } .error-record-parse-ip = Unexpected IP address format. The IP address should be either an IPv4 address, like 198.51.100.3, or an IPv6 address, like 2001:db8:cafe:bc68::2. + .error-input-missing_value = At least one IP addresses is required. button-add-address = Add an other address diff --git a/locales/fr/main.ftl b/locales/fr/main.ftl index aef3987..8d7e43a 100644 --- a/locales/fr/main.ftl +++ b/locales/fr/main.ftl @@ -11,14 +11,14 @@ zone-content-section-mail-header = Courriel zone-content-section-services-header = Services zone-content-section-general-header = Général -zone-content-record-type-address = +zone-content-record-type-addresses = .type-name = Adresses IP -zone-content-record-type-mailserver = +zone-content-record-type-mailservers = .type-name = Serveurs de courriel .data-preference = Préférence : { $preference } -zone-content-record-type-nameserver = +zone-content-record-type-nameservers = .type-name = Serveurs de noms zone-content-record-type-service = @@ -43,11 +43,18 @@ record-input-name = button-create-record-next-step = Étape suivante +record-input-ttl = + .input-label = Durée dans le cache (TTL), en seconde + .help = Optionnel, 1 heure par défaut (3600 secondes) + .error-input-type_error = La durée dans le cache doit être un nombre entier positif. + .error-record-parse-number = La durée dans le cache doit être un nombre entier positif. + record-input-addresses = .input-label = Adresse IP #{ $index } .error-record-parse-ip = Format d’adresse IP inconnu. L’adresse IP doit être soit une adresse IPv4, comme 198.51.100.3, soit une adresse IPv6, comme 2001:db8:cafe:bc68::2. + .error-input-missing_value = Au moins une adresse IP est requise. button-add-address = Ajouter une autre adresse diff --git a/src/localization.rs b/src/localization.rs index a9667a6..3b2e699 100644 --- a/src/localization.rs +++ b/src/localization.rs @@ -171,6 +171,7 @@ pub struct ExtractLanguageService { impl ExtractLanguageService { // https://httpwg.org/specs/rfc9110.html#field.accept-language + // TODO: Test language selection for compound locales (eg. fr-FR) pub fn language_from_header(&self, headers: &axum::http::HeaderMap) -> LanguageIdentifier { let lang_preferences = headers .get("Accept-Language") diff --git a/templates/pages/new_record.html b/templates/pages/new_record.html index 1e5a317..643bc95 100644 --- a/templates/pages/new_record.html +++ b/templates/pages/new_record.html @@ -5,10 +5,10 @@ {% block main %}

{{ tr(msg="record-creation-process-heading", zone=current_zone, lang=lang) }}

+ {% set domain_error = errors | get(key="/name", default="") %} -{{ domain_error | json_encode(pretty=true) }} {% if not new_record_name or (new_record_name and domain_error) %} {% include "pages/new_record/choose_name.html" %} {% elif not config and not rtype %} diff --git a/templates/pages/new_record/configure_record.html b/templates/pages/new_record/configure_record.html index f3dc180..d45981d 100644 --- a/templates/pages/new_record/configure_record.html +++ b/templates/pages/new_record/configure_record.html @@ -7,11 +7,33 @@ + {% set ttl_error = errors | get(key="/addresses/ttl", default="") %}
- - + +

+ {{ tr(msg="record-input-ttl", attr="help", lang=lang) }} +

+ + {% if ttl_error %} +

+ {{ tr( + msg="record-input-ttl", + attr="error-" ~ ttl_error.code | replace(from=":", to="-"), + lang=lang) }} +

+ {% endif %}
+ {% set global_address_error = errors | get(key="/addresses/data", default="") %} {% for address in input_data.addresses.data.addresses | default(value=[""]) %} {% set address_error = errors | get(key="/addresses/data/addresses/" ~ loop.index0 ~ "/address", default="") %}
@@ -30,15 +52,23 @@ data-new-item-template-attr="name id" data-template-name="addresses[data][addresses][{i}][address]" data-template-id="address-{i}" - {% if domain_error %}aria-invalid="true"{% endif %} + aria-describedby="{% if address_error %}address-{{ loop.index0 }}-error{% endif %}" + {% if address_error %}aria-invalid="true"{% endif %} value="{{ address.address | default(value="") }}" > - {% if address_error %} + {% if global_address_error or address_error %}

- {{ tr( - msg="record-input-addresses", - attr="error-" ~ address_error.code | replace(from=":", to="-"), - lang=lang) }} + {% if global_address_error %} + {{ tr( + msg="record-input-addresses", + attr="error-" ~ global_address_error.code | replace(from=":", to="-"), + lang=lang) }} + {% else %} + {{ tr( + msg="record-input-addresses", + attr="error-" ~ address_error.code | replace(from=":", to="-"), + lang=lang) }} + {% endif %}

{% endif %}