correct search in Leaderboard and implement search in MyEntries

This commit is contained in:
mattyl006 2022-11-16 14:53:27 +01:00
parent 2a9215c365
commit b1419783e3
12 changed files with 135 additions and 94 deletions

2
.env
View File

@ -1,3 +1,3 @@
REACT_APP_KC_URL=https://auth-dev.csi.wmi.amu.edu.pl/ REACT_APP_KC_URL=https://auth-dev.csi.wmi.amu.edu.pl/
REACT_APP_KC_REALM=gonito-dev REACT_APP_KC_REALM=gonito-dev
REACT_APP_KC_CLIENT_ID=gonito-dev-localhost REACT_APP_KC_CLIENT_ID=gonito-dev-heroku

View File

@ -1,7 +1,7 @@
import {API} from '../utils/globals'; import {API} from '../utils/globals';
import KeyCloakService from '../services/KeyCloakService'; import KeyCloakService from '../services/KeyCloakService';
const getMyEntries = (challengeName, setDataOriginalState, setDataState, setLoadingState, setScoreSorted) => { const getMyEntries = (challengeName, setDataOriginalState, setDataStateForSearch, setDataState, setLoadingState, setScoreSorted) => {
fetch(`${API}/challenge-my-submissions/${challengeName}`, { fetch(`${API}/challenge-my-submissions/${challengeName}`, {
headers: {'Authorization': `Bearer ${KeyCloakService.getToken()}`} headers: {'Authorization': `Bearer ${KeyCloakService.getToken()}`}
}) })
@ -47,6 +47,7 @@ const getMyEntries = (challengeName, setDataOriginalState, setDataState, setLoad
initSetScoreSorted.push(false); initSetScoreSorted.push(false);
} }
setScoreSorted(initSetScoreSorted); setScoreSorted(initSetScoreSorted);
setDataStateForSearch(result);
setDataState(result); setDataState(result);
setLoadingState(false); setLoadingState(false);
}); });

View File

