From 5d97d4e0b3d295729905a5dbc67b00bb5fb74bf6 Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Mon, 19 Feb 2024 14:15:40 +0200 Subject: [PATCH] storage: Scroll dialog fields into view as needed When fields fail validation, the first of them is scrolled into view at the top of the dialog. Additionally, when the encryption fields of the Format dialog are revealed, they are scrolled into view. https://bugzilla.redhat.com/show_bug.cgi?id=2264540 --- pkg/storaged/block/format-dialog.jsx | 3 +++ pkg/storaged/dialog.jsx | 40 +++++++++++++++++++++++++--- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/pkg/storaged/block/format-dialog.jsx b/pkg/storaged/block/format-dialog.jsx index 67761cf10dd..d2b67f6f86c 100644 --- a/pkg/storaged/block/format-dialog.jsx +++ b/pkg/storaged/block/format-dialog.jsx @@ -440,6 +440,9 @@ function format_dialog_internal(client, path, start, size, enable_dos_extended, } if (vals.type == "efi" && !vals.mount_point) dlg.set_values({ mount_point: "/boot/efi" }); + } else if (trigger == "crypto") { + if (vals.crypto != "none" && vals.crypto != " keep") + dlg.show_field("crypto_options", "end"); } }, Action: { diff --git a/pkg/storaged/dialog.jsx b/pkg/storaged/dialog.jsx index c76a1b06781..36faa1ded96 100644 --- a/pkg/storaged/dialog.jsx +++ b/pkg/storaged/dialog.jsx @@ -286,7 +286,7 @@ const Row = ({ field, values, errors, onChange }) => { ); return ( - + { field_elts } { nested_elts } @@ -294,7 +294,7 @@ const Row = ({ field, values, errors, onChange }) => { ); } else if (!field.bare) { return ( - + { field_elts } { nested_elts } @@ -465,7 +465,16 @@ export const dialog_open = (def) => { return null; })).then(results => { const errors = { }; - fields.forEach((f, i) => { if (results[i]) errors[f.tag] = results[i]; }); + let scrolled = false; + fields.forEach((f, i) => { + if (results[i]) { + if (!scrolled) { + show_field(f.tag); + scrolled = true; + } + errors[f.tag] = results[i]; + } + }); if (Object.keys(errors).length > 0) return Promise.reject(errors); }); @@ -473,6 +482,29 @@ export const dialog_open = (def) => { const dlg = show_modal_dialog(props(), footer_props(null, null)); + function show_field(tag, align) { + function scroll() { + const dialog_element = document.querySelector('#dialog .pf-v5-c-modal-box__body'); + const field_element = document.querySelector('#dialog [data-tag="' + tag + '"]'); + + if (field_element) { + if (dialog_element) { + // check if we need to scroll + const dialog_rect = dialog_element.getBoundingClientRect(); + const field_rect = field_element.getBoundingClientRect(); + if (field_rect.top >= dialog_rect.top && field_rect.bottom <= dialog_rect.bottom) + return; + } + + field_element.scrollIntoView({ behavior: "smooth", block: align || "start" }); + } + } + // By the time show_field is called from the "update" + // callback, newly visible fields don't exist yet in the + // DOM, so delay the scrolling a bit. + window.setTimeout(scroll, 10); + } + const self = { run: (title, promise) => { update_footer(title, promise); @@ -537,6 +569,8 @@ export const dialog_open = (def) => { update(); }, + show_field: show_field, + close: () => { dlg.footerProps.dialog_done(); }