Compare commits

..

No commits in common. "3ff0c6ea8715cf6c565edc32fbf66f04186c895a" and "234e4a47f7b7436ecdd55600d60d1edc089a5aa0" have entirely different histories.

12 changed files with 212 additions and 322 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-back-dev.csi.wmi.amu.edu.pl/api REACT_APP_API=https://gonito.net/api

View File

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

View File

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

View File

@ -1,16 +0,0 @@
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,78 +1,70 @@
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';
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'>
Center for Artificial Intelligence (C4AI) Artificial Intelligence Centre (CSI)
</H2> </H2>
<Body as="p" margin="0 0 16px 0"> <Body as='p' margin='0 0 16px 0'>
<Medium as="span" display="inline"> <Medium as='span' display='inline'>Gonito.net</Medium> belongs to the
Gonito.net <Medium as='span' display='inline'>&nbsp;Artificial Intelligence Centre (CSI)&nbsp;</Medium>
</Medium>{' '} at Adam Mickiewicz University (UAM) which conducts research on the development of artificial
belongs to the intelligence, carries out scientific and research and development projects, integrates the research
<Medium as="span" display="inline"> of scientists from various departments of Adam Mickiewicz University and outside it - from leading
&nbsp;Center for Artificial Intelligence (C4AI)&nbsp; scientific centers in Poland and abroad as well as those employed in business entities.
</Medium> </Body>
at Adam Mickiewicz University (UAM) which conducts research on the <Medium as='p'>
development of artificial intelligence, carries out scientific and CSI also cooperates with business entities in creating new solutions to be implemented in
research and development projects, integrates the research of enterprises.
scientists from various departments of Adam Mickiewicz University and </Medium>
outside it - from leading scientific centers in Poland and abroad as </FlexColumn>
well as those employed in business entities. );
</Body> };
<Medium as="p">
C4AI also cooperates with business entities in creating new solutions
to be implemented in enterprises.
</Medium>
</FlexColumn>
);
};
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'>
Center for Artificial Intelligence (C4AI) Artificial Intelligence Centre (CSI)
</H2> </H2>
<Body as="p" margin="0 0 24px 0"> <Body as='p' margin='0 0 24px 0'>
<Medium as="span" display="inline"> <Medium as='span' display='inline'>Gonito.net</Medium> belongs to the
Gonito.net <Medium as='span' display='inline'>&nbsp;Artificial Intelligence Centre (CSI)&nbsp;</Medium>
</Medium>{' '} at Adam Mickiewicz University (UAM) which conducts research on the development of artificial
belongs to the intelligence, carries out scientific and research and development projects, integrates the
<Medium as="span" display="inline"> research
&nbsp;Center for Artificial Intelligence (C4AI)&nbsp; of scientists from various departments of Adam Mickiewicz University and outside it - from
</Medium> leading
at Adam Mickiewicz University (UAM) which conducts research on the scientific centers in Poland and abroad as well as those employed in business entities.
development of artificial intelligence, carries out scientific and </Body>
research and development projects, integrates the research of <Medium as='p'>
scientists from various departments of Adam Mickiewicz University CSI also cooperates with business entities in creating new solutions to be implemented in
and outside it - from leading scientific centers in Poland and enterprises.
abroad as well as those employed in business entities. </Medium>
</Body> </FlexColumn>
<Medium as="p"> <Svg src={uamLogo} width='200px' height='242px' size='contain'/>
C4AI also cooperates with business entities in creating new </FlexRow>
solutions to be implemented in enterprises. );
</Medium> };
</FlexColumn>
<Svg src={uamLogo} width="200px" height="242px" size="contain" />
</FlexRow>
);
};
return ( return (
<> <>
<Media query={theme.mobile}>{mobileRender()}</Media> <Media query={theme.mobile}>
<Media query={theme.desktop}>{desktopRender()}</Media> {mobileRender()}
</> </Media>
); <Media query={theme.desktop}>
{desktopRender()}
</Media>
</>
);
}; };
export default Csi; export default Csi;

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,63 +28,59 @@ 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;
`; `;
const CodeShell = (props) => { const CodeShell = (props) => {
const [ico, setIco] = React.useState(copyIco); const [ico, setIco] = React.useState(copyIco);
const clickCopyButton = () => { const clickCopyButton = () => {
let commands = ''; let commands = '';
if (props.commands.length > 1) { if (props.commands.length > 1) {
for (let command of props.commands) commands += command + '\n'; for (let command of props.commands)
} else commands = props.commands; commands += command + '\n';
navigator.clipboard.writeText(commands).then((r) => console.log(r)); } else commands = props.commands;
setIco(checkIco); navigator.clipboard.writeText(commands).then(r => console.log(r));
setTimeout(() => { setIco(checkIco);
setIco(copyIco); setTimeout(() => {
}, 2000); setIco(copyIco);
}; }, 3000);
};
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 */
return command; } else if (command[0] === '\s') {
}; return <>&nbsp;{formatCommand(command.slice(1))}</>;
}
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)}
> </Code>
{formatCommand(command)} );
</Code> })
); );
}); };
};
return ( return (
<CodeShellStyle as="ul" maxWidth={props.maxWidth}> <CodeShellStyle as='ul' maxWidth={props.maxWidth}>
<Svg <Svg position='absolute' top='12px' right='12px' cursor='pointer'
position="absolute" backgroundColor={theme.colors.white} src={ico} onClick={clickCopyButton}/>
top="12px" {ico === checkIco ? <CopiedMessageStyle>copied!</CopiedMessageStyle> : ''}
right="12px" {renderCommands()}
cursor="pointer" </CodeShellStyle>
backgroundColor={theme.colors.white} );
src={ico}
onClick={clickCopyButton}
/>
{ico === checkIco ? <CopiedMessageStyle>copied!</CopiedMessageStyle> : ''}
{renderCommands()}
</CodeShellStyle>
);
}; };
export default CodeShell; export default CodeShell;

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, Medium } from '../../utils/fonts'; import { H1, H2, 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,13 +48,7 @@ const Challenge = (props) => {
/> />
); );
case 2: case 2:
return ( return <HowTo challengeName={challengeName} user={user} />;
<HowTo
popUpMessageHandler={props.popUpMessageHandler}
challengeName={challengeName}
user={user}
/>
);
case 3: case 3:
return <MyEntries challengeName={challengeName} />; return <MyEntries challengeName={challengeName} />;
case 4: case 4:
@ -70,33 +64,29 @@ const Challenge = (props) => {
}; };
const mobileRender = () => { const mobileRender = () => {
if (!loading) { return (
return ( <FlexColumn
<FlexColumn minHeight="100vh"
minHeight="100vh" gap="12px"
gap="12px" alignmentY="flex-start"
alignmentY="flex-start" padding="66px 0 0 0"
padding="66px 0 0 0" >
> <Loading visible={loading} />
<Loading visible={loading} /> <H1 as="h1" margin="0 0 8px 0" textAlign="center">
<H1 as="h1" margin="0 0 8px 0" textAlign="center"> {challenge.title}
{challenge.title} </H1>
</H1> <MobileChallengeMenu
<MobileChallengeMenu challengeName={challengeName}
challengeName={challengeName} section={props.section}
section={props.section} />
/> <Container
<Container width="75%"
width="75%" height="1px"
height="1px" backgroundColor={theme.colors.dark}
backgroundColor={theme.colors.dark} />
/> {sectionRender()}
{sectionRender()} </FlexColumn>
</FlexColumn> );
);
} else {
return <Loading />;
}
}; };
const desktopRender = () => { const desktopRender = () => {
@ -135,7 +125,19 @@ const Challenge = (props) => {
</> </>
); );
} else { } else {
return <Loading />; return (
<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 ? 1 : 0} active={index === props.section}
to={`/challenge/${props.challengeName}/${options[index] to={`/challenge/${props.challengeName}/${options[index]
.toLowerCase() .toLowerCase()
.replace(' ', '')}`} .replace(' ', '')}`}

View File

@ -1,25 +1,9 @@
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'}
@ -30,7 +14,6 @@ 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,17 +17,6 @@ const HowToContent = (props) => {
} }
}; };
const repoKeyRender = () => {
if (props.userFullInfo) {
return (
<CodeShell
codeBlockIndex={0}
commands={[props.userFullInfo.individualKey]}
/>
);
}
};
return ( return (
<FlexColumn <FlexColumn
as="article" as="article"
@ -47,7 +36,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
@ -57,12 +46,10 @@ 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{' '} Add the following ssh key <Medium as="span">REPO_KEY_HERE</Medium> to
<Medium as="span">{props.userFullInfo ? '' : 'REPO_KEY_HERE'}</Medium>{' '} your deploy keys in your git repository settings.
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,89 +1,50 @@
import React from 'react'; import React from 'react';
import { createPortal } from 'react-dom'; import {FlexColumn} from '../../utils/containers';
import { FlexColumn } from '../../utils/containers'; import {H2, Menu} from '../../utils/fonts';
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);
}; };
const repoUrlHandler = (e) => { const repoUrlHandler = (e) => {
setRepoUrl(e.target.value); setRepoUrl(e.target.value);
}; };
const repoBranchHandler = (e) => { const repoBranchHandler = (e) => {
setRepoBranch(e.target.value); setRepoBranch(e.target.value);
}; };
const challengeSubmissionSubmit = () => { const challengeSubmissionSubmit = () => {
setLoading(true); challengeSubmission(props.challengeName, repoUrl, repoBranch, description, props.setLoading);
challengeSubmission( };
props.challengeName,
repoUrl,
repoBranch,
description,
setLoading
);
};
if (!loading) {
return ( return (
<FlexColumn <FlexColumn margin='40px 0 0 0' padding='24px' as='section' gap='64px' maxWidth='624px' width='100%'
margin="40px 0 0 0" alignmentX='flex-start'>
padding="24px" <H2 as='h2' width='100%' textAlign='center'>
as="section" Submit a solution to the challenge
gap="64px" </H2>
maxWidth="624px" <FlexColumn width='100%' gap='32px'>
width="100%" <SubmitInput label='Submission description' handler={descriptionHandler}/>
alignmentX="flex-start" <SubmitInput label='Submission repo URL' handler={repoUrlHandler}/>
> <SubmitInput label='Submission repo branch' handler={repoBranchHandler}/>
<H2 as="h2" width="100%" textAlign="center"> </FlexColumn>
Submit a solution to the challenge <Button width='122px' height='44px' handler={challengeSubmissionSubmit}>
</H2> <Menu color={theme.colors.white}>
<FlexColumn width="100%" gap="32px"> Submit
<SubmitInput </Menu>
label="Submission description" </Button>
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}>
<Menu color={theme.colors.white}>Submit</Menu>
</Button>
</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,8 +76,6 @@ 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'};