From 2b7a86dc44356b2fb74dc8039a58589ff5015e6a Mon Sep 17 00:00:00 2001 From: Vladyslav Palyvoda Date: Wed, 20 Nov 2024 14:20:14 +0200 Subject: [PATCH] feat: Handle 404 pages (#493) --- src/components/ErrorContent/index.tsx | 25 +++++++++++++++++++- src/pages/cdpipeline-details/view.tsx | 34 ++++++++++++++++++++------- src/pages/component-details/view.tsx | 22 ++++++++++++++--- src/pages/pipeline-details/view.tsx | 31 +++++++++++++++++++----- src/pages/stage-details/view.tsx | 30 +++++++++++++++-------- 5 files changed, 113 insertions(+), 29 deletions(-) diff --git a/src/components/ErrorContent/index.tsx b/src/components/ErrorContent/index.tsx index 48c95a0a..cbf9b739 100644 --- a/src/components/ErrorContent/index.tsx +++ b/src/components/ErrorContent/index.tsx @@ -61,8 +61,31 @@ export const ErrorContent = ({ ); + case 404: + return ( + + + + + Sorry. The requested resource was not found. + + + More details + + + + ); default: - return 'Not Found'; + return 'Oops! Something went wrong. Please try again later.'; } }, [error?.status, orientation, theme.typography]); diff --git a/src/pages/cdpipeline-details/view.tsx b/src/pages/cdpipeline-details/view.tsx index b197b729..d84b1a9e 100644 --- a/src/pages/cdpipeline-details/view.tsx +++ b/src/pages/cdpipeline-details/view.tsx @@ -2,6 +2,8 @@ import { Router } from '@kinvolk/headlamp-plugin/lib'; import { Grid, Typography, useTheme } from '@mui/material'; import React from 'react'; import { useParams } from 'react-router-dom'; +import { ErrorContent } from '../../components/ErrorContent'; +import { LoadingWrapper } from '../../components/LoadingWrapper'; import { PageWrapper } from '../../components/PageWrapper'; import { QuickLink } from '../../components/QuickLink'; import { Section } from '../../components/Section'; @@ -29,6 +31,27 @@ export const PageView = () => { const { data: QuickLinksURLS } = useQuickLinksURLsQuery(namespace); const permissions = useTypedPermissions(); + const resourceIsLoaded = !CDPipeline.isLoading && !CDPipeline.error; + + const renderPageContent = React.useCallback(() => { + if (CDPipeline.error) { + return ; + } + + return ( + + + + + + + + + + + ); + }, [CDPipeline.error, CDPipeline.isLoading]); + return ( { isTextButton /> - {!CDPipeline.isLoading && ( + {resourceIsLoaded && ( <> { title={{name}} description={`Defines the sequence and logic for promoting artifacts through various environments. It maps out an artifact's progression path from development to production.`} > - - - - - - - - + {renderPageContent()} ); diff --git a/src/pages/component-details/view.tsx b/src/pages/component-details/view.tsx index ce5a4fe9..6337cff6 100644 --- a/src/pages/component-details/view.tsx +++ b/src/pages/component-details/view.tsx @@ -2,6 +2,8 @@ import { Router } from '@kinvolk/headlamp-plugin/lib'; import { Stack } from '@mui/material'; import React from 'react'; import { useParams } from 'react-router-dom'; +import { ErrorContent } from '../../components/ErrorContent'; +import { LoadingWrapper } from '../../components/LoadingWrapper'; import { PageWrapper } from '../../components/PageWrapper'; import { QuickLink } from '../../components/QuickLink'; import { Section } from '../../components/Section'; @@ -37,6 +39,21 @@ export const PageView = () => { const { activeTab, handleChangeTab } = useTabsContext(); + const resourceIsLoaded = !component.isLoading && !component.error; + + const renderPageContent = React.useCallback(() => { + if (component.error) { + return ; + } + + return ( + + + + + ); + }, [activeTab, component.error, component.isLoading, handleChangeTab, tabs]); + return ( { ]} headerSlot={ <> - {!!component.data && ( + {resourceIsLoaded && (
{ title={name} description={'Review your codebases, monitor their status, and execute build pipelines.'} > - - + {renderPageContent()} ); diff --git a/src/pages/pipeline-details/view.tsx b/src/pages/pipeline-details/view.tsx index 8eb8ab1e..3669c499 100644 --- a/src/pages/pipeline-details/view.tsx +++ b/src/pages/pipeline-details/view.tsx @@ -1,6 +1,7 @@ import { Router } from '@kinvolk/headlamp-plugin/lib'; import React from 'react'; import { useParams } from 'react-router-dom'; +import { ErrorContent } from '../../components/ErrorContent'; import { LoadingWrapper } from '../../components/LoadingWrapper'; import { PageWrapper } from '../../components/PageWrapper'; import { Section } from '../../components/Section'; @@ -30,6 +31,28 @@ export const PageView = () => { const tabs = useTabs(); const { activeTab, handleChangeTab } = useTabsContext(); + const resourceIsLoaded = + !pipelineRun.isLoading && !pipelineRunDataIsLoading && !pipelineRun.error; + + const renderPageContent = React.useCallback(() => { + if (pipelineRun.error) { + return ; + } + + return ( + + + + ); + }, [ + pipelineRun.error, + pipelineRun.isLoading, + pipelineRunDataIsLoading, + tabs, + activeTab, + handleChangeTab, + ]); + return ( { ]} headerSlot={
- {!pipelineRun.isLoading && ( + {resourceIsLoaded && ( {
} > -
- - - -
+
{renderPageContent()}
); }; diff --git a/src/pages/stage-details/view.tsx b/src/pages/stage-details/view.tsx index c6074169..05cf8a03 100644 --- a/src/pages/stage-details/view.tsx +++ b/src/pages/stage-details/view.tsx @@ -1,7 +1,9 @@ import { Router } from '@kinvolk/headlamp-plugin/lib'; -import { Box, CircularProgress, Stack } from '@mui/material'; +import { Box, Stack } from '@mui/material'; import React from 'react'; import { useParams } from 'react-router-dom'; +import { ErrorContent } from '../../components/ErrorContent'; +import { LoadingWrapper } from '../../components/LoadingWrapper'; import { PageWrapper } from '../../components/PageWrapper'; import { QuickLink } from '../../components/QuickLink'; import { Section } from '../../components/Section'; @@ -28,7 +30,7 @@ export const PageView = () => { const { CDPipeline, stages, QuickLinks, QuickLinksURLs } = useDataContext(); const { - stage: { data: stage, isLoading: isStageLoading }, + stage: { data: stage, isLoading: isStageLoading, error: stageError }, } = useDynamicDataContext(); const grafanaQuickLink = @@ -53,6 +55,20 @@ export const PageView = () => { const { activeTab, handleChangeTab } = useTabsContext(); + const resourceIsLoaded = !isStageLoading && !stageError; + + const renderPageContent = React.useCallback(() => { + if (stageError) { + return ; + } + + return ( + + + + ); + }, [activeTab, handleChangeTab, isStageLoading, stageError, tabs]); + return ( { ]} headerSlot={ !isDataLoading && - !isStageLoading && ( + resourceIsLoaded && ( { 'Manage, deploy, test, and troubleshoot your applications across distinct Environments.' } > - {!isStageLoading ? ( - t.typography.pxToRem(20) }}> - - - ) : ( - - )} + {renderPageContent()} );