diff --git a/.erb-lint.yml b/.erb-lint.yml index cf33d296b7c..d5cedd40c18 100644 --- a/.erb-lint.yml +++ b/.erb-lint.yml @@ -58,7 +58,9 @@ linters: - '*/app/views/users/rules_of_use/*' - '*/app/views/users/service_provider_inactive/*' - '*/app/views/users/service_provider_revoke/*' - - '*/app/views/users/shared/*' + - '*/app/views/users/shared/_otp_delivery_preference_selection.html.erb' + - '*/app/views/users/shared/_otp_make_default_number.html.erb' + - '*/app/views/users/shared/_phone_number_edit.html.erb' - '*/app/views/users/totp_setup/*' - '*/app/views/users/two_factor_authentication_setup/*' - '*/app/views/users/verify_password/*' diff --git a/app/javascript/app/form-field-format.js b/app/javascript/app/form-field-format.js deleted file mode 100644 index 9cdba9905be..00000000000 --- a/app/javascript/app/form-field-format.js +++ /dev/null @@ -1,36 +0,0 @@ -import Cleave from 'cleave.js'; - -/* eslint-disable no-new */ -function formatForm() { - if (document.querySelector('.dob')) { - new Cleave('.dob', { - date: true, - datePattern: ['m', 'd', 'Y'], - }); - } - - if (document.querySelector('.personal-key')) { - new Cleave('.personal-key', { - blocks: [4, 4, 4, 4], - delimiter: '-', - }); - } - - if (document.querySelector('.backup-code')) { - new Cleave('.backup-code', { - blocks: [4, 4, 4], - delimiter: '-', - }); - } - - if (document.querySelector('.zipcode')) { - new Cleave('.zipcode', { - numericOnly: true, - blocks: [5, 4], - delimiter: '-', - delimiterLazyShow: true, - }); - } -} - -document.addEventListener('DOMContentLoaded', formatForm); diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index 0c49af61b31..802a1112228 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -1,8 +1,6 @@ require('../app/components/index'); require('../app/utils/index'); require('../app/pw-toggle'); -require('../app/form-field-format'); require('../app/print-personal-key'); require('../app/i18n-dropdown'); require('../app/accessible-forms'); -require('../app/ssn-field'); diff --git a/app/javascript/packs/form-validation.js b/app/javascript/packs/form-validation.js index 0a3fd242d26..d9f79c7129a 100644 --- a/app/javascript/packs/form-validation.js +++ b/app/javascript/packs/form-validation.js @@ -3,7 +3,7 @@ import { loadPolyfills } from '@18f/identity-polyfill'; /** @typedef {{t:(key:string)=>string, key:(key:string)=>string}} LoginGovI18n */ /** @typedef {{LoginGov:{I18n:LoginGovI18n}}} LoginGovGlobal */ -const PATTERN_TYPES = ['dob', 'personal-key', 'ssn', 'state_id_number', 'zipcode']; +const PATTERN_TYPES = ['personal-key', 'ssn', 'zipcode']; /** * Given a submit event, disables all submit buttons within the target form. @@ -41,10 +41,8 @@ function checkInputValidity(event) { } else if (input.validity.patternMismatch) { PATTERN_TYPES.forEach((type) => { if (input.classList.contains(type)) { - // i18n-tasks-use t('idv.errors.pattern_mismatch.dob') // i18n-tasks-use t('idv.errors.pattern_mismatch.personal_key') // i18n-tasks-use t('idv.errors.pattern_mismatch.ssn') - // i18n-tasks-use t('idv.errors.pattern_mismatch.state_id_number') // i18n-tasks-use t('idv.errors.pattern_mismatch.zipcode') input.setCustomValidity(I18n.t(`idv.errors.pattern_mismatch.${I18n.key(type)}`)); } diff --git a/app/javascript/packs/formatted-fields.js b/app/javascript/packs/formatted-fields.js new file mode 100644 index 00000000000..07605584a45 --- /dev/null +++ b/app/javascript/packs/formatted-fields.js @@ -0,0 +1,23 @@ +import Cleave from 'cleave.js'; + +const SELECTOR_CONFIGS = { + '.personal-key': { + blocks: [4, 4, 4, 4], + delimiter: '-', + }, + '.backup-code': { + blocks: [4, 4, 4], + delimiter: '-', + }, + '.zipcode': { + numericOnly: true, + blocks: [5, 4], + delimiter: '-', + delimiterLazyShow: true, + }, +}; + +Object.entries(SELECTOR_CONFIGS) + .map(([selector, config]) => [document.querySelector(selector), config]) + .filter(([element]) => element) + .forEach(([element, config]) => new Cleave(element, config)); diff --git a/app/javascript/app/ssn-field.js b/app/javascript/packs/ssn-field.js similarity index 100% rename from app/javascript/app/ssn-field.js rename to app/javascript/packs/ssn-field.js diff --git a/app/views/idv/address/new.html.erb b/app/views/idv/address/new.html.erb index 2072586c35d..6e13a990eca 100644 --- a/app/views/idv/address/new.html.erb +++ b/app/views/idv/address/new.html.erb @@ -49,3 +49,4 @@ <%= render 'idv/doc_auth/back', step: 'verify' %> +<%= javascript_packs_tag_once('formatted-fields') %> diff --git a/app/views/idv/doc_auth/_ssn_init.html.erb b/app/views/idv/doc_auth/_ssn_init.html.erb index 110da425170..a66baf8e84c 100644 --- a/app/views/idv/doc_auth/_ssn_init.html.erb +++ b/app/views/idv/doc_auth/_ssn_init.html.erb @@ -24,16 +24,7 @@ ) do |f| %>
- - <%= f.input( - :ssn, - as: :password, - label: t('idv.form.ssn_label_html'), - required: true, - pattern: '^\d{3}-?\d{2}-?\d{4}$', - maxlength: 11, - input_html: { aria: { invalid: false }, class: 'ssn ssn-toggle', value: '' } - ) %> + <%= render 'shared/ssn_field', f: f %>
diff --git a/app/views/idv/doc_auth/_ssn_update.html.erb b/app/views/idv/doc_auth/_ssn_update.html.erb index 796f6d2fbd1..e4b78383f48 100644 --- a/app/views/idv/doc_auth/_ssn_update.html.erb +++ b/app/views/idv/doc_auth/_ssn_update.html.erb @@ -17,16 +17,7 @@ ) do |f| %>
- - <%= f.input( - :ssn, - as: :password, - label: t('idv.form.ssn_label_html'), - required: true, - pattern: '^\d{3}-?\d{2}-?\d{4}$', - maxlength: 11, - input_html: { aria: { invalid: false }, class: 'ssn ssn-toggle', value: '' } - ) %> + <%= render 'shared/ssn_field', f: f %>
@@ -39,4 +30,3 @@ <% end %> <%= render 'idv/doc_auth/back', action: 'cancel_update_ssn' %> - diff --git a/app/views/idv/gpo/_new_address.html.erb b/app/views/idv/gpo/_new_address.html.erb index 003f5f5d733..e2cae1457e9 100644 --- a/app/views/idv/gpo/_new_address.html.erb +++ b/app/views/idv/gpo/_new_address.html.erb @@ -30,3 +30,4 @@ <% end %> +<%= javascript_packs_tag_once('formatted-fields') %> diff --git a/app/views/partials/backup_code/_entry_fields.html.erb b/app/views/partials/backup_code/_entry_fields.html.erb index 9592e55904c..f6ba24cbadf 100644 --- a/app/views/partials/backup_code/_entry_fields.html.erb +++ b/app/views/partials/backup_code/_entry_fields.html.erb @@ -9,3 +9,4 @@ aria: { invalid: false }, spellcheck: 'false' } %> +<%= javascript_packs_tag_once('formatted-fields') %> diff --git a/app/views/partials/personal_key/_entry_fields.html.erb b/app/views/partials/personal_key/_entry_fields.html.erb index 6a7b8a67db0..eb3f744fca9 100644 --- a/app/views/partials/personal_key/_entry_fields.html.erb +++ b/app/views/partials/personal_key/_entry_fields.html.erb @@ -11,3 +11,4 @@ aria: { invalid: false }, spellcheck: 'false' } %> +<%= javascript_packs_tag_once('formatted-fields') %> diff --git a/app/views/shared/_personal_key_input.html.erb b/app/views/shared/_personal_key_input.html.erb index 6a8e2a26f3b..a851e7b13b2 100644 --- a/app/views/shared/_personal_key_input.html.erb +++ b/app/views/shared/_personal_key_input.html.erb @@ -8,3 +8,4 @@ aria-invalid="false" spellcheck="false" type="text" /> +<%= javascript_packs_tag_once('formatted-fields') %> diff --git a/app/views/shared/_ssn_field.html.erb b/app/views/shared/_ssn_field.html.erb new file mode 100644 index 00000000000..77b06f83834 --- /dev/null +++ b/app/views/shared/_ssn_field.html.erb @@ -0,0 +1,16 @@ +<%# +locals: +* f: from validated_form_for +%> + +<%# maxlength set and includes '-' delimiters to work around cleave bug %> +<%= f.input( + :ssn, + as: :password, + label: t('idv.form.ssn_label_html'), + required: true, + pattern: '^\d{3}-?\d{2}-?\d{4}$', + maxlength: 11, + input_html: { aria: { invalid: false }, class: 'ssn ssn-toggle', value: '' } + ) %> +<%= javascript_packs_tag_once('ssn-field') %> diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index 9342d46d6ae..348c6d32ad2 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -99,7 +99,6 @@ ignore_unused: - 'errors.messages.*' - 'forms.two_factor_choice.legend' - 'forms.two_factor_recovery_choice.legend' - - 'idv.errors.pattern_mismatch.*' - 'jobs.sms_otp_sender_job.login_message' - 'jobs.sms_otp_sender_job.verify_message' - 'service_providers.*' diff --git a/config/locales/idv/en.yml b/config/locales/idv/en.yml index b6da1715c74..43b2ef59104 100644 --- a/config/locales/idv/en.yml +++ b/config/locales/idv/en.yml @@ -30,11 +30,9 @@ en: incorrect_password: The password you entered is not correct. mail_limit_reached: You have requested too much mail in the last month. pattern_mismatch: - dob: Your date of birth must be entered in as mm/dd/yyyy personal_key: 'Please enter your personal key for this account. Example: ABC1-DEF2-G3HI-J456' ssn: 'Your Social Security Number must be entered in as ###-##-####' - state_id_number: Your ID number cannot be more than 25 characters. zipcode: 'Your zipcode must be entered in as #####-####' unsupported_otp_delivery_method: Select a method to receive a code. failure: diff --git a/config/locales/idv/es.yml b/config/locales/idv/es.yml index e990e9d77de..2cc46cfe61c 100644 --- a/config/locales/idv/es.yml +++ b/config/locales/idv/es.yml @@ -32,11 +32,9 @@ es: incorrect_password: La contraseña que ingresó no es correcta. mail_limit_reached: Usted ha solicitado demasiado correo en el último mes. pattern_mismatch: - dob: Su fecha de nacimiento debe ser ingresada en este formato mes/día/año. personal_key: 'Introduzca su clave personal para esta cuenta. Ejemplo: ABC1-DEF2-G3HI-J456' ssn: 'Su número de Seguro Social debe ser ingresado como ### - ## - ####' - state_id_number: Su número de ID no puede tener más de 25 caracteres zipcode: 'Su código postal debe ser ingresado como #####-####' unsupported_otp_delivery_method: Seleccione una manera de recibir un código. failure: diff --git a/config/locales/idv/fr.yml b/config/locales/idv/fr.yml index 30a6a9054d6..dfb5d8f85f0 100644 --- a/config/locales/idv/fr.yml +++ b/config/locales/idv/fr.yml @@ -34,12 +34,10 @@ fr: incorrect_password: Le mot de passe que vous avez inscrit est incorrect. mail_limit_reached: Vous avez demandé trop de lettres au cours du dernier mois. pattern_mismatch: - dob: 'Votre date de naissance doit être inscrite de cette façon: mm/jj/aaaa' personal_key: 'Veuillez inscrire votre clé personnelle pour ce compte, par exemple : ABC1-DEF2-G3HI-J456' ssn: 'Votre numéro de sécurité sociale doit être inscrit de cette façon : ###-##-####' - state_id_number: Votre numéro d’identification ne peut excéder 25 caractères zipcode: 'Votre code ZIP doit être inscrit de cette façon : #####-####' unsupported_otp_delivery_method: Sélectionnez une méthode pour recevoir un code. failure: