diff --git a/src/api/getChallengeLeaderboard.js b/src/api/getChallengeLeaderboard.js index 3f1dce4..799ec37 100644 --- a/src/api/getChallengeLeaderboard.js +++ b/src/api/getChallengeLeaderboard.js @@ -1,19 +1,66 @@ import { API } from '../utils/globals'; +import KeyCloakService from '../services/KeyCloakService'; -const getChallengeLeaderboard = async ( - setDataState, +const getChallengeLeaderboard = ( + endpoint, challengeName, - setLoading + setDataStates, + setLoadingState, + setScoreSorted ) => { - await fetch(`${API}/leaderboard/${challengeName}`) + fetch(`${API}/${endpoint}/${challengeName}`, { + headers: { Authorization: `Bearer ${KeyCloakService.getToken()}` }, + }) .then((response) => response.json()) .then((data) => { - setDataState(data.entries); + let item = {}; + let result = []; + let initSetScoreSorted = []; + let tests = data.tests; + for (let submission of data.entries) { + for (let evaluation of submission.evaluations) { + item = { + ...item, + evaluations: { + ...item.evaluations, + [`${evaluation.test.metric}.${evaluation.test.name}`]: + evaluation.score, + }, + }; + } + for (let test of tests) { + if (!item.evaluations) { + item.evaluations = {}; + } + if (!Object.hasOwn(item.evaluations, `${test.metric}.${test.name}`)) { + item = { + ...item, + evaluations: { + ...item.evaluations, + [`${test.metric}.${test.name}`]: -999999999, + }, + }; + } + } + item = { + ...item.evaluations, + id: submission.id, + submitter: submission.submitter, + when: submission.when, + tags: submission.tags, + }; + result.push(item); + item = {}; + } + // eslint-disable-next-line no-unused-vars + for (let _ of tests) { + initSetScoreSorted.push(false); + } + console.log(result); + for (let setDataState of setDataStates) setDataState(result); + if (setScoreSorted) setScoreSorted(initSetScoreSorted); + if (setLoadingState) setLoadingState(false); }); - - if (setLoading) { - setLoading(false); - } }; export default getChallengeLeaderboard; diff --git a/src/pages/Leaderboard/Leaderboard.js b/src/pages/Leaderboard/Leaderboard.js index b1c4d3d..cb0a2d6 100644 --- a/src/pages/Leaderboard/Leaderboard.js +++ b/src/pages/Leaderboard/Leaderboard.js @@ -1,20 +1,15 @@ import React from 'react'; -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/Table'; -import PropsTypes from 'prop-types'; import getChallengeLeaderboard from '../../api/getChallengeLeaderboard'; import leaderboardSearchQueryHandler from './leaderboardSearchQueryHandler'; -import { - CALC_PAGES, - EVALUATIONS_FORMAT, - RENDER_WHEN, -} from '../../utils/globals'; +import { CALC_PAGES } from '../../utils/globals'; import Search from '../../components/generic/Search'; import Pager from '../../components/generic/Pager'; import Loading from '../../components/generic/Loading'; +import orderKeys from './orderKeys'; +import { ELEMENTS_PER_PAGE } from '../../utils/globals'; const Leaderboard = (props) => { const [entriesFromApi, setEntriesFromApi] = React.useState([]); @@ -22,286 +17,175 @@ const Leaderboard = (props) => { const [pageNr, setPageNr] = React.useState(1); const [loading, setLoading] = React.useState(true); const [submitterSorted, setSubmitterSorted] = React.useState(false); - const [descriptionSorted, setDescriptionSorted] = React.useState(false); - const [entriesSorted, setEntriesSorted] = React.useState(false); + // const [descriptionSorted, setDescriptionSorted] = React.useState(false); + // const [entriesSorted, setEntriesSorted] = React.useState(false); const [whenSorted, setWhenSorted] = React.useState(false); const [scoresSorted, setScoresSorted] = React.useState([]); + const [idSorted, setIdSorted] = React.useState([]); React.useEffect(() => { - challengeDataRequest(props.challengeName); + getChallengeLeaderboard( + 'leaderboard', + props.challengeName, + [setEntries, setEntriesFromApi], + setLoading, + setScoresSorted + ); }, [props.challengeName]); - const challengeDataRequest = (challengeName) => { - getChallengeLeaderboard(setEntriesFromApi, challengeName); - getChallengeLeaderboard(setEntries, challengeName, setLoading); - }; - - const getMetricIndex = (metricName) => { - let i = 0; - for (let evaluation of entriesFromApi[0].evaluations) { - if (`${evaluation.test.metric}.${evaluation.test.name}` === metricName) { - return i; - } - i++; - } - }; - const searchQueryHandler = (event) => { leaderboardSearchQueryHandler(event, entriesFromApi, setPageNr, setEntries); }; - const getPossibleMetrics = () => { - let metrics = []; - for (let entry of entriesFromApi) { - for (let evaluation of entry.evaluations) { - let metric = evaluation.test.metric; - let name = evaluation.test.name; - if (metric && !metrics.includes(`${metric}.${name}`)) { - metrics.push(`${metric}.${name}`); - } + const sortByUpdate = React.useCallback( + (elem) => { + let newEntries = entries.slice(); + const possibleMetrics = orderKeys(entries[0]).filter( + (key) => !['id', 'submitter', 'when'].includes(key) + ); + let metricIndex = possibleMetrics.indexOf(elem); + let newScoresSorted = scoresSorted.slice(); + switch (elem) { + case 'id': + if (idSorted) { + setIdSorted(false); + newEntries = newEntries.sort((a, b) => + a.id > b.id ? 1 : b.id > a.id ? -1 : 0 + ); + } else { + setIdSorted(true); + newEntries = newEntries.sort((a, b) => + a.id < b.id ? 1 : b.id < a.id ? -1 : 0 + ); + } + break; + case 'submitter': + if (submitterSorted) { + setSubmitterSorted(false); + newEntries = newEntries.sort((a, b) => + a.submitter.toLowerCase() < b.submitter.toLowerCase() + ? 1 + : b.submitter.toLowerCase() < a.submitter.toLowerCase() + ? -1 + : 0 + ); + } else { + setSubmitterSorted(true); + newEntries = newEntries.sort((a, b) => + a.submitter.toLowerCase() > b.submitter.toLowerCase() + ? 1 + : b.submitter.toLowerCase() > a.submitter.toLowerCase() + ? -1 + : 0 + ); + } + break; + case 'when': + if (whenSorted) { + setWhenSorted(false); + newEntries = newEntries.sort((a, b) => + a.when < b.when ? 1 : b.when < a.when ? -1 : 0 + ); + } else { + setWhenSorted(true); + newEntries = newEntries.sort((a, b) => + a.when > b.when ? 1 : b.when > a.when ? -1 : 0 + ); + } + break; + default: + if (scoresSorted[metricIndex]) { + newEntries = newEntries.sort( + (a, b) => (b ? b[elem] : -1) - (a ? a[elem] : -1) + ); + newScoresSorted[metricIndex] = false; + setScoresSorted(newScoresSorted); + } else { + newEntries = newEntries.sort( + (a, b) => (a ? a[elem] : -1) - (b ? b[elem] : -1) + ); + newScoresSorted[metricIndex] = true; + setScoresSorted(newScoresSorted); + } + break; } - } - return metrics; - }; + setEntries(newEntries); + }, + [entries, idSorted, scoresSorted, submitterSorted, whenSorted] + ); - const getLeaderboardHeader = () => { - let header = ['#', 'submitter', 'description']; - for (let metric of getPossibleMetrics()) { - header.push(metric); - } - header.push('entries'); - header.push('when'); - return header; - }; - - const getLeaderboardHeaderMobile = () => { - let header = ['#', 'submitter', 'description', 'entries', 'when']; - for (let metric of getPossibleMetrics()) { - header.push(metric); - } - return header; - }; - - const sortByUpdate = (elem) => { - let metricIndex = 0; - let newEntries = entries; - switch (elem) { - case 'submitter': - if (submitterSorted) { - newEntries = newEntries.sort((a, b) => - a.submitter.toLowerCase() < b.submitter.toLowerCase() - ? 1 - : b.submitter.toLowerCase() < a.submitter.toLowerCase() - ? -1 - : 0 - ); - setSubmitterSorted(false); - } else { - newEntries = newEntries.sort((a, b) => - a.submitter.toLowerCase() > b.submitter.toLowerCase() - ? 1 - : b.submitter.toLowerCase() > a.submitter.toLowerCase() - ? -1 - : 0 - ); - setSubmitterSorted(true); - } - break; - case 'description': - if (descriptionSorted) { - newEntries = newEntries.sort((a, b) => - a.description.toLowerCase() < b.description.toLowerCase() - ? 1 - : b.description.toLowerCase() < a.description.toLowerCase() - ? -1 - : 0 - ); - setDescriptionSorted(false); - } else { - newEntries = newEntries.sort((a, b) => - a.description.toLowerCase() > b.description.toLowerCase() - ? 1 - : b.description.toLowerCase() > a.description.toLowerCase() - ? -1 - : 0 - ); - setDescriptionSorted(true); - } - break; - case 'entries': - if (entriesSorted) { - newEntries = newEntries.sort((a, b) => b.times - a.times); - setEntriesSorted(false); - } else { - newEntries = newEntries.sort((a, b) => a.times - b.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: - metricIndex = getMetricIndex(elem); - // eslint-disable-next-line no-case-declarations - let newScoresSorted = scoresSorted; - if (scoresSorted[metricIndex]) { - newEntries = newEntries.sort( - (a, b) => - b.evaluations[metricIndex].score - - a.evaluations[metricIndex].score - ); - newScoresSorted[metricIndex] = false; - setScoresSorted(newScoresSorted); - } else { - newEntries = newEntries.sort( - (a, b) => - a.evaluations[metricIndex].score - - b.evaluations[metricIndex].score - ); - newScoresSorted[metricIndex] = true; - setScoresSorted(newScoresSorted); - } - break; - } - setEntries(newEntries); - }; - - const mobileRender = () => { - return ( - -

- Leaderboard -

- {!loading ? ( - <> - - - - - ) : ( - - )} - - ); - }; - - const desktopRender = () => { - return ( - -

- Leaderboard -

- {!loading ? ( - <> - -
- - - ) : ( - - )} - - ); - }; + const n = (pageNr - 1) * (ELEMENTS_PER_PAGE * 2); + let elements = entries.slice(n, n + ELEMENTS_PER_PAGE * 2); return ( - <> - {mobileRender()} - {desktopRender()} - + +

Leaderboard

+ {!loading ? ( + <> + + searchQueryHandler(event, entries, setPageNr, setEntries) + } + /> + {elements.length > 0 && entries[0] && ( +
+ )} + + + ) : ( + + )} + ); }; -Leaderboard.propsTypes = { - challengeName: PropsTypes.string, -}; - -Leaderboard.defaultProps = { - challengeName: '', -}; - export default Leaderboard; + +// case 'description': +// if (descriptionSorted) { +// newEntries = newEntries.sort((a, b) => +// a.description.toLowerCase() < b.description.toLowerCase() +// ? 1 +// : b.description.toLowerCase() < a.description.toLowerCase() +// ? -1 +// : 0 +// ); +// setDescriptionSorted(false); +// } else { +// newEntries = newEntries.sort((a, b) => +// a.description.toLowerCase() > b.description.toLowerCase() +// ? 1 +// : b.description.toLowerCase() > a.description.toLowerCase() +// ? -1 +// : 0 +// ); +// setDescriptionSorted(true); +// } +// break; +// case 'entries': +// if (entriesSorted) { +// newEntries = newEntries.sort((a, b) => b.times - a.times); +// setEntriesSorted(false); +// } else { +// newEntries = newEntries.sort((a, b) => a.times - b.times); +// setEntriesSorted(true); +// } +// break; diff --git a/src/pages/Leaderboard/orderKeys.js b/src/pages/Leaderboard/orderKeys.js new file mode 100644 index 0000000..6b1e680 --- /dev/null +++ b/src/pages/Leaderboard/orderKeys.js @@ -0,0 +1,23 @@ +const orderKeys = (elem) => { + if (elem) { + let result = ['id']; + const elemKeys = Object.keys(elem); + const dev0keys = elemKeys + .filter((key) => key.split('.')[1] === 'dev-0') + .sort(); + const dev1keys = elemKeys + .filter((key) => key.split('.')[1] === 'dev-1') + .sort(); + const testAkeys = elemKeys + .filter((key) => key.split('.')[1] === 'test-A') + .sort(); + result = result.concat(dev0keys); + result = result.concat(dev1keys); + result = result.concat(testAkeys); + result.push('when'); + return result; + } + return null; +}; + +export default orderKeys;