Compare commits

...

15 Commits

72 changed files with 1420 additions and 924 deletions

4
.env
View File

@ -2,4 +2,6 @@ REACT_APP_KC_URL=https://auth-dev.csi.wmi.amu.edu.pl/
REACT_APP_KC_REALM=gonito-dev
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-back-dev.csi.wmi.amu.edu.pl/api
# https://gonito.net/api
# https://gonito-back-dev.csi.wmi.amu.edu.pl/api

View File

@ -1,225 +0,0 @@
import { ThemeProvider } from 'styled-components';
import theme from './utils/theme';
import LandingPage from './pages/LandingPage';
import Challenges from './pages/Challanges/Challenges';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import NavBar from './components/navigation/NavBar';
import {
CHALLENGE_PAGE,
CHALLENGES_PAGE,
IS_MOBILE,
POLICY_PRIVACY_PAGE,
LOGIN_REQUIRED_PAGES,
ROOT_URL,
CHALLENGE_SECTIONS,
} from './utils/globals';
import KeyCloakService from './services/KeyCloakService';
import React from 'react';
import LoggedBar from './components/navigation/LoggedBar';
import addUser from './api/addUser';
import Loading from './components/generic/Loading';
import { FlexColumn } from './utils/containers';
import PopupMessage from './components/generic/PopupMessage';
import PolicyPrivacy from './pages/PolicyPrivacy';
import Challenge from './pages/Challenge';
const App = () => {
const [loggedBarVisible, setLoggedBarVisible] = React.useState('100vw');
const [loggedBarHover, setLoggedBarHover] = React.useState(false);
const [popUpHeader, setPopUpHeader] = React.useState('');
const [popUpMessage, setPopUpMessage] = React.useState('');
const [confirmPopUpHandler, setConfirmPopUpHandler] = React.useState(null);
React.useEffect(() => {
if (sessionStorage.getItem('logout') === 'yes') {
const pageName = window.location.pathname.split('/').at(-1);
if (LOGIN_REQUIRED_PAGES.includes(pageName)) {
window.location.replace(`${ROOT_URL}/challenges`);
}
}
if (sessionStorage.getItem('logged') !== 'yes') {
if (KeyCloakService.isLoggedIn()) {
sessionStorage.setItem('logged', 'yes');
addUser();
}
}
if (
sessionStorage.getItem('logged') === 'yes' &&
(window.location.pathname === `${POLICY_PRIVACY_PAGE}/login` ||
window.location.pathname === `${POLICY_PRIVACY_PAGE}/register`)
) {
window.location.replace(`${ROOT_URL}/challenges`);
}
setTimeout(() => {
if (sessionStorage.getItem('logged') === 'yes') {
if (!KeyCloakService.isLoggedIn()) {
KeyCloakService.doLogin();
}
}
}, 1500);
});
const popUpMessageHandler = (header, message, confirmHandler) => {
setPopUpHeader(header);
setPopUpMessage(message);
if (confirmHandler !== null && confirmHandler !== undefined) {
setConfirmPopUpHandler(() => confirmHandler());
} else {
setConfirmPopUpHandler(null);
}
};
const popUpMessageRender = () => {
if (popUpHeader !== '' || popUpMessage !== '') {
return (
<PopupMessage
header={popUpHeader}
message={popUpMessage}
confirmHandler={confirmPopUpHandler}
popUpMessageHandler={popUpMessageHandler}
/>
);
}
};
const loggedBarVisibleHandler = () => {
if (loggedBarVisible === '0' && !loggedBarHover)
setLoggedBarVisible('100vw');
else setLoggedBarVisible('0');
};
const loggedBarHoverTrue = () => {
setLoggedBarHover(true);
};
const loggedBarHoverFalse = () => {
setLoggedBarHover(false);
};
const renderApp = () => {
return (
<BrowserRouter>
<ThemeProvider theme={theme}>
{popUpMessageRender()}
<NavBar
loggedBarVisibleHandler={loggedBarVisibleHandler}
popUpMessageHandler={popUpMessageHandler}
/>
{!IS_MOBILE() ? (
<LoggedBar
visible={loggedBarVisible}
loggedBarVisibleHandler={loggedBarVisibleHandler}
loggedBarHoverTrue={loggedBarHoverTrue}
loggedBarHoverFalse={loggedBarHoverFalse}
username={KeyCloakService.getUsername()}
/>
) : (
''
)}
<Routes>
<Route
path={`${CHALLENGE_PAGE}/:challengeId`}
element={<Challenge section={CHALLENGE_SECTIONS.LEADERBOARD} />}
/>
<Route
path={`${CHALLENGE_PAGE}/:challengeId/leaderboard`}
element={<Challenge section={CHALLENGE_SECTIONS.LEADERBOARD} />}
/>
<Route
path={`${CHALLENGE_PAGE}/:challengeId/allentries`}
element={<Challenge section={CHALLENGE_SECTIONS.ALL_ENTRIES} />}
/>
<Route
path={`${CHALLENGE_PAGE}/:challengeId/readme`}
element={<Challenge section={CHALLENGE_SECTIONS.README} />}
/>
<Route
path={`${CHALLENGE_PAGE}/:challengeId/howto`}
element={
<Challenge
popUpMessageHandler={popUpMessageHandler}
section={CHALLENGE_SECTIONS.HOW_TO}
/>
}
/>
<Route
path={`${CHALLENGE_PAGE}/:challengeId/myentries`}
element={<Challenge section={CHALLENGE_SECTIONS.MY_ENTRIES} />}
/>
<Route
path={`${CHALLENGE_PAGE}/:challengeId/submit`}
element={<Challenge section={CHALLENGE_SECTIONS.SUBMIT} />}
/>
<Route path={CHALLENGES_PAGE} element={<Challenges />} />
<Route
path={POLICY_PRIVACY_PAGE}
element={
<PolicyPrivacy popUpMessageHandler={popUpMessageHandler} />
}
/>
<Route
path={`${POLICY_PRIVACY_PAGE}/login`}
element={
<PolicyPrivacy
popUpMessageHandler={popUpMessageHandler}
beforeLogin
/>
}
/>
<Route
path={`${POLICY_PRIVACY_PAGE}/register`}
element={
<PolicyPrivacy
popUpMessageHandler={popUpMessageHandler}
beforeRegister
/>
}
/>
{KeyCloakService.isLoggedIn() ? (
<>
<Route exact path="/" element={<Challenges />} />
<Route element={<Challenges />} />
</>
) : (
<>
<Route
exact
path="/"
element={
<LandingPage popUpMessageHandler={popUpMessageHandler} />
}
/>
<Route
element={
<LandingPage popUpMessageHandler={popUpMessageHandler} />
}
/>
</>
)}
</Routes>
</ThemeProvider>
</BrowserRouter>
);
};
if (sessionStorage.getItem('logged') === 'yes') {
if (KeyCloakService.isLoggedIn()) {
return renderApp();
} else {
return (
<ThemeProvider theme={theme}>
<FlexColumn width="100vw" height="100vh">
<Loading />
</FlexColumn>
</ThemeProvider>
);
}
} else {
return renderApp();
}
};
export default App;

33
src/App/App.js Normal file
View File

@ -0,0 +1,33 @@
import React from 'react';
import { ThemeProvider } from 'styled-components';
import theme from '../utils/theme';
import PopUpMessageManager from './components/PopUpMessageManager';
import RoutingManager from './components/RoutingManager';
import NavigationManager from './components/NavigationManager';
import { BrowserRouter } from 'react-router-dom';
import startManage from './functions/startManage';
import startApp from './functions/startApp';
const App = () => {
React.useMemo(() => {
startManage();
}, []);
const renderApp = React.useCallback(() => {
return (
<ThemeProvider theme={theme}>
<PopUpMessageManager>
<BrowserRouter>
<NavigationManager>
<RoutingManager />
</NavigationManager>
</BrowserRouter>
</PopUpMessageManager>
</ThemeProvider>
);
}, []);
return startApp(renderApp);
};
export default App;

View File

@ -0,0 +1,47 @@
import React from 'react';
import NavBar from '../../components/navigation/NavBar/NavBar';
import LoggedBar from '../../components/navigation/LoggedBar';
import KeyCloakService from '../../services/KeyCloakService';
import { CHILDREN_WITH_PROPS, IS_MOBILE } from '../../utils/globals';
const NavigationManager = (props) => {
const [loggedBarVisible, setLoggedBarVisible] = React.useState('100vw');
const [loggedBarHover, setLoggedBarHover] = React.useState(false);
const [navOptions, setNavOptions] = React.useState(true);
const loggedBarVisibleHandler = React.useCallback(() => {
if (loggedBarVisible === '0' && !loggedBarHover)
setLoggedBarVisible('100vw');
else setLoggedBarVisible('0');
}, [loggedBarHover, loggedBarVisible]);
const hideNavOptions = React.useCallback(() => {
setNavOptions(false);
}, []);
const showNavOptions = React.useCallback(() => {
setNavOptions(true);
}, []);
return (
<>
<NavBar
loggedBarVisibleHandler={loggedBarVisibleHandler}
popUpMessageHandler={props.popUpMessageHandler}
navOptions={navOptions}
/>
{!IS_MOBILE() && (
<LoggedBar
visible={loggedBarVisible}
loggedBarVisibleHandler={loggedBarVisibleHandler}
loggedBarHoverTrue={() => setLoggedBarHover(true)}
loggedBarHoverFalse={() => setLoggedBarHover(false)}
username={KeyCloakService.getUsername()}
/>
)}
{CHILDREN_WITH_PROPS(props.children, { hideNavOptions, showNavOptions })}
</>
);
};
export default NavigationManager;

View File

@ -0,0 +1,41 @@
import React from 'react';
import PopupMessage from '../../components/generic/PopupMessage';
import { CHILDREN_WITH_PROPS } from '../../utils/globals';
const PopUpMessageManager = (props) => {
const [popUpHeader, setPopUpHeader] = React.useState('');
const [popUpMessage, setPopUpMessage] = React.useState('');
const [confirmPopUpHandler, setConfirmPopUpHandler] = React.useState(null);
const popUpMessageHandler = (header, message, confirmHandler) => {
setPopUpHeader(header);
setPopUpMessage(message);
if (confirmHandler !== null && confirmHandler !== undefined) {
setConfirmPopUpHandler(() => confirmHandler());
} else {
setConfirmPopUpHandler(null);
}
};
const popUpMessageRender = () => {
if (popUpHeader !== '' || popUpMessage !== '') {
return (
<PopupMessage
header={popUpHeader}
message={popUpMessage}
confirmHandler={confirmPopUpHandler}
popUpMessageHandler={popUpMessageHandler}
/>
);
}
};
return (
<>
{popUpMessageRender()}
{CHILDREN_WITH_PROPS(props.children, { popUpMessageHandler })}
</>
);
};
export default PopUpMessageManager;

View File

