Add interactive roadmap error handling and loading
This commit is contained in:
26
components/roadmap/roadmap-error.tsx
Normal file
26
components/roadmap/roadmap-error.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { RoadmapType } from '../../lib/roadmap';
|
||||||
|
import { Container, Heading, Link, Text } from '@chakra-ui/react';
|
||||||
|
import siteConfig from '../../content/site.json';
|
||||||
|
|
||||||
|
type RoadmapProps = {
|
||||||
|
roadmap: RoadmapType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function RoadmapError(props: RoadmapProps) {
|
||||||
|
const { roadmap } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container
|
||||||
|
bg={'red.600'}
|
||||||
|
maxW={'container.md'}
|
||||||
|
position="relative"
|
||||||
|
mt="50px"
|
||||||
|
p='20px'
|
||||||
|
rounded='5px'
|
||||||
|
color='white'
|
||||||
|
>
|
||||||
|
<Heading mb='4px' size='md'>Oops! There's an error</Heading>
|
||||||
|
<Text>Try refreshing or <Link target='_blank' fontWeight={700} textDecoration={'underline'} fontSize='14px' href={siteConfig.url.issue}>report a bug</Link> and use the <Link fontWeight={700} textDecoration={'underline'} href={`/${roadmap.id}`}>non-interactive version</Link></Text>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
20
components/roadmap/roadmap-loader.tsx
Normal file
20
components/roadmap/roadmap-loader.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { Container, Spinner } from '@chakra-ui/react';
|
||||||
|
|
||||||
|
export function RoadmapLoader() {
|
||||||
|
return (
|
||||||
|
<Container
|
||||||
|
maxW={'container.md'}
|
||||||
|
position="relative"
|
||||||
|
mt="60px"
|
||||||
|
textAlign="center"
|
||||||
|
>
|
||||||
|
<Spinner
|
||||||
|
thickness="7px"
|
||||||
|
speed="0.65s"
|
||||||
|
emptyColor="gray.200"
|
||||||
|
color="gray.500"
|
||||||
|
size="xl"
|
||||||
|
/>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
@@ -1,52 +1,33 @@
|
|||||||
import { Box, Container, Flex, Heading, Spinner, Text } from '@chakra-ui/react';
|
import { useFetch } from 'use-http';
|
||||||
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
import { Box, Container } from '@chakra-ui/react';
|
||||||
import { GlobalHeader } from '../../components/global-header';
|
import { GlobalHeader } from '../../components/global-header';
|
||||||
import { OpensourceBanner } from '../../components/opensource-banner';
|
import { OpensourceBanner } from '../../components/opensource-banner';
|
||||||
import { UpdatesBanner } from '../../components/updates-banner';
|
import { UpdatesBanner } from '../../components/updates-banner';
|
||||||
import { Footer } from '../../components/footer';
|
import { Footer } from '../../components/footer';
|
||||||
import { getAllRoadmaps, getRoadmapById, RoadmapType } from '../../lib/roadmap';
|
import { getAllRoadmaps, getRoadmapById, RoadmapType } from '../../lib/roadmap';
|
||||||
import Helmet from '../../components/helmet';
|
import Helmet from '../../components/helmet';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
|
||||||
import { wireframeJSONToSVG } from '../../lib/renderer';
|
import { wireframeJSONToSVG } from '../../lib/renderer';
|
||||||
import { RoadmapPageHeader } from '../../components/roadmap/roadmap-page-header';
|
import { RoadmapPageHeader } from '../../components/roadmap/roadmap-page-header';
|
||||||
import { ContentDrawer } from '../../components/roadmap/content-drawer';
|
import { ContentDrawer } from '../../components/roadmap/content-drawer';
|
||||||
import { useFetch } from 'use-http';
|
import { RoadmapError } from '../../components/roadmap/roadmap-error';
|
||||||
import { Simulate } from 'react-dom/test-utils';
|
import { RoadmapLoader } from '../../components/roadmap/roadmap-loader';
|
||||||
import load = Simulate.load;
|
|
||||||
|
|
||||||
type RoadmapProps = {
|
type RoadmapProps = {
|
||||||
roadmap: RoadmapType;
|
roadmap: RoadmapType;
|
||||||
};
|
};
|
||||||
|
|
||||||
function RoadmapLoader() {
|
|
||||||
return (
|
|
||||||
<Container
|
|
||||||
maxW={'container.md'}
|
|
||||||
position="relative"
|
|
||||||
mt="60px"
|
|
||||||
textAlign="center"
|
|
||||||
>
|
|
||||||
<Spinner
|
|
||||||
thickness="7px"
|
|
||||||
speed="0.65s"
|
|
||||||
emptyColor="gray.200"
|
|
||||||
color="gray.500"
|
|
||||||
size="xl"
|
|
||||||
/>
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function RoadmapRenderer(props: RoadmapProps) {
|
function RoadmapRenderer(props: RoadmapProps) {
|
||||||
const { roadmap } = props;
|
const { roadmap } = props;
|
||||||
|
|
||||||
const { loading: isLoading, error, get } = useFetch();
|
const { loading: isLoading, error: hasErrorLoading, get } = useFetch();
|
||||||
|
|
||||||
const roadmapRef = useRef(null);
|
const roadmapRef = useRef(null);
|
||||||
|
|
||||||
const [isRendering, setIsRendering] = useState(false);
|
const [isRendering, setIsRendering] = useState(false);
|
||||||
const [roadmapJson, setRoadmapJson] = useState(null);
|
const [roadmapJson, setRoadmapJson] = useState(null);
|
||||||
const [groupId, setGroupId] = useState('');
|
const [groupId, setGroupId] = useState('');
|
||||||
const [hasError, setHasError] = useState(false);
|
const [hasErrorRendering, setHasErrorRendering] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
get(`/project/${roadmap.id}.json`)
|
get(`/project/${roadmap.id}.json`)
|
||||||
@@ -55,7 +36,7 @@ function RoadmapRenderer(props: RoadmapProps) {
|
|||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
setHasError(true);
|
setHasErrorRendering(true);
|
||||||
});
|
});
|
||||||
}, [get, roadmap.id]);
|
}, [get, roadmap.id]);
|
||||||
|
|
||||||
@@ -113,13 +94,17 @@ function RoadmapRenderer(props: RoadmapProps) {
|
|||||||
container.appendChild(svgElement);
|
container.appendChild(svgElement);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
setHasError(true);
|
setHasErrorRendering(true);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
setIsRendering(false);
|
setIsRendering(false);
|
||||||
});
|
});
|
||||||
}, [roadmapJson]);
|
}, [roadmapJson]);
|
||||||
|
|
||||||
|
if (hasErrorLoading || hasErrorRendering) {
|
||||||
|
return <RoadmapError roadmap={roadmap} />
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container maxW={'container.lg'} position="relative">
|
<Container maxW={'container.lg'} position="relative">
|
||||||
{(isLoading || isRendering) && <RoadmapLoader />}
|
{(isLoading || isRendering) && <RoadmapLoader />}
|
||||||
|
Reference in New Issue
Block a user