diff --git a/web/package/agama-web-ui.changes b/web/package/agama-web-ui.changes index 8be41863b7..3356e8ecdd 100644 --- a/web/package/agama-web-ui.changes +++ b/web/package/agama-web-ui.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Jun 14 13:55:27 UTC 2024 - David Diaz + +- Do not render the overview page when selecting a product + (gh#openSUSE/agama#1331). + ------------------------------------------------------------------- Fri Jun 14 07:37:58 UTC 2024 - David Diaz diff --git a/web/src/App.jsx b/web/src/App.jsx index 4eda8d27b0..30316590f1 100644 --- a/web/src/App.jsx +++ b/web/src/App.jsx @@ -20,9 +20,8 @@ */ import React, { useEffect, useState } from "react"; +import { Navigate, Outlet, useLocation } from "react-router-dom"; import { Loading } from "./components/layout"; -import { Outlet } from "react-router-dom"; -import { ProductSelectionProgress } from "~/components/product"; import { Questions } from "~/components/questions"; import { ServerError, Installation } from "~/components/core"; import { useInstallerL10n } from "./context/installerL10n"; @@ -40,8 +39,9 @@ import { BUSY } from "~/client/status"; */ function App() { const client = useInstallerClient(); + const location = useLocation(); const { connected, error } = useInstallerClientStatus(); - const { products } = useProduct(); + const { selectedProduct, products } = useProduct(); const { language } = useInstallerL10n(); const [status, setStatus] = useState(undefined); const [phase, setPhase] = useState(undefined); @@ -84,8 +84,12 @@ function App() { return ; } - if (phase === CONFIG && status === BUSY) { - return ; + if (selectedProduct === null && location.pathname !== "/products") { + return ; + } + + if (phase === CONFIG && status === BUSY && location.pathname !== "/products/progress") { + return ; } return ; diff --git a/web/src/App.test.jsx b/web/src/App.test.jsx index 828a89fa39..760cdc2e5b 100644 --- a/web/src/App.test.jsx +++ b/web/src/App.test.jsx @@ -32,12 +32,14 @@ jest.mock("~/client"); // list of available products let mockProducts; +let mockSelectedProduct; + jest.mock("~/context/product", () => ({ ...jest.requireActual("~/context/product"), useProduct: () => { return { products: mockProducts, - selectedProduct: null + selectedProduct: mockSelectedProduct }; } })); @@ -158,9 +160,9 @@ describe("App", () => { getStatusFn.mockResolvedValue(BUSY); }); - it("renders the product selection progress", async () => { + it("redirects to product selection progress", async () => { installerRender(, { withL10n: true }); - await screen.findByText(/Product progress/); + await screen.findByText("Navigating to /products/progress"); }); }); @@ -179,6 +181,7 @@ describe("App", () => { describe("on the INSTALL phase", () => { beforeEach(() => { getPhaseFn.mockResolvedValue(INSTALL); + mockSelectedProduct = { id: "Fake product" }; }); it("renders the application content", async () => { diff --git a/web/src/components/overview/OverviewPage.jsx b/web/src/components/overview/OverviewPage.jsx index 29ea0a91bb..2011517eb1 100644 --- a/web/src/components/overview/OverviewPage.jsx +++ b/web/src/components/overview/OverviewPage.jsx @@ -32,9 +32,8 @@ import { NotificationDrawerListItemHeader, Stack, } from "@patternfly/react-core"; -import { useProduct } from "~/context/product"; import { useInstallerClient } from "~/context/installer"; -import { Link, Navigate } from "react-router-dom"; +import { Link } from "react-router-dom"; import { Center } from "~/components/layout"; import { CardField, EmptyState, Page, InstallButton } from "~/components/core"; import L10nSection from "./L10nSection"; @@ -88,7 +87,6 @@ const IssuesList = ({ issues }) => { }; export default function OverviewPage() { - const { selectedProduct } = useProduct(); const [issues, setIssues] = useState([]); const client = useInstallerClient(); @@ -96,10 +94,6 @@ export default function OverviewPage() { client.issues().then(setIssues); }, [client]); - if (selectedProduct === null) { - return ; - } - const resultSectionProps = issues.isEmpty ? {} diff --git a/web/src/components/overview/OverviewPage.test.jsx b/web/src/components/overview/OverviewPage.test.jsx index 51ec494b80..02592374f7 100644 --- a/web/src/components/overview/OverviewPage.test.jsx +++ b/web/src/components/overview/OverviewPage.test.jsx @@ -50,17 +50,6 @@ beforeEach(() => { }); }); -describe("when no product is selected", () => { - beforeEach(() => { - mockSelectedProduct = null; - }); - - it("redirects to the products page", async () => { - installerRender(); - screen.getByText("Navigating to /products"); - }); -}); - describe("when a product is selected", () => { beforeEach(() => { mockSelectedProduct = { name: "Tumbleweed" }; diff --git a/web/src/components/product/ProductSelectionPage.jsx b/web/src/components/product/ProductSelectionPage.jsx index fa89f06faf..454a9e39d7 100644 --- a/web/src/components/product/ProductSelectionPage.jsx +++ b/web/src/components/product/ProductSelectionPage.jsx @@ -20,7 +20,6 @@ */ import React, { useState } from "react"; -import { useNavigate } from "react-router-dom"; import { Card, CardBody, Flex, @@ -42,18 +41,17 @@ const Label = ({ children }) => ( ); function ProductSelectionPage() { - const navigate = useNavigate(); const { products, selectedProduct, selectProduct } = useProduct(); const [nextProduct, setNextProduct] = useState(selectedProduct); + const [isLoading, setIsLoading] = useState(false); const onSubmit = async (e) => { e.preventDefault(); if (nextProduct) { await selectProduct(nextProduct.id); + setIsLoading(true); } - - navigate("/"); }; if (!products) return ( @@ -93,11 +91,12 @@ function ProductSelectionPage() { ))} - {selectedProduct && } + {selectedProduct && !isLoading && } {_("Select")} diff --git a/web/src/components/product/ProductSelectionProgress.jsx b/web/src/components/product/ProductSelectionProgress.jsx index f6cf185ecb..ec9e40bb73 100644 --- a/web/src/components/product/ProductSelectionProgress.jsx +++ b/web/src/components/product/ProductSelectionProgress.jsx @@ -20,6 +20,7 @@ */ import React, { useEffect, useState } from "react"; +import { Navigate } from "react-router-dom"; import { Card, CardBody, Grid, GridItem, @@ -30,10 +31,10 @@ import { import { _ } from "~/i18n"; import { Center } from "~/components/layout"; -import SimpleLayout from "~/SimpleLayout"; import { useCancellablePromise } from "~/utils"; import { useInstallerClient } from "~/context/installer"; import { useProduct } from "~/context/product"; +import { IDLE } from "~/client/status"; const Progress = ({ selectedProduct, storageProgress, softwareProgress }) => { const variant = (progress) => { @@ -107,10 +108,16 @@ const Progress = ({ selectedProduct, storageProgress, softwareProgress }) => { */ function ProductSelectionProgress() { const { cancellablePromise } = useCancellablePromise(); - const { storage, software } = useInstallerClient(); + const { manager, storage, software } = useInstallerClient(); const { selectedProduct } = useProduct(); const [storageProgress, setStorageProgress] = useState({}); const [softwareProgress, setSoftwareProgress] = useState({}); + const [status, setStatus] = useState(); + + useEffect(() => { + manager.getStatus().then(setStatus); + return manager.onStatusChange(setStatus); + }, [manager, setStatus]); useEffect(() => { const updateProgress = (progress) => { @@ -136,29 +143,30 @@ function ProductSelectionProgress() { return software.onProgressChange(updateProgress); }, [cancellablePromise, setSoftwareProgress, software]); + if (status === IDLE) return ; + return ( - -
- - - - - -

- {_("Configuring the product, please wait ...")} -

- -
-
-
-
-
-
-
+
+ + + + + +

+ {_("Configuring the product, please wait ...")} +

+ { status && + } +
+
+
+
+
+
); } diff --git a/web/src/components/product/routes.js b/web/src/components/product/routes.js index 902e25dbcc..3762d113f7 100644 --- a/web/src/components/product/routes.js +++ b/web/src/components/product/routes.js @@ -20,11 +20,23 @@ */ import React from "react"; +import { Page } from "~/components/core"; import ProductSelectionPage from "./ProductSelectionPage"; +import ProductSelectionProgress from "./ProductSelectionProgress"; const productsRoute = { path: "/products", - element: + element: , + children: [ + { + index: true, + element: + }, + { + path: "progress", + element: + } + ] }; export {