@ -0,0 +1,108 @@
import { Route, Routes } from 'react-router-dom';
import {
CHALLENGES_PAGE,
CHALLENGE_PAGE,
CHALLENGE_SECTIONS,
POLICY_PRIVACY_PAGE,
} from '../../utils/globals';
import Challenge from '../../pages/Challenge';
import Challenges from '../../pages/Challanges';
import PolicyPrivacy from '../../pages/PolicyPrivacy';
import LandingPage from '../../pages/LandingPage';
import KeyCloakService from '../../services/KeyCloakService';
const RoutingManager = (props) => {
return (
<Routes>
<Route
path={`${CHALLENGE_PAGE}/:challengeId`}
element={<Challenge section={CHALLENGE_SECTIONS.LEADERBOARD} />}
/>
<Route
path={`${CHALLENGE_PAGE}/:challengeId/leaderboard`}
element={<Challenge section={CHALLENGE_SECTIONS.LEADERBOARD} />}
/>
<Route
path={`${CHALLENGE_PAGE}/:challengeId/allentries`}
element={<Challenge section={CHALLENGE_SECTIONS.ALL_ENTRIES} />}
/>
<Route
path={`${CHALLENGE_PAGE}/:challengeId/readme`}
element={<Challenge section={CHALLENGE_SECTIONS.README} />}
/>
<Route
path={`${CHALLENGE_PAGE}/:challengeId/howto`}
element={
<Challenge
popUpMessageHandler={props.popUpMessageHandler}
section={CHALLENGE_SECTIONS.HOW_TO}
/>
}
/>
<Route
path={`${CHALLENGE_PAGE}/:challengeId/myentries`}
element={<Challenge section={CHALLENGE_SECTIONS.MY_ENTRIES} />}
/>
<Route
path={`${CHALLENGE_PAGE}/:challengeId/submit`}
element={<Challenge section={CHALLENGE_SECTIONS.SUBMIT} />}
/>
<Route path={CHALLENGES_PAGE} element={<Challenges />} />
<Route
path={POLICY_PRIVACY_PAGE}
element={
<PolicyPrivacy popUpMessageHandler={props.popUpMessageHandler} />
}
/>
<Route
path={`${POLICY_PRIVACY_PAGE}/login`}
element={
<PolicyPrivacy
popUpMessageHandler={props.popUpMessageHandler}
beforeLogin
/>
}
/>
<Route
path={`${POLICY_PRIVACY_PAGE}/register`}
element={
<PolicyPrivacy
popUpMessageHandler={props.popUpMessageHandler}
beforeRegister
/>
}
/>
{KeyCloakService.isLoggedIn() ? (
<>
<Route exact path="/" element={<Challenges />} />
<Route element={<Challenges />} />
</>
) : (
<>
<Route
exact
path="/"
element={
<LandingPage
popUpMessageHandler={props.popUpMessageHandler}
showNavOptions={props.showNavOptions}
hideNavOptions={props.hideNavOptions}
/>
}
/>
<Route
element={
<LandingPage
popUpMessageHandler={props.popUpMessageHandler}
showNavOptions={props.showNavOptions}
hideNavOptions={props.hideNavOptions}
/>
}
/>
</>
)}
</Routes>
);
};
export default RoutingManager;

View File

@ -0,0 +1,29 @@
import Loading from '../../components/generic/Loading';
import { FlexColumn } from '../../utils/containers';
import SESSION_STORAGE from '../../utils/sessionStorage';
import KeyCloakService from '../../services/KeyCloakService';
import { ThemeProvider } from 'styled-components';
import theme from '../../utils/theme';
const startApp = (renderApp) => {
if (
sessionStorage.getItem(SESSION_STORAGE.LOGGED) ===
SESSION_STORAGE.STATIC_VALUE.YES
) {
if (KeyCloakService.isLoggedIn()) {
return renderApp();
} else {
return (
<ThemeProvider theme={theme}>
<FlexColumn width="100vw" height="100vh">
<Loading />
</FlexColumn>
</ThemeProvider>
);
}
} else {
return renderApp();
}
};
export default startApp;

View File

@ -0,0 +1,55 @@
import {
POLICY_PRIVACY_PAGE,
LOGIN_REQUIRED_PAGES,
ROOT_URL,
} from '../../utils/globals';
import addUser from '../../api/addUser';
import SESSION_STORAGE from '../../utils/sessionStorage';
import KeyCloakService from '../../services/KeyCloakService';
const startManage = () => {
if (
sessionStorage.getItem(SESSION_STORAGE.LOGOUT) ===
SESSION_STORAGE.STATIC_VALUE.YES
) {
const pageName = window.location.pathname.split('/').at(-1);
if (LOGIN_REQUIRED_PAGES.includes(pageName)) {
window.location.replace(`${ROOT_URL}/challenges`);
}
}
if (
sessionStorage.getItem(SESSION_STORAGE.LOGGED) !==
SESSION_STORAGE.STATIC_VALUE.YES
) {
if (KeyCloakService.isLoggedIn()) {
sessionStorage.setItem(
SESSION_STORAGE.LOGGED,
SESSION_STORAGE.STATIC_VALUE.YES
);
addUser();
}
}
if (
sessionStorage.getItem(SESSION_STORAGE.LOGGED) ===
SESSION_STORAGE.STATIC_VALUE.YES &&
(window.location.pathname === `${POLICY_PRIVACY_PAGE}/login` ||
window.location.pathname === `${POLICY_PRIVACY_PAGE}/register`)
) {
window.location.replace(`${ROOT_URL}/challenges`);
}
setTimeout(() => {
if (
sessionStorage.getItem(SESSION_STORAGE.LOGGED) ===
SESSION_STORAGE.STATIC_VALUE.YES
) {
if (!KeyCloakService.isLoggedIn()) {
KeyCloakService.doLogin();
}
}
}, 1500);
};
export default startManage;

1
src/App/index.js Normal file
View File

@ -0,0 +1 @@
export { default } from './App';

View File

