[web] Migrate two-factor-authentication module to BS5 (#25181)

* Delete unused file error.pug

* Revert-me: Enable 2FA locally

* Migrate 2FA pages to BS5

* Add BS5 notification classes to hydrate-form.js

* Revert "Revert-me: Enable 2FA locally"

This reverts commit 2874bedb05e579623e5beb6cf518aa8608808802.

* Fix: Re-add .text-capitalize on button

* Use `notification` mixin for success state

* Append complex notifications with icons in `showMessages`

* Keep the BS3 version of the notification in `showMessages`, move the BS5 implementation to `createNotificationFromMessageBS5`

Check the Boostrap version with `!window?.Frontend?.['bootstrap-3']`, which is a bit hacky

* Update breakpoings in 2FA form to leave more room for error notification

* Address PR comments:

* Remove useless `createTextNode`
* Use `isBootstrap5`
* `Setup` -> `Set Up`

GitOrigin-RevId: d7285853ea1191da7711b7bada8d65ff064bc27d
This commit is contained in:
Antoine Clausse
2025-05-06 16:18:02 +02:00
committed by Copybot
parent 6881ba956a
commit f0856c862f

View File

@@ -3,6 +3,7 @@ import { FetchError, postJSON } from '../../infrastructure/fetch-json'
import { canSkipCaptcha, validateCaptchaV2 } from './captcha'
import inputValidator from './input-validator'
import { disableElement, enableElement } from '../utils/disableElement'
import { isBootstrap5 } from '@/features/utils/bootstrap-5'
// Form helper(s) to handle:
// - Attaching to the relevant form elements
@@ -133,6 +134,66 @@ function hideFormElements(formEl) {
}
}
/**
* Creates a notification element from a message object, with BS5 classes.
*
* @param {Object} message
* @param {'error' | 'success' | 'warning' | 'info'} message.type
* @param {string} message.key
* @param {string} message.text
* @param {string[]} message.hints
* @returns {HTMLDivElement}
*/
function createNotificationFromMessageBS5(message) {
const messageEl = document.createElement('div')
messageEl.className = classNames('mb-3 notification', {
'notification-type-error': message.type === 'error',
'notification-type-success': message.type === 'success',
'notification-type-warning': message.type === 'warning',
'notification-type-info': message.type === 'info',
})
messageEl.setAttribute('aria-live', 'assertive')
messageEl.setAttribute('role', message.type === 'error' ? 'alert' : 'status')
const materialIcon = {
info: 'info',
success: 'check_circle',
error: 'error',
warning: 'warning',
}[message.type]
if (materialIcon) {
const iconEl = document.createElement('div')
iconEl.className = 'notification-icon'
const iconSpan = document.createElement('span')
iconSpan.className = 'material-symbols'
iconSpan.setAttribute('aria-hidden', 'true')
iconSpan.textContent = materialIcon
iconEl.append(iconSpan)
messageEl.append(iconEl)
}
const contentAndCtaEl = document.createElement('div')
contentAndCtaEl.className = 'notification-content-and-cta'
const contentEl = document.createElement('div')
contentEl.className = 'notification-content'
contentEl.append(message.text || `Error: ${message.key}`)
if (message.hints && message.hints.length) {
const listEl = document.createElement('ul')
message.hints.forEach(hint => {
const listItemEl = document.createElement('li')
listItemEl.textContent = hint
listEl.append(listItemEl)
})
contentEl.append(listEl)
}
contentAndCtaEl.append(contentEl)
messageEl.append(contentAndCtaEl)
return messageEl
}
// TODO: remove the showMessages function after every form alerts are updated to use the new style
// TODO: rename showMessagesNewStyle to showMessages after the above is done
function showMessages(formEl, messageBag) {
@@ -157,6 +218,9 @@ function showMessages(formEl, messageBag) {
customErrorElements.forEach(el => {
el.hidden = false
})
} else if (isBootstrap5()) {
const notification = createNotificationFromMessageBS5(message)
messagesEl.append(notification)
} else {
// No custom error element for key on page, append a new error message
const messageEl = document.createElement('div')