From 745526cae662efd74e24ba090c4e9b2b425ed5ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 25 Feb 2025 09:35:03 +0000 Subject: [PATCH 01/12] fix(web): fallback to the backend language * Do not fallback to the navigator installer anymore. --- web/src/context/installerL10n.tsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/web/src/context/installerL10n.tsx b/web/src/context/installerL10n.tsx index a01a320099..3732f73144 100644 --- a/web/src/context/installerL10n.tsx +++ b/web/src/context/installerL10n.tsx @@ -134,6 +134,16 @@ function languageToLocale(language: string): string { return `${locale}.UTF-8`; } +/** + * Returns the language tag from the backend. + * + * @return Language tag from the backend locale. + */ +async function languageFromBackend(): Promise { + const config = await fetchConfig(); + return languageFromLocale(config.uiLocale); +} + /** * Returns the first supported language from the given list. * @@ -230,8 +240,7 @@ function InstallerL10nProvider({ children }: { children?: React.ReactNode }) { const [keymap, setKeymap] = useState(undefined); const syncBackendLanguage = useCallback(async () => { - const config = await fetchConfig(); - const backendLanguage = languageFromLocale(config.uiLocale); + const backendLanguage = await languageFromBackend(); if (backendLanguage === language) return; // FIXME: fallback to en-US if the language is not supported. @@ -240,7 +249,7 @@ function InstallerL10nProvider({ children }: { children?: React.ReactNode }) { const changeLanguage = useCallback( async (lang?: string) => { - const wanted = lang || languageFromQuery(); + const wanted = lang || languageFromQuery() || (await languageFromBackend()); // Just for development purposes if (wanted === "xx" || wanted === "xx-XX") { @@ -253,7 +262,6 @@ function InstallerL10nProvider({ children }: { children?: React.ReactNode }) { wanted, wanted?.split("-")[0], // fallback to the language (e.g., "es" for "es-AR") agamaLanguage(), - ...navigator.languages, ].filter((l) => l); const newLanguage = findSupportedLanguage(candidateLanguages) || "en-US"; const mustReload = storeAgamaLanguage(newLanguage); From 9769cd0f4bb9639aa806100208894e203a0dcb19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 25 Feb 2025 11:02:43 +0000 Subject: [PATCH 02/12] fix(web): useProduct returns the correct type --- web/src/queries/software.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/web/src/queries/software.ts b/web/src/queries/software.ts index 3117bca5f4..36578a8306 100644 --- a/web/src/queries/software.ts +++ b/web/src/queries/software.ts @@ -195,7 +195,10 @@ const useProduct = ( }) as [{ data: string; isPending: boolean }, { data: Product[]; isPending: boolean }]; if (isSelectedPending || isProductsPending) { - return {}; + return { + products: [], + selectedProduct: undefined, + }; } const selectedProduct = products.find((p: Product) => p.id === selected); From 33aa6a1d717b8c259653b20805030ec083e197d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 25 Feb 2025 11:03:09 +0000 Subject: [PATCH 03/12] fix(web): do not use suspense API in the installation progress --- web/src/App.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index 52cdc7e723..d53fa8ebb1 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -41,7 +41,9 @@ function App() { const location = useLocation(); const { isBusy, phase } = useInstallerStatus({ suspense: true }); const { connected, error } = useInstallerClientStatus(); - const { selectedProduct, products } = useProduct({ suspense: true }); + const { selectedProduct, products } = useProduct({ + suspense: phase !== InstallationPhase.Install, + }); const { language } = useInstallerL10n(); useL10nConfigChanges(); useProductChanges(); From 9731003371c04b9c09ea1d888f6b083654695de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 25 Feb 2025 11:04:16 +0000 Subject: [PATCH 04/12] fix(web): simplify localization markup --- web/src/components/l10n/KeyboardSelection.tsx | 19 +++++-------- web/src/components/l10n/LocaleSelection.tsx | 20 +++++--------- web/src/components/l10n/TimezoneSelection.tsx | 27 +++++++++---------- 3 files changed, 25 insertions(+), 41 deletions(-) diff --git a/web/src/components/l10n/KeyboardSelection.tsx b/web/src/components/l10n/KeyboardSelection.tsx index 9ad48eb1d9..febcd26890 100644 --- a/web/src/components/l10n/KeyboardSelection.tsx +++ b/web/src/components/l10n/KeyboardSelection.tsx @@ -21,12 +21,11 @@ */ import React, { useState } from "react"; -import { Content, Form, FormGroup, Radio } from "@patternfly/react-core"; +import { Content, Flex, Form, FormGroup, Radio } from "@patternfly/react-core"; import { useNavigate } from "react-router-dom"; import { ListSearch, Page } from "~/components/core"; import { _ } from "~/i18n"; import { useConfigMutation, useL10n } from "~/queries/l10n"; -import textStyles from "@patternfly/react-styles/css/utilities/Text/text"; // TODO: Add documentation // TODO: Evaluate if worth it extracting the selector @@ -55,12 +54,10 @@ export default function KeyboardSelection() { name="keymap" onChange={() => setSelected(id)} label={ - <> - - {name} - {" "} + + {name} {id} - + } value={id} isChecked={id === selected} @@ -80,11 +77,9 @@ export default function KeyboardSelection() { - -
- {keymapsList} -
-
+
+ {keymapsList} +
diff --git a/web/src/components/l10n/LocaleSelection.tsx b/web/src/components/l10n/LocaleSelection.tsx index d75e6897f7..08e1219984 100644 --- a/web/src/components/l10n/LocaleSelection.tsx +++ b/web/src/components/l10n/LocaleSelection.tsx @@ -54,15 +54,9 @@ export default function LocaleSelection() { onChange={() => setSelected(id)} label={ - - {name} - - - {territory} - - - {id} - + {name} + {territory} + {id} } value={id} @@ -83,11 +77,9 @@ export default function LocaleSelection() { - -
- {localesList} -
-
+
+ {localesList} +
diff --git a/web/src/components/l10n/TimezoneSelection.tsx b/web/src/components/l10n/TimezoneSelection.tsx index 54d5d0522c..61db7b4414 100644 --- a/web/src/components/l10n/TimezoneSelection.tsx +++ b/web/src/components/l10n/TimezoneSelection.tsx @@ -21,13 +21,13 @@ */ import React, { useState } from "react"; -import { Content, Divider, Flex, Form, FormGroup, Radio } from "@patternfly/react-core"; +import { Content, Flex, Form, FormGroup, Radio } from "@patternfly/react-core"; import { useNavigate } from "react-router-dom"; import { ListSearch, Page } from "~/components/core"; import { timezoneTime } from "~/utils"; import { useConfigMutation, useL10n } from "~/queries/l10n"; import { Timezone } from "~/types/l10n"; -import textStyles from "@patternfly/react-styles/css/utilities/Text/text"; +import spacingStyles from "@patternfly/react-styles/css/utilities/Spacing/spacing"; import { _ } from "~/i18n"; type TimezoneWithDetails = Timezone & { details: string }; @@ -89,18 +89,17 @@ export default function TimezoneSelection() { name="timezone" onChange={() => setSelected(id)} label={ - <> - - {parts.join("-")} - {" "} + + + {parts.join("-")} + {country} - + } description={ - + {timezoneTime(id, date) || ""} - -
{details}
+ {details}
} value={id} @@ -126,11 +125,9 @@ export default function TimezoneSelection() { - -
- {timezonesList} -
-
+
+ {timezonesList} +
From 82fc4ef79202751ea099cf1457788e4fcf0e01d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 25 Feb 2025 11:04:49 +0000 Subject: [PATCH 05/12] fix(web): drop the isManagedSidebar prop --- web/src/components/layout/Layout.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/web/src/components/layout/Layout.tsx b/web/src/components/layout/Layout.tsx index df901d97b9..27239170cd 100644 --- a/web/src/components/layout/Layout.tsx +++ b/web/src/components/layout/Layout.tsx @@ -74,13 +74,10 @@ const Layout = ({ mountSidebar && setIsSidebarOpen(newWindowSize >= agamaWidthBreakpoints.lg); }; - const pageProps: Omit> = { - isManagedSidebar: true, - }; + const pageProps: Omit> = {}; if (mountSidebar) { - pageProps.sidebar = ; - pageProps.isManagedSidebar = false; + pageProps.sidebar = ; } if (mountHeader) { pageProps.masthead = ( From 9baa115a6c2cee2aeea2a9d0d47ce369d3a466d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 25 Feb 2025 11:05:06 +0000 Subject: [PATCH 06/12] fix(web): do not use a section in the Overview page --- web/src/components/overview/OverviewPage.tsx | 22 +++++++++----------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/web/src/components/overview/OverviewPage.tsx b/web/src/components/overview/OverviewPage.tsx index 052c19a7f4..0852b55ac6 100644 --- a/web/src/components/overview/OverviewPage.tsx +++ b/web/src/components/overview/OverviewPage.tsx @@ -38,18 +38,16 @@ export default function OverviewPage() { - - - - - - - + + + {_( + "These are the most relevant installation settings. Feel free to browse the sections in the menu for further details.", + )} + + + + + From 16c3c67e8453cc1aa69ddcec78bf20c4991a5040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 25 Feb 2025 11:05:26 +0000 Subject: [PATCH 07/12] fix(web): set a missing aria-label in the software page --- web/src/components/software/SoftwarePage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/components/software/SoftwarePage.tsx b/web/src/components/software/SoftwarePage.tsx index 9c4c66b1a8..a770a649e9 100644 --- a/web/src/components/software/SoftwarePage.tsx +++ b/web/src/components/software/SoftwarePage.tsx @@ -173,7 +173,7 @@ function SoftwarePage(): React.ReactNode { {proposal.size && ( - + From 1cf7dd96fc90551b8a21c4dbf04d48103f0581ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 25 Feb 2025 12:06:44 +0000 Subject: [PATCH 08/12] docs(web): update changes file --- web/package/agama-web-ui.changes | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/web/package/agama-web-ui.changes b/web/package/agama-web-ui.changes index 86a79ceae6..ad3b60e2d9 100644 --- a/web/package/agama-web-ui.changes +++ b/web/package/agama-web-ui.changes @@ -1,3 +1,13 @@ +------------------------------------------------------------------- +Tue Feb 25 12:02:20 UTC 2025 - Imobach Gonzalez Sosa + +- Use the backend's language as fallback, ignoring the browser's one + It reduces the chances to produce unwanted side-effects when connecting + to the web user interface (gh#agama-project/agama#2071). +- Do not block when connecting during system installation. +- Make some small fixes/improvements to the overview, localization + and software pages markup. + ------------------------------------------------------------------- Thu Feb 20 12:46:04 UTC 2025 - Ancor Gonzalez Sosa From eb2290154332e8ed2f2439b3ac0f0d83d4d691f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 25 Feb 2025 12:43:23 +0000 Subject: [PATCH 09/12] test(web): allow injecting an initialLanguage to InstallerL10nProvider --- web/src/context/installerL10n.tsx | 10 ++++++++-- web/src/test-utils.tsx | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/web/src/context/installerL10n.tsx b/web/src/context/installerL10n.tsx index 3732f73144..e7f8127b73 100644 --- a/web/src/context/installerL10n.tsx +++ b/web/src/context/installerL10n.tsx @@ -234,9 +234,15 @@ async function loadTranslations(locale: string) { * * @see useInstallerL10n */ -function InstallerL10nProvider({ children }: { children?: React.ReactNode }) { +function InstallerL10nProvider({ + initialLanguage, + children, +}: { + initialLanguage?: string; + children?: React.ReactNode; +}) { const { connected } = useInstallerClientStatus(); - const [language, setLanguage] = useState(undefined); + const [language, setLanguage] = useState(initialLanguage); const [keymap, setKeymap] = useState(undefined); const syncBackendLanguage = useCallback(async () => { diff --git a/web/src/test-utils.tsx b/web/src/test-utils.tsx index 1cdf7db152..b0f36e8ee8 100644 --- a/web/src/test-utils.tsx +++ b/web/src/test-utils.tsx @@ -114,7 +114,7 @@ const Providers = ({ children, withL10n }) => { if (withL10n) { return ( - {children} + {children} ); } From b46b50e5aaf239388167ebcba7ce2e660ac0fa56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20D=C3=ADaz=20Gonz=C3=A1lez?= Date: Tue, 25 Feb 2025 12:50:10 +0000 Subject: [PATCH 10/12] fix(web): adapt tests broken at 745526cae66 --- .../components/product/LicenseDialog.test.tsx | 5 ++ web/src/context/installerL10n.test.tsx | 63 +------------------ 2 files changed, 7 insertions(+), 61 deletions(-) diff --git a/web/src/components/product/LicenseDialog.test.tsx b/web/src/components/product/LicenseDialog.test.tsx index e23275efcd..863dde48b4 100644 --- a/web/src/components/product/LicenseDialog.test.tsx +++ b/web/src/components/product/LicenseDialog.test.tsx @@ -46,6 +46,11 @@ jest.mock("~/utils", () => ({ locationReload: jest.fn(), })); +jest.mock("~/api/l10n", () => ({ + ...jest.requireActual("~/api/l10n"), + fetchConfig: () => ({ uiLocale: "en_US.UTF-8" }), +})); + jest.mock("~/context/installerL10n", () => ({ ...jest.requireActual("~/context/installerL10n"), useInstallerL10n: () => ({ language: mockUILanguage }), diff --git a/web/src/context/installerL10n.test.tsx b/web/src/context/installerL10n.test.tsx index b8f3153090..3fc32e88d4 100644 --- a/web/src/context/installerL10n.test.tsx +++ b/web/src/context/installerL10n.test.tsx @@ -1,5 +1,5 @@ /* - * Copyright (c) [2023] SUSE LLC + * Copyright (c) [2023-2025] SUSE LLC * * All Rights Reserved. * @@ -120,37 +120,6 @@ describe("InstallerL10nProvider", () => { }); }); - describe("when the language is set to an unsupported language", () => { - beforeEach(() => { - document.cookie = "agamaLang=de-DE; path=/;"; - mockFetchConfigFn.mockResolvedValue({ uiLocale: "de_DE.UTF-8" }); - }); - - it("uses the first supported language from the browser", async () => { - render( - - - - - , - ); - - await waitFor(() => expect(utils.locationReload).toHaveBeenCalled()); - - // renders again after reloading - render( - - - - - , - ); - - await waitFor(() => screen.getByText("hola")); - expect(mockUpdateConfigFn).toHaveBeenCalledWith({ uiLocale: "es_ES.UTF-8" }); - }); - }); - describe("when the language is not set", () => { beforeEach(() => { // Ensure both, UI and backend mock languages, are in sync since @@ -159,7 +128,7 @@ describe("InstallerL10nProvider", () => { mockFetchConfigFn.mockResolvedValue({ uiLocale: "es_ES.UTF-8" }); }); - it("sets the preferred language from browser and reloads", async () => { + it("sets the language from backend", async () => { render( @@ -180,34 +149,6 @@ describe("InstallerL10nProvider", () => { ); await waitFor(() => screen.getByText("hola")); }); - - describe("when the browser language does not contain the full locale", () => { - beforeEach(() => { - jest.spyOn(window.navigator, "languages", "get").mockReturnValue(["es", "cs-CZ"]); - }); - - it("sets the first which language matches", async () => { - render( - - - - - , - ); - - await waitFor(() => expect(utils.locationReload).toHaveBeenCalled()); - - // renders again after reloading - render( - - - - - , - ); - await waitFor(() => screen.getByText("hola!")); - }); - }); }); }); From 57047ae4aaddd540f7e3dee007f6a4fbad80caeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20D=C3=ADaz=20Gonz=C3=A1lez?= Date: Tue, 25 Feb 2025 12:53:46 +0000 Subject: [PATCH 11/12] fix(web): partially revert d393f2204a3 Because a better fix was sent with commit eb2290154332e8 --- web/src/components/product/LicenseDialog.test.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/web/src/components/product/LicenseDialog.test.tsx b/web/src/components/product/LicenseDialog.test.tsx index 863dde48b4..e23275efcd 100644 --- a/web/src/components/product/LicenseDialog.test.tsx +++ b/web/src/components/product/LicenseDialog.test.tsx @@ -46,11 +46,6 @@ jest.mock("~/utils", () => ({ locationReload: jest.fn(), })); -jest.mock("~/api/l10n", () => ({ - ...jest.requireActual("~/api/l10n"), - fetchConfig: () => ({ uiLocale: "en_US.UTF-8" }), -})); - jest.mock("~/context/installerL10n", () => ({ ...jest.requireActual("~/context/installerL10n"), useInstallerL10n: () => ({ language: mockUILanguage }), From 71903d5736ff2e38be553c2765571f513123e821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Tue, 25 Feb 2025 13:09:07 +0000 Subject: [PATCH 12/12] fix(web): fix changes order --- web/package/agama-web-ui.changes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/package/agama-web-ui.changes b/web/package/agama-web-ui.changes index 022067b6cf..20d8c9de15 100644 --- a/web/package/agama-web-ui.changes +++ b/web/package/agama-web-ui.changes @@ -1,5 +1,5 @@ ------------------------------------------------------------------- -Tue Feb 25 12:02:20 UTC 2025 - Imobach Gonzalez Sosa +Tue Feb 25 13:08:43 UTC 2025 - Imobach Gonzalez Sosa - Use the backend's language as fallback, ignoring the browser's one It reduces the chances to produce unwanted side-effects when connecting