@ -10,9 +10,10 @@ const challengeSubmission = (
submissionTags,
dispatch
) => {
const tagNames = submissionTags.map((tag) => tag.name).join(',');
const details = {
f1: description,
f2: submissionTags,
f2: tagNames,
f3: repoUrl,
f4: repoBranch,
};
@ -20,6 +21,8 @@ const challengeSubmission = (
for (let property in details) {
let encodedKey = encodeURIComponent(property);
let encodedValue = encodeURIComponent(details[property]);
if (property === 'f2')
encodedValue = encodedValue.replaceAll('%2C', '%2C+');
formBody.push(encodedKey + '=' + encodedValue);
}
formBody = formBody.join('&');

View File

@ -0,0 +1,18 @@
import KeyCloakService from '../services/KeyCloakService';
import { API } from '../utils/globals';
const deleteSubmission = (submissionId) => {
fetch(`${API}/delete-submission/${submissionId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
Authorization: `Bearer ${KeyCloakService.getToken()}`,
},
})
.then((resp) => resp.json())
.then((data) => {
console.log(data);
});
};
export default deleteSubmission;

View File

@ -0,0 +1,39 @@
<svg width="396" height="110" viewBox="0 0 396 110" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M126.589 80.1711V90.4774H116.231V86.1171H105.374V87.7027H100.594V86.1171H90.136V90.4774H79.7778V80.1711H90.136V84.5315H100.594V82.9459H105.374V84.5315H116.231V80.1711H126.589Z" fill="#E52713"/>
<path d="M147.404 58.1712V68.4775H136.947V64.1171H116.23V68.4775H105.872V64.1171H88.0443V72.3423H69.8179V64.1171H49.1017V65.7027H44.321V64.1171H27.5886V68.4775H17.1309V58.1712H27.5886V62.5315H44.321V60.9459H49.1017V62.5315H69.8179V54.2072H88.0443V62.5315H105.872V58.1712H116.23V62.5315H136.947V58.1712H147.404Z" fill="#E52713"/>
<path d="M153.779 35.1802V45.4865H143.42V41.1262H129.477V42.7118H124.596V41.1262H109.856V47.964H94.518V41.1262H81.3712V42.7118H76.5905V41.1262H63.9416V51.7298H40.9346V41.1262H30.7756V45.4865H20.4175V41.1262H10.3581V45.4865H0V35.1802H10.3581V39.5406H20.4175V35.1802H30.7756V39.5406H40.9346V28.8379H63.9416V39.5406H76.5905V37.955H81.3712V39.5406H94.518V32.7028H109.856V39.5406H124.596V37.955H129.477V39.5406H143.42V35.1802H153.779Z" fill="#E52713"/>
<path d="M134.656 15.8558V26.1621H124.298V21.8018H104.976V23.3874H100.195V21.8018H78.0847V26.1621H67.7265V21.8018H32.7678V26.1621H22.4097V15.8558H32.7678V20.2162H67.7265V15.8558H78.0847V20.2162H100.195V18.6306H104.976V20.2162H124.298V15.8558H134.656Z" fill="#E52713"/>
<path d="M104.877 0V10.3063H94.5186V5.94594H81.8698V7.63063H77.0891V5.94594H64.5398V10.3063H54.1816V0H64.5398V4.36036H77.0891V2.77477H81.8698V4.36036H94.5186V0H104.877Z" fill="#E52713"/>
<path d="M117.625 99.6937H107.267V110H117.625V99.6937Z" fill="#E52713"/>
<path d="M175.69 17.9369C175.69 11.991 180.272 7.13513 186.646 7.13513C190.53 7.13513 193.917 9.11711 195.71 12.2883L193.817 13.3784C192.522 10.9009 189.734 9.21621 186.646 9.21621C181.367 9.21621 177.782 13.0811 177.782 17.9369C177.782 22.7928 181.367 26.6576 186.646 26.6576C189.734 26.6576 192.522 24.973 193.817 22.4955L195.71 23.4865C194.016 26.5586 190.53 28.6396 186.646 28.6396C180.272 28.6396 175.69 23.8829 175.69 17.9369Z" fill="black"/>
<path d="M214.135 26.3603V28.3423H201.884V7.53149H214.035V9.51348H204.075V16.8468H213.338V18.8288H204.075V26.3603H214.135Z" fill="black"/>
<path d="M235.947 7.53149V28.3423H234.154L222.501 11.3964V28.3423H220.41V7.53149H222.202L233.855 24.4774V7.53149H235.947Z" fill="black"/>
<path d="M256.563 9.41435H250.089V28.2432H247.998V9.41435H241.524V7.43237H256.464V9.41435H256.563Z" fill="black"/>
<path d="M274.491 26.3603V28.3423H262.241V7.53149H274.392V9.51348H264.432V16.8468H273.694V18.8288H264.432V26.3603H274.491Z" fill="black"/>
<path d="M288.634 20.018H282.758V28.3423H280.666V7.53149H289.032C292.518 7.53149 295.307 10.3063 295.307 13.7747C295.307 16.5495 293.414 19.027 290.825 19.7207L295.904 28.3423H293.514L288.634 20.018ZM282.857 18.036H289.132C291.423 18.036 293.315 16.1531 293.315 13.7747C293.315 11.3964 291.423 9.51348 289.132 9.51348H282.857V18.036Z" fill="black"/>
<path d="M313.931 9.41435V17.045H323.194V19.027H313.931V28.2432H311.84V7.43237H323.592V9.41435H313.931Z" fill="black"/>
<path d="M328.672 17.9369C328.672 11.991 333.353 7.13513 339.528 7.13513C345.703 7.13513 350.285 11.991 350.285 17.9369C350.285 23.8829 345.603 28.7387 339.428 28.7387C333.253 28.7387 328.672 23.8829 328.672 17.9369ZM348.193 17.9369C348.193 13.0811 344.408 9.21621 339.428 9.21621C334.449 9.21621 330.664 13.0811 330.664 17.9369C330.664 22.7928 334.449 26.6576 339.428 26.6576C344.408 26.6576 348.193 22.7928 348.193 17.9369Z" fill="black"/>
<path d="M364.527 20.018H358.651V28.3423H356.559V7.53149H364.925C368.411 7.53149 371.2 10.3063 371.2 13.7747C371.2 16.5495 369.308 19.027 366.718 19.7207L371.798 28.3423H369.407L364.527 20.018ZM358.651 18.036H364.925C367.216 18.036 369.108 16.1531 369.108 13.7747C369.108 11.3964 367.216 9.51348 364.925 9.51348H358.651V18.036Z" fill="black"/>
<path d="M188.837 56.8829H178.877L176.885 62.036H174.694L182.762 41.2252H184.953L193.02 62.036H190.829L188.837 56.8829ZM188.14 54.9009L183.957 43.8018L179.774 54.9009H188.14Z" fill="black"/>
<path d="M206.366 53.7117H200.49V62.036H198.398V41.2252H206.765C210.251 41.2252 213.039 44 213.039 47.4685C213.039 50.2432 211.147 52.7207 208.557 53.4144L213.637 62.036H211.247L206.366 53.7117ZM200.49 51.7297H206.765C209.055 51.7297 210.948 49.8468 210.948 47.4685C210.948 45.0901 209.055 43.2072 206.765 43.2072H200.49V51.7297Z" fill="black"/>
<path d="M232.063 43.1081H225.589V61.9369H223.497V43.1081H217.023V41.1261H231.963V43.1081H232.063Z" fill="black"/>
<path d="M239.831 41.2252V62.036H237.739V41.2252H239.831Z" fill="black"/>
<path d="M249.392 43.1081V50.7387H258.655V52.7207H249.392V61.9369H247.301V41.1261H259.053V43.1081H249.392Z" fill="black"/>
<path d="M267.42 41.2252V62.036H265.328V41.2252H267.42Z" fill="black"/>
<path d="M273.694 51.6307C273.694 45.6847 278.276 40.8289 284.65 40.8289C288.534 40.8289 291.921 42.8108 293.713 45.982L291.821 47.0721C290.526 44.5946 287.738 42.9099 284.65 42.9099C279.371 42.9099 275.786 46.7748 275.786 51.6307C275.786 56.4865 279.371 60.3514 284.65 60.3514C287.738 60.3514 290.526 58.6667 291.821 56.1892L293.713 57.1802C292.02 60.2523 288.534 62.3334 284.65 62.3334C278.276 62.3334 273.694 57.5766 273.694 51.6307Z" fill="black"/>
<path d="M301.98 41.2252V62.036H299.888V41.2252H301.98Z" fill="black"/>
<path d="M321.401 56.8829H311.441L309.449 62.036H307.258L315.326 41.2252H317.517L325.584 62.036H323.393L321.401 56.8829ZM320.604 54.9009L316.421 43.8018L312.238 54.9009H320.604Z" fill="black"/>
<path d="M342.616 60.054V62.036H330.963V41.2252H333.054V60.054H342.616Z" fill="black"/>
<path d="M178.977 74.9189V95.7297H176.885V74.9189H178.977Z" fill="black"/>
<path d="M201.984 74.9189V95.7297H200.191L188.538 78.7837V95.7297H186.447V74.9189H188.24L199.892 91.8648V74.9189H201.984Z" fill="black"/>
<path d="M222.601 76.8017H216.127V95.6306H214.035V76.8017H207.562V74.8198H222.501V76.8017H222.601Z" fill="black"/>
<path d="M240.528 93.7477V95.7297H228.278V74.9189H240.429V76.9009H230.469V84.2342H239.732V86.2162H230.469V93.7477H240.528Z" fill="black"/>
<path d="M258.456 93.7477V95.7297H246.803V74.9189H248.894V93.7477H258.456Z" fill="black"/>
<path d="M275.786 93.7477V95.7297H264.133V74.9189H266.224V93.7477H275.786Z" fill="black"/>
<path d="M283.554 74.9189V95.7297H281.463V74.9189H283.554Z" fill="black"/>
<path d="M311.043 86.9099C311.043 91.8649 307.258 96.1261 300.784 96.1261C294.311 96.1261 289.829 91.2703 289.829 85.3243C289.829 79.3784 294.41 74.5225 300.784 74.5225C304.669 74.5225 308.055 76.6036 309.848 79.6757L307.955 80.7658C306.661 78.2883 303.872 76.6036 300.784 76.6036C295.506 76.6036 291.92 80.4685 291.92 85.3243C291.92 90.1802 295.506 94.045 300.784 94.045C305.665 94.045 308.453 91.2703 308.852 87.8018H300.585V85.8198H311.043V86.9099Z" fill="black"/>
<path d="M329.568 93.7477V95.7297H317.318V74.9189H329.369V76.9009H319.409V84.2342H328.672V86.2162H319.409V93.7477H329.568Z" fill="black"/>
<path d="M351.38 74.9189V95.7297H349.587L337.934 78.7837V95.7297H335.843V74.9189H337.636L349.288 91.8648V74.9189H351.38Z" fill="black"/>
<path d="M357.655 85.3243C357.655 79.3784 362.236 74.5225 368.611 74.5225C372.495 74.5225 375.881 76.5045 377.674 79.6757L375.782 80.7658C374.487 78.2883 371.698 76.6036 368.611 76.6036C363.332 76.6036 359.746 80.4685 359.746 85.3243C359.746 90.1802 363.332 94.045 368.611 94.045C371.698 94.045 374.487 92.3604 375.782 89.8829L377.674 90.8739C375.981 93.9459 372.495 96.027 368.611 96.027C362.137 96.027 357.655 91.2703 357.655 85.3243Z" fill="black"/>
<path d="M396 93.7477V95.7297H383.75V74.9189H395.9V76.9009H385.941V84.2342H395.203V86.2162H385.941V93.7477H396Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 7.5 KiB

8
src/assets/csi_logo.svg Normal file
View File

@ -0,0 +1,8 @@
<svg width="154" height="110" viewBox="0 0 154 110" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M126.771 80.1709V90.4772H116.398V86.1168H105.526V87.7024H100.738V86.1168H90.2656V90.4772H79.8926V80.1709H90.2656V84.5313H100.738V82.9457H105.526V84.5313H116.398V80.1709H126.771Z" fill="#E52713"/>
<path d="M147.617 58.171V68.4773H137.144V64.1169H116.398V68.4773H106.025V64.1169H88.1713V72.3422H69.9187V64.1169H49.1726V65.7025H44.385V64.1169H27.6286V68.4773H17.1558V58.171H27.6286V62.5314H44.385V60.9458H49.1726V62.5314H69.9187V54.207H88.1713V62.5314H106.025V58.171H116.398V62.5314H137.144V58.171H147.617Z" fill="#E52713"/>
<path d="M154 35.1802V45.4865H143.627V41.1262H129.663V42.7118H124.776V41.1262H110.014V47.964H94.6541V41.1262H81.4883V42.7118H76.7008V41.1262H64.0337V51.7298H40.9935V41.1262H30.82V45.4865H20.4469V41.1262H10.3731V45.4865H0V35.1802H10.3731V39.5406H20.4469V35.1802H30.82V39.5406H40.9935V28.8379H64.0337V39.5406H76.7008V37.955H81.4883V39.5406H94.6541V32.7028H110.014V39.5406H124.776V37.955H129.663V39.5406H143.627V35.1802H154Z" fill="#E52713"/>
<path d="M134.85 15.856V26.1623H124.477V21.8019H105.127V23.3875H100.34V21.8019H78.1971V26.1623H67.824V21.8019H32.815V26.1623H22.4419V15.856H32.815V20.2163H67.824V15.856H78.1971V20.2163H100.34V18.6307H105.127V20.2163H124.477V15.856H134.85Z" fill="#E52713"/>
<path d="M105.028 0V10.3063H94.6548V5.94594H81.9877V7.63063H77.2002V5.94594H64.6328V10.3063H54.2598V0H64.6328V4.36036H77.2002V2.77477H81.9877V4.36036H94.6548V0H105.028Z" fill="#E52713"/>
<path d="M117.794 99.6938H107.421V110H117.794V99.6938Z" fill="#E52713"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,33 @@
<svg width="221" height="88" viewBox="0 0 221 88" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.68457 10.6815C1.68457 4.80179 6.23903 0 12.5757 0C16.437 0 19.8034 1.95992 21.5856 5.09578L19.7044 6.17373C18.4172 3.72384 15.645 2.05791 12.5757 2.05791C7.32813 2.05791 3.76378 5.87974 3.76378 10.6815C3.76378 15.4833 7.32813 19.3052 12.5757 19.3052C15.645 19.3052 18.4172 17.6392 19.7044 15.1893L21.5856 16.1693C19.9024 19.2072 16.437 21.2651 12.5757 21.2651C6.23903 21.2651 1.68457 16.5613 1.68457 10.6815Z" fill="#343434"/>
<path d="M39.9019 19.0113V20.9712H27.7236V0.39209H39.8028V2.352H29.9018V9.60369H39.1098V11.5636H29.9018V19.0113H39.9019Z" fill="#343434"/>
<path d="M61.5857 0.39209V20.9712H59.8035L48.2193 4.21392V20.9712H46.1401V0.39209H47.9223L59.5065 17.1494V0.39209H61.5857Z" fill="#343434"/>
<path d="M82.0804 2.25337H75.6447V20.8726H73.5655V2.25337H67.1299V0.293457H81.9814V2.25337H82.0804Z" fill="#343434"/>
<path d="M99.9023 19.0113V20.9712H87.7241V0.39209H99.8033V2.352H89.9023V9.60369H99.1103V11.5636H89.9023V19.0113H99.9023Z" fill="#343434"/>
<path d="M113.962 12.7396H108.12V20.9712H106.041V0.39209H114.358C117.823 0.39209 120.595 3.13597 120.595 6.56582C120.595 9.3097 118.714 11.7596 116.14 12.4456L121.19 20.9712H118.813L113.962 12.7396ZM108.219 10.7796H114.457C116.734 10.7796 118.615 8.91772 118.615 6.56582C118.615 4.21392 116.734 2.352 114.457 2.352H108.219V10.7796Z" fill="#343434"/>
<path d="M139.11 2.25337V9.79904H148.318V11.759H139.11V20.8726H137.031V0.293457H148.714V2.25337H139.11Z" fill="#343434"/>
<path d="M153.764 10.6815C153.764 4.80179 158.417 0 164.556 0C170.694 0 175.249 4.80179 175.249 10.6815C175.249 16.5613 170.595 21.3631 164.457 21.3631C158.318 21.3631 153.764 16.5613 153.764 10.6815ZM173.17 10.6815C173.17 5.87974 169.407 2.05791 164.457 2.05791C159.506 2.05791 155.744 5.87974 155.744 10.6815C155.744 15.4833 159.506 19.3052 164.457 19.3052C169.407 19.3052 173.17 15.4833 173.17 10.6815Z" fill="#343434"/>
<path d="M189.407 12.7396H183.566V20.9712H181.486V0.39209H189.803C193.269 0.39209 196.041 3.13597 196.041 6.56582C196.041 9.3097 194.16 11.7596 191.585 12.4456L196.635 20.9712H194.259L189.407 12.7396ZM183.566 10.7796H189.803C192.08 10.7796 193.962 8.91772 193.962 6.56582C193.962 4.21392 192.08 2.352 189.803 2.352H183.566V10.7796Z" fill="#343434"/>
<path d="M14.7537 49.1938H4.85275L2.87255 54.2896H0.694336L8.71414 33.7104H10.8924L18.9122 54.2896H16.7339L14.7537 49.1938ZM14.0607 47.2339L9.90226 36.2583L5.74385 47.2339H14.0607Z" fill="#343434"/>
<path d="M32.1796 46.0579H26.338V54.2896H24.2588V33.7104H32.5756C36.041 33.7104 38.8132 36.4543 38.8132 39.8842C38.8132 42.6281 36.9321 45.078 34.3578 45.7639L39.4073 54.2896H37.0311L32.1796 46.0579ZM26.338 44.098H32.5756C34.8528 44.098 36.734 42.2361 36.734 39.8842C36.734 37.5323 34.8528 35.6704 32.5756 35.6704H26.338V44.098Z" fill="#343434"/>
<path d="M57.7244 35.5722H51.2888V54.1914H49.2096V35.5722H42.7739V33.6123H57.6254V35.5722H57.7244Z" fill="#343434"/>
<path d="M65.4464 33.7104V54.2896H63.3672V33.7104H65.4464Z" fill="#343434"/>
<path d="M74.9518 35.5722V43.1179H84.1597V45.0778H74.9518V54.1914H72.8726V33.6123H84.5557V35.5722H74.9518Z" fill="#343434"/>
<path d="M92.8726 33.7104V54.2896H90.7935V33.7104H92.8726Z" fill="#343434"/>
<path d="M99.1104 43.9999C99.1104 38.1202 103.665 33.3184 110.001 33.3184C113.863 33.3184 117.229 35.2783 119.011 38.4141L117.13 39.4921C115.843 37.0422 113.071 35.3763 110.001 35.3763C104.754 35.3763 101.19 39.1981 101.19 43.9999C101.19 48.8017 104.754 52.6235 110.001 52.6235C113.071 52.6235 115.843 50.9576 117.13 48.5077L119.011 49.4877C117.328 52.5255 113.863 54.5834 110.001 54.5834C103.665 54.5834 99.1104 49.8796 99.1104 43.9999Z" fill="#343434"/>
<path d="M127.229 33.7104V54.2896H125.149V33.7104H127.229Z" fill="#343434"/>
<path d="M146.535 49.1938H136.635L134.654 54.2896H132.476L140.496 33.7104H142.674L150.694 54.2896H148.516L146.535 49.1938ZM145.743 47.2339L141.585 36.2583L137.427 47.2339H145.743Z" fill="#343434"/>
<path d="M167.625 52.3296V54.2896H156.041V33.7104H158.12V52.3296H167.625Z" fill="#343434"/>
<path d="M4.95177 67.0288V87.6079H2.87256V67.0288H4.95177Z" fill="#343434"/>
<path d="M27.823 67.0288V87.6079H26.0408L14.4567 70.8506V87.6079H12.3774V67.0288H14.1596L25.7438 83.7861V67.0288H27.823Z" fill="#343434"/>
<path d="M48.3182 68.8911H41.8825V87.5103H39.8033V68.8911H33.3677V66.9312H48.2192V68.8911H48.3182Z" fill="#343434"/>
<path d="M66.1401 85.648V87.6079H53.9619V67.0288H66.0411V68.9887H56.1401V76.2404H65.3481V78.2003H56.1401V85.648H66.1401Z" fill="#343434"/>
<path d="M83.9616 85.648V87.6079H72.3774V67.0288H74.4567V85.648H83.9616Z" fill="#343434"/>
<path d="M101.189 85.648V87.6079H89.605V67.0288H91.6842V85.648H101.189Z" fill="#343434"/>
<path d="M108.912 67.0288V87.6079H106.833V67.0288H108.912Z" fill="#343434"/>
<path d="M136.239 78.8862C136.239 83.786 132.476 87.9998 126.041 87.9998C119.605 87.9998 115.149 83.198 115.149 77.3183C115.149 71.4385 119.704 66.6367 126.041 66.6367C129.902 66.6367 133.268 68.6946 135.05 71.7325L133.169 72.8104C131.882 70.3606 129.11 68.6946 126.041 68.6946C120.793 68.6946 117.229 72.5165 117.229 77.3183C117.229 82.12 120.793 85.9419 126.041 85.9419C130.892 85.9419 133.664 83.198 134.06 79.7681H125.843V77.8082H136.239V78.8862Z" fill="#343434"/>
<path d="M154.655 85.648V87.6079H142.477V67.0288H154.457V68.9887H144.556V76.2404H153.764V78.2003H144.556V85.648H154.655Z" fill="#343434"/>
<path d="M176.338 67.0288V87.6079H174.555L162.971 70.8506V87.6079H160.892V67.0288H162.674L174.258 83.7861V67.0288H176.338Z" fill="#343434"/>
<path d="M182.575 77.3183C182.575 71.4385 187.13 66.6367 193.466 66.6367C197.328 66.6367 200.694 68.5966 202.476 71.7325L200.595 72.8104C199.308 70.3606 196.536 68.6946 193.466 68.6946C188.219 68.6946 184.654 72.5165 184.654 77.3183C184.654 82.12 188.219 85.9419 193.466 85.9419C196.536 85.9419 199.308 84.2759 200.595 81.8261L202.476 82.806C200.793 85.8439 197.328 87.9018 193.466 87.9018C187.031 87.9018 182.575 83.198 182.575 77.3183Z" fill="#343434"/>
<path d="M220.694 85.648V87.6079H208.516V67.0288H220.595V68.9887H210.694V76.2404H219.902V78.2003H210.694V85.648H220.694Z" fill="#343434"/>
</svg>

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -1,105 +0,0 @@
import React from 'react';
import {FlexColumn, FlexRow, ImageBackground} from '../../utils/containers';
import {Body, H2, Medium} from '../../utils/fonts';
import CircleNumber from '../generic/CircleNumber';
import Media from 'react-media';
import theme from '../../utils/theme';
import commercialImage from '../../assets/commercial-image.svg';
const Commercial = () => {
const listItemsContent = [
'A company comes to CSI with a business need',
'CSI determines the need with an appropriate challenge on Gonito',
'The challenge is solved by willing users',
'The company appropriately rewards users who have contributed to the required outcome',
];
const mobileRender = () => {
return (
<FlexColumn as='section' alignmentX='flex-start'>
<H2 as='h2' margin='0 0 24px 0'>
Commercial challenges
</H2>
<FlexColumn gap='20px'>
<Body as='p'>
The artificial intelligence center works with companies by accepting
machine learning challenges from them that are available to solve on Gonito.
Each commercial challenge is properly scored which translates into an award
for solving it according to the client's requirements.
</Body>
<FlexColumn as='ul' gap='16px' alignmentX='flex-start'>
{
listItemsContent.map((item, index) => {
return (
<FlexRow key={`commercial-item-${index}`} width='100%' gap='8px'>
<CircleNumber number={String(index + 1)}/>
<Medium width='80%' as='li'>
{item}
</Medium>
</FlexRow>
);
})
}
</FlexColumn>
<Body as='p'>
Open challenges can allow you to find the right people to work with.
Find a challenge for your team and take it on!
</Body>
</FlexColumn>
</FlexColumn>
);
};
const desktopRender = () => {
return (
<FlexRow gap='46px'>
<FlexColumn as='section' alignmentX='flex-start' maxWidth='490px'>
<H2 as='h2' margin='0 0 48px 0'>
Commercial challenges
</H2>
<FlexColumn gap='32px'>
<Body as='p'>
The artificial intelligence center works with companies by accepting
machine learning challenges from them that are available to solve on Gonito.
Each commercial challenge is properly scored which translates into an award
for solving it according to the client's requirements.
</Body>
<FlexColumn as='ul' gap='24px' alignmentX='flex-start'>
{
listItemsContent.map((item, index) => {
return (
<FlexRow key={`commercial-item-${index}`} width='100%' gap='16px'>
<CircleNumber number={String(index + 1)}/>
<Medium width='80%' as='li'>
{item}
</Medium>
</FlexRow>
);
})
}
</FlexColumn>
<Body as='p'>
Open challenges can allow you to find the right people to work with.
Find a challenge for your team and take it on!
</Body>
</FlexColumn>
</FlexColumn>
<ImageBackground image={commercialImage} width='200px' height='284px' size='contain'/>
</FlexRow>
);
};
return (
<>
<Media query={theme.mobile}>
{mobileRender()}
</Media>
<Media query={theme.desktop}>
{desktopRender()}
</Media>
</>
);
};
export default Commercial;

View File

@ -1,45 +0,0 @@
import React from 'react';
import {Container, FlexRow} from '../../utils/containers';
import styled from 'styled-components';
import {Medium} from '../../utils/fonts';
import {CSI_LINK} from '../../utils/globals';
const FooterStyle = styled(FlexRow)`
width: 100%;
height: 48px;
display: flex;
justify-content: center;
align-items: center;
background-color: ${({theme}) => theme.colors.green};
z-index: 1000;
position: relative;
p, a {
color: ${({theme}) => theme.colors.white}
}
a {
text-decoration: underline;
cursor: pointer;
}
@media (min-width: ${({theme}) => theme.overMobile}) {
height: 72px;
}
`;
const Footer = () => {
return (
<FooterStyle as='footer'>
<Medium as='p'>
Read more about&nbsp;
<Container as='a' display='inline' target='_blank'
href={CSI_LINK}>
CSI
</Container>
</Medium>
</FooterStyle>
);
};
export default Footer;

View File

@ -1,93 +0,0 @@
import React from 'react';
import { Body, H1, Medium } from '../../utils/fonts';
import { Container, FlexColumn, FlexRow, Svg } from '../../utils/containers';
import theme from '../../utils/theme';
import ButtonLink from '../generic/ButtonLink';
import Media from 'react-media';
import codepenIco from '../../assets/codepen_ico.svg';
import styled from 'styled-components';
import KeyCloakService from '../../services/KeyCloakService';
const TitleParagraph = styled(Medium)`
font-size: 20px;
line-height: 28px;
`;
const Hero = (props) => {
const mobileRender = () => {
return (
<FlexColumn alignmentX="flex-start" gap="24px" maxWidth="452px">
<H1 as="h1">
Welcome to
<Container display="inline" color={theme.colors.green}>
&nbsp;Gonito!
</Container>
</H1>
<Body as="p">
A data challenge platform for machine learning research, competition,
cooperation and reproducibility.
</Body>
<ButtonLink
as="button"
onClick={() =>
props.popUpMessageHandler(
'Reminder',
'Remember to check your spam mailbox to confirm your account.',
() => KeyCloakService.doRegister
)
}
>
Join us!
</ButtonLink>
</FlexColumn>
);
};
const desktopRender = () => {
return (
<FlexColumn alignmentX="flex-start" gap="24px">
<H1 as="h1">
Welcome to
<Container display="inline" color={theme.colors.green}>
&nbsp;Gonito!
</Container>
</H1>
<FlexRow gap="20px">
<Container>
<TitleParagraph as="p" maxWidth="286px" margin="0 0 20px 0">
A data challenge platform for machine learning research,
competition, cooperation and reproducibility.
</TitleParagraph>
<ButtonLink
as="button"
onClick={() =>
props.popUpMessageHandler(
'Reminder',
'Remember to check your spam mailbox to confirm your account.',
() => KeyCloakService.doRegister
)
}
>
Join us!
</ButtonLink>
</Container>
<Svg
src={codepenIco}
width="180px"
height="150px"
size="contain"
backgroundColor={theme.colors.green}
/>
</FlexRow>
</FlexColumn>
);
};
return (
<>
<Media query={theme.mobile}>{mobileRender()}</Media>
<Media query={theme.desktop}>{desktopRender()}</Media>
</>
);
};
export default Hero;

View File

@ -1,82 +0,0 @@
import React from 'react';
import {FlexColumn, FlexRow, ImageBackground, Svg} from '../../utils/containers';
import {Body, H2} from '../../utils/fonts';
import cubeIcon from '../../assets/cube_ico.svg';
import theme from '../../utils/theme';
import Media from 'react-media';
import ellipse from '../../assets/ellipse.svg';
const Motivation = () => {
const content = [
'Explore interesting solutions to problems using AI',
'Train by solving our challenges',
'Participate in competitions with commercial challenges'
];
const mobileRender = () => {
return (
<FlexColumn as='section' alignmentX='flex-start' gap='24px' width='100%'>
<H2 as='h2'>
Motivation
</H2>
<FlexColumn as='ul' gap='16px' alignmentX='flex-start'>
{
content.map((paragraph, index) => {
return (
<FlexRow key={`motivation-${index}`} as='li' gap='12px' alignmentX='flex-start'
alignmentY='flex-start'>
<Svg src={cubeIcon} width='14px' height='14px' margin='4px 0 0 0'
backgroundColor={theme.colors.green}/>
<Body as='p' width='90%'>
{paragraph}
</Body>
</FlexRow>
);
})
}
</FlexColumn>
</FlexColumn>
);
};
const desktopRender = () => {
return (
<ImageBackground as='section' image={ellipse}
gap='48px' width='612px' height='458px'>
<H2 as='h2'>
Motivation
</H2>
<FlexColumn as='ul' gap='22px' alignmentX='flex-start'>
{
content.map((paragraph, index) => {
return (
<FlexRow key={`motivation-${index}`} as='li' gap='16px' alignmentY='flex-start'>
<Svg src={cubeIcon} width='20px' height='20px' size='cover' margin='2px 0 0 0'
backgroundColor={theme.colors.green}/>
<Body as='p' maxWidth='380px'>
{paragraph}
</Body>
</FlexRow>
);
})
}
</FlexColumn>
</ImageBackground>
);
};
return (
<>
<Media query={theme.mobile}>
{mobileRender()}
</Media>
<Media query={theme.desktop}>
{desktopRender()}
</Media>
</>
);
};
export default Motivation;

View File

@ -1,48 +0,0 @@
import React from 'react';
import {FlexColumn, Grid} from '../../utils/containers';
import {H2} from '../../utils/fonts';
import Placeholder from '../generic/Placeholder';
import styled from 'styled-components';
const PartnershipsStyle = styled(FlexColumn)`
justify-content: flex-start;
gap: 32px;
@media (min-width: ${({theme}) => theme.overMobile}) {
gap: 64px;
.grid {
grid-template-rows: 1fr 1fr;
grid-template-columns: 1fr 1fr;
grid-gap: 64px;
}
}
`;
const Partnerships = () => {
return (
<PartnershipsStyle as='section'>
<H2 as='h2'>
Our partnerships
</H2>
<FlexColumn width='100%'>
<Grid className='grid' gridGap='32px 0'>
<Placeholder>
1
</Placeholder>
<Placeholder>
2
</Placeholder>
<Placeholder>
3
</Placeholder>
<Placeholder>
4
</Placeholder>
</Grid>
</FlexColumn>
</PartnershipsStyle>
);
};
export default Partnerships;

View File

@ -1,14 +1,14 @@
import React from 'react';
import styled from 'styled-components';
import {Label} from '../../utils/fonts';
import { Label } from '../../utils/fonts';
import PropsTypes from 'prop-types';
const ButtonLinkStyle = styled(Label)`
background-color: ${({theme}) => theme.colors.green};
color: ${({theme}) => theme.colors.white};
background-color: ${({ theme }) => theme.colors.green};
color: ${({ theme }) => theme.colors.white};
border-radius: 12px;
text-align: center;
width: 122px;
width: 144px;
padding: 4px 0;
cursor: pointer;
transition: transform 0.3s ease-in-out;
@ -18,32 +18,32 @@ const ButtonLinkStyle = styled(Label)`
transform: scale(1.15);
}
@media (min-width: ${({theme}) => theme.overMobile}) {
@media (min-width: ${({ theme }) => theme.overMobile}) {
display: flex;
justify-content: center;
align-items: center;
height: 44px;
height: 48px;
}
`;
const ButtonLink = (props) => {
return (
<ButtonLinkStyle as={props.as} onClick={props.onClick}>
{props.children}
</ButtonLinkStyle>
);
return (
<ButtonLinkStyle as={props.as} onClick={props.onClick}>
{props.children}
</ButtonLinkStyle>
);
};
ButtonLink.propTypes = {
as: PropsTypes.string,
onClick: PropsTypes.func,
children: PropsTypes.node,
as: PropsTypes.string,
onClick: PropsTypes.func,
children: PropsTypes.node,
};
ButtonLink.defaultProps = {
children: '',
as: 'div',
onClick: null,
children: '',
as: 'div',
onClick: null,
};
export default ButtonLink;
export default ButtonLink;

View File

@ -0,0 +1,14 @@
import styled from 'styled-components';
import { FlexColumn } from '../../../utils/containers';
const EntireScreenLoadingStyle = styled(FlexColumn)`
width: 100%;
height: 100vh;
z-index: 1000;
position: fixed;
top: 0;
left: 0;
background-color: ${({ theme }) => theme.colors.white};
`;
export default EntireScreenLoadingStyle;

View File

@ -0,0 +1,13 @@
import React from 'react';
import EntireScreenLoadingStyle from './EntireScreenLoadingStyle';
import Loading from '../Loading';
const EntireScreenLoading = () => {
return (
<EntireScreenLoadingStyle>
<Loading />
</EntireScreenLoadingStyle>
);
};
export default EntireScreenLoading;

View File

@ -1,24 +1,29 @@
import React from 'react';
import {H1} from '../../utils/fonts';
import { H1 } from '../../utils/fonts';
import theme from '../../utils/theme';
import {Link} from 'react-router-dom';
import { Link } from 'react-router-dom';
import styled from 'styled-components';
const LogoStyle = styled(H1)`
font-size: 24px;
@media (min-width: ${({theme}) => theme.overMobile}) {
@media (min-width: ${({ theme }) => theme.overMobile}) {
font-size: 32px;
line-height: 32px;
}
`;
const Logo = () => {
return (
<LogoStyle as={Link} cursor='pointer' to='/' color={theme.colors.green}>
Gonito
</LogoStyle>
);
const Logo = (props) => {
return (
<LogoStyle
as={props.navOptions ? Link : 'span'}
cursor="pointer"
to="/"
color={theme.colors.green}
>
Gonito
</LogoStyle>
);
};
export default Logo;
export default Logo;

View File

@ -1,79 +1,19 @@
import React from 'react';
import { Container, FlexColumn, FlexRow, Grid } from '../../utils/containers';
import {
Container,
FlexColumn,
FlexRow,
Grid,
} from '../../../utils/containers';
import Media from 'react-media';
import theme from '../../utils/theme';
import { ELEMENTS_PER_PAGE, IS_MOBILE } from '../../utils/globals';
import { Body, Medium } from '../../utils/fonts';
import styled from 'styled-components';
import ColumnFilterIcon from './ColumnFilterIcon';
const TableStyle = styled(FlexColumn)`
overflow-x: ${({metrics}) => metrics > 10 ? 'scroll' : 'auto'};
`;
const Line = styled(FlexRow)`
position: absolute;
top: ${({ top }) => (top ? top : 'auto')};
bottom: ${({ bottom }) => (bottom ? bottom : 'auto')};
left: 0;
width: 100%;
background-color: ${({ theme }) => theme.colors.dark04};
height: ${({ height }) => (height ? height : '1px')};
`;
const MobileTableStyle = styled(Container)`
width: 100%;
border-collapse: collapse;
margin: 32px 0;
tr:nth-of-type(odd) {
background: ${({ theme }) => theme.colors.dark03};
}
th {
background: ${({ theme }) => theme.colors.dark05};
color: ${({ theme }) => theme.colors.white};
}
td,
th {
padding: 6px;
border: 1px solid ${({ theme }) => theme.colors.white};
text-align: left;
}
display: block;
thead,
tbody,
th,
td {
display: block;
}
thead tr {
position: absolute;
top: -9999px;
left: -9999px;
}
td {
border: none;
border-bottom: 1px solid ${({ theme }) => theme.colors.dark01};
position: relative;
padding-left: 50%;
}
.mobile-table-header {
font-weight: 400;
position: absolute;
top: 6px;
left: 6px;
width: 45%;
padding-right: 10px;
white-space: nowrap;
}
`;
import theme from '../../../utils/theme';
import { ELEMENTS_PER_PAGE, IS_MOBILE } from '../../../utils/globals';
import { Body, Medium } from '../../../utils/fonts';
import ColumnFilterIcon from '../ColumnFilterIcon';
// import deleteSubmission from '../../api/deleteSubmission';
import TableStyle from './styles/TableStyle';
import TableLine from './styles/TableLine';
import MobileTableStyle from './styles/MobileTableStyle';
const Table = (props) => {
const [, updateState] = React.useState();
@ -128,6 +68,7 @@ const Table = (props) => {
const rowRender = (elem) => {
let RowStyle = Body;
console.log(elem);
if (elem.submitter === props.user) RowStyle = Medium;
return props.staticColumnElements.map((elemName, i) => {
return (
@ -139,6 +80,8 @@ const Table = (props) => {
margin="auto 0"
minWidth="88px"
overflowWrap="anywhere"
cursor="pointer"
// onClick={props.myEntries && (() => deleteSubmission(elem.id))}
>
{IS_MOBILE() && (
<Container className="mobile-table-header">
@ -196,8 +139,6 @@ const Table = (props) => {
padding="0 4px 0 0"
overflowWrap="anywhere"
minWidth="72px"
// minWidth={elem === 'result' ? '72px' : 'none'}
>
{elem.replace('.', ' ')}
</Medium>
@ -212,7 +153,7 @@ const Table = (props) => {
</FlexRow>
);
})}
<Line
<TableLine
height="2px"
top="calc(100% + 2px)"
as="td"

View File

@ -0,0 +1 @@
export { default } from './Table';

View File

@ -0,0 +1,58 @@
import styled from 'styled-components';
import { Container } from '../../../../utils/containers';
const MobileTableStyle = styled(Container)`
width: 100%;
border-collapse: collapse;
margin: 32px 0;
tr:nth-of-type(odd) {
background: ${({ theme }) => theme.colors.dark03};
}
th {
background: ${({ theme }) => theme.colors.dark05};
color: ${({ theme }) => theme.colors.white};
}
td,
th {
padding: 6px;
border: 1px solid ${({ theme }) => theme.colors.white};
text-align: left;
}
display: block;
thead,
tbody,
th,
td {
display: block;
}
thead tr {
position: absolute;
top: -9999px;
left: -9999px;
}
td {
border: none;
border-bottom: 1px solid ${({ theme }) => theme.colors.dark01};
position: relative;
padding-left: 50%;
}
.mobile-table-header {
font-weight: 400;
position: absolute;
top: 6px;
left: 6px;
width: 45%;
padding-right: 10px;
white-space: nowrap;
}
`;
export default MobileTableStyle;

View File

@ -0,0 +1,14 @@
import styled from 'styled-components';
import { FlexRow } from '../../../../utils/containers';
const TableLine = styled(FlexRow)`
position: absolute;
top: ${({ top }) => (top ? top : 'auto')};
bottom: ${({ bottom }) => (bottom ? bottom : 'auto')};
left: 0;
width: 100%;
background-color: ${({ theme }) => theme.colors.dark04};
height: ${({ height }) => (height ? height : '1px')};
`;
export default TableLine;

View File

@ -0,0 +1,8 @@
import styled from 'styled-components';
import { FlexColumn } from '../../../../utils/containers';
const TableStyle = styled(FlexColumn)`
overflow-x: ${({ metrics }) => (metrics > 10 ? 'scroll' : 'auto')};
`;
export default TableStyle;

View File

@ -43,6 +43,7 @@ const NavBar = (props) => {
const mobileMenuHoverFalse = () => {
setMobileMenuHover(false);
};
const toggleNavMenu = () => {
if (navMenuTranslateY === 'calc(-100vh - 42px)') setNavMenuTranslateY('0');
else if (!mobileMenuHover) setNavMenuTranslateY('calc(-100vh - 42px)');
@ -51,51 +52,57 @@ const NavBar = (props) => {
return (
<NavBarStyle as="header">
<FlexRow height="100%" alignmentX="space-between" as="nav">
<Logo />
<MenuButton as="button" onClick={toggleNavMenu} />
<FlexRow as="ul" className="ul-desktop" gap="32px">
<FlexRow as={Link} to={CHALLENGES_PAGE} gap="16px">
<Svg width="16px" height="16px" src={cupIco} />
<Menu as="li">Challenges</Menu>
</FlexRow>
<FlexRow as={Link} to={POLICY_PRIVACY_PAGE} gap="12px">
<Svg size="cover" width="16px" height="16px" src={policyIco} />
<Menu as="li">Privacy policy</Menu>
</FlexRow>
{!KeyCloakService.isLoggedIn() ? (
<FlexRow
as="button"
onClick={() =>
props.popUpMessageHandler(
'Reminder',
'Remember to check your spam mailbox to confirm your account.',
() => KeyCloakService.doRegister
)
}
gap="16px"
>
<Svg width="16px" height="16px" src={registerIco} />
<Menu as="li">Register</Menu>
<Logo navOptions={props.navOptions} />
{props.navOptions && (
<>
<MenuButton as="button" onClick={toggleNavMenu} />
<FlexRow as="ul" className="ul-desktop" gap="32px">
<FlexRow as={Link} to={CHALLENGES_PAGE} gap="16px">
<Svg width="16px" height="16px" src={cupIco} />
<Menu as="li">Challenges</Menu>
</FlexRow>
<FlexRow as={Link} to={POLICY_PRIVACY_PAGE} gap="12px">
<Svg size="cover" width="16px" height="16px" src={policyIco} />
<Menu as="li">Privacy policy</Menu>
</FlexRow>
{!KeyCloakService.isLoggedIn() && (
<FlexRow
as="button"
onClick={() =>
props.popUpMessageHandler(
'Reminder',
'Remember to check your spam mailbox to confirm your account.',
() => KeyCloakService.doRegister
)
}
gap="16px"
>
<Svg width="16px" height="16px" src={registerIco} />
<Menu as="li">Register</Menu>
</FlexRow>
)}
{KeyCloakService.isLoggedIn() ? (
<Svg
as="button"
onClick={props.loggedBarVisibleHandler}
width="32px"
height="32px"
src={userIco}
margin="0 16px 0 0"
/>
) : (
<FlexRow
as="button"
onClick={KeyCloakService.doLogin}
gap="16px"
>
<Svg width="16px" height="16px" src={loginIco} />
<Menu as="li">Sign in</Menu>
</FlexRow>
)}
</FlexRow>
) : (
''
)}
{KeyCloakService.isLoggedIn() ? (
<Svg
as="button"
onClick={props.loggedBarVisibleHandler}
width="32px"
height="32px"
src={userIco}
margin="0 16px 0 0"
/>
) : (
<FlexRow as="button" onClick={KeyCloakService.doLogin} gap="16px">
<Svg width="16px" height="16px" src={loginIco} />
<Menu as="li">Sign in</Menu>
</FlexRow>
)}
</FlexRow>
</>
)}
</FlexRow>
<MobileNavMenu
mobileMenuHoverTrue={mobileMenuHoverTrue}

View File

@ -11,7 +11,7 @@ import {
} from '../../utils/globals';
import Loading from '../../components/generic/Loading';
import Pager from '../../components/generic/Pager';
import Table from '../../components/generic/Table';
import Table from '../../components/generic/Table/Table';
import Search from '../../components/generic/Search';
import allEntriesSearchQueryHandler from './allEntriesSearchQueryHandler';
import getAllEntries from '../../api/getAllEntries';

View File

@ -69,6 +69,16 @@ const MiniChallenge = (props) => {
}
};
const baselineRender = () => {
if (props.baseline) {
return (
<IconLabel size="24px" gap="8px" type="baseline">
{props.baseline}
</IconLabel>
);
}
};
return (
<ChallengeStyle as={Link} to={`${CHALLENGE_PAGE}/${props.name}`}>
<FlexColumn as="article">
@ -99,12 +109,10 @@ const MiniChallenge = (props) => {
{props.metric ? props.metric : 'xxx'}
</IconLabel>
<IconLabel size="24px" gap="8px" type="bestScore">
{props.bestScore ? props.bestScore : 'xxx'}
{props.bestScore ? props.bestScore.slice(0, 6) : 'xxx'}
</IconLabel>
{deadlineRender()}
<IconLabel size="24px" gap="8px" type="baseline">
{props.baseline ? props.baseline : 'xxx'}
</IconLabel>
{baselineRender()}
{props.prize ? (
<IconLabel size="24px" gap="8px" type="prize">
{props.prize}

View File

@ -1,46 +0,0 @@
import React from 'react';
import { FlexColumn } from '../utils/containers';
import Motivation from '../components/content_sections/Motivation';
import Csi from '../components/content_sections/Csi';
import Commercial from '../components/content_sections/Commercial';
import Hero from '../components/content_sections/Hero';
import Partnerships from '../components/content_sections/Partnerships';
import styled from 'styled-components';
const LandingPageStyle = styled(FlexColumn)`
justify-content: flex-start;
width: 100%;
min-height: 100vh;
padding: 90px 0 32px;
.main-container {
max-width: 452px;
gap: 48px;
width: 80%;
}
@media (min-width: ${({ theme }) => theme.overMobile}) {
padding: 172px 0 124px;
.main-container {
max-width: none;
gap: 124px;
}
}
`;
const LandingPage = (props) => {
return (
<LandingPageStyle as="main">
<FlexColumn className="main-container">
<Hero popUpMessageHandler={props.popUpMessageHandler} />
<Motivation />
<Csi />
<Commercial />
<Partnerships />
</FlexColumn>
</LandingPageStyle>
);
};
export default LandingPage;

View File

@ -0,0 +1,35 @@
import React from 'react';
import { FlexColumn } from '../../utils/containers';
import Motivation from './components/Motivation/Motivation';
import Csi from './components/Csi/Csi';
import Commercial from './components/Commercial/Commercial';
import Hero from './components/Hero/Hero';
import Partnerships from './components/Partnerships/Partnerships';
import LandingPageStyle from './LandingPageStyle';
import EntireScreenLoading from '../../components/generic/EntireScreenLoading/EntrieScreenLoading';
const LandingPage = (props) => {
const [show, setShow] = React.useState(false);
React.useEffect(() => {
setTimeout(() => {
setShow(true);
}, 1000);
}, []);
if (show) {
return (
<LandingPageStyle as="main">
<Hero popUpMessageHandler={props.popUpMessageHandler} />
<FlexColumn className="LandingPageStyle__main-container">
<Motivation />
<Csi />
<Commercial />
<Partnerships />
</FlexColumn>
</LandingPageStyle>
);
} else return <EntireScreenLoading />;
};
export default LandingPage;

View File

@ -0,0 +1,25 @@
import styled from 'styled-components';
import { FlexColumn } from '../../utils/containers';
const LandingPageStyle = styled(FlexColumn)`
justify-content: flex-start;
width: 100%;
min-height: 100vh;
padding: 0 32px;
.LandingPageStyle__main-container {
max-width: 452px;
gap: 48px;
width: 80%;
}
@media (min-width: ${({ theme }) => theme.overMobile}) {
padding: 0 124px 124px;
.LandingPageStyle__main-container {
max-width: none;
gap: 124px;
}
}
`;
export default LandingPageStyle;

View File

@ -0,0 +1,115 @@
import React from 'react';
import {
FlexColumn,
FlexRow,
ImageBackground,
} from '../../../../utils/containers';
import { Body, H2, Medium } from '../../../../utils/fonts';
import CircleNumber from '../../../../components/generic/CircleNumber';
import Media from 'react-media';
import theme from '../../../../utils/theme';
import commercialImage from '../../../../assets/commercial-image.svg';
const Commercial = () => {
const listItemsContent = [
'A company comes to CSI with a business need',
'CSI determines the need with an appropriate challenge on Gonito',
'The challenge is solved by willing users',
'The company appropriately rewards users who have contributed to the required outcome',
];
const mobileRender = () => {
return (
<FlexColumn as="section" alignmentX="flex-start">
<H2 as="h2" margin="0 0 24px 0">
Commercial challenges
</H2>
<FlexColumn gap="20px">
<Body as="p">
The artificial intelligence center works with companies by accepting
machine learning challenges from them that are available to solve on
Gonito. Each commercial challenge is properly scored which
translates into an award for solving it according to the client's
requirements.
</Body>
<FlexColumn as="ul" gap="16px" alignmentX="flex-start">
{listItemsContent.map((item, index) => {
return (
<FlexRow
key={`commercial-item-${index}`}
width="100%"
gap="8px"
>
<CircleNumber number={String(index + 1)} />
<Medium width="80%" as="li">
{item}
</Medium>
</FlexRow>
);
})}
</FlexColumn>
<Body as="p">
Open challenges can allow you to find the right people to work with.
Find a challenge for your team and take it on!
</Body>
</FlexColumn>
</FlexColumn>
);
};
const desktopRender = () => {
return (
<FlexRow gap="46px">
<FlexColumn as="section" alignmentX="flex-start" maxWidth="490px">
<H2 as="h2" margin="0 0 48px 0">
Commercial challenges
</H2>
<FlexColumn gap="32px">
<Body as="p">
The artificial intelligence center works with companies by
accepting machine learning challenges from them that are available
to solve on Gonito. Each commercial challenge is properly scored
which translates into an award for solving it according to the
client's requirements.
</Body>
<FlexColumn as="ul" gap="24px" alignmentX="flex-start">
{listItemsContent.map((item, index) => {
return (
<FlexRow
key={`commercial-item-${index}`}
width="100%"
gap="16px"
>
<CircleNumber number={String(index + 1)} />
<Medium width="80%" as="li">
{item}
</Medium>
</FlexRow>
);
})}
</FlexColumn>
<Body as="p">
Open challenges can allow you to find the right people to work
with. Find a challenge for your team and take it on!
</Body>
</FlexColumn>
</FlexColumn>
<ImageBackground
image={commercialImage}
width="180px"
height="274px"
size="contain"
/>
</FlexRow>
);
};
return (
<>
<Media query={theme.mobile}>{mobileRender()}</Media>
<Media query={theme.desktop}>{desktopRender()}</Media>
</>
);
};
export default Commercial;

View File

@ -0,0 +1 @@
export { default } from './Commercial';

View File

@ -1,9 +1,9 @@
import React from 'react';
import { FlexColumn, FlexRow, Svg } from '../../utils/containers';
import { Body, H2, Medium } from '../../utils/fonts';
import { FlexColumn, FlexRow, Svg } from '../../../../utils/containers';
import { Body, H2, Medium } from '../../../../utils/fonts';
import Media from 'react-media';
import theme from '../../utils/theme';
import uamLogo from '../../assets/uam-logo.svg';
import theme from '../../../../utils/theme';
import csiLogo from '../../../../assets/csi_logo.svg';
const Csi = () => {
const mobileRender = () => {
@ -37,33 +37,31 @@ const Csi = () => {
const desktopRender = () => {
return (
<FlexRow gap="46px">
<FlexColumn as="section" alignmentX="flex-start" maxWidth="490px">
<H2 as="h2" margin="0 0 48px 0">
Center for Artificial Intelligence (C4AI)
</H2>
<Body as="p" margin="0 0 24px 0">
<Medium as="span" display="inline">
Gonito.net
</Medium>{' '}
belongs to the
<Medium as="span" display="inline">
&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>
<Medium as="p">
C4AI also cooperates with business entities in creating new
solutions to be implemented in enterprises.
<FlexColumn as="section" alignmentX="flex-start" maxWidth="640px">
<FlexRow margin="0 0 48px 0">
<H2 as="h2">Center for Artificial Intelligence (C4AI)</H2>
<Svg src={csiLogo} size="contain" width="230px" height="80px" />
</FlexRow>
<Body as="p" margin="0 0 24px 0">
<Medium as="span" display="inline">
Gonito.net
</Medium>{' '}
belongs to the
<Medium as="span" display="inline">
&nbsp;Center for Artificial Intelligence (C4AI)&nbsp;
</Medium>
</FlexColumn>
<Svg src={uamLogo} width="200px" height="242px" size="contain" />
</FlexRow>
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>
<Medium as="p">
C4AI also cooperates with business entities in creating new solutions
to be implemented in enterprises.
</Medium>
</FlexColumn>
);
};

View File

@ -0,0 +1 @@
export { default } from './Csi';

View File

@ -0,0 +1,123 @@
import React from 'react';
import { Body, H1, Medium } from '../../../../utils/fonts';
import { Container, FlexColumn, FlexRow } from '../../../../utils/containers';
import theme from '../../../../utils/theme';
import ButtonLink from '../../../../components/generic/ButtonLink';
import Media from 'react-media';
import KeyCloakService from '../../../../services/KeyCloakService';
import MadeByCsi from '../MadeByCsi/MadeByCsi';
import HeroStyle from './HeroStyle';
const Hero = (props) => {
const mobileRender = () => {
return (
<FlexColumn
alignmentX="flex-start"
gap="24px"
margin="80px 0 48px 0"
maxWidth="452px"
>
<H1 as="h1">
Welcome to
<Container display="inline" color={theme.colors.green}>
&nbsp;Gonito!
</Container>
</H1>
<Body as="p">
A data challenge platform for machine learning research, competition,
cooperation and reproducibility.
</Body>
<ButtonLink
as="button"
onClick={() =>
props.popUpMessageHandler(
'Reminder',
'Remember to check your spam mailbox to confirm your account.',
() => KeyCloakService.doRegister
)
}
>
Join us!
</ButtonLink>
</FlexColumn>
);
};
const desktopRender = () => {
return (
<HeroStyle>
<FlexColumn alignmentX="flex-start" gap="40px">
<H1 as="h1">
Welcome to
<Container display="inline" color={theme.colors.green}>
&nbsp;Gonito!
</Container>
</H1>
<Medium as="p" className="HeroStyle__title-paragraph">
A data challenge platform for machine learning research,
competition, cooperation and reproducibility.
</Medium>
<MadeByCsi position="horizontal" />
<ButtonLink
as="button"
onClick={() =>
props.popUpMessageHandler(
'Reminder',
'Remember to check your spam mailbox to confirm your account.',
() => KeyCloakService.doRegister
)
}
>
Join us!
</ButtonLink>
</FlexColumn>
</HeroStyle>
);
};
const desktopRender2 = () => {
return (
<HeroStyle>
<FlexRow gap="100px">
<FlexColumn gap="50px" alignmentX="flex-start">
<H1 as="h1">
Welcome to
<Container display="inline" color={theme.colors.green}>
&nbsp;Gonito!
</Container>
</H1>
<Medium as="p" className="HeroStyle__title-paragraph">
A data challenge platform for machine learning research,
competition, cooperation and reproducibility.
</Medium>
<ButtonLink
as="button"
onClick={() =>
props.popUpMessageHandler(
'Reminder',
'Remember to check your spam mailbox to confirm your account.',
() => KeyCloakService.doRegister
)
}
>
Join us!
</ButtonLink>
</FlexColumn>
<MadeByCsi />
</FlexRow>
</HeroStyle>
);
};
return (
<>
<Media query={theme.mobile}>{mobileRender()}</Media>
<Media query="(min-width: 1025px) and (max-width: 1440px)">
{desktopRender()}
</Media>
<Media query="(min-width: 1441px)">{desktopRender2()}</Media>
</>
);
};
export default Hero;

View File

@ -0,0 +1,31 @@
import styled from 'styled-components';
import { FlexColumn } from '../../../../utils/containers';
const HeroStyle = styled(FlexColumn)`
justify-content: flex-start;
gap: 24px;
max-width: 452px;
@media (min-width: 1441px) {
max-width: none;
}
@media (min-width: ${({ theme }) => theme.overMobile}) {
justify-content: center;
width: 100%;
height: calc(100vh - 48px);
}
.HeroStyle__title-paragraph {
font-size: 24px;
line-height: 36px;
font-weight: 300;
max-width: 580px;
@media (min-width: 1441px) {
max-width: 600px;
}
}
`;
export default HeroStyle;

View File

@ -0,0 +1 @@
export { default } from './Hero';

View File

@ -0,0 +1,41 @@
import React from 'react';
import { H1 } from '../../../../utils/fonts';
import { Container, FlexRow, Svg } from '../../../../utils/containers';
import theme from '../../../../utils/theme';
import csiLogo from '../../../../assets/csi_logo.svg';
import csiLogoContent from '../../../../assets/csi_logo_content.svg';
import MadeByCsiStyle from './MadeByCsiStyle';
const MadeByCsi = (props) => {
return (
<MadeByCsiStyle
as="a"
horizontal={props.position}
href="https://csi.amu.edu.pl/"
target="_blank"
>
<H1
as="span"
fontSize={props.position === 'horizontal' ? '36px' : '44px'}
>
Made
<Container as="span" display="inline" color={theme.colors.green}>
&nbsp;by
</Container>
</H1>
<FlexRow gap="20px" className="MadeByCsiStyle__logo-container">
<Svg
className="MadeByCsiStyle__csiLogo"
width="154px"
height="110px"
size="cover"
src={csiLogo}
/>
<Svg width="220px" height="110px" src={csiLogoContent} />
</FlexRow>
</MadeByCsiStyle>
);
};
export default MadeByCsi;

View File

@ -0,0 +1,28 @@
import styled from 'styled-components';
import { FlexColumn } from '../../../../utils/containers';
const MadeByCsiStyle = styled(FlexColumn)`
flex-direction: ${({ horizontal }) => (horizontal ? 'row' : 'column')};
gap: ${({ horizontal }) => (horizontal ? '50px' : '48px')};
align-items: ${({ horizontal }) => (horizontal ? 'center' : 'flex-start')};
cursor: pointer;
* {
cursor: pointer;
}
.MadeByCsiStyle__csiLogo {
transition: background-color 0.4s ease-in-out;
}
.MadeByCsiStyle__logo-container {
transition: transform 0.3s ease-in-out;
}
&:hover {
.MadeByCsiStyle__csiLogo {
background-color: #e52713;
}
.MadeByCsiStyle__logo-container {
transform: scale(1.05);
}
}
`;
export default MadeByCsiStyle;

View File

@ -0,0 +1 @@
export { default } from './MadeByCsi';

View File

@ -0,0 +1,34 @@
import React from 'react';
import { FlexColumn, FlexRow } from '../../../../utils/containers';
import { Body, H2 } from '../../../../utils/fonts';
import cubeIconRender from './functions/cubeIconRender';
import ellipse from '../../../../assets/ellipse.svg';
import MotivationStyle from './MotivationStyle';
import { IS_MOBILE } from '../../../../utils/globals';
import { MOTIVATION__CONTENT } from './utils';
const Motivation = () => {
return (
<MotivationStyle as="section" image={IS_MOBILE() ? null : ellipse}>
<H2 as="h2">Motivation</H2>
<FlexColumn as="ul" className="MotivationStyle__list">
{MOTIVATION__CONTENT.map((paragraph, index) => {
return (
<FlexRow
key={`motivation-${index}`}
as="li"
className="MotivationStyle__item"
>
{cubeIconRender()}
<Body as="p" className="MotivationStyle__paragraph">
{paragraph}
</Body>
</FlexRow>
);
})}
</FlexColumn>
</MotivationStyle>
);
};
export default Motivation;

View File

@ -0,0 +1,48 @@
import styled from 'styled-components';
// import { ImageBackground } from '../../../../utils/containers';
import { ImageBackground } from '../../../../utils/containers';
const MotivationStyle = styled(ImageBackground)`
align-items: flex-start;
gap: 24px;
width: 100%;
.MotivationStyle__list {
gap: 16px;
align-items: flex-start;
}
.MotivationStyle__item {
gap: 12px;
align-items: flex-start;
justify-content: flex-start;
}
.MotivationStyle__paragraph {
width: 90%;
}
@media (min-width: ${({ theme }) => theme.overMobile}) {
gap: 48px;
width: 612px;
height: 458px;
align-items: center;
.MotivationStyle__list {
gap: 22px;
}
.MotivationStyle__item {
gap: 16px;
justify-content: flex-start;
align-items: center;
}
.MotivationStyle__paragraph {
width: auto;
max-width: 380px;
}
}
`;
export default MotivationStyle;

View File

@ -0,0 +1,30 @@
import cubeIcon from '../../../../../assets/cube_ico.svg';
import theme from '../../../../../utils/theme';
import { IS_MOBILE } from '../../../../../utils/globals';
import { Svg } from '../../../../../utils/containers';
const cubeIconRender = () => {
if (IS_MOBILE()) {
return (
<Svg
src={cubeIcon}
width="14px"
height="14px"
margin="4px 0 0 0"
backgroundColor={theme.colors.green}
/>
);
}
return (
<Svg
src={cubeIcon}
width="20px"
height="20px"
size="cover"
margin="2px 0 0 0"
backgroundColor={theme.colors.green}
/>
);
};
export default cubeIconRender;

View File

@ -0,0 +1 @@
export { default } from './Motivation';

View File

@ -0,0 +1,7 @@
const MOTIVATION__CONTENT = [
'Explore interesting solutions to problems using AI',
'Train by solving our challenges',
'Participate in competitions with commercial challenges',
];
export { MOTIVATION__CONTENT };

View File

@ -0,0 +1,25 @@
import React from 'react';
import { FlexColumn, Grid } from '../../../../utils/containers';
import { H2 } from '../../../../utils/fonts';
import Placeholder from '../../../../components/generic/Placeholder';
import PartnershipsStyle from './PartnershipsStyle';
const Partnerships = () => {
return (
<PartnershipsStyle as="section">
<H2 as="h2">Our partnerships</H2>
<FlexColumn width="100%">
<Grid className="grid" gridGap="32px 0">
<Placeholder>allegro</Placeholder>
<Placeholder>pons</Placeholder>
<Placeholder>samsung</Placeholder>
<Placeholder>domdata</Placeholder>
<Placeholder>pwn.pl</Placeholder>
<Placeholder>cararena.pl</Placeholder>
</Grid>
</FlexColumn>
</PartnershipsStyle>
);
};
export default Partnerships;

View File

@ -0,0 +1,21 @@
import styled from 'styled-components';
import { FlexColumn } from '../../../../utils/containers';
const PartnershipsStyle = styled(FlexColumn)`
justify-content: flex-start;
gap: 32px;
margin: 0 0 48px 0;
@media (min-width: ${({ theme }) => theme.overMobile}) {
gap: 64px;
margin: 0;
.grid {
grid-template-rows: 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 64px;
}
}
`;
export default PartnershipsStyle;

View File

@ -0,0 +1 @@
export { default } from './Partnerships';

View File

@ -0,0 +1 @@
export { default } from './LandingPage';

View File

@ -3,7 +3,7 @@ import Media from 'react-media';
import theme from '../../utils/theme';
import { FlexColumn } from '../../utils/containers';
import { H2 } from '../../utils/fonts';
import Table from '../../components/generic/Table';
import Table from '../../components/generic/Table/Table';
import PropsTypes from 'prop-types';
import getChallengeLeaderboard from '../../api/getChallengeLeaderboard';
import leaderboardSearchQueryHandler from './leaderboardSearchQueryHandler';

View File

@ -12,7 +12,7 @@ import {
import Media from 'react-media';
import theme from '../../utils/theme';
import Loading from '../../components/generic/Loading';
import Table from '../../components/generic/Table';
import Table from '../../components/generic/Table/Table';
import myEntriesSearchQueryHandler from './myEntriesSearchQueryHandler';
import Search from '../../components/generic/Search';
@ -190,6 +190,7 @@ const MyEntries = (props) => {
pageNr={pageNr}
elements={myEntries}
sortByUpdate={sortByUpdate}
myEntries
/>
<Pager
pageNr={pageNr}

View File

@ -2,16 +2,16 @@ import React from 'react';
import { createPortal } from 'react-dom';
import { FlexColumn } from '../../utils/containers';
import { H2, Menu } from '../../utils/fonts';
import SubmitInput from '../../components/generic/SubmitInput';
import Button from '../../components/generic/Button';
import theme from '../../utils/theme';
import challengeSubmission from '../../api/challengeSubmissionPost';
import Loading from '../../components/generic/Loading';
import getTags from '../../api/getTags';
import TagsChoose from './components/TagsChoose';
import SubmitReducer from './model/SubmitReducer';
import SUBMIT_ACTION from './model/SubmitActionEnum';
import SubmitStyle from './SubmitStyle';
import SubmissionLoading from './components/SubmissionLoading/SubmissionLoading';
import renderSubmitInputs from './functions/renderSubmitInputs';
const Submit = (props) => {
const [state, dispatch] = React.useReducer(SubmitReducer, {
@ -27,7 +27,7 @@ const Submit = (props) => {
getTags(dispatch);
}, []);
const challengeSubmissionSubmit = () => {
const challengeSubmissionSubmit = React.useCallback(() => {
dispatch({ type: SUBMIT_ACTION.TOGGLE_SUBMISSION_LOADING });
challengeSubmission(
props.challengeName,
@ -37,34 +37,13 @@ const Submit = (props) => {
state.submissionTags,
dispatch
);
};
const setDescription = (value) => {
dispatch({ type: SUBMIT_ACTION.SET_DESCRIPTION, payload: value });
};
const setRepoUrl = (value) => {
dispatch({ type: SUBMIT_ACTION.SET_REPO_URL, payload: value });
};
const setRepoBranch = (value) => {
dispatch({ type: SUBMIT_ACTION.SET_REPO_BRANCH, payload: value });
};
const toggleSubmissionTag = React.useCallback(
(tag) => {
let actionType = '';
if (state.submissionTags.includes(tag))
actionType = SUBMIT_ACTION.REMOVE_SUBMISSION_TAG;
else actionType = SUBMIT_ACTION.ADD_SUBMISSION_TAG;
dispatch({ type: actionType, payload: tag });
},
[state.submissionTags]
);
const clearSubmissionTags = () => {
dispatch({ type: SUBMIT_ACTION.CLEAR_SUBMISSION_TAGS });
};
}, [
props.challengeName,
state.description,
state.repoBranch,
state.repoUrl,
state.submissionTags,
]);
if (!state.submissionLoading) {
return (
@ -73,18 +52,17 @@ const Submit = (props) => {
Submit a solution to the challenge
</H2>
<FlexColumn className="SubmitStyle__form">
<SubmitInput
label="Submission description"
handler={setDescription}
/>
<SubmitInput label="Submission repo URL" handler={setRepoUrl} />
<SubmitInput label="Submission repo branch" handler={setRepoBranch} />
{renderSubmitInputs(dispatch)}
<TagsChoose
label="Submission tags"
toggleSubmissionTag={toggleSubmissionTag}
updateTags={(submissionTags, tags) => {
dispatch({
type: SUBMIT_ACTION.UPDATE_TAGS,
payload: { submissionTags: submissionTags, tags: tags },
});
}}
tags={state.tags}
submissionTags={state.submissionTags}
clearSubmissionTags={clearSubmissionTags}
/>
</FlexColumn>
<Button width="122px" height="44px" handler={challengeSubmissionSubmit}>
@ -93,21 +71,7 @@ const Submit = (props) => {
</SubmitStyle>
);
} 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
);
return createPortal(<SubmissionLoading />, document.body);
}
};

View File

@ -0,0 +1,15 @@
import React from 'react';
import Loading from '../../../../components/generic/Loading';
import { H2 } from '../../../../utils/fonts';
import SubmissionLoadingStyle from './SubmissionLoadingStyle';
const SubmissionLoading = () => {
return (
<SubmissionLoadingStyle>
<H2 as="h1">Submission processing...</H2>
<Loading />
</SubmissionLoadingStyle>
);
};
export default SubmissionLoading;

View File

@ -0,0 +1,14 @@
import styled from 'styled-components';
import { FlexColumn } from '../../../../utils/containers';
const SubmissionLoadingStyle = styled(FlexColumn)`
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
z-index: 100;
background-color: ${({ theme }) => theme.colors.white};
`;
export default SubmissionLoadingStyle;

View File

@ -0,0 +1 @@
export { default } from './SubmissionLoading';

View File

@ -23,12 +23,7 @@ const TagsChoose = (props) => {
className="TagsChooseStyle__grid"
onChange={(e) => props.handler(e.target.value)}
>
<FlexRow
width="100%"
height="100%"
className="TagsChooseStyle__tags-container"
gap="16px"
>
<FlexRow className="TagsChooseStyle__tags-container">
{props.submissionTags.map((tag, i) =>
i === 0 ? tag.name : `, ${tag.name}`
)}
@ -40,9 +35,8 @@ const TagsChoose = (props) => {
<TagsChoosePopUp
tags={props.tags}
submissionTags={props.submissionTags}
toggleSubmissionTag={props.toggleSubmissionTag}
updateTags={props.updateTags}
setTagsPopUp={setTagsPopUp}
clearSubmissionTags={props.clearSubmissionTags}
/>,
document.body
)}

View File

@ -21,6 +21,7 @@ const TagsChooseStyle = styled(FlexColumn)`
}
.TagsChooseStyle__tags-container {
width: 100%;
height: 100%;
justify-content: flex-start;
align-items: flex-start;

View File

@ -6,8 +6,36 @@ import theme from '../../../../utils/theme';
import Button from '../../../../components/generic/Button';
import TagsChoosePopUpStyle from './TagsChoosePopUpStyle';
import renderTagItems from './functions/renderTagItems';
import tagsSearchQueryHandler from './functions/tagsSearchQueryHandler';
const TagsChoosePopUp = (props) => {
const [tagsChoosed, setTagsChoosed] = React.useState([]);
const [tagsInit, setTagsInit] = React.useState([]);
const [tags, setTags] = React.useState([]);
React.useEffect(() => {
setTags(props.tags.slice());
setTagsInit(props.tags.slice());
setTagsChoosed(props.submissionTags.slice());
}, [props.tags, props.submissionTags]);
const toggleTagChoose = (clickedTag) => {
let newTagsChoosed = tagsChoosed;
let newTags = tags;
if (tagsChoosed.includes(clickedTag)) {
newTagsChoosed = newTagsChoosed.filter(
(tag) => tag.name !== clickedTag.name
);
newTags.push(clickedTag);
newTags = newTags.sort((a, b) => a.name.localeCompare(b.name));
} else {
newTagsChoosed.push(clickedTag);
newTags = newTags.filter((tag) => tag.name !== clickedTag.name);
}
setTagsChoosed(newTagsChoosed);
setTags(newTags);
};
return (
<PopUp
width="50%"
@ -16,26 +44,37 @@ const TagsChoosePopUp = (props) => {
closeHandler={() => props.setTagsPopUp(false)}
>
<TagsChoosePopUpStyle>
<Search />
<Search
searchQueryHandler={(e) =>
tagsSearchQueryHandler(e, tagsInit, tagsChoosed, setTags)
}
/>
<FlexColumn as="ul" className="TagsChoosePopUpStyle__tags-list">
{renderTagItems(
props.submissionTags,
props.toggleSubmissionTag,
tagsChoosed,
toggleTagChoose,
`1px dotted ${theme.colors.green}`,
theme.colors.green03,
true
)}
{renderTagItems(props.tags, props.toggleSubmissionTag, 'none')}
{renderTagItems(tags, toggleTagChoose, 'none')}
</FlexColumn>
<FlexRow width="100%" gap="20px" alignmentX="flex-start">
<Button height="32px" width="76px">
<FlexRow className="TagsChoosePopUpStyle__buttons-container">
<Button
height="32px"
width="76px"
handler={() => {
props.updateTags(tagsChoosed, tags);
props.setTagsPopUp(false);
}}
>
Done
</Button>
<Button
height="32px"
width="76px"
backgroundColor={theme.colors.dark08}
handler={() => props.clearSubmissionTags()}
handler={() => setTagsChoosed([])}
>
Clear
</Button>

View File

@ -26,6 +26,12 @@ const TagsChoosePopUpStyle = styled(FlexColumn)`
background-color: ${({ theme }) => theme.colors.green03};
}
}
.TagsChoosePopUpStyle__buttons-container {
width: 100%;
gap: 20px;
justify-content: flex-start;
}
`;
export default TagsChoosePopUpStyle;

View File

@ -0,0 +1,18 @@
const tagsSearchQueryHandler = (event, tagsInit, tagsChoosed, setTags) => {
let tagsToSearch = tagsInit;
for (let tagChoosen of tagsChoosed)
tagsToSearch = tagsToSearch.filter((tag) => tag.name !== tagChoosen.name);
const searchQuery = event.target.value;
let tagsToRender = [];
if (searchQuery === '') {
setTags(tagsToSearch);
} else {
for (let tag of tagsToSearch) {
if (tag.name.toLowerCase().includes(searchQuery.toLowerCase()))
tagsToRender.push(tag);
}
setTags(tagsToRender);
}
};
export default tagsSearchQueryHandler;

View File

@ -0,0 +1,18 @@
import { SUBMIT_INPUTS } from '../utils';
import SubmitInput from '../../../components/generic/SubmitInput';
const renderSubmitInputs = (dispatch) => {
return SUBMIT_INPUTS.map((input, index) => {
return (
<SubmitInput
key={`submit-input-${index}`}
label={input.label}
handler={(value) => {
dispatch({ type: input.action, payload: value });
}}
/>
);
});
};
export default renderSubmitInputs;

View File

@ -4,9 +4,7 @@ const SUBMIT_ACTION = {
SET_REPO_BRANCH: 'set_repo_branch',
TOGGLE_SUBMISSION_LOADING: 'toggle_submission_loading',
LOAD_TAGS: 'load_tags',
ADD_SUBMISSION_TAG: 'add_submission_tag',
REMOVE_SUBMISSION_TAG: 'remove_submission_tag',
CLEAR_SUBMISSION_TAGS: 'clear_submission_tags',
UPDATE_TAGS: 'update_tags',
};
export default SUBMIT_ACTION;

View File

@ -2,7 +2,6 @@ import SUBMIT_ACTION from './SubmitActionEnum';
const SubmitReducer = (state, action) => {
console.log(`SubmitReducer: ${action.type}`);
let newSubmissionTags = state.submissionTags;
let newTags = state.tags;
switch (action.type) {
case SUBMIT_ACTION.SET_DESCRIPTION:
@ -16,24 +15,12 @@ const SubmitReducer = (state, action) => {
case SUBMIT_ACTION.LOAD_TAGS:
if (state.tags.length === 0) newTags = action.payload;
return { ...state, tags: newTags };
case SUBMIT_ACTION.ADD_SUBMISSION_TAG:
if (!newSubmissionTags.includes(action.payload)) {
newTags = state.tags;
newSubmissionTags.push(action.payload);
newTags = newTags.filter((tag) => tag.name !== action.payload.name);
}
return { ...state, submissionTags: newSubmissionTags, tags: newTags };
case SUBMIT_ACTION.REMOVE_SUBMISSION_TAG:
if (newSubmissionTags.includes(action.payload)) {
newSubmissionTags = newSubmissionTags.filter(
(tag) => tag.name !== action.payload.name
);
newTags.push(action.payload);
newTags = newTags.sort((a, b) => a.name.localeCompare(b.name));
}
return { ...state, submissionTags: newSubmissionTags, tags: newTags };
case SUBMIT_ACTION.CLEAR_SUBMISSION_TAGS:
return { ...state, submissionTags: [] };
case SUBMIT_ACTION.UPDATE_TAGS:
return {
...state,
submissionTags: action.payload.submissionTags,
tags: action.payload.tags,
};
default:
throw new Error('Undefined action in SubmitReducer!');
}

View File

@ -0,0 +1,9 @@
import SUBMIT_ACTION from './model/SubmitActionEnum';
const SUBMIT_INPUTS = [
{ label: 'Submission description', action: SUBMIT_ACTION.SET_DESCRIPTION },
{ label: 'Submission repo URL', action: SUBMIT_ACTION.SET_REPO_URL },
{ label: 'Submission repo branch', action: SUBMIT_ACTION.SET_REPO_BRANCH },
];
export { SUBMIT_INPUTS };

View File

@ -9,7 +9,7 @@ const H1 = styled(Container)`
line-height: 24px;
letter-spacing: 0.1px;
@media (min-width: ${({ theme }) => theme.overMobile}) {
font-size: 48px;
font-size: ${({ fontSize }) => (fontSize ? fontSize : '60px')};
line-height: 52px;
}
`;
@ -69,6 +69,7 @@ const Label = styled(Menu)`
@media (min-width: ${({ theme }) => theme.overMobile}) {
font-size: 22px;
line-height: 24px;
font-weight: 400;
}
`;

View File

@ -6,6 +6,7 @@ import cupIco from '../assets/cup_ico.svg';
import textIco from '../assets/text_ico.svg';
import imageIco from '../assets/image_ico.svg';
import tabularIco from '../assets/tabular_ico.svg';
import React from 'react';
const ELEMENTS_PER_PAGE = 12;
const MINI_DESCRIPTION_LENGTH = 70;
@ -119,6 +120,14 @@ const IS_MOBILE = () => {
return document.body.clientWidth <= 1024;
};
const CHILDREN_WITH_PROPS = (propsChildren, props) =>
React.Children.map(propsChildren, (child) => {
if (React.isValidElement(child)) {
return React.cloneElement(child, props);
}
return child;
});
export {
ELEMENTS_PER_PAGE,
API,
@ -142,4 +151,5 @@ export {
EVALUATIONS_FORMAT,
PREVIOUS_PAGE,
NEXT_PAGE,
CHILDREN_WITH_PROPS,
};

View File

@ -0,0 +1,10 @@
const SESSION_STORAGE = {
LOGOUT: 'logout',
LOGGED: 'logged',
STATIC_VALUE: {
YES: 'yes',
NO: 'no',
},
};
export default SESSION_STORAGE;