From d1ef18e6f9ed1527b66cec07eba6acaf9a95819c Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sat, 6 Apr 2024 08:04:14 +0000 Subject: [PATCH] Focus default action in modal windows Users of common WIMP GUIs (as opposed to interfaces primarily meant for touch input) expect dialog boxes to have keyboard focus set on the button for default action so that it can be executed by a single key press. Usually that is chosen to proceed with the operation but in cases where that leads to data loss the UI designers often pre-select Cancel as a precaution. This patch adds suitable property to all invocations of msgBoxConfirm() method of `this.$bvModal` BootstrapVue object. For regular actions the confirmation button is selected and can be activated by Enter or Space bar. For actions deemed dangerous Cancel is focused instead so it takes two key presses (first being Tab to shift the focus) to prooceed. This also improves accessibility following the Web Content Accessibility Guidelines (WCAG) published by W3C. Tested: manually verified that modals are consistently shown with the specified button focused, Enter and Space bar key presses produce the same effect as left pointer button click: when Cancel is focused it just closes the window, when OK is focused it sends the corresponding request to the Redfish endpoint. Change-Id: I66bfd02e48e08dc18994b11bbdd5d6b3ea27047f Signed-off-by: Paul Fertser --- docs/guide/guidelines/internationalization.md | 1 + src/views/Logs/Dumps/Dumps.vue | 2 ++ src/views/Logs/EventLogs/EventLogs.vue | 3 +++ src/views/Logs/PostCodeLogs/PostCodeLogs.vue | 1 + src/views/Operations/KeyClear/KeyClear.vue | 1 + src/views/Operations/RebootBmc/RebootBmc.vue | 1 + .../Operations/ServerPowerOperations/ServerPowerOperations.vue | 2 ++ src/views/SecurityAndAccess/Certificates/Certificates.vue | 1 + src/views/SecurityAndAccess/Ldap/TableRoleGroups.vue | 2 ++ src/views/SecurityAndAccess/Sessions/Sessions.vue | 2 ++ src/views/SecurityAndAccess/UserManagement/UserManagement.vue | 2 ++ src/views/Settings/Network/TableIpv4.vue | 1 + src/views/Settings/SnmpAlerts/SnmpAlerts.vue | 2 ++ 13 files changed, 21 insertions(+) diff --git a/docs/guide/guidelines/internationalization.md b/docs/guide/guidelines/internationalization.md index 7afc4598b8..f9ee473798 100644 --- a/docs/guide/guidelines/internationalization.md +++ b/docs/guide/guidelines/internationalization.md @@ -72,5 +72,6 @@ this.$bvModal title: this.$tc('pageDumps.modal.deleteDump'), okTitle: this.$tc('pageDumps.modal.deleteDump'), cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'ok', }) ``` diff --git a/src/views/Logs/Dumps/Dumps.vue b/src/views/Logs/Dumps/Dumps.vue index 77161d4f85..020d2b3cc9 100644 --- a/src/views/Logs/Dumps/Dumps.vue +++ b/src/views/Logs/Dumps/Dumps.vue @@ -332,6 +332,7 @@ export default { title: this.$tc('pageDumps.modal.deleteDump'), okTitle: this.$tc('pageDumps.modal.deleteDump'), cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'ok', }) .then((deleteConfrimed) => { if (deleteConfrimed) { @@ -368,6 +369,7 @@ export default { this.selectedRows.length, ), cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'ok', }, ) .then((deleteConfrimed) => { diff --git a/src/views/Logs/EventLogs/EventLogs.vue b/src/views/Logs/EventLogs/EventLogs.vue index 6994849f1e..0e7c494eab 100644 --- a/src/views/Logs/EventLogs/EventLogs.vue +++ b/src/views/Logs/EventLogs/EventLogs.vue @@ -489,6 +489,7 @@ export default { okTitle: this.$t('global.action.delete'), okVariant: 'danger', cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'cancel', }) .then((deleteConfirmed) => { if (deleteConfirmed) { @@ -535,6 +536,7 @@ export default { title: this.$tc('pageEventLogs.modal.deleteTitle'), okTitle: this.$t('global.action.delete'), cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'ok', }) .then((deleteConfirmed) => { if (deleteConfirmed) this.deleteLogs([uri]); @@ -557,6 +559,7 @@ export default { ), okTitle: this.$t('global.action.delete'), cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'ok', }, ) .then((deleteConfirmed) => { diff --git a/src/views/Logs/PostCodeLogs/PostCodeLogs.vue b/src/views/Logs/PostCodeLogs/PostCodeLogs.vue index 57bbdb599a..6b3030bc88 100644 --- a/src/views/Logs/PostCodeLogs/PostCodeLogs.vue +++ b/src/views/Logs/PostCodeLogs/PostCodeLogs.vue @@ -321,6 +321,7 @@ export default { okTitle: this.$t('global.action.delete'), okVariant: 'danger', cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'cancel', }) .then((deleteConfirmed) => { if (deleteConfirmed) { diff --git a/src/views/Operations/KeyClear/KeyClear.vue b/src/views/Operations/KeyClear/KeyClear.vue index 2524da102b..fbdf4c4608 100644 --- a/src/views/Operations/KeyClear/KeyClear.vue +++ b/src/views/Operations/KeyClear/KeyClear.vue @@ -91,6 +91,7 @@ export default { okTitle: this.$t('pageKeyClear.modal.clear'), okVariant: 'danger', cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'cancel', }) .then((clearConfirmed) => { if (clearConfirmed) { diff --git a/src/views/Operations/RebootBmc/RebootBmc.vue b/src/views/Operations/RebootBmc/RebootBmc.vue index 900619cd59..fe575489c5 100644 --- a/src/views/Operations/RebootBmc/RebootBmc.vue +++ b/src/views/Operations/RebootBmc/RebootBmc.vue @@ -65,6 +65,7 @@ export default { title: this.$t('pageRebootBmc.modal.confirmTitle'), okTitle: this.$t('global.action.confirm'), cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'ok', }) .then((confirmed) => { if (confirmed) this.rebootBmc(); diff --git a/src/views/Operations/ServerPowerOperations/ServerPowerOperations.vue b/src/views/Operations/ServerPowerOperations/ServerPowerOperations.vue index e3864b4af5..281bbef46e 100644 --- a/src/views/Operations/ServerPowerOperations/ServerPowerOperations.vue +++ b/src/views/Operations/ServerPowerOperations/ServerPowerOperations.vue @@ -219,6 +219,7 @@ export default { title: this.$t('pageServerPowerOperations.modal.confirmRebootTitle'), okTitle: this.$t('global.action.confirm'), cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'ok', }; if (this.form.rebootOption === 'orderly') { @@ -243,6 +244,7 @@ export default { title: this.$t('pageServerPowerOperations.modal.confirmShutdownTitle'), okTitle: this.$t('global.action.confirm'), cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'ok', }; if (this.form.shutdownOption === 'orderly') { diff --git a/src/views/SecurityAndAccess/Certificates/Certificates.vue b/src/views/SecurityAndAccess/Certificates/Certificates.vue index 0dc1d5e1fc..35e4b81920 100644 --- a/src/views/SecurityAndAccess/Certificates/Certificates.vue +++ b/src/views/SecurityAndAccess/Certificates/Certificates.vue @@ -250,6 +250,7 @@ export default { title: this.$t('pageCertificates.deleteCertificate'), okTitle: this.$t('global.action.delete'), cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'ok', }, ) .then((deleteConfirmed) => { diff --git a/src/views/SecurityAndAccess/Ldap/TableRoleGroups.vue b/src/views/SecurityAndAccess/Ldap/TableRoleGroups.vue index ed759894d0..eeebfb9b60 100644 --- a/src/views/SecurityAndAccess/Ldap/TableRoleGroups.vue +++ b/src/views/SecurityAndAccess/Ldap/TableRoleGroups.vue @@ -197,6 +197,7 @@ export default { title: this.$t('pageLdap.modal.deleteRoleGroup'), okTitle: this.$t('global.action.delete'), cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'ok', }, ) .then((deleteConfirmed) => { @@ -227,6 +228,7 @@ export default { title: this.$t('pageLdap.modal.deleteRoleGroup'), okTitle: this.$t('global.action.delete'), cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'ok', }, ) .then((deleteConfirmed) => { diff --git a/src/views/SecurityAndAccess/Sessions/Sessions.vue b/src/views/SecurityAndAccess/Sessions/Sessions.vue index 7436465332..636aafe012 100644 --- a/src/views/SecurityAndAccess/Sessions/Sessions.vue +++ b/src/views/SecurityAndAccess/Sessions/Sessions.vue @@ -261,6 +261,7 @@ export default { title: this.$tc('pageSessions.modal.disconnectTitle'), okTitle: this.$t('pageSessions.action.disconnect'), cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'ok', }) .then((deleteConfirmed) => { if (deleteConfirmed) this.disconnectSessions([uri]); @@ -283,6 +284,7 @@ export default { ), okTitle: this.$t('pageSessions.action.disconnect'), cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'ok', }, ) .then((deleteConfirmed) => { diff --git a/src/views/SecurityAndAccess/UserManagement/UserManagement.vue b/src/views/SecurityAndAccess/UserManagement/UserManagement.vue index e9b1fdaaf9..ab3166889d 100644 --- a/src/views/SecurityAndAccess/UserManagement/UserManagement.vue +++ b/src/views/SecurityAndAccess/UserManagement/UserManagement.vue @@ -274,6 +274,7 @@ export default { title: this.$tc('pageUserManagement.deleteUser'), okTitle: this.$tc('pageUserManagement.deleteUser'), cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'ok', }, ) .then((deleteConfirmed) => { @@ -329,6 +330,7 @@ export default { this.selectedRows.length, ), cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'ok', }, ) .then((deleteConfirmed) => { diff --git a/src/views/Settings/Network/TableIpv4.vue b/src/views/Settings/Network/TableIpv4.vue index 8bd21cb9e3..0a06e0e472 100644 --- a/src/views/Settings/Network/TableIpv4.vue +++ b/src/views/Settings/Network/TableIpv4.vue @@ -224,6 +224,7 @@ export default { : this.$t('global.action.disable'), okVariant: 'danger', cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'cancel', }, ) .then((dhcpEnableConfirmed) => { diff --git a/src/views/Settings/SnmpAlerts/SnmpAlerts.vue b/src/views/Settings/SnmpAlerts/SnmpAlerts.vue index 528033be3e..dba181f256 100644 --- a/src/views/Settings/SnmpAlerts/SnmpAlerts.vue +++ b/src/views/Settings/SnmpAlerts/SnmpAlerts.vue @@ -209,6 +209,7 @@ export default { title: this.$tc('pageSnmpAlerts.modal.deleteSnmpDestinationTitle'), okTitle: this.$tc('pageSnmpAlerts.deleteDestination'), cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'ok', }, ) .then((deleteConfirmed) => { @@ -243,6 +244,7 @@ export default { this.selectedRows.length, ), cancelTitle: this.$t('global.action.cancel'), + autoFocusButton: 'ok', }, ) .then((deleteConfirmed) => {