sort method correction on desktop
This commit is contained in:
parent
5bc8831824
commit
a653176baf
@ -5,8 +5,11 @@ const getChallengeLeaderboard = (setDataState, challengeName, setLoading) => {
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
setDataState(data.entries);
|
||||
if (setLoading)
|
||||
setLoading(false);
|
||||
if (setLoading) {
|
||||
setTimeout(() => {
|
||||
setLoading(false);
|
||||
}, 3000);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1,23 +1,103 @@
|
||||
import React from 'react';
|
||||
import {FlexColumn} from '../../utils/containers';
|
||||
import {FlexColumn, FlexRow, Grid, Svg} from '../../utils/containers';
|
||||
import Media from 'react-media';
|
||||
import theme from '../../utils/theme';
|
||||
import Loading from './Loading';
|
||||
import PropsTypes from 'prop-types';
|
||||
import {ELEMENTS_PER_PAGE, IS_MOBILE} from '../../utils/globals';
|
||||
import {Body, Medium} from '../../utils/fonts';
|
||||
import arrow from '../../assets/arrow.svg';
|
||||
import styled from 'styled-components';
|
||||
|
||||
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 Table = (props) => {
|
||||
const [, updateState] = React.useState();
|
||||
const forceUpdate = React.useCallback(() => updateState({}), []);
|
||||
|
||||
const mobileRender = () => {
|
||||
return (
|
||||
<FlexColumn as='table' margin='20px 0 32px 0' minHeight='380px'>
|
||||
{props.renderElements('10px', props.headerElements)}
|
||||
{/*{props.renderElements('10px', props.headerElements)}*/}
|
||||
</FlexColumn>
|
||||
);
|
||||
};
|
||||
|
||||
const desktopRender = () => {
|
||||
const n = (props.pageNr - 1) * ELEMENTS_PER_PAGE;
|
||||
let submissionToMap = props.submissions.slice(n, n + ELEMENTS_PER_PAGE);
|
||||
return (
|
||||
<FlexColumn as='table' margin='32px 0 72px 0' width='100%'>
|
||||
{props.renderElements('32px', props.headerElements)}
|
||||
<FlexColumn as='tbody' width='100%'>
|
||||
{submissionToMap.map(({
|
||||
submitter,
|
||||
when,
|
||||
evaluations,
|
||||
times
|
||||
}, index) => {
|
||||
return (
|
||||
<Grid as='tr' key={`leaderboard-row-${index}`}
|
||||
backgroundColor={index % 2 === 1 ? theme.colors.dark01 : 'transparent'}
|
||||
gridTemplateColumns={!IS_MOBILE() ? '1fr 3fr ' + '2fr '.repeat(evaluations.length) + '1fr 2fr' : '1fr 3fr 1fr 1fr 2fr'}
|
||||
gridGap='20px' position='relative' width='100%' padding='4px'>
|
||||
{index === 0 ? props.headerElements.map((elem, i) => {
|
||||
return (
|
||||
<FlexRow key={`leaderboard-header-${i}`} alignmentX='flex-start' as='td'
|
||||
onClick={() => {
|
||||
props.sortByUpdate(elem);
|
||||
forceUpdate();
|
||||
}}>
|
||||
<Medium textAlign={elem === 'submitter' ? 'left' : 'right'}
|
||||
width={elem === 'when' ? '100%' : 'auto'} padding='0 6px 0 0'
|
||||
minWidth={elem === 'result' ? '72px' : 'none'} fontSize='18px'>
|
||||
{elem}
|
||||
</Medium>
|
||||
{elem !== '#' ?
|
||||
<>
|
||||
<Svg width='8px' rotate='180deg' src={arrow}
|
||||
backgroundColor={theme.colors.dark} margin='2px 0 0 0'/>
|
||||
<Svg width='8px' src={arrow} backgroundColor={theme.colors.dark}
|
||||
margin='0 0 2px 0'/>
|
||||
</> : ''}
|
||||
</FlexRow>
|
||||
);
|
||||
}) : ''}
|
||||
{index === 0 ? <Line as='td' height='2px' top='38px' shadow={theme.shadow}/> : ''}
|
||||
<Body as='td'>
|
||||
{index + n}
|
||||
</Body>
|
||||
<Body as='td'>
|
||||
{submitter ? submitter : '[anonymous]'}
|
||||
</Body>
|
||||
{!IS_MOBILE() ? evaluations.map((metric, i) => {
|
||||
return (
|
||||
<Body key={`metric-result-${i}`} as='td' textAlign='left' minWidth='72px'>
|
||||
{metric.score.slice(0, 7)}
|
||||
</Body>
|
||||
);
|
||||
}) : <Body as='td' textAlign='left' minWidth='72px'>
|
||||
{evaluations[0] ? evaluations[0].score.slice(0, 7) : 'xxx'}
|
||||
</Body>}
|
||||
<Body as='td' padding='0 2px 0 0' textAlign='left'>
|
||||
{times ? times : 1}
|
||||
</Body>
|
||||
<Body as='td' textAlign='right'>
|
||||
{when ? `${when.slice(11, 16)} ${when.slice(0, 10)}`
|
||||
: 'xxx'}
|
||||
</Body>
|
||||
{index !== 0 ? <Line top='0' as='td'/> : ''}
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</FlexColumn>
|
||||
</FlexColumn>
|
||||
);
|
||||
};
|
||||
|
@ -1,27 +1,25 @@
|
||||
import React from 'react';
|
||||
import Media from 'react-media';
|
||||
import theme from '../../../utils/theme';
|
||||
import {FlexColumn, FlexRow} from '../../../utils/containers';
|
||||
import {H2, H3} from '../../../utils/fonts';
|
||||
import {FlexColumn} from '../../../utils/containers';
|
||||
import {H2} from '../../../utils/fonts';
|
||||
import Table from '../../elements/Table';
|
||||
import PropsTypes from 'prop-types';
|
||||
import getChallengeLeaderboard from '../../../api/getChallengeLeaderboard';
|
||||
import _renderSubmissions from './_renderSubmissions';
|
||||
import _tableSearchQueryHandler from './_tableSearchQueryHandler';
|
||||
import {CALC_PAGES} from '../../../utils/globals';
|
||||
import Search from '../../elements/Search';
|
||||
import Pager from '../../elements/Pager';
|
||||
import Filter from '../../elements/Filter';
|
||||
import FilterBy from '../FilterBy';
|
||||
import sortOptions from './sortOptions';
|
||||
|
||||
const Leaderboard = (props) => {
|
||||
const [entriesFromApi, setEntriesFromApi] = React.useState([]);
|
||||
const [entries, setEntries] = React.useState([]);
|
||||
const [pageNr, setPageNr] = React.useState(1);
|
||||
const [loading, setLoading] = React.useState(true);
|
||||
const [metricChoose, setMetricChoose] = React.useState(null);
|
||||
const [sortBy, setSortBy] = React.useState(5);
|
||||
const [submitterSorted, setSubmitterSorted] = React.useState(false);
|
||||
const [entriesSorted, setEntriesSorted] = React.useState(false);
|
||||
const [whenSorted, setWhenSorted] = React.useState(false);
|
||||
const [scoreSorted, setScoreSorted] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
challengeDataRequest(props.challengeName);
|
||||
@ -32,21 +30,16 @@ const Leaderboard = (props) => {
|
||||
getChallengeLeaderboard(setEntries, challengeName, setLoading);
|
||||
};
|
||||
|
||||
const getMainMetricIndex = () => {
|
||||
const getMetricIndex = (metricName) => {
|
||||
let i = 0;
|
||||
for (let evaluation of entriesFromApi[0].evaluations) {
|
||||
if (evaluation.test.metric === props.mainMetric) {
|
||||
if (evaluation.test.metric === metricName) {
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
};
|
||||
|
||||
const renderSubmissions = (gridGap, headerElements) => {
|
||||
return _renderSubmissions(pageNr, entries
|
||||
? entries : [], gridGap, (metricChoose ? metricChoose : getMainMetricIndex()), sortBy, headerElements);
|
||||
};
|
||||
|
||||
const tableSearchQueryHandler = (event) => {
|
||||
_tableSearchQueryHandler(event, entriesFromApi, setPageNr, setEntries);
|
||||
};
|
||||
@ -88,12 +81,50 @@ const Leaderboard = (props) => {
|
||||
return header;
|
||||
};
|
||||
|
||||
const metricChooseHandler = (value) => {
|
||||
setMetricChoose(value);
|
||||
};
|
||||
|
||||
const sortByHandler = (value) => {
|
||||
setSortBy(value);
|
||||
const sortByUpdate = (elem) => {
|
||||
let newEntries = entries;
|
||||
console.log(elem);
|
||||
switch (elem) {
|
||||
case 'submitter':
|
||||
if (submitterSorted) {
|
||||
newEntries = newEntries.sort((a, b) => (a.submitter > b.submitter) ? 1 : ((b.submitter > a.submitter) ? -1 : 0));
|
||||
setSubmitterSorted(false);
|
||||
} else {
|
||||
newEntries = newEntries.sort((a, b) => (a.submitter < b.submitter) ? 1 : ((b.submitter < a.submitter) ? -1 : 0));
|
||||
setSubmitterSorted(true);
|
||||
}
|
||||
break;
|
||||
case 'entries':
|
||||
if (entriesSorted) {
|
||||
newEntries = newEntries.sort((a, b) => a.times - b.times);
|
||||
setEntriesSorted(false);
|
||||
} else {
|
||||
newEntries = newEntries.sort((a, b) => b.times - a.times);
|
||||
setEntriesSorted(true);
|
||||
}
|
||||
break;
|
||||
case 'when':
|
||||
if (whenSorted) {
|
||||
newEntries = newEntries.sort((a, b) => (a.when > b.when) ? 1 : ((b.when > a.when) ? -1 : 0));
|
||||
setWhenSorted(false);
|
||||
} else {
|
||||
newEntries = newEntries.sort((a, b) => (a.when < b.when) ? 1 : ((b.when < a.when) ? -1 : 0));
|
||||
setWhenSorted(true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// eslint-disable-next-line no-case-declarations
|
||||
let metricIndex = getMetricIndex(elem);
|
||||
if (scoreSorted) {
|
||||
newEntries = newEntries.sort((a, b) => b.evaluations[metricIndex].score - a.evaluations[metricIndex].score);
|
||||
setScoreSorted(false);
|
||||
} else {
|
||||
newEntries = newEntries.sort((a, b) => a.evaluations[metricIndex].score - b.evaluations[metricIndex].score);
|
||||
setScoreSorted(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
setEntries(newEntries);
|
||||
};
|
||||
|
||||
const mobileRender = () => {
|
||||
@ -103,22 +134,9 @@ const Leaderboard = (props) => {
|
||||
Leaderboard
|
||||
</H2>
|
||||
<Search searchQueryHandler={tableSearchQueryHandler}/>
|
||||
{!loading ? <FlexRow width='100%' gap='16px' as='section' margin='16px 0'>
|
||||
<H3>
|
||||
Metric:
|
||||
</H3>
|
||||
{getPossibleMetrics() ? getPossibleMetrics().map((metric, index) => {
|
||||
return (
|
||||
<Filter option={metricChoose} index={index} borderRadius='4px'
|
||||
key={`metric-${index}`} handler={metricChooseHandler}
|
||||
id={`metric-${index}`} name={`metric-${index}`}>
|
||||
{metric}
|
||||
</Filter>);
|
||||
}) : ''}
|
||||
</FlexRow> : ''}
|
||||
<Table challengeName={props.challengeName} loading={loading}
|
||||
renderElements={renderSubmissions}
|
||||
headerElements={['#', 'submitter', 'result', 'entries', 'when']}/>
|
||||
headerElements={['#', 'submitter', 'result', 'entries', 'when']}
|
||||
pageNr={pageNr} submissions={entries} sortByUpdate={sortByUpdate}/>
|
||||
<Pager pageNr={pageNr} width='48px' borderRadius='64px'
|
||||
pages={CALC_PAGES(entries ? entries : [])}
|
||||
nextPage={nextPage} previousPage={previousPage}
|
||||
@ -134,12 +152,8 @@ const Leaderboard = (props) => {
|
||||
Leaderboard
|
||||
</H2>
|
||||
<Search searchQueryHandler={tableSearchQueryHandler}/>
|
||||
<FilterBy header='Sort by' options={sortOptions} gridTemplateColumns='auto auto auto auto'
|
||||
option={sortBy} textAlign='center' margin='32px 0 0 0'
|
||||
alignmentX='center' handler={sortByHandler}/>
|
||||
<Table challengeName={props.challengeName} loading={loading}
|
||||
renderElements={renderSubmissions}
|
||||
headerElements={getLeaderboardHeader()}/>
|
||||
<Table challengeName={props.challengeName} loading={loading} headerElements={getLeaderboardHeader()}
|
||||
pageNr={pageNr} submissions={entries} sortByUpdate={sortByUpdate}/>
|
||||
<Pager pageNr={pageNr} width='72px' borderRadius='64px'
|
||||
pages={CALC_PAGES(entries ? entries : [])}
|
||||
nextPage={nextPage} previousPage={previousPage}
|
||||
|
@ -1,116 +0,0 @@
|
||||
import {ELEMENTS_PER_PAGE, IS_MOBILE} from '../../../utils/globals';
|
||||
import {FlexColumn, FlexRow, Grid, Svg} from '../../../utils/containers';
|
||||
import {Body, Medium} from '../../../utils/fonts';
|
||||
import styled from 'styled-components';
|
||||
import theme from '../../../utils/theme';
|
||||
import arrow from '../../../assets/arrow.svg';
|
||||
|
||||
|
||||
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 sortBySwitch = (submissions, metricChoose, sortBy) => {
|
||||
switch (sortBy) {
|
||||
case 0:
|
||||
return submissions.sort((a, b) => (a.submitter < b.submitter) ? 1 : ((b.submitter < a.submitter) ? -1 : 0));
|
||||
case 1:
|
||||
if (metricChoose)
|
||||
return submissions.sort((a, b) => a.evaluations[metricChoose].score - b.evaluations[metricChoose].score);
|
||||
return submissions;
|
||||
case 2:
|
||||
return submissions.sort((a, b) => a.times - b.times);
|
||||
case 3:
|
||||
return submissions.sort((a, b) => (a.when > b.when) ? 1 : ((b.when > a.when) ? -1 : 0));
|
||||
case 4:
|
||||
return submissions.sort((a, b) => (a.submitter > b.submitter) ? 1 : ((b.submitter > a.submitter) ? -1 : 0));
|
||||
case 5:
|
||||
if (metricChoose)
|
||||
return submissions.sort((a, b) => b.evaluations[metricChoose].score - a.evaluations[metricChoose].score);
|
||||
return submissions;
|
||||
case 6:
|
||||
return submissions.sort((a, b) => b.times - a.times);
|
||||
case 7:
|
||||
return submissions.sort((a, b) => (a.when < b.when) ? 1 : ((b.when < a.when) ? -1 : 0));
|
||||
default:
|
||||
return submissions.sort((a, b) => b.evaluations[metricChoose].score - a.evaluations[metricChoose].score);
|
||||
}
|
||||
};
|
||||
|
||||
const _renderSubmissions = (pageNr, submissions, gridGap, metricChoose, sortBy, headerElements) => {
|
||||
const n = (pageNr - 1) * ELEMENTS_PER_PAGE;
|
||||
|
||||
if (submissions) {
|
||||
submissions = sortBySwitch(submissions, metricChoose, sortBy);
|
||||
submissions = submissions.slice(n, n + ELEMENTS_PER_PAGE);
|
||||
return (
|
||||
<FlexColumn as='tbody' width='100%'>
|
||||
{submissions.map(({
|
||||
submitter,
|
||||
when,
|
||||
evaluations,
|
||||
times
|
||||
}, index) => {
|
||||
return (
|
||||
<Grid as='tr' key={`leaderboard-row-${index}`}
|
||||
backgroundColor={index % 2 === 1 ? theme.colors.dark01 : 'transparent'}
|
||||
gridTemplateColumns={!IS_MOBILE() ? '1fr 3fr ' + '2fr '.repeat(evaluations.length) + '1fr 2fr' : '1fr 3fr 1fr 1fr 2fr'}
|
||||
gridGap='20px' position='relative' width='100%' padding='4px'>
|
||||
{index === 0 ? headerElements.map((elem, i) => {
|
||||
return (
|
||||
<FlexRow alignmentX='flex-start'>
|
||||
<Medium key={`leaderboard-header-${i}`}
|
||||
textAlign={elem === 'submitter' ? 'left' : 'right'}
|
||||
width={elem === 'when' ? '100%' : 'auto'} padding='0 6px 0 0'
|
||||
minWidth={elem === 'result' ? '72px' : 'none'} fontSize='18px' as='td'>
|
||||
{elem}
|
||||
</Medium>
|
||||
{elem !== '#' ?
|
||||
<>
|
||||
<Svg width='8px' rotate='180deg' src={arrow}
|
||||
backgroundColor={theme.colors.dark} margin='2px 0 0 0'/>
|
||||
<Svg width='8px' src={arrow} backgroundColor={theme.colors.dark}
|
||||
margin='0 0 2px 0'/>
|
||||
</> : ''}
|
||||
</FlexRow>
|
||||
);
|
||||
}) : ''}
|
||||
{index === 0 ? <Line height='2px' top='38px' shadow={theme.shadow}/> : ''}
|
||||
<Body as='td'>
|
||||
{index + n}
|
||||
</Body>
|
||||
<Body as='td'>
|
||||
{submitter ? submitter : '[anonymous]'}
|
||||
</Body>
|
||||
{!IS_MOBILE() ? evaluations.map((metric, i) => {
|
||||
return (
|
||||
<Body key={`metric-result-${i}`} as='td' textAlign='left' minWidth='72px'>
|
||||
{metric.score.slice(0, 7)}
|
||||
</Body>
|
||||
);
|
||||
}) : <Body as='td' textAlign='left' minWidth='72px'>
|
||||
{evaluations[metricChoose] ? evaluations[metricChoose].score.slice(0, 7) : 'xxx'}
|
||||
</Body>}
|
||||
<Body as='td' padding='0 2px 0 0' textAlign='left'>
|
||||
{times ? times : 1}
|
||||
</Body>
|
||||
<Body as='td' textAlign='right'>
|
||||
{when ? `${when.slice(11, 16)} ${when.slice(0, 10)}`
|
||||
: 'xxx'}
|
||||
</Body>
|
||||
{index !== 0 ? <Line top='0' as='td'/> : ''}
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</FlexColumn>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default _renderSubmissions;
|
Loading…
Reference in New Issue
Block a user