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,12 +81,37 @@ function DependsOn(props) {
let images = response.data.data.BaseImageList;
setImages(images);
}
setIsLoading(false);
})
.catch((e) => {
console.error(e);
setIsLoading(false);
});
}, []);
const renderDependencies = () => {
return images?.length ? (
<Card className={classes.card} raised>
<CardContent>
<Typography className={classes.content}>
{images.map((dependence, index) => {
return (
<Link key={index} className={classes.link} to={`/image/${encodeURIComponent(dependence.RepoName)}`}>
{dependence.RepoName}
</Link>
);
})}
</Typography>
</CardContent>
</Card>
) : (
<div>
<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
@ -101,26 +128,7 @@ function DependsOn(props) {
variant="fullWidth"
sx={{ margin: '5% 0% 5% 0%', background: 'rgba(0, 0, 0, 0.38)', height: '0.00625rem', width: '100%' }}
/>
{images?.length ? (
<Card className={classes.card} raised>
<CardContent>
<Typography className={classes.content}>
{images.map((dependence, index) => {
return (
<Link key={index} className={classes.link} to={`/image/${encodeURIComponent(dependence.RepoName)}`}>
{dependence.RepoName}
</Link>
);
})}
</Typography>
</CardContent>
</Card>
) : (
<div>
<img src={Monitor} alt="Monitor" className={classes.monitor}></img>
<Typography className={classes.none}> Nothing found </Typography>
</div>
)}
{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,47 +145,50 @@ function Explore() {
return (
<Container maxWidth="lg">
{isLoading && <Loading />}
<Grid container className={classes.gridWrapper}>
<Grid container item xs={12}>
<Grid item xs={0}></Grid>
<Grid item xs={12}>
<Stack direction="row" className={classes.resultsRow}>
<Typography variant="body2" className={classes.results}>
Results {exploreData.length}
</Typography>
{/* <FormControl sx={{m:'1', minWidth:"4.6875rem"}} className={classes.sortForm} size="small">
{isLoading ? (
<Loading />
) : (
<Grid container className={classes.gridWrapper}>
<Grid container item xs={12}>
<Grid item xs={0}></Grid>
<Grid item xs={12}>
<Stack direction="row" className={classes.resultsRow}>
<Typography variant="body2" className={classes.results}>
Results {exploreData.length}
</Typography>
{/* <FormControl sx={{m:'1', minWidth:"4.6875rem"}} className={classes.sortForm} size="small">
<InputLabel>Sort</InputLabel>
<Select label="Sort" value={sortFilter} onChange={handleSortChange} MenuProps={{disableScrollLock: true}}>
<MenuItem value='relevance'>Relevance</MenuItem>
</Select>
</FormControl> */}
</Stack>
</Grid>
</Grid>
<Grid container item xs={12} spacing={5} pt={1}>
<Grid item xs={3}>
{renderFilterCards()}
</Grid>
<Grid item xs={9}>
{!(exploreData && exploreData.length) ? (
<Grid container className={classes.nodataWrapper}>
<div style={{ marginTop: 20 }}>
<div style={{}}>
<Alert style={{ marginTop: 10, width: '100%' }} variant="outlined" severity="warning">
Looks like we don&apos;t have anything matching that search. Try searching something else.
</Alert>
</div>
</div>
</Grid>
) : (
<Stack direction="column" spacing={2}>
{renderRepoCards()}
</Stack>
)}
</Grid>
</Grid>
<Grid container item xs={12} spacing={5} pt={1}>
<Grid item xs={3}>
{renderFilterCards()}
</Grid>
<Grid item xs={9}>
{!(exploreData && exploreData.length) ? (
<Grid container className={classes.nodataWrapper}>
<div style={{ marginTop: 20 }}>
<div style={{}}>
<Alert style={{ marginTop: 10, width: '100%' }} variant="outlined" severity="warning">
Looks like we don&apos;t have anything matching that search. Try searching something else.
</Alert>
</div>
</div>
</Grid>
) : (
<Stack direction="column" spacing={2}>
{renderRepoCards()}
</Stack>
)}
</Grid>
</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,31 +152,37 @@ function Home({ data, updateData }) {
};
return (
<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}>
<Typography variant="h3" className={classes.title}>
Most popular
</Typography>
<Typography variant="h3" className={classes.titleRed}>
images
</Typography>
</Stack>
</Grid>
<Grid container spacing={1}>
{renderPreviewCards()}
</Grid>{' '}
<Grid></Grid>
{/* <Typography variant="h4" align="left" className={classes.sectionTitle}>
<>
{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}>
<Typography variant="h3" className={classes.title}>
Most popular
</Typography>
<Typography variant="h3" className={classes.titleRed}>
images
</Typography>
</Stack>
</Grid>
<Grid container spacing={1}>
{renderPreviewCards()}
</Grid>{' '}
<Grid></Grid>
{/* <Typography variant="h4" align="left" className={classes.sectionTitle}>
Bookmarks
</Typography>
{renderBookmarks()} */}
<Stack></Stack>
<Typography variant="h4" align="left" className={classes.sectionTitle}>
Recently updated repositories
</Typography>
{renderRecentlyUpdated()}
</Stack>
<Stack></Stack>
<Typography variant="h4" align="left" className={classes.sectionTitle}>
Recently updated repositories
</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,14 +81,37 @@ function IsDependentOn(props) {
let images = response.data.data.DerivedImageList;
setImages(images);
}
setIsLoading(false);
})
.catch((e) => {
console.error(e);
//setImages([]);
setIsLoading(false);
});
//setIsLoaded(true);
}, []);
const renderDependents = () => {
return images?.length ? (
<Card className={classes.card} raised>
<CardContent>
<Typography className={classes.content}>
{images.map((dependence, index) => {
return (
<Link key={index} to={`/image/${encodeURIComponent(dependence.RepoName)}`} className={classes.link}>
{dependence.RepoName}
</Link>
);
})}
</Typography>
</CardContent>
</Card>
) : (
<div>
<img src={Monitor} alt="Monitor" className={classes.monitor}></img>
<Typography className={classes.none}> Nothing found </Typography>
</div>
);
};
return (
<div>
<Typography
@ -103,27 +128,7 @@ function IsDependentOn(props) {
variant="fullWidth"
sx={{ margin: '5% 0% 5% 0%', background: 'rgba(0, 0, 0, 0.38)', height: '0.00625rem', width: '100%' }}
/>
{images?.length ? (
<Card className={classes.card} raised>
<CardContent>
<Typography className={classes.content}>
{images.map((dependence, index) => {
return (
<Link key={index} to={`/image/${encodeURIComponent(dependence.RepoName)}`} className={classes.link}>
{dependence.RepoName}
</Link>
);
})}
</Typography>
</CardContent>
</Card>
) : (
<div>
<img src={Monitor} alt="Monitor" className={classes.monitor}></img>
<Typography className={classes.none}> Nothing found </Typography>
</div>
)}
{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,100 +261,104 @@ function RepoDetails() {
// };
return (
<div className={classes.pageWrapper}>
<Card className={classes.cardRoot}>
<CardContent>
<Grid container className={classes.header}>
<Grid item xs={8}>
<Stack alignItems="center" direction="row" spacing={2}>
<CardMedia
classes={{
root: classes.media,
img: classes.avatar
}}
component="img"
image={randomImage()}
alt="icon"
/>
<Typography variant="h3" className={classes.repoName}>
{name}
</Typography>
{/* {vulnerabilityCheck()}
<>
{isLoading ? (
<Loading />
) : (
<div className={classes.pageWrapper}>
<Card className={classes.cardRoot}>
<CardContent>
<Grid container className={classes.header}>
<Grid item xs={8}>
<Stack alignItems="center" direction="row" spacing={2}>
<CardMedia
classes={{
root: classes.media,
img: classes.avatar
}}
component="img"
image={randomImage()}
alt="icon"
/>
<Typography variant="h3" className={classes.repoName}>
{name}
</Typography>
{/* {vulnerabilityCheck()}
{signatureCheck()} */}
{/* <BookmarkIcon sx={{color:"#52637A"}}/> */}
</Stack>
<Typography
pt={1}
sx={{ fontSize: 16, lineHeight: '1.5rem', color: 'rgba(0, 0, 0, 0.6)', paddingLeft: '4rem' }}
gutterBottom
align="left"
>
{
// @ts-ignore
repoDetailData?.title || 'N/A'
}
</Typography>
<Stack alignItems="center" sx={{ paddingLeft: '4rem' }} direction="row" spacing={2} pt={1}>
{platformChips()}
</Stack>
</Grid>
<Grid item xs={4}>
<Typography variant="body1" sx={{ color: '#52637A', fontSize: '1rem' }}>
Copy and pull to pull this image
</Typography>
<FormControl sx={{ m: 1, paddingLeft: '1.5rem' }} variant="outlined">
<OutlinedInput
// value={`Pull ${name}`}
value="N/A"
className={classes.inputForm}
sx={{ m: 1, width: '20.625rem', borderRadius: '0.5rem', color: '#14191F' }}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="copy"
edge="end"
onClick={() => navigator.clipboard.writeText(`Pull ${name}`)}
data-testid="pullcopy-btn"
>
<ContentCopyIcon />
</IconButton>
</InputAdornment>
}
aria-describedby="outlined-weight-helper-text"
inputProps={{
'aria-label': 'weight'
}}
/>
</FormControl>
</Grid>
</Grid>
<Grid container>
<Grid item xs={8} className={classes.tabs}>
<TabContext value={selectedTab}>
<Box>
<TabList
onChange={handleTabChange}
TabIndicatorProps={{ className: classes.selectedTab }}
sx={{ '& button.Mui-selected': { color: '#14191F', fontWeight: '600' } }}
{/* <BookmarkIcon sx={{color:"#52637A"}}/> */}
</Stack>
<Typography
pt={1}
sx={{ fontSize: 16, lineHeight: '1.5rem', color: 'rgba(0, 0, 0, 0.6)', paddingLeft: '4rem' }}
gutterBottom
align="left"
>
<Tab value="Overview" label="Overview" className={classes.tabContent} />
<Tab value="Tags" label="Tags" className={classes.tabContent} />
{/* <Tab value="Dependencies" label={`${dependencies || 0} Dependencies`} className={classes.tabContent}/>
{
// @ts-ignore
repoDetailData?.title || 'N/A'
}
</Typography>
<Stack alignItems="center" sx={{ paddingLeft: '4rem' }} direction="row" spacing={2} pt={1}>
{platformChips()}
</Stack>
</Grid>
<Grid item xs={4}>
<Typography variant="body1" sx={{ color: '#52637A', fontSize: '1rem' }}>
Copy and pull to pull this image
</Typography>
<FormControl sx={{ m: 1, paddingLeft: '1.5rem' }} variant="outlined">
<OutlinedInput
// value={`Pull ${name}`}
value="N/A"
className={classes.inputForm}
sx={{ m: 1, width: '20.625rem', borderRadius: '0.5rem', color: '#14191F' }}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="copy"
edge="end"
onClick={() => navigator.clipboard.writeText(`Pull ${name}`)}
data-testid="pullcopy-btn"
>
<ContentCopyIcon />
</IconButton>
</InputAdornment>
}
aria-describedby="outlined-weight-helper-text"
inputProps={{
'aria-label': 'weight'
}}
/>
</FormControl>
</Grid>
</Grid>
<Grid container>
<Grid item xs={8} className={classes.tabs}>
<TabContext value={selectedTab}>
<Box>
<TabList
onChange={handleTabChange}
TabIndicatorProps={{ className: classes.selectedTab }}
sx={{ '& button.Mui-selected': { color: '#14191F', fontWeight: '600' } }}
>
<Tab value="Overview" label="Overview" className={classes.tabContent} />
<Tab value="Tags" label="Tags" className={classes.tabContent} />
{/* <Tab value="Dependencies" label={`${dependencies || 0} Dependencies`} className={classes.tabContent}/>
<Tab value="Dependents" label={`${dependents || 0} Dependents`} className={classes.tabContent}/>
<Tab value="Vulnerabilities" label="Vulnerabilities" className={classes.tabContent}/>
<Tab value="6" label="Tab 6" className={classes.tabContent}/>
<Tab value="7" label="Tab 7" className={classes.tabContent}/>
<Tab value="8" label="Tab 8" className={classes.tabContent}/> */}
</TabList>
<Grid container>
<Grid item xs={12}>
<TabPanel value="Overview" className={classes.tabPanel}>
{renderOverview()}
</TabPanel>
<TabPanel value="Tags" className={classes.tabPanel}>
<Tags data={repoDetailData} />
</TabPanel>
{/* <TabPanel value="Dependencies" className={classes.tabPanel}>
</TabList>
<Grid container>
<Grid item xs={12}>
<TabPanel value="Overview" className={classes.tabPanel}>
{renderOverview()}
</TabPanel>
<TabPanel value="Tags" className={classes.tabPanel}>
<Tags data={repoDetailData} />
</TabPanel>
{/* <TabPanel value="Dependencies" className={classes.tabPanel}>
{renderDependencies()}
</TabPanel>
<TabPanel value="Dependents" className={classes.tabPanel}>
@ -363,29 +367,31 @@ function RepoDetails() {
<TabPanel value="Vulnerabilities" className={classes.tabPanel}>
{renderVulnerabilities()}
</TabPanel> */}
</Grid>
</Grid>
</Box>
</TabContext>
</Grid>
<Grid item xs={4} className={classes.metadata}>
<RepoDetailsMetadata
// @ts-ignore
weeklyDownloads={repoDetailData?.downloads}
// @ts-ignore
repoURL={repoDetailData?.source}
// @ts-ignore
lastUpdated={repoDetailData?.lastUpdated}
// @ts-ignore
size={repoDetailData?.size}
// @ts-ignore
latestTag={repoDetailData?.newestTag}
/>
</Grid>
</Grid>
</CardContent>
</Card>
</div>
</Grid>
</Grid>
</Box>
</TabContext>
</Grid>
<Grid item xs={4} className={classes.metadata}>
<RepoDetailsMetadata
// @ts-ignore
weeklyDownloads={repoDetailData?.downloads}
// @ts-ignore
repoURL={repoDetailData?.source}
// @ts-ignore
lastUpdated={repoDetailData?.lastUpdated}
// @ts-ignore
size={repoDetailData?.size}
// @ts-ignore
latestTag={repoDetailData?.newestTag}
/>
</Grid>
</Grid>
</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,132 +196,136 @@ export default function SignIn({ isAuthEnabled, setIsAuthEnabled, isLoggedIn, se
return (
<Box className={classes.cardContainer} data-testid="signin-container">
<Card className={classes.loginCard}>
<CardContent className={classes.loginCardContent}>
<CssBaseline />
<Typography align="left" className={classes.text} component="h1" variant="h4">
Sign in
</Typography>
<Typography align="left" className={classes.subtext} variant="body1" gutterBottom>
Welcome back! Please enter your details.
</Typography>
{isLoading ? (
<Loading />
) : (
<Card className={classes.loginCard}>
<CardContent className={classes.loginCardContent}>
<CssBaseline />
<Typography align="left" className={classes.text} component="h1" variant="h4">
Sign in
</Typography>
<Typography align="left" className={classes.subtext} variant="body1" gutterBottom>
Welcome back! Please enter your details.
</Typography>
<Box component="form" onSubmit={null} noValidate autoComplete="off" sx={{ mt: 1 }}>
<div>
<Button
<Box component="form" onSubmit={null} noValidate autoComplete="off" sx={{ mt: 1 }}>
<div>
<Button
fullWidth
variant="contained"
className={classes.button}
sx={{
mt: 3,
mb: 1,
background: '#161614',
'&:hover': {
backgroundColor: '#1565C0',
color: '#FFFFFF'
}
}}
>
{' '}
Continue with GitHub
<img src={git} alt="git logo" className={classes.gitLogo}></img>
</Button>
<Button
fullWidth
variant="contained"
className={classes.button}
sx={{
mt: 1,
mb: 1,
background: 'transparent',
color: '#52637A',
'&:hover': {
backgroundColor: '#1565C0',
color: '#FFFFFF'
}
}}
>
{' '}
Continue with Google
<img src={google} alt="google logo" className={classes.gitLogo}></img>
</Button>
</div>
<br></br>
<h2 className={classes.line}>
<span className={classes.lineSpan}>or</span>
</h2>
<TextField
margin="normal"
required
fullWidth
variant="contained"
className={classes.button}
sx={{
mt: 3,
mb: 1,
background: '#161614',
'&:hover': {
backgroundColor: '#1565C0',
color: '#FFFFFF'
}
}}
>
{' '}
Continue with GitHub
<img src={git} alt="git logo" className={classes.gitLogo}></img>
</Button>
<Button
id="username"
label="Username"
name="username"
className={classes.textField}
onInput={(e) => handleChange(e, 'username')}
error={usernameError != null}
helperText={usernameError}
/>
<TextField
margin="normal"
required
fullWidth
variant="contained"
className={classes.button}
sx={{
mt: 1,
mb: 1,
background: 'transparent',
color: '#52637A',
'&:hover': {
backgroundColor: '#1565C0',
color: '#FFFFFF'
}
}}
>
{' '}
Continue with Google
<img src={google} alt="google logo" className={classes.gitLogo}></img>
</Button>
</div>
<br></br>
<h2 className={classes.line}>
<span className={classes.lineSpan}>or</span>
</h2>
<TextField
margin="normal"
required
fullWidth
id="username"
label="Username"
name="username"
className={classes.textField}
onInput={(e) => handleChange(e, 'username')}
error={usernameError != null}
helperText={usernameError}
/>
<TextField
margin="normal"
required
fullWidth
name="password"
label="Enter password"
type="password"
id="password"
className={classes.textField}
onInput={(e) => handleChange(e, 'password')}
error={passwordError != null}
helperText={passwordError}
/>
{requestProcessing && <CircularProgress style={{ marginTop: 20 }} color="secondary" />}
{requestError && (
<Alert style={{ marginTop: 20 }} severity="error">
Authentication Failed. Please try again.
</Alert>
)}
<div>
<Button
fullWidth
variant="contained"
className={classes.button}
sx={{
mt: 3,
mb: 1,
background: '#1479FF',
'&:hover': {
backgroundColor: '#1565C0'
}
}}
onClick={handleClick}
>
{' '}
Continue
</Button>
<Button
fullWidth
variant="contained"
className={classes.button}
sx={{
mt: 1,
mb: 1,
background: 'transparent',
color: '#52637A',
'&:hover': {
backgroundColor: '#EFEFEF',
color: '#52637A'
}
}}
>
{' '}
Continue as guest
</Button>
</div>
</Box>
<TermsOfService sx={{ mt: 2, mb: 4 }} />
</CardContent>
</Card>
name="password"
label="Enter password"
type="password"
id="password"
className={classes.textField}
onInput={(e) => handleChange(e, 'password')}
error={passwordError != null}
helperText={passwordError}
/>
{requestProcessing && <CircularProgress style={{ marginTop: 20 }} color="secondary" />}
{requestError && (
<Alert style={{ marginTop: 20 }} severity="error">
Authentication Failed. Please try again.
</Alert>
)}
<div>
<Button
fullWidth
variant="contained"
className={classes.button}
sx={{
mt: 3,
mb: 1,
background: '#1479FF',
'&:hover': {
backgroundColor: '#1565C0'
}
}}
onClick={handleClick}
>
{' '}
Continue
</Button>
<Button
fullWidth
variant="contained"
className={classes.button}
sx={{
mt: 1,
mb: 1,
background: 'transparent',
color: '#52637A',
'&:hover': {
backgroundColor: '#EFEFEF',
color: '#52637A'
}
}}
>
{' '}
Continue as guest
</Button>
</div>
</Box>
<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(
// @ts-ignore
cveData?.cveList
{isLoading ? (
<Loading />
) : (
renderCVEs(
// @ts-ignore
cveData?.cveList
)
)}
</div>
);