Compare commits

..

7 Commits

12 changed files with 325 additions and 215 deletions

2
.env
View File

@ -2,4 +2,4 @@ REACT_APP_KC_URL=https://auth-dev.csi.wmi.amu.edu.pl/
REACT_APP_KC_REALM=gonito-dev REACT_APP_KC_REALM=gonito-dev
REACT_APP_KC_CLIENT_ID=gonito-dev-localhost REACT_APP_KC_CLIENT_ID=gonito-dev-localhost
REACT_APP_API=https://gonito.net/api REACT_APP_API=https://gonito-back-dev.csi.wmi.amu.edu.pl/api

View File

@ -116,7 +116,12 @@ const App = () => {
/> />
<Route <Route
path={`${CHALLENGE_PAGE}/:challengeId/howto`} path={`${CHALLENGE_PAGE}/:challengeId/howto`}
element={<Challenge section={2} />} element={
<Challenge
popUpMessageHandler={popUpMessageHandler}
section={2}
/>
}
/> />
<Route <Route
path={`${CHALLENGE_PAGE}/:challengeId/myentries`} path={`${CHALLENGE_PAGE}/:challengeId/myentries`}

View File

@ -1,11 +1,17 @@
import KeyCloakService from '../services/KeyCloakService'; import KeyCloakService from '../services/KeyCloakService';
import {API} from '../utils/globals'; import { API } from '../utils/globals';
const challengeSubmission = (challengeName, repoUrl, repoBranch, description, setLoading) => { const challengeSubmission = (
challengeName,
repoUrl,
repoBranch,
description,
setLoading
) => {
const details = { const details = {
'f1': description, f1: description,
'f3': repoUrl, f3: repoUrl,
'f4': repoBranch f4: repoBranch,
}; };
let formBody = []; let formBody = [];
for (let property in details) { for (let property in details) {
@ -18,13 +24,15 @@ const challengeSubmission = (challengeName, repoUrl, repoBranch, description, se
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
'Authorization': `Bearer ${KeyCloakService.getToken()}` Authorization: `Bearer ${KeyCloakService.getToken()}`,
}, },
body: formBody body: formBody,
}).then((resp) => resp.json()) })
.then((resp) => resp.json())
.then((data) => { .then((data) => {
setLoading(true); setLoading(true);
window.location.replace(`https://gonito.net/open-view-progress/${data}#form`); const processUrl = API.replace('/api', '');
window.location.replace(`${processUrl}/open-view-progress/${data}#form`);
}); });
}; };

View File

