diff --git a/apps/assisted-disconnected-ui/src/components/ClusterPage.tsx b/apps/assisted-disconnected-ui/src/components/ClusterPage.tsx index 2cc95a611c..2cfa0453af 100644 --- a/apps/assisted-disconnected-ui/src/components/ClusterPage.tsx +++ b/apps/assisted-disconnected-ui/src/components/ClusterPage.tsx @@ -1,10 +1,67 @@ -import { SingleClusterPage } from '@openshift-assisted/ui-lib/ocm'; +import * as React from 'react'; +import { SingleClusterPage, Store } from '@openshift-assisted/ui-lib/ocm'; import { useParams } from 'react-router-dom-v5-compat'; +import { + ClustersAPI, + getHostProgressStages, + ResourceUIState, +} from '@openshift-assisted/ui-lib/common'; +import { Cluster } from '@openshift-assisted/types/assisted-installer-service'; + import ResetSingleClusterModal from './ResetSingleClusterModal'; +import SingleClusterFinalizerPage from './SingleClusterFinalizerPage'; + +const currentClusterSelector = (state: Store.RootStateDay1) => state.currentCluster; + +const useFinalizerPage = () => { + const { uiState, data: cluster } = Store.useSelectorDay1(currentClusterSelector); + const clusterRef = React.useRef(); + const [consoleUrl, setConsoleUrl] = React.useState(); + + React.useEffect(() => { + // Fetch console URL for finalizer page. + // We wont be able to do so after we render it, as backend will be already gone at the time. + if ( + !consoleUrl && + cluster?.id && + ['installing', 'installing-pending-user-action'].includes(cluster.status) + ) { + void (async () => { + try { + const resp = await ClustersAPI.getCredentials(cluster.id); + setConsoleUrl(resp.data.consoleUrl); + } catch { + // Nothing to do + } + })(); + } + }, [cluster?.id, cluster?.status, consoleUrl]); + + if (!clusterRef.current && cluster && uiState === ResourceUIState.POLLING_ERROR) { + const boostrapHost = cluster.hosts?.find((h) => h.bootstrap); + if (boostrapHost) { + const stages = getHostProgressStages(boostrapHost); + const rebootIdx = stages.findIndex((s) => s === 'Rebooting'); + const currentStage = boostrapHost.progress?.currentStage; + // Show finalizing page as soon as we fail to poll and bootstrap is Rebooting or state before + if (!!currentStage && stages.slice(rebootIdx - 2, stages.length).includes(currentStage)) { + clusterRef.current = cluster; + } + } + } + + return { cluster: clusterRef.current, consoleUrl }; +}; const ClusterPage = () => { const { clusterId } = useParams() as { clusterId: string }; - return } />; + const { cluster, consoleUrl } = useFinalizerPage(); + + return cluster ? ( + + ) : ( + } /> + ); }; export default ClusterPage; diff --git a/apps/assisted-disconnected-ui/src/components/SingleClusterFinalizerPage.tsx b/apps/assisted-disconnected-ui/src/components/SingleClusterFinalizerPage.tsx new file mode 100644 index 0000000000..f46fa5fb73 --- /dev/null +++ b/apps/assisted-disconnected-ui/src/components/SingleClusterFinalizerPage.tsx @@ -0,0 +1,60 @@ +import { + Bullseye, + Button, + EmptyState, + EmptyStateBody, + EmptyStateFooter, + EmptyStateHeader, + EmptyStateVariant, + Spinner, +} from '@patternfly/react-core'; +import { Cluster } from '@openshift-assisted/types/assisted-installer-service'; +import { + TroubleshootingOpenshiftConsoleButton, + useTranslation, +} from '@openshift-assisted/ui-lib/common'; + +const SingleClusterFinalizerPage = ({ + cluster, + consoleUrl, +}: { + cluster: Cluster; + consoleUrl?: string; +}) => { + const { t } = useTranslation(); + return ( + + + } + /> + + {t('ai:Cluster installation is still in-progress.')} +
+ {t('ai:Click the webconsole URL below to check if it is up and running.')} +
+ {t( + 'ai:* If you close this browser window, the webconsole URL can be found also inside the credentials file you have downloaded. Cluster installation is still in-progress.', + )} +
+
+ + {consoleUrl && ( + + )} + + +
+
+ ); +}; + +export default SingleClusterFinalizerPage; diff --git a/libs/locales/lib/en/translation.json b/libs/locales/lib/en/translation.json index f5dc9c123f..f7f634d112 100644 --- a/libs/locales/lib/en/translation.json +++ b/libs/locales/lib/en/translation.json @@ -27,6 +27,7 @@ "ai:{{operatorsCountString}} installed": "{{operatorsCountString}} installed", "ai:{{selectedAgentsCount}} host selected out of {{matchingAgentsCount}} matching.": "{{selectedAgentsCount}} host selected out of {{matchingAgentsCount}} identified.", "ai:{{selectedAgentsCount}} host selected out of {{matchingAgentsCount}} matching._plural": "{{selectedAgentsCount}} hosts selected out of {{matchingAgentsCount}} identified.", + "ai:* If you close this browser window, the webconsole URL can be found also inside the credentials file you have downloaded. Cluster installation is still in-progress.": "* If you close this browser window, the webconsole URL can be found also inside the credentials file you have downloaded. Cluster installation is still in-progress.", "ai:This IP will be allocated by the DHCP server": "This IP address is allocated by the DHCP server.", "ai:1 (Single Node OpenShift - not highly available cluster)": "1 (Single Node OpenShift - not highly available cluster)", "ai:1-{{count}} characters": "1-{{count}} characters", @@ -160,6 +161,7 @@ "ai:Click the Add host button.": "Click the Add host button.", "ai:Click the Add host button._plural": "Click the Add hosts button.", "ai:Click the Add hosts button.": "Click the Add hosts button.", + "ai:Click the webconsole URL below to check if it is up and running.": "Click the webconsole URL below to check if it is up and running.", "ai:Close": "Close", "ai:Cluster": "Cluster", "ai:Cluster address": "Cluster address", @@ -172,6 +174,7 @@ "ai:Cluster Events": "Cluster Events", "ai:Cluster hosts": "Cluster hosts", "ai:Cluster installation failed": "Cluster installation failed", + "ai:Cluster installation is still in-progress.": "Cluster installation is still in-progress.", "ai:Cluster installation process": "Cluster installation process", "ai:Cluster installation was cancelled": "Cluster installation was cancelled.", "ai:Cluster must have at least 3 hosts.": "Cluster must have at least 3 hosts.", diff --git a/libs/ui-lib/lib/common/components/clusterDetail/index.ts b/libs/ui-lib/lib/common/components/clusterDetail/index.ts index 39110c9f17..8121626408 100644 --- a/libs/ui-lib/lib/common/components/clusterDetail/index.ts +++ b/libs/ui-lib/lib/common/components/clusterDetail/index.ts @@ -3,3 +3,4 @@ export { default as ClusterProgress } from './ClusterProgress'; export { default as ClusterCredentials } from './ClusterCredentials'; export { default as KubeconfigDownload } from './KubeconfigDownload'; export { default as PostInstallAlert } from './PostInstallAlert'; +export { TroubleshootingOpenshiftConsoleButton } from './ConsoleModal'; diff --git a/libs/ui-lib/lib/ocm/components/clusterDetail/RebootNodeZeroModal.css b/libs/ui-lib/lib/ocm/components/clusterDetail/RebootNodeZeroModal.css deleted file mode 100644 index f66a7286e5..0000000000 --- a/libs/ui-lib/lib/ocm/components/clusterDetail/RebootNodeZeroModal.css +++ /dev/null @@ -1,7 +0,0 @@ -.ai-reboot-modal .detail-list dt { - margin-top: var(--pf-v5-global--spacer--lg); -} - -.ai-reboot-modal__item { - margin-top: var(--pf-v5-global--spacer--lg); -} diff --git a/libs/ui-lib/lib/ocm/components/clusterDetail/RebootNodeZeroModal.tsx b/libs/ui-lib/lib/ocm/components/clusterDetail/RebootNodeZeroModal.tsx deleted file mode 100644 index bfd2f37a36..0000000000 --- a/libs/ui-lib/lib/ocm/components/clusterDetail/RebootNodeZeroModal.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import React from 'react'; -import { Button, Checkbox, Modal, ModalVariant, Text, TextContent } from '@patternfly/react-core'; - -import { useClusterStatusVarieties } from './ClusterDetailStatusVarieties'; -import { KubeconfigDownload, ClusterCredentials } from '../../../common'; - -import './RebootNodeZeroModal.css'; -import { Cluster } from '@openshift-assisted/types/assisted-installer-service'; - -// TODO(mlibra): Following will be reimplemented based on future decisions in https://issues.redhat.com/browse/AGENT-522 -export const RebootNodeZeroModal: React.FC<{ cluster: Cluster }> = ({ cluster }) => { - const [rebootConfirmed, setRebootCofirmed] = React.useState(false); - const clusterVarieties = useClusterStatusVarieties(cluster); - const { credentials, credentialsError, fetchCredentials } = clusterVarieties; - - const onReboot = () => { - // console.error('onReboot handler to be implemented'); - // TODO(mlibra): Make HTTP Rest call to the assisted-service to restart the node, such endpoint is not yet implemented - }; - - // Do not merge, development only: - // credentials = credentials || { - // username: 'mock-user', - // password: 'mock-password', - // consoleUrl: 'https://www.google.com/search?q=mock', - // }; - - return ( - - Reboot - , - ]} - > - - - This node is about to reboot. Make sure you have downloaded the kubeconfig before you - proceed to reboot. - - - - - setRebootCofirmed(!rebootConfirmed)} - id="checkbox-confirm-reboot" - name="confirm-reboot" - /> - - ); -}; diff --git a/libs/ui-lib/lib/ocm/components/clusters/ClusterPage.tsx b/libs/ui-lib/lib/ocm/components/clusters/ClusterPage.tsx index e24f6188a1..97ffe7238a 100644 --- a/libs/ui-lib/lib/ocm/components/clusters/ClusterPage.tsx +++ b/libs/ui-lib/lib/ocm/components/clusters/ClusterPage.tsx @@ -177,9 +177,6 @@ const ClusterPageGeneric = ({ openshiftVersion={cluster.openshiftVersion} platformType={cluster.platform?.type} > - {/* TODO(mlibra): Will be reworked within https://issues.redhat.com/browse/AGENT-522 - - */} {getContent(cluster, infraEnv)} {uiState === ResourceUIState.POLLING_ERROR && } {uiState === ResourceUIState.UPDATE_ERROR && }