Implemented loading screen state accross app.

Signed-off-by: Raul Kele <raulkeleblk@gmail.com>
This commit is contained in:
Raul Kele 2022-10-10 14:21:01 +03:00
parent 2a3320fb64
commit dce87afba9
10 changed files with 454 additions and 378 deletions

View File

@ -18,7 +18,10 @@
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
animation: bounce 1s;
animation-direction: alternate;
animation-timing-function: cubic-bezier(.5, 0.05, 1, .5);
animation-iteration-count: infinite;
}
}
@ -45,3 +48,26 @@
transform: rotate(360deg);
}
}
@-webkit-keyframes bounce {
from {
transform: translate3d(0, 0, 0);
}
to {
transform: translate3d(0, 50px, 0);
}
}
@keyframes bounce {
from {
transform: translate3d(0, 0, 0);
}
to {
transform: translate3d(0, 50px, 0);
}
}
.bounce {
-webkit-animation-name: bounce;
animation-name: bounce;
}

View File

@ -9,6 +9,7 @@ import makeStyles from '@mui/styles/makeStyles';
import { Link } from 'react-router-dom';
import { host } from '../host';
import Monitor from '../assets/Monitor.png';
import Loading from './Loading';
const useStyles = makeStyles(() => ({
card: {
@ -69,9 +70,10 @@ function DependsOn(props) {
const [images, setImages] = useState([]);
const { name } = props;
const classes = useStyles();
// const [isLoaded, setIsLoaded] = useState(false);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
setIsLoading(true);
api
.get(`${host()}${endpoints.dependsOnForImage(name)}`)
.then((response) => {
@ -79,29 +81,16 @@ function DependsOn(props) {
let images = response.data.data.BaseImageList;
setImages(images);
}
setIsLoading(false);
})
.catch((e) => {
console.error(e);
setIsLoading(false);
});
}, []);
return (
<div data-testid="depends-on-container">
<Typography
variant="h4"
gutterBottom
component="div"
align="left"
className={classes.title}
style={{ color: 'rgba(0, 0, 0, 0.87)', fontSize: '1.5rem', fontWeight: '600', paddingTop: '0.5rem' }}
>
Depends On
</Typography>
<Divider
variant="fullWidth"
sx={{ margin: '5% 0% 5% 0%', background: 'rgba(0, 0, 0, 0.38)', height: '0.00625rem', width: '100%' }}
/>
{images?.length ? (
const renderDependencies = () => {
return images?.length ? (
<Card className={classes.card} raised>
<CardContent>
<Typography className={classes.content}>
@ -120,7 +109,26 @@ function DependsOn(props) {
<img src={Monitor} alt="Monitor" className={classes.monitor}></img>
<Typography className={classes.none}> Nothing found </Typography>
</div>
)}
);
};
return (
<div data-testid="depends-on-container">
<Typography
variant="h4"
gutterBottom
component="div"
align="left"
className={classes.title}
style={{ color: 'rgba(0, 0, 0, 0.87)', fontSize: '1.5rem', fontWeight: '600', paddingTop: '0.5rem' }}
>
Depends On
</Typography>
<Divider
variant="fullWidth"
sx={{ margin: '5% 0% 5% 0%', background: 'rgba(0, 0, 0, 0.38)', height: '0.00625rem', width: '100%' }}
/>
{isLoading ? <Loading /> : renderDependencies()}
</div>
);
}

View File

@ -72,6 +72,7 @@ function Explore() {
};
useEffect(() => {
setIsLoading(true);
api
.get(`${host()}${endpoints.globalSearch({ searchQuery: search, filter: buildFilterQuery() })}`)
.then((response) => {
@ -89,10 +90,6 @@ function Explore() {
});
}, [search, queryParams, imageFilters, osFilters, archFilters]);
useEffect(() => {
setIsLoading(false);
}, []);
const renderRepoCards = () => {
return (
exploreData &&
@ -148,7 +145,9 @@ function Explore() {
return (
<Container maxWidth="lg">
{isLoading && <Loading />}
{isLoading ? (
<Loading />
) : (
<Grid container className={classes.gridWrapper}>
<Grid container item xs={12}>
<Grid item xs={0}></Grid>
@ -189,6 +188,7 @@ function Explore() {
</Grid>
</Grid>
</Grid>
)}
</Container>
);
}

View File

@ -10,6 +10,7 @@ import makeStyles from '@mui/styles/makeStyles';
import { host } from '../host';
import Monitor from '../assets/Monitor.png';
import { isEmpty } from 'lodash';
import Loading from './Loading';
const useStyles = makeStyles(() => ({
card: {
@ -141,6 +142,35 @@ function HistoryLayers(props) {
}
}, [name]);
const renderHistoryData = () => {
return (
historyData && (
<Card className={classes.card} raised>
<CardContent className={classes.content}>
<Grid item xs={11}>
<Stack sx={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between' }}>
<Typography variant="body1" align="left" className={classes.title}>
Command
</Typography>
<Typography variant="body1" align="left" className={classes.values}>
{transform.formatBytes(historyData[selectedIndex].Layer?.Size)}
</Typography>
</Stack>
</Grid>
<Typography variant="body1" align="left" className={classes.title} sx={{ backgroundColor: '#F7F7F7' }}>
{historyData[selectedIndex].HistoryDescription?.CreatedBy}
</Typography>
{!historyData[selectedIndex].HistoryDescription?.EmptyLayer ? (
<Typography data-testid="hash-typography">#: {historyData[selectedIndex].Layer?.Digest}</Typography>
) : (
<Typography data-testid="no-hash-typography"></Typography>
)}
</CardContent>
</Card>
)
);
};
return (
<div>
<Typography
@ -181,30 +211,7 @@ function HistoryLayers(props) {
</div>
)}
{isLoaded && historyData && (
<Card className={classes.card} raised>
<CardContent className={classes.content}>
<Grid item xs={11}>
<Stack sx={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between' }}>
<Typography variant="body1" align="left" className={classes.title}>
Command
</Typography>
<Typography variant="body1" align="left" className={classes.values}>
{transform.formatBytes(historyData[selectedIndex].Layer?.Size)}
</Typography>
</Stack>
</Grid>
<Typography variant="body1" align="left" className={classes.title} sx={{ backgroundColor: '#F7F7F7' }}>
{historyData[selectedIndex].HistoryDescription?.CreatedBy}
</Typography>
{!historyData[selectedIndex].HistoryDescription?.EmptyLayer ? (
<Typography data-testid="hash-typography">#: {historyData[selectedIndex].Layer?.Digest}</Typography>
) : (
<Typography data-testid="no-hash-typography"></Typography>
)}
</CardContent>
</Card>
)}
{!isLoaded ? <Loading /> : renderHistoryData()}
</div>
);
}

View File

@ -6,6 +6,7 @@ import React, { useEffect, useState } from 'react';
import PreviewCard from './PreviewCard';
import RepoCard from './RepoCard';
import { mapToRepo } from 'utilities/objectModels';
import Loading from './Loading';
const useStyles = makeStyles(() => ({
gridWrapper: {
@ -61,11 +62,13 @@ const useStyles = makeStyles(() => ({
}));
function Home({ data, updateData }) {
// const [isLoading, setIsLoading] = useState(true);
const [isLoading, setIsLoading] = useState(true);
const [homeData, setHomeData] = useState([]);
const classes = useStyles();
useEffect(() => {
window.scrollTo(0, 0);
setIsLoading(true);
api
.get(`${host()}${endpoints.repoList}`)
.then((response) => {
@ -75,7 +78,7 @@ function Home({ data, updateData }) {
return mapToRepo(responseRepo);
});
updateData(repoData);
// setIsLoading(false);
setIsLoading(false);
}
})
.catch((e) => {
@ -149,6 +152,10 @@ function Home({ data, updateData }) {
};
return (
<>
{isLoading ? (
<Loading />
) : (
<Stack spacing={4} alignItems="center" className={classes.gridWrapper}>
<Grid container item xs={12} sx={{ mt: 2, mb: 1 }} justifyContent="center">
<Stack sx={{ display: 'inline' }} direction="row" justifyContent="center" spacing={1}>
@ -174,6 +181,8 @@ function Home({ data, updateData }) {
</Typography>
{renderRecentlyUpdated()}
</Stack>
)}
</>
);
}

View File

@ -9,6 +9,7 @@ import makeStyles from '@mui/styles/makeStyles';
import { Link } from 'react-router-dom';
import { host } from '../host';
import Monitor from '../assets/Monitor.png';
import Loading from './Loading';
const useStyles = makeStyles(() => ({
card: {
@ -69,9 +70,10 @@ function IsDependentOn(props) {
const [images, setImages] = useState([]);
const { name } = props;
const classes = useStyles();
//const [isLoaded, setIsLoaded] = useState(false);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
setIsLoading(true);
api
.get(`${host()}${endpoints.isDependentOnForImage(name)}`)
.then((response) => {
@ -79,32 +81,16 @@ function IsDependentOn(props) {
let images = response.data.data.DerivedImageList;
setImages(images);
}
setIsLoading(false);
})
.catch((e) => {
console.error(e);
//setImages([]);
setIsLoading(false);
});
//setIsLoaded(true);
}, []);
return (
<div>
<Typography
variant="h4"
gutterBottom
component="div"
align="left"
className={classes.title}
style={{ color: 'rgba(0, 0, 0, 0.87)', fontSize: '1.5rem', fontWeight: '600', paddingTop: '0.5rem' }}
>
Is Dependent On
</Typography>
<Divider
variant="fullWidth"
sx={{ margin: '5% 0% 5% 0%', background: 'rgba(0, 0, 0, 0.38)', height: '0.00625rem', width: '100%' }}
/>
{images?.length ? (
const renderDependents = () => {
return images?.length ? (
<Card className={classes.card} raised>
<CardContent>
<Typography className={classes.content}>
@ -123,7 +109,26 @@ function IsDependentOn(props) {
<img src={Monitor} alt="Monitor" className={classes.monitor}></img>
<Typography className={classes.none}> Nothing found </Typography>
</div>
)}
);
};
return (
<div>
<Typography
variant="h4"
gutterBottom
component="div"
align="left"
className={classes.title}
style={{ color: 'rgba(0, 0, 0, 0.87)', fontSize: '1.5rem', fontWeight: '600', paddingTop: '0.5rem' }}
>
Is Dependent On
</Typography>
<Divider
variant="fullWidth"
sx={{ margin: '5% 0% 5% 0%', background: 'rgba(0, 0, 0, 0.38)', height: '0.00625rem', width: '100%' }}
/>
{isLoading ? <Loading /> : renderDependents()}
</div>
);
}

View File

@ -4,8 +4,8 @@ import logo from '../assets/Zot2.svg';
const useStyles = makeStyles(() => ({
wrapper: {
position: 'fixed',
top: 0,
position: 'relative',
top: '10%',
left: 0,
right: 0,
bottom: 0,
@ -13,9 +13,8 @@ const useStyles = makeStyles(() => ({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
marginTop: 6,
paddingRight: 20,
backgroundColor: 'rgba(0, 0, 0, 0.3)'
width: '100%',
height: '100%'
}
}));

View File

@ -33,6 +33,7 @@ import repocube3 from '../assets/repocube-3.png';
import repocube4 from '../assets/repocube-4.png';
import { TabContext, TabList, TabPanel } from '@mui/lab';
import RepoDetailsMetadata from './RepoDetailsMetadata';
import Loading from './Loading';
// @ts-ignore
const useStyles = makeStyles(() => ({
@ -132,7 +133,7 @@ const randomImage = () => {
function RepoDetails() {
const [repoDetailData, setRepoDetailData] = useState({});
// @ts-ignore
//const [isLoading, setIsLoading] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const [selectedTab, setSelectedTab] = useState('Overview');
// get url param from <Route here (i.e. image name)
@ -150,8 +151,6 @@ function RepoDetails() {
images: repoInfo.Images,
lastUpdated: repoInfo.Summary?.LastUpdated,
size: repoInfo.Summary?.Size,
//latestDigest: repoInfo.Summary?.NewestImage.Digest,
//layers: repoInfo.Summary?.NewestImage.Layers,
platforms: repoInfo.Summary?.Platforms,
vendors: repoInfo.Summary?.Vendors,
newestTag: repoInfo.Summary?.NewestImage,
@ -162,12 +161,13 @@ function RepoDetails() {
overview: repoInfo.Summary?.NewestImage.Documentation
};
setRepoDetailData(imageData);
//setIsLoading(false);
}
setIsLoading(false);
})
.catch((e) => {
console.error(e);
setRepoDetailData({});
setIsLoading(false);
});
}, [name]);
//function that returns a random element from an array
@ -261,6 +261,10 @@ function RepoDetails() {
// };
return (
<>
{isLoading ? (
<Loading />
) : (
<div className={classes.pageWrapper}>
<Card className={classes.cardRoot}>
<CardContent>
@ -386,6 +390,8 @@ function RepoDetails() {
</CardContent>
</Card>
</div>
)}
</>
);
}

View File

@ -20,6 +20,7 @@ import git from '../assets/Git.png';
// styling
import { makeStyles } from '@mui/styles';
import { Card, CardContent } from '@mui/material';
import Loading from './Loading';
const useStyles = makeStyles(() => ({
cardContainer: {
@ -105,11 +106,14 @@ export default function SignIn({ isAuthEnabled, setIsAuthEnabled, isLoggedIn, se
const [password, setPassword] = useState(null);
const [requestProcessing, setRequestProcessing] = useState(false);
const [requestError, setRequestError] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const navigate = useNavigate();
const classes = useStyles();
useEffect(() => {
setIsLoading(true);
if (isAuthEnabled && isLoggedIn) {
setIsLoading(false);
navigate('/home');
} else {
api
@ -118,11 +122,13 @@ export default function SignIn({ isAuthEnabled, setIsAuthEnabled, isLoggedIn, se
if (response.status === 200) {
setIsAuthEnabled(false);
setIsLoggedIn(true);
setIsLoading(false);
navigate('/home');
}
})
.catch(() => {
setIsAuthEnabled(true);
setIsLoading(false);
});
}
}, []);
@ -190,6 +196,9 @@ export default function SignIn({ isAuthEnabled, setIsAuthEnabled, isLoggedIn, se
return (
<Box className={classes.cardContainer} data-testid="signin-container">
{isLoading ? (
<Loading />
) : (
<Card className={classes.loginCard}>
<CardContent className={classes.loginCardContent}>
<CssBaseline />
@ -316,6 +325,7 @@ export default function SignIn({ isAuthEnabled, setIsAuthEnabled, isLoggedIn, se
<TermsOfService sx={{ mt: 2, mb: 4 }} />
</CardContent>
</Card>
)}
</Box>
);
}

View File

@ -13,6 +13,7 @@ import PestControlIcon from '@mui/icons-material/PestControl';
import Monitor from '../assets/Monitor.png';
import { isEmpty } from 'lodash';
import { Link } from 'react-router-dom';
import Loading from './Loading';
const useStyles = makeStyles(() => ({
card: {
@ -258,10 +259,11 @@ function VulnerabilitiyCard(props) {
function VulnerabilitiesDetails(props) {
const classes = useStyles();
const [cveData, setCveData] = useState({});
// const [isLoading, setIsLoading] = useState(true);
const [isLoading, setIsLoading] = useState(true);
const { name } = props;
useEffect(() => {
setIsLoading(true);
api
.get(`${host()}${endpoints.vulnerabilitiesForRepo(name)}`)
.then((response) => {
@ -271,7 +273,7 @@ function VulnerabilitiesDetails(props) {
cveList: cveInfo?.CVEList
};
setCveData(cveListData);
// setIsLoading(false);
setIsLoading(false);
}
})
.catch((e) => {
@ -323,9 +325,13 @@ function VulnerabilitiesDetails(props) {
width: '100%'
}}
/>
{renderCVEs(
{isLoading ? (
<Loading />
) : (
renderCVEs(
// @ts-ignore
cveData?.cveList
)
)}
</div>
);