@ -0,0 +1,16 @@
import {API} from '../utils/globals';
import KeyCloakService from '../services/KeyCloakService';
const getFullUser = (setDataState, setLoadingState) => {
fetch(`${API}/full-user-info`, {
headers: {'Authorization': `Bearer ${KeyCloakService.getToken()}`}
})
.then(response => response.json())
.then(data => {
setDataState(data);
if (setLoadingState)
setLoadingState(false);
});
};
export default getFullUser;

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import {FlexColumn, FlexRow, Svg} from '../../utils/containers'; import { FlexColumn, FlexRow, Svg } from '../../utils/containers';
import {Body, H2, Medium} from '../../utils/fonts'; import { Body, H2, Medium } from '../../utils/fonts';
import Media from 'react-media'; import Media from 'react-media';
import theme from '../../utils/theme'; import theme from '../../utils/theme';
import uamLogo from '../../assets/uam-logo.svg'; import uamLogo from '../../assets/uam-logo.svg';
@ -8,21 +8,28 @@ import uamLogo from '../../assets/uam-logo.svg';
const Csi = () => { const Csi = () => {
const mobileRender = () => { const mobileRender = () => {
return ( return (
<FlexColumn as='section' alignmentX='flex-start'> <FlexColumn as="section" alignmentX="flex-start">
<H2 as='h2' margin='0 0 24px 0'> <H2 as="h2" margin="0 0 24px 0">
Artificial Intelligence Centre (CSI) Center for Artificial Intelligence (C4AI)
</H2> </H2>
<Body as='p' margin='0 0 16px 0'> <Body as="p" margin="0 0 16px 0">
<Medium as='span' display='inline'>Gonito.net</Medium> belongs to the <Medium as="span" display="inline">
<Medium as='span' display='inline'>&nbsp;Artificial Intelligence Centre (CSI)&nbsp;</Medium> Gonito.net
at Adam Mickiewicz University (UAM) which conducts research on the development of artificial </Medium>{' '}
intelligence, carries out scientific and research and development projects, integrates the research belongs to the
of scientists from various departments of Adam Mickiewicz University and outside it - from leading <Medium as="span" display="inline">
scientific centers in Poland and abroad as well as those employed in business entities. &nbsp;Center for Artificial Intelligence (C4AI)&nbsp;
</Medium>
at Adam Mickiewicz University (UAM) which conducts research on the
development of artificial intelligence, carries out scientific and
research and development projects, integrates the research of
scientists from various departments of Adam Mickiewicz University and
outside it - from leading scientific centers in Poland and abroad as
well as those employed in business entities.
</Body> </Body>
<Medium as='p'> <Medium as="p">
CSI also cooperates with business entities in creating new solutions to be implemented in C4AI also cooperates with business entities in creating new solutions
enterprises. to be implemented in enterprises.
</Medium> </Medium>
</FlexColumn> </FlexColumn>
); );
@ -30,39 +37,40 @@ const Csi = () => {
const desktopRender = () => { const desktopRender = () => {
return ( return (
<FlexRow gap='46px'> <FlexRow gap="46px">
<FlexColumn as='section' alignmentX='flex-start' maxWidth='490px'> <FlexColumn as="section" alignmentX="flex-start" maxWidth="490px">
<H2 as='h2' margin='0 0 48px 0'> <H2 as="h2" margin="0 0 48px 0">
Artificial Intelligence Centre (CSI) Center for Artificial Intelligence (C4AI)
</H2> </H2>
<Body as='p' margin='0 0 24px 0'> <Body as="p" margin="0 0 24px 0">
<Medium as='span' display='inline'>Gonito.net</Medium> belongs to the <Medium as="span" display="inline">
<Medium as='span' display='inline'>&nbsp;Artificial Intelligence Centre (CSI)&nbsp;</Medium> Gonito.net
at Adam Mickiewicz University (UAM) which conducts research on the development of artificial </Medium>{' '}
intelligence, carries out scientific and research and development projects, integrates the belongs to the
research <Medium as="span" display="inline">
of scientists from various departments of Adam Mickiewicz University and outside it - from &nbsp;Center for Artificial Intelligence (C4AI)&nbsp;
leading </Medium>
scientific centers in Poland and abroad as well as those employed in business entities. at Adam Mickiewicz University (UAM) which conducts research on the
development of artificial intelligence, carries out scientific and
research and development projects, integrates the research of
scientists from various departments of Adam Mickiewicz University
and outside it - from leading scientific centers in Poland and
abroad as well as those employed in business entities.
</Body> </Body>
<Medium as='p'> <Medium as="p">
CSI also cooperates with business entities in creating new solutions to be implemented in C4AI also cooperates with business entities in creating new
enterprises. solutions to be implemented in enterprises.
</Medium> </Medium>
</FlexColumn> </FlexColumn>
<Svg src={uamLogo} width='200px' height='242px' size='contain'/> <Svg src={uamLogo} width="200px" height="242px" size="contain" />
</FlexRow> </FlexRow>
); );
}; };
return ( return (
<> <>
<Media query={theme.mobile}> <Media query={theme.mobile}>{mobileRender()}</Media>
{mobileRender()} <Media query={theme.desktop}>{desktopRender()}</Media>
</Media>
<Media query={theme.desktop}>
{desktopRender()}
</Media>
</> </>
); );
}; };

View File

@ -1,23 +1,23 @@
import React from 'react'; import React from 'react';
import {FlexColumn, Svg} from '../../utils/containers'; import { FlexColumn, Svg } from '../../utils/containers';
import styled from 'styled-components'; import styled from 'styled-components';
import theme from '../../utils/theme'; import theme from '../../utils/theme';
import copyIco from '../../assets/copy_ico.svg'; import copyIco from '../../assets/copy_ico.svg';
import checkIco from '../../assets/check_ico.svg'; import checkIco from '../../assets/check_ico.svg';
import {Body, Code} from '../../utils/fonts'; import { Body, Code } from '../../utils/fonts';
const CodeShellStyle = styled(FlexColumn)` const CodeShellStyle = styled(FlexColumn)`
position: relative; position: relative;
padding: 24px 14px 14px; padding: 24px 14px 14px;
gap: 8px; gap: 8px;
background-color: ${({theme}) => theme.colors.dark07}; background-color: ${({ theme }) => theme.colors.dark07};
border: 1px solid ${({theme}) => theme.colors.dark}; border: 1px solid ${({ theme }) => theme.colors.dark};
border-radius: 4px; border-radius: 4px;
width: 100%; width: 100%;
align-items: flex-start; align-items: flex-start;
max-width: ${({maxWidth}) => maxWidth ? maxWidth : 'none'}; max-width: ${({ maxWidth }) => (maxWidth ? maxWidth : 'none')};
@media (min-width: ${({theme}) => theme.overMobile}) { @media (min-width: ${({ theme }) => theme.overMobile}) {
gap: 12px; gap: 12px;
padding: 40px 32px 32px; padding: 40px 32px 32px;
} }
@ -28,8 +28,8 @@ const CopiedMessageStyle = styled(Body)`
position: absolute; position: absolute;
top: -24px; top: -24px;
right: -10px; right: -10px;
background-color: ${({theme}) => theme.colors.green}; background-color: ${({ theme }) => theme.colors.green};
color: ${({theme}) => theme.colors.white}; color: ${({ theme }) => theme.colors.white};
border-radius: 4px; border-radius: 4px;
padding: 6px; padding: 6px;
`; `;
@ -40,43 +40,47 @@ const CodeShell = (props) => {
const clickCopyButton = () => { const clickCopyButton = () => {
let commands = ''; let commands = '';
if (props.commands.length > 1) { if (props.commands.length > 1) {
for (let command of props.commands) for (let command of props.commands) commands += command + '\n';
commands += command + '\n';
} else commands = props.commands; } else commands = props.commands;
navigator.clipboard.writeText(commands).then(r => console.log(r)); navigator.clipboard.writeText(commands).then((r) => console.log(r));
setIco(checkIco); setIco(checkIco);
setTimeout(() => { setTimeout(() => {
setIco(copyIco); setIco(copyIco);
}, 3000); }, 2000);
}; };
const formatCommand = (command) => { const formatCommand = (command) => {
if (command[0] === '\t') { if (command[0] === '\t') {
return <>&nbsp;&nbsp;&nbsp;&nbsp;{formatCommand(command.slice(1))}</>; return <>&nbsp;&nbsp;&nbsp;&nbsp;{formatCommand(command.slice(1))}</>;
/* eslint-disable */
} else if (command[0] === '\s') {
return <>&nbsp;{formatCommand(command.slice(1))}</>;
} }
return command; return command;
}; };
const renderCommands = () => { const renderCommands = () => {
return props.commands.map((command, index) => {
return ( return (
props.commands.map((command, index) => { <Code
return ( key={`command-${props.codeBlockIndex}-${index}`}
<Code key={`command-${props.codeBlockIndex}-${index}`} as='li' as="li"
before={!props.disablePrompt}> before={!props.disablePrompt}
>
{formatCommand(command)} {formatCommand(command)}
</Code> </Code>
); );
}) });
);
}; };
return ( return (
<CodeShellStyle as='ul' maxWidth={props.maxWidth}> <CodeShellStyle as="ul" maxWidth={props.maxWidth}>
<Svg position='absolute' top='12px' right='12px' cursor='pointer' <Svg
backgroundColor={theme.colors.white} src={ico} onClick={clickCopyButton}/> position="absolute"
top="12px"
right="12px"
cursor="pointer"
backgroundColor={theme.colors.white}
src={ico}
onClick={clickCopyButton}
/>
{ico === checkIco ? <CopiedMessageStyle>copied!</CopiedMessageStyle> : ''} {ico === checkIco ? <CopiedMessageStyle>copied!</CopiedMessageStyle> : ''}
{renderCommands()} {renderCommands()}
</CodeShellStyle> </CodeShellStyle>

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { Container, FlexColumn, FlexRow, Svg } from '../../utils/containers'; import { Container, FlexColumn, FlexRow, Svg } from '../../utils/containers';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { H1, H2, Medium } from '../../utils/fonts'; import { H1, Medium } from '../../utils/fonts';
import theme from '../../utils/theme'; import theme from '../../utils/theme';
import MobileChallengeMenu from './MobileChallengeMenu'; import MobileChallengeMenu from './MobileChallengeMenu';
import Leaderboard from './Leaderboard/Leaderboard'; import Leaderboard from './Leaderboard/Leaderboard';
@ -48,7 +48,13 @@ const Challenge = (props) => {
/> />
); );
case 2: case 2:
return <HowTo challengeName={challengeName} user={user} />; return (
<HowTo
popUpMessageHandler={props.popUpMessageHandler}
challengeName={challengeName}
user={user}
/>
);
case 3: case 3:
return <MyEntries challengeName={challengeName} />; return <MyEntries challengeName={challengeName} />;
case 4: case 4:
@ -64,6 +70,7 @@ const Challenge = (props) => {
}; };
const mobileRender = () => { const mobileRender = () => {
if (!loading) {
return ( return (
<FlexColumn <FlexColumn
minHeight="100vh" minHeight="100vh"
@ -87,6 +94,9 @@ const Challenge = (props) => {
{sectionRender()} {sectionRender()}
</FlexColumn> </FlexColumn>
); );
} else {
return <Loading />;
}
}; };
const desktopRender = () => { const desktopRender = () => {
@ -125,19 +135,7 @@ const Challenge = (props) => {
</> </>
); );
} else { } else {
return ( return <Loading />;
<FlexColumn
position="fixed"
top="0"
left="0"
width="100%"
height="100vh"
zIndex="10"
>
<H2 as="h1">Submission processing...</H2>
<Loading />
</FlexColumn>
);
} }
}; };

View File

@ -48,7 +48,7 @@ const DesktopChallengeMenu = (props) => {
<Option <Option
key={`challenge_menu_option-${index}`} key={`challenge_menu_option-${index}`}
as={Link} as={Link}
active={index === props.section} active={index === props.section ? 1 : 0}
to={`/challenge/${props.challengeName}/${options[index] to={`/challenge/${props.challengeName}/${options[index]
.toLowerCase() .toLowerCase()
.replace(' ', '')}`} .replace(' ', '')}`}

View File

@ -1,9 +1,25 @@
import React from 'react'; import React from 'react';
import getFullUser from '../../../api/getFullUserInfo';
import KeyCloakService from '../../../services/KeyCloakService';
import { FlexColumn } from '../../../utils/containers'; import { FlexColumn } from '../../../utils/containers';
import { IS_MOBILE } from '../../../utils/globals'; import { IS_MOBILE } from '../../../utils/globals';
import HowToContent from './sections/HowToContent'; import HowToContent from './sections/HowToContent';
const HowTo = (props) => { const HowTo = (props) => {
const [userFullInfo, setUserFullInfo] = React.useState(null);
React.useEffect(() => {
getFullUser(setUserFullInfo);
if (!KeyCloakService.isLoggedIn()) {
props.popUpMessageHandler(
'Please log in',
'To see everything you must log in',
() => KeyCloakService.doLogin
);
}
}, [props]);
return ( return (
<FlexColumn <FlexColumn
margin={IS_MOBILE() ? null : '64px 0 0 0'} margin={IS_MOBILE() ? null : '64px 0 0 0'}
@ -14,6 +30,7 @@ const HowTo = (props) => {
> >
<FlexColumn maxWidth="680px" alignmentX="flex-start" gap="48px"> <FlexColumn maxWidth="680px" alignmentX="flex-start" gap="48px">
<HowToContent <HowToContent
userFullInfo={userFullInfo}
user={props.user ? props.user : 'yourID'} user={props.user ? props.user : 'yourID'}
challengeName={props.challengeName} challengeName={props.challengeName}
/> />

View File

@ -17,6 +17,17 @@ const HowToContent = (props) => {
} }
}; };
const repoKeyRender = () => {
if (props.userFullInfo) {
return (
<CodeShell
codeBlockIndex={0}
commands={[props.userFullInfo.individualKey]}
/>
);
}
};
return ( return (
<FlexColumn <FlexColumn
as="article" as="article"
@ -36,7 +47,7 @@ const HowToContent = (props) => {
<Body as="p" margin="auto 0"> <Body as="p" margin="auto 0">
Create a private git repository with the name Create a private git repository with the name
<Medium as="span">&nbsp;{props.challengeName}</Medium> <Medium as="span">&nbsp;{props.challengeName}</Medium>
.&nbsp;The name of the repository must match! &nbsp;The name of the repository must match!
</Body> </Body>
</Grid> </Grid>
<Grid <Grid
@ -46,10 +57,12 @@ const HowToContent = (props) => {
> >
<CircleNumber number="2" /> <CircleNumber number="2" />
<Body as="p" margin="auto 0"> <Body as="p" margin="auto 0">
Add the following ssh key <Medium as="span">REPO_KEY_HERE</Medium> to Add the following ssh key{' '}
your deploy keys in your git repository settings. <Medium as="span">{props.userFullInfo ? '' : 'REPO_KEY_HERE'}</Medium>{' '}
to your deploy keys in your git repository settings.
</Body> </Body>
</Grid> </Grid>
{repoKeyRender()}
<Grid <Grid
width="100%" width="100%"
gridTemplateColumns="auto 1fr" gridTemplateColumns="auto 1fr"

View File

@ -1,15 +1,18 @@
import React from 'react'; import React from 'react';
import {FlexColumn} from '../../utils/containers'; import { createPortal } from 'react-dom';
import {H2, Menu} from '../../utils/fonts'; import { FlexColumn } from '../../utils/containers';
import { H2, Menu } from '../../utils/fonts';
import SubmitInput from '../generic/SubmitInput'; import SubmitInput from '../generic/SubmitInput';
import Button from '../generic/Button'; import Button from '../generic/Button';
import theme from '../../utils/theme'; import theme from '../../utils/theme';
import challengeSubmission from '../../api/challengeSubmissionPost'; import challengeSubmission from '../../api/challengeSubmissionPost';
import Loading from '../generic/Loading';
const Submit = (props) => { const Submit = (props) => {
const [description, setDescription] = React.useState(''); const [description, setDescription] = React.useState('');
const [repoUrl, setRepoUrl] = React.useState(''); const [repoUrl, setRepoUrl] = React.useState('');
const [repoBranch, setRepoBranch] = React.useState(''); const [repoBranch, setRepoBranch] = React.useState('');
const [loading, setLoading] = React.useState(false);
const descriptionHandler = (e) => { const descriptionHandler = (e) => {
setDescription(e.target.value); setDescription(e.target.value);
@ -24,27 +27,63 @@ const Submit = (props) => {
}; };
const challengeSubmissionSubmit = () => { const challengeSubmissionSubmit = () => {
challengeSubmission(props.challengeName, repoUrl, repoBranch, description, props.setLoading); setLoading(true);
challengeSubmission(
props.challengeName,
repoUrl,
repoBranch,
description,
setLoading
);
}; };
if (!loading) {
return ( return (
<FlexColumn margin='40px 0 0 0' padding='24px' as='section' gap='64px' maxWidth='624px' width='100%' <FlexColumn
alignmentX='flex-start'> margin="40px 0 0 0"
<H2 as='h2' width='100%' textAlign='center'> padding="24px"
as="section"
gap="64px"
maxWidth="624px"
width="100%"
alignmentX="flex-start"
>
<H2 as="h2" width="100%" textAlign="center">
Submit a solution to the challenge Submit a solution to the challenge
</H2> </H2>
<FlexColumn width='100%' gap='32px'> <FlexColumn width="100%" gap="32px">
<SubmitInput label='Submission description' handler={descriptionHandler}/> <SubmitInput
<SubmitInput label='Submission repo URL' handler={repoUrlHandler}/> label="Submission description"
<SubmitInput label='Submission repo branch' handler={repoBranchHandler}/> handler={descriptionHandler}
/>
<SubmitInput label="Submission repo URL" handler={repoUrlHandler} />
<SubmitInput
label="Submission repo branch"
handler={repoBranchHandler}
/>
</FlexColumn> </FlexColumn>
<Button width='122px' height='44px' handler={challengeSubmissionSubmit}> <Button width="122px" height="44px" handler={challengeSubmissionSubmit}>
<Menu color={theme.colors.white}> <Menu color={theme.colors.white}>Submit</Menu>
Submit
</Menu>
</Button> </Button>
</FlexColumn> </FlexColumn>
); );
} else {
return createPortal(
<FlexColumn
position="fixed"
top="0"
left="0"
width="100%"
height="100vh"
zIndex="100"
backgroundColor={theme.colors.white}
>
<H2 as="h1">Submission processing...</H2>
<Loading />
</FlexColumn>,
document.body
);
}
}; };
export default Submit; export default Submit;

View File

@ -76,6 +76,8 @@ const Code = styled(Container)`
line-height: 18px; line-height: 18px;
font-weight: 300; font-weight: 300;
color: ${({theme}) => theme.colors.white}; color: ${({theme}) => theme.colors.white};
max-width: 600px;
overflow-wrap: break-word;
&:before { &:before {
display: ${({before}) => before ? 'inline-block' : 'none'}; display: ${({before}) => before ? 'inline-block' : 'none'};