From b06a52b58bf4bb4d13f7c3d6f55f18433671c3e1 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Fri, 2 Feb 2024 16:07:41 -0500 Subject: [PATCH] Port and limit entrypoints to TypeScript changelog: Internal, TypeScript, Port JavaScript to TypeScript --- app/components/base_component.rb | 2 +- .../{time_component.js => time_component.ts} | 0 ...ponent.js => validated_field_component.ts} | 0 app/javascript/packs/masked-text-toggle.js | 4 -- app/javascript/packs/masked-text-toggle.ts | 4 ++ ...eference.js => otp-delivery-preference.ts} | 63 ++++++------------- ...e-session.js => session-expire-session.ts} | 0 spec/components/base_component_spec.rb | 12 ++-- webpack.config.js | 2 +- 9 files changed, 30 insertions(+), 57 deletions(-) rename app/components/{time_component.js => time_component.ts} (100%) rename app/components/{validated_field_component.js => validated_field_component.ts} (100%) delete mode 100644 app/javascript/packs/masked-text-toggle.js create mode 100644 app/javascript/packs/masked-text-toggle.ts rename app/javascript/packs/{otp-delivery-preference.js => otp-delivery-preference.ts} (57%) rename app/javascript/packs/{session-expire-session.js => session-expire-session.ts} (100%) diff --git a/app/components/base_component.rb b/app/components/base_component.rb index 05beba4c8ba..684e313b4b1 100644 --- a/app/components/base_component.rb +++ b/app/components/base_component.rb @@ -5,7 +5,7 @@ def before_render def self.scripts @scripts ||= begin - scripts = sidecar_files_basenames(['js', 'ts']) + scripts = sidecar_files_basenames(['ts']) scripts.concat superclass.scripts if superclass.respond_to?(:scripts) scripts end diff --git a/app/components/time_component.js b/app/components/time_component.ts similarity index 100% rename from app/components/time_component.js rename to app/components/time_component.ts diff --git a/app/components/validated_field_component.js b/app/components/validated_field_component.ts similarity index 100% rename from app/components/validated_field_component.js rename to app/components/validated_field_component.ts diff --git a/app/javascript/packs/masked-text-toggle.js b/app/javascript/packs/masked-text-toggle.js deleted file mode 100644 index ad14e181850..00000000000 --- a/app/javascript/packs/masked-text-toggle.js +++ /dev/null @@ -1,4 +0,0 @@ -import MaskedTextToggle from '@18f/identity-masked-text-toggle'; - -const wrappers = document.querySelectorAll('.masked-text__toggle'); -wrappers.forEach((toggle) => new MaskedTextToggle(/** @type {HTMLInputElement} */ (toggle)).bind()); diff --git a/app/javascript/packs/masked-text-toggle.ts b/app/javascript/packs/masked-text-toggle.ts new file mode 100644 index 00000000000..ecf9fa6b07f --- /dev/null +++ b/app/javascript/packs/masked-text-toggle.ts @@ -0,0 +1,4 @@ +import MaskedTextToggle from '@18f/identity-masked-text-toggle'; + +const wrappers = document.querySelectorAll('.masked-text__toggle'); +wrappers.forEach((toggle) => new MaskedTextToggle(toggle).bind()); diff --git a/app/javascript/packs/otp-delivery-preference.js b/app/javascript/packs/otp-delivery-preference.ts similarity index 57% rename from app/javascript/packs/otp-delivery-preference.js rename to app/javascript/packs/otp-delivery-preference.ts index 4576e00799c..49a42871b0b 100644 --- a/app/javascript/packs/otp-delivery-preference.js +++ b/app/javascript/packs/otp-delivery-preference.ts @@ -1,46 +1,31 @@ import { t } from '@18f/identity-i18n'; - -/** @typedef {import('@18f/identity-phone-input').PhoneInputElement} PhoneInput */ +import type { PhoneInputElement } from '@18f/identity-phone-input'; /** * Returns the OTP delivery preference element. - * - * @return {HTMLElement} */ -const getOTPDeliveryMethodContainer = () => - /** @type {HTMLElement} */ (document.querySelector('.js-otp-delivery-preferences')); +const getOTPDeliveryMethodContainer = (): HTMLElement => + document.querySelector('.js-otp-delivery-preferences')!; -/** - * @return {HTMLInputElement[]} - */ const getOTPDeliveryMethods = () => - Array.from(document.querySelectorAll('.js-otp-delivery-preference')); + Array.from(document.querySelectorAll('.js-otp-delivery-preference')); /** * Returns true if the delivery option is valid for the selected option, or false otherwise. - * - * @param {string} delivery - * @param {HTMLOptionElement} selectedOption - * @return {boolean} */ -const isDeliveryOptionSupported = (delivery, selectedOption) => +const isDeliveryOptionSupported = (delivery: string, selectedOption: HTMLOptionElement): boolean => selectedOption.getAttribute(`data-supports-${delivery}`) !== 'false'; -/** - * @param {string} delivery - * @param {string} location - * @return {string=} - */ -const getHintTextForDisabledDeliveryOption = (delivery, location) => +const getHintTextForDisabledDeliveryOption = ( + delivery: string, + location: string, +): string | undefined => // i18n-tasks-use t('two_factor_authentication.otp_delivery_preference.voice_unsupported') // i18n-tasks-use t('two_factor_authentication.otp_delivery_preference.sms_unsupported') t(`two_factor_authentication.otp_delivery_preference.${delivery}_unsupported`, { location }); -/** - * @param {string=} hintText - */ function setHintText( - hintText = t('two_factor_authentication.otp_delivery_preference.instruction'), + hintText: string = t('two_factor_authentication.otp_delivery_preference.instruction'), ) { const hintElement = document.querySelector('#otp_delivery_preference_instruction'); if (hintElement) { @@ -50,38 +35,31 @@ function setHintText( /** * Returns true if all inputs are disabled, or false otherwise. - * - * @param {HTMLInputElement[]} inputs - * @return {boolean} */ -const isAllDisabled = (inputs) => inputs.every((input) => input.disabled); +const isAllDisabled = (inputs: HTMLInputElement[]): boolean => + inputs.every((input) => input.disabled); /** * Returns the next non-disabled input in the set of inputs, if one exists. - * - * @param {HTMLInputElement[]} inputs - * @return {HTMLInputElement=} */ -const getFirstEnabledInput = (inputs) => inputs.find((input) => !input.disabled); +const getFirstEnabledInput = (inputs: HTMLInputElement[]): HTMLInputElement | undefined => + inputs.find((input) => !input.disabled); /** * Toggles the delivery preferences selection visible or hidden. * - * @param {boolean} isVisible Whether the selection element should be visible. + * @param isVisible Whether the selection element should be visible. */ -const toggleDeliveryPreferencesVisible = (isVisible) => +const toggleDeliveryPreferencesVisible = (isVisible: boolean) => getOTPDeliveryMethodContainer().classList.toggle('display-none', !isVisible); -/** - * @param {Event} event - */ -function updateOTPDeliveryMethods(event) { +function updateOTPDeliveryMethods(event: Event) { if (!(event.target instanceof HTMLSelectElement)) { return; } const { target: select, currentTarget } = event; - const { textInput } = /** @type {PhoneInput} */ (currentTarget); + const { textInput } = currentTarget as PhoneInputElement; if (!textInput) { return; } @@ -90,7 +68,7 @@ function updateOTPDeliveryMethods(event) { const methods = getOTPDeliveryMethods(); setHintText(); - const location = /** @type {string} */ (selectedOption.dataset.countryName); + const location = selectedOption.dataset.countryName!; methods.forEach((method) => { const delivery = method.value; @@ -113,7 +91,6 @@ function updateOTPDeliveryMethods(event) { toggleDeliveryPreferencesVisible(!isAllMethodsDisabled); } -document.querySelectorAll('lg-phone-input').forEach((node) => { - const phoneInput = /** @type {PhoneInput} */ (node); +document.querySelectorAll('lg-phone-input').forEach((phoneInput) => { phoneInput.addEventListener('change', updateOTPDeliveryMethods); }); diff --git a/app/javascript/packs/session-expire-session.js b/app/javascript/packs/session-expire-session.ts similarity index 100% rename from app/javascript/packs/session-expire-session.js rename to app/javascript/packs/session-expire-session.ts diff --git a/spec/components/base_component_spec.rb b/spec/components/base_component_spec.rb index f8eb34f2dba..286ab6c4dd1 100644 --- a/spec/components/base_component_spec.rb +++ b/spec/components/base_component_spec.rb @@ -30,7 +30,6 @@ def call def self.sidecar_files(extensions) files = [] - files << '/components/example_component_with_script_js.js' if extensions.include?('js') files << '/components/example_component_with_script_ts.ts' if extensions.include?('ts') files.presence || super(extensions) end @@ -44,8 +43,8 @@ def call end def self.sidecar_files(extensions) - if extensions.include?('js') - ['/components/example_component_with_script_rendering_other_component_with_script.js'] + if extensions.include?('ts') + ['/components/example_component_with_script_rendering_other_component_with_script.ts'] else super(extensions) end @@ -56,8 +55,8 @@ def self.sidecar_files(extensions) # rubocop:disable RSpec/LeakyConstantDeclaration class NestedExampleComponentWithScript < ExampleComponentWithScript def self.sidecar_files(extensions) - if extensions.include?('js') - ['/components/nested_example_component_with_script.js'] + if extensions.include?('ts') + ['/components/nested_example_component_with_script.ts'] else super(extensions) end @@ -67,7 +66,6 @@ def self.sidecar_files(extensions) it 'adds script to class variable when rendered' do expect(view_context).to receive(:enqueue_component_scripts).with( - 'example_component_with_script_js', 'example_component_with_script_ts', ) @@ -77,7 +75,6 @@ def self.sidecar_files(extensions) it 'adds own and parent scripts to class variable when rendered' do expect(view_context).to receive(:enqueue_component_scripts).with( 'nested_example_component_with_script', - 'example_component_with_script_js', 'example_component_with_script_ts', ) @@ -95,7 +92,6 @@ def self.sidecar_files(extensions) ] when 2 expect(args).to eq [ - 'example_component_with_script_js', 'example_component_with_script_ts', ] end diff --git a/webpack.config.js b/webpack.config.js index ee6fd03b494..71663a36490 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -16,7 +16,7 @@ const hashSuffix = isProductionEnv ? '-[chunkhash:8].digested' : ''; const devServerPort = process.env.WEBPACK_PORT; const devtool = process.env.WEBPACK_DEVTOOL || (isProductionEnv ? 'source-map' : 'eval-source-map'); -const entries = glob('app/{components,javascript/packs}/*.{ts,tsx,js,jsx}'); +const entries = glob('app/{components,javascript/packs}/*.{ts,tsx}'); module.exports = /** @type {import('webpack').Configuration} */ ({ mode,