From 359715d3c68351ad7de0eb69832e42fc9801f86e Mon Sep 17 00:00:00 2001 From: Katerina Koukiou Date: Thu, 24 Aug 2023 13:28:22 +0200 Subject: [PATCH 1/3] webui: Let error reporting dialog test area auto resize Fixes https://issues.redhat.com/browse/INSTALLER-3649 Related: rhbz#2234964 Related: rhbz#2231339 --- ui/webui/src/components/Error.jsx | 38 +++++++++++++++++-------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/ui/webui/src/components/Error.jsx b/ui/webui/src/components/Error.jsx index bbe2629a051..e9c80f6bc3a 100644 --- a/ui/webui/src/components/Error.jsx +++ b/ui/webui/src/components/Error.jsx @@ -27,6 +27,8 @@ import { HelperTextItem, Modal, ModalVariant, + Stack, + StackItem, TextArea, TextContent, TextVariants, @@ -92,18 +94,25 @@ export const BZReportModal = ({ titleIconVariant={titleIconVariant} variant={ModalVariant.large} footer={ - <> - - {buttons} - + + + + {_("Reporting an issue will send information over the network. Plese review and edit the attached log to remove any sensitive information.")} + + + + + {buttons} + + }>
{detailsLabel && @@ -125,11 +134,6 @@ export const BZReportModal = ({ isDisabled={logContent === undefined || preparingReport} rows={25} /> - - - {_("Reporting an issue will send information over the network. Plese review and edit the attached log to remove any sensitive information.")} - -
From 783565d47261af531d962e832c305bfa8a02193a Mon Sep 17 00:00:00 2001 From: Radek Vykydal Date: Wed, 23 Aug 2023 11:14:04 +0200 Subject: [PATCH 2/3] webui: monitor network connection state from the Anaconda backend Resolves: rhbz#2234964 Related: rhbz#2231339 --- ui/webui/src/actions/network-actions.js | 31 +++++++++ ui/webui/src/apis/network.js | 83 +++++++++++++++++++++++++ ui/webui/src/components/app.jsx | 6 +- ui/webui/src/reducer.js | 15 +++++ 4 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 ui/webui/src/actions/network-actions.js create mode 100644 ui/webui/src/apis/network.js diff --git a/ui/webui/src/actions/network-actions.js b/ui/webui/src/actions/network-actions.js new file mode 100644 index 00000000000..f270db51047 --- /dev/null +++ b/ui/webui/src/actions/network-actions.js @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2023 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with This program; If not, see . + */ + +import { + getConnected, +} from "../apis/network.js"; + +export const getConnectedAction = () => { + return async (dispatch) => { + const connected = await getConnected(); + + return dispatch({ + type: "GET_NETWORK_CONNECTED", + payload: { connected } + }); + }; +}; diff --git a/ui/webui/src/apis/network.js b/ui/webui/src/apis/network.js new file mode 100644 index 00000000000..7954aceedea --- /dev/null +++ b/ui/webui/src/apis/network.js @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2023 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with This program; If not, see . + */ + +import cockpit from "cockpit"; + +import { getConnectedAction } from "../actions/network-actions.js"; +import { debug } from "../helpers/log.js"; + +export class NetworkClient { + constructor (address) { + if (NetworkClient.instance && (!address || NetworkClient.instance.address === address)) { + return NetworkClient.instance; + } + + NetworkClient.instance?.client.close(); + + NetworkClient.instance = this; + + this.client = cockpit.dbus( + "org.fedoraproject.Anaconda.Modules.Network", + { superuser: "try", bus: "none", address } + ); + this.address = address; + } + + init () { + this.client.addEventListener("close", () => console.error("Network client closed")); + } +} + +/** + * @returns {Promise} The bool state of the network connection + */ +export const getConnected = () => { + return ( + new NetworkClient().client.call( + "/org/fedoraproject/Anaconda/Modules/Network", + "org.freedesktop.DBus.Properties", + "Get", + ["org.fedoraproject.Anaconda.Modules.Network", "Connected"] + ) + .then(res => res[0].v) + ); +}; + +export const startEventMonitorNetwork = ({ dispatch }) => { + return new NetworkClient().client.subscribe( + { }, + (path, iface, signal, args) => { + switch (signal) { + case "PropertiesChanged": + if (args[0] === "org.fedoraproject.Anaconda.Modules.Network" && Object.hasOwn(args[1], "Connected")) { + dispatch(getConnectedAction()); + } else { + debug(`Unhandled signal on ${path}: ${iface}.${signal}`, JSON.stringify(args)); + } + break; + default: + debug(`Unhandled signal on ${path}: ${iface}.${signal}`, JSON.stringify(args)); + } + } + ); +}; + +export const initDataNetwork = ({ dispatch }) => { + return Promise.all([ + dispatch(getConnectedAction()) + ]); +}; diff --git a/ui/webui/src/components/app.jsx b/ui/webui/src/components/app.jsx index a399afa52c0..9b0c0f5f810 100644 --- a/ui/webui/src/components/app.jsx +++ b/ui/webui/src/components/app.jsx @@ -36,6 +36,7 @@ import { LocalizationClient, initDataLocalization, startEventMonitorLocalization import { StorageClient, initDataStorage, startEventMonitorStorage } from "../apis/storage.js"; import { PayloadsClient } from "../apis/payloads"; import { RuntimeClient, getIsFinal } from "../apis/runtime"; +import { NetworkClient, initDataNetwork, startEventMonitorNetwork } from "../apis/network.js"; import { readConf } from "../helpers/conf.js"; import { debug } from "../helpers/log.js"; @@ -69,7 +70,8 @@ export const Application = () => { new StorageClient(address), new PayloadsClient(address), new RuntimeClient(address), - new BossClient(address) + new BossClient(address), + new NetworkClient(address), ]; clients.forEach(c => c.init()); @@ -78,11 +80,13 @@ export const Application = () => { Promise.all([ initDataStorage({ dispatch }), initDataLocalization({ dispatch }), + initDataNetwork({ dispatch }), ]) .then(() => { setStoreInitialized(true); startEventMonitorStorage({ dispatch }); startEventMonitorLocalization({ dispatch }); + startEventMonitorNetwork({ dispatch }); }, onCritFail({ context: N_("Reading information about the computer failed.") })); getIsFinal().then( diff --git a/ui/webui/src/reducer.js b/ui/webui/src/reducer.js index 9e8aaba23a2..bae1b36d551 100644 --- a/ui/webui/src/reducer.js +++ b/ui/webui/src/reducer.js @@ -35,10 +35,16 @@ export const localizationInitialState = { commonLocales: [] }; +/* Intial state for the network store substate */ +export const networkInitialState = { + connected: null +}; + /* Initial state for the global store */ export const initialState = { localization: localizationInitialState, storage: storageInitialState, + network: networkInitialState, }; /* Custom hook to use the reducer with async actions */ @@ -64,6 +70,7 @@ export const reducer = (state, action) => { return ({ localization: localizationReducer(state.localization, action), storage: storageReducer(state.storage, action), + network: networkReducer(state.network, action), }); }; @@ -90,3 +97,11 @@ export const localizationReducer = (state = localizationInitialState, action) => return state; } }; + +export const networkReducer = (state = networkInitialState, action) => { + if (action.type === "GET_NETWORK_CONNECTED") { + return { ...state, connected: action.payload.connected }; + } else { + return state; + } +}; From 1da57de19d40df021150dff543706c805705a941 Mon Sep 17 00:00:00 2001 From: Radek Vykydal Date: Thu, 24 Aug 2023 09:33:56 +0200 Subject: [PATCH 3/3] webui: add offline version to BZ report dialog Resolves: rhbz#2234964 Related: rhbz#2231339 --- ui/webui/src/components/AnacondaHeader.jsx | 4 ++-- ui/webui/src/components/Error.jsx | 17 +++++++++++------ ui/webui/src/components/HeaderKebab.jsx | 3 ++- ui/webui/src/components/app.jsx | 9 +++++++-- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/ui/webui/src/components/AnacondaHeader.jsx b/ui/webui/src/components/AnacondaHeader.jsx index b1610935a16..f3d722ed040 100644 --- a/ui/webui/src/components/AnacondaHeader.jsx +++ b/ui/webui/src/components/AnacondaHeader.jsx @@ -31,7 +31,7 @@ import { HeaderKebab } from "./HeaderKebab.jsx"; const _ = cockpit.gettext; -export const AnacondaHeader = ({ beta, title, reportLinkURL }) => { +export const AnacondaHeader = ({ beta, title, reportLinkURL, isConnected }) => { const prerelease = _("Pre-release"); const betanag = beta ? ( @@ -68,7 +68,7 @@ export const AnacondaHeader = ({ beta, title, reportLinkURL }) => { {title} {betanag} - + ); diff --git a/ui/webui/src/components/Error.jsx b/ui/webui/src/components/Error.jsx index e9c80f6bc3a..3e353d015f8 100644 --- a/ui/webui/src/components/Error.jsx +++ b/ui/webui/src/components/Error.jsx @@ -34,7 +34,7 @@ import { TextVariants, Text, } from "@patternfly/react-core"; -import { ExternalLinkAltIcon } from "@patternfly/react-icons"; +import { ExternalLinkAltIcon, DisconnectedIcon } from "@patternfly/react-icons"; import { exitGui } from "../helpers/exit.js"; @@ -64,7 +64,8 @@ export const BZReportModal = ({ logFile, detailsLabel, detailsContent, - buttons + buttons, + isConnected }) => { const [logContent, setLogContent] = useState(); const [preparingReport, setPreparingReport] = useState(false); @@ -97,14 +98,16 @@ export const BZReportModal = ({ - {_("Reporting an issue will send information over the network. Plese review and edit the attached log to remove any sensitive information.")} + {isConnected + ? {_("Reporting an issue will send information over the network. Please review and edit the attached log to remove any sensitive information.")} + : }> {_("Network not available. Configure the network in the top bar menu to report the issue.")} }