@ -6,7 +6,7 @@ import {H2} from '../../../utils/fonts';
import Table from '../Table'; import Table from '../Table';
import PropsTypes from 'prop-types'; import PropsTypes from 'prop-types';
import getChallengeLeaderboard from '../../../api/getChallengeLeaderboard'; import getChallengeLeaderboard from '../../../api/getChallengeLeaderboard';
import _tableSearchQueryHandler from './_tableSearchQueryHandler'; import leaderboardSearchQueryHandler from './leaderboardSearchQueryHandler';
import {CALC_PAGES, EVALUATIONS_FORMAT, RENDER_WHEN} from '../../../utils/globals'; import {CALC_PAGES, EVALUATIONS_FORMAT, RENDER_WHEN} from '../../../utils/globals';
import Search from '../../generic/Search'; import Search from '../../generic/Search';
import Pager from '../../generic/Pager'; import Pager from '../../generic/Pager';
@ -22,8 +22,6 @@ const Leaderboard = (props) => {
const [whenSorted, setWhenSorted] = React.useState(false); const [whenSorted, setWhenSorted] = React.useState(false);
const [scoreSorted, setScoreSorted] = React.useState(false); const [scoreSorted, setScoreSorted] = React.useState(false);
// const [columnIcons, setColumnIcons] = React.useState([]);
React.useEffect(() => { React.useEffect(() => {
challengeDataRequest(props.challengeName); challengeDataRequest(props.challengeName);
}, [props.challengeName]); }, [props.challengeName]);
@ -43,8 +41,8 @@ const Leaderboard = (props) => {
} }
}; };
const tableSearchQueryHandler = (event) => { const searchQueryHandler = (event) => {
_tableSearchQueryHandler(event, entriesFromApi, setPageNr, setEntries); leaderboardSearchQueryHandler(event, entriesFromApi, setPageNr, setEntries);
}; };
const nextPage = () => { const nextPage = () => {
@ -135,7 +133,7 @@ const Leaderboard = (props) => {
<H2 as='h2' margin='0 0 12px 0'> <H2 as='h2' margin='0 0 12px 0'>
Leaderboard Leaderboard
</H2> </H2>
<Search searchQueryHandler={tableSearchQueryHandler}/> <Search searchQueryHandler={searchQueryHandler}/>
<Table challengeName={props.challengeName} loading={loading} <Table challengeName={props.challengeName} loading={loading}
headerElements={['#', 'submitter', 'result', 'entries', 'when']} headerElements={['#', 'submitter', 'result', 'entries', 'when']}
pageNr={pageNr} submissions={entries} sortByUpdate={sortByUpdate}/> pageNr={pageNr} submissions={entries} sortByUpdate={sortByUpdate}/>
@ -155,7 +153,7 @@ const Leaderboard = (props) => {
</H2> </H2>
{!loading ? {!loading ?
<> <>
<Search searchQueryHandler={tableSearchQueryHandler}/> <Search searchQueryHandler={searchQueryHandler}/>
<Table challengeName={props.challengeName} headerElements={getLeaderboardHeader()} <Table challengeName={props.challengeName} headerElements={getLeaderboardHeader()}
gridTemplateColumns={entries[0] ? '1fr 3fr ' + '2fr '.repeat(entries[0].evaluations.length) + '1fr 2fr' : ''} gridTemplateColumns={entries[0] ? '1fr 3fr ' + '2fr '.repeat(entries[0].evaluations.length) + '1fr 2fr' : ''}
staticColumnElements={ staticColumnElements={

View File

@ -1,18 +0,0 @@
const _tableSearchQueryHandler = (event, entriesFromApi, setPageNr, setEntries) => {
let searchQuery = event.target.value;
let submissionsToRender = [];
setPageNr(1);
if (searchQuery === '')
setEntries(entriesFromApi);
else {
for (let entry of entriesFromApi) {
const {submitter, when, evaluations, times} = entry;
const str = `${submitter} ${when.slice(11, 16)} ${when.slice(0, 10)} ${evaluations} ${times}`;
if (str.toLowerCase().includes(searchQuery.toLowerCase()))
submissionsToRender.push(entry);
}
setEntries(submissionsToRender);
}
};
export default _tableSearchQueryHandler;

View File

@ -0,0 +1,22 @@
const leaderboardSearchQueryHandler = (event, entriesFromApi, setPageNr, setEntries) => {
let searchQuery = event.target.value;
let submissionsToRender = [];
setPageNr(1);
if (searchQuery === '')
setEntries(entriesFromApi);
else {
for (let entry of entriesFromApi) {
const {id, submitter, when, times} = entry;
let evaluations = '';
for (let evaluation of entry.evaluations) {
evaluations += ` ${evaluation.score}`;
}
const str = `${id} ${submitter} ${when.slice(11, 16)} ${when.slice(0, 10)} ${evaluations} ${times}`;
if (str.toLowerCase().includes(searchQuery.toLowerCase()))
submissionsToRender.push(entry);
}
setEntries(submissionsToRender);
}
};
export default leaderboardSearchQueryHandler;

View File

@ -1,17 +1,19 @@
import React from 'react'; import React from 'react';
import {FlexColumn} from '../../utils/containers'; import {FlexColumn} from '../../../utils/containers';
import {H2} from '../../utils/fonts'; import {H2} from '../../../utils/fonts';
import getMyEntries from '../../api/getMyEntries'; import getMyEntries from '../../../api/getMyEntries';
import Pager from '../generic/Pager'; import Pager from '../../generic/Pager';
import {CALC_PAGES, EVALUATIONS_FORMAT, RENDER_WHEN} from '../../utils/globals'; import {CALC_PAGES, EVALUATIONS_FORMAT, RENDER_WHEN} from '../../../utils/globals';
import Media from 'react-media'; import Media from 'react-media';
import theme from '../../utils/theme'; import theme from '../../../utils/theme';
import _tableSearchQueryHandler from './Leaderboard/_tableSearchQueryHandler'; import Loading from '../../generic/Loading';
import Loading from '../generic/Loading'; import Table from '../Table';
import Table from './Table'; import myEntriesSearchQueryHandler from './myEntriesSearchQueryHandler';
import Search from '../../generic/Search';
const MyEntries = (props) => { const MyEntries = (props) => {
const [myEntriesFromAPI, setMyEntriesFromAPI] = React.useState({}); const [myEntriesFromAPI, setMyEntriesFromAPI] = React.useState({});
const [myEntriesAll, setMyEntriesAll] = React.useState({});
const [myEntries, setMyEntries] = React.useState({}); const [myEntries, setMyEntries] = React.useState({});
const [loading, setLoading] = React.useState(true); const [loading, setLoading] = React.useState(true);
const [pageNr, setPageNr] = React.useState(1); const [pageNr, setPageNr] = React.useState(1);
@ -23,8 +25,8 @@ const MyEntries = (props) => {
challengesRequest(); challengesRequest();
}, []); }, []);
const tableSearchQueryHandler = (event) => { const searchQueryHandler = (event) => {
_tableSearchQueryHandler(event, myEntriesFromAPI, setPageNr, setMyEntries); myEntriesSearchQueryHandler(event, myEntriesAll, setPageNr, setMyEntries);
}; };
const getPossibleMetrics = () => { const getPossibleMetrics = () => {
@ -62,7 +64,7 @@ const MyEntries = (props) => {
}; };
const challengesRequest = () => { const challengesRequest = () => {
getMyEntries(props.challengeName, setMyEntriesFromAPI, setMyEntries, setLoading, setScoresSorted); getMyEntries(props.challengeName, setMyEntriesFromAPI, setMyEntriesAll, setMyEntries, setLoading, setScoresSorted);
}; };
const mobileRender = () => { const mobileRender = () => {
@ -108,6 +110,7 @@ const MyEntries = (props) => {
</H2> </H2>
{myEntries && !loading ? {myEntries && !loading ?
<> <>
<Search searchQueryHandler={searchQueryHandler}/>
<Table challengeName={props.challengeName} headerElements={getMyEntriesHeader()} <Table challengeName={props.challengeName} headerElements={getMyEntriesHeader()}
possibleMetrics={getPossibleMetrics()} possibleMetrics={getPossibleMetrics()}
gridTemplateColumns={'1fr ' + '4fr '.repeat(getMyEntriesHeader().length - 1)} gridTemplateColumns={'1fr ' + '4fr '.repeat(getMyEntriesHeader().length - 1)}

View File

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

View File

@ -0,0 +1,24 @@
const myEntriesSearchQueryHandler = (event, entriesFromApi, setPageNr, setEntries) => {
let searchQuery = event.target.value;
let submissionsToRender = [];
setPageNr(1);
if (searchQuery === '')
setEntries(entriesFromApi);
else {
for (let entry of entriesFromApi) {
const {id, when} = entry;
let evaluations = '';
for (let evaluation of Object.values(entry.evaluations)) {
evaluations += ` ${evaluation}`;
}
const str = `${id} ${when.slice(11, 16)} ${when.slice(0, 10)} ${evaluations}`;
console.log(entry);
console.log(str);
if (str.toLowerCase().includes(searchQuery.toLowerCase()))
submissionsToRender.push(entry);
}
setEntries(submissionsToRender);
}
};
export default myEntriesSearchQueryHandler;

View File

@ -63,60 +63,70 @@ const Table = (props) => {
const desktopRender = () => { const desktopRender = () => {
const n = (props.pageNr - 1) * (ELEMENTS_PER_PAGE * 2); const n = (props.pageNr - 1) * (ELEMENTS_PER_PAGE * 2);
let elementsToMap = props.elements.slice(n, n + (ELEMENTS_PER_PAGE * 2)); let elementsToMap = props.elements.slice(n, n + (ELEMENTS_PER_PAGE * 2));
return ( if (elementsToMap.length > 0) {
<FlexColumn as='table' margin='32px 0 72px 0' width='100%'> return (
<FlexColumn as='tbody' width='100%'> <FlexColumn as='table' margin='32px 0 72px 0' width='100%'>
<Grid <FlexColumn as='tbody' width='100%'>
gridGap='20px' position='relative' width='100%' padding='4px' margin='0 0 6px 0' <Grid
gridTemplateColumns={props.gridTemplateColumns}> gridGap='20px' position='relative' width='100%' padding='4px' margin='0 0 6px 0'
{props.headerElements.map((elem, i) => { gridTemplateColumns={props.gridTemplateColumns}>
{props.headerElements.map((elem, i) => {
return (
<FlexRow key={`table-header-${i}`} alignmentX='flex-start' as='td'
onClick={() => {
if (activeIcon === i) {
let newRotateActiveIcon = !rotateActiveIcon;
setRotateActiveIcon(newRotateActiveIcon);
} else {
setRotateActiveIcon(false);
}
setActiveIcon(i);
props.sortByUpdate(elem, i);
forceUpdate();
}}>
<Medium textAlign={elem === 'submitter' ? 'left' : 'right'}
width={elem === 'when' ? '100%' : 'auto'} padding='0 6px 0 0'
minWidth={elem === 'result' ? '72px' : 'none'}>
{elem}
</Medium>
{elem !== '#' ?
<ColumnFilterIcon index={i} active={activeIcon}
rotateIcon={rotateActiveIcon}/>
: ''}
</FlexRow>
);
})}
<Line height='2px' top='32px' shadow={theme.shadow}/>
</Grid>
{elementsToMap.map((elem, index) => {
return ( return (
<FlexRow key={`table-header-${i}`} alignmentX='flex-start' as='td' <Grid as='tr' key={`leaderboard-row-${index}`}
onClick={() => { backgroundColor={index % 2 === 1 ? theme.colors.dark01 : 'transparent'}
if (activeIcon === i) { gridTemplateColumns={props.gridTemplateColumns}
let newRotateActiveIcon = !rotateActiveIcon; gridGap='20px' position='relative' width='100%' padding='4px'>
setRotateActiveIcon(newRotateActiveIcon); {props.staticColumnElements.map((elemName, i) => {
} else { return (
setRotateActiveIcon(false); <Body key={`leaderboard-static-elemName-${i}-${elem[elemName.name]}`}
} as='td'
setActiveIcon(i); order={elemName.order} textAlign={elemName.align}>
props.sortByUpdate(elem, i); {elemName.format ? elemName.format(elem[elemName.name]) : elem[elemName.name]}
forceUpdate(); </Body>
}}> );
<Medium textAlign={elem === 'submitter' ? 'left' : 'right'} })}
width={elem === 'when' ? '100%' : 'auto'} padding='0 6px 0 0' {props.headerElements ? metricsRender(elem) : ''}
minWidth={elem === 'result' ? '72px' : 'none'}> </Grid>
{elem}
</Medium>
{elem !== '#' ?
<ColumnFilterIcon index={i} active={activeIcon} rotateIcon={rotateActiveIcon}/>
: ''}
</FlexRow>
); );
})} })}
<Line height='2px' top='32px' shadow={theme.shadow}/> </FlexColumn>
</Grid>
{elementsToMap.map((elem, index) => {
return (
<Grid as='tr' key={`leaderboard-row-${index}`}
backgroundColor={index % 2 === 1 ? theme.colors.dark01 : 'transparent'}
gridTemplateColumns={props.gridTemplateColumns}
gridGap='20px' position='relative' width='100%' padding='4px'>
{props.staticColumnElements.map((elemName, i) => {
return (
<Body key={`leaderboard-static-elemName-${i}-${elem[elemName.name]}`} as='td'
order={elemName.order} textAlign={elemName.align}>
{elemName.format ? elemName.format(elem[elemName.name]) : elem[elemName.name]}
</Body>
);
})}
{props.headerElements ? metricsRender(elem) : ''}
</Grid>
);
})}
</FlexColumn> </FlexColumn>
</FlexColumn> );
); } else {
return (
<Medium margin='72px 0'>
Query not found
</Medium>
);
}
}; };
return ( return (

View File

@ -4,7 +4,7 @@ import {FlexColumn, FlexRow, Svg} from '../../utils/containers';
import Search from '../../components/generic/Search'; import Search from '../../components/generic/Search';
import Pager from '../../components/generic/Pager'; import Pager from '../../components/generic/Pager';
import FiltersMenu from '../../components/challenges_list/FiltersMenu'; import FiltersMenu from '../../components/challenges_list/FiltersMenu';
import _searchQueryHandler from './_searchQueryHandler'; import challengeSearchQueryHandler from './challengeSearchQueryHandler';
import _renderChallenges from './_renderChallenges'; import _renderChallenges from './_renderChallenges';
import Media from 'react-media'; import Media from 'react-media';
import theme from '../../utils/theme'; import theme from '../../utils/theme';
@ -50,7 +50,7 @@ const Challenges = () => {
}; };
const searchQueryHandler = (event) => { const searchQueryHandler = (event) => {
_searchQueryHandler(event, challengesFromAPI, setPageNr, setChallenges); challengeSearchQueryHandler(event, challengesFromAPI, setPageNr, setChallenges);
}; };
const nextPage = () => { const nextPage = () => {

View File

@ -1,4 +1,4 @@
const _searchQueryHandler = (event, challengesFromAPI, setPageNr, setChallenges) => { const challengeSearchQueryHandler = (event, challengesFromAPI, setPageNr, setChallenges) => {
let searchQuery = event.target.value; let searchQuery = event.target.value;
let challengesToRender = []; let challengesToRender = [];
setPageNr(1); setPageNr(1);
@ -16,4 +16,4 @@ const _searchQueryHandler = (event, challengesFromAPI, setPageNr, setChallenges)
} }
}; };
export default _searchQueryHandler; export default challengeSearchQueryHandler;

View File

@ -7,7 +7,7 @@ import MobileChallengeMenu from '../components/specific_challenge/MobileChalleng
import Leaderboard from '../components/specific_challenge/Leaderboard/Leaderboard'; import Leaderboard from '../components/specific_challenge/Leaderboard/Leaderboard';
import Readme from '../components/specific_challenge/Readme'; import Readme from '../components/specific_challenge/Readme';
import HowTo from '../components/specific_challenge/HowTo'; import HowTo from '../components/specific_challenge/HowTo';
import MyEntries from '../components/specific_challenge/MyEntries'; import MyEntries from '../components/specific_challenge/MyEntries/MyEntries';
import Submit from '../components/specific_challenge/Submit'; import Submit from '../components/specific_challenge/Submit';
import Media from 'react-media'; import Media from 'react-media';
import DesktopChallengeMenu from '../components/specific_challenge/DesktopChallengeMenu'; import DesktopChallengeMenu from '../components/specific_challenge/DesktopChallengeMenu';