MyEntries with new table and logic

This commit is contained in:
Mateusz Tylka 2023-06-09 15:50:45 +02:00
parent e5d0e50102
commit b8b4c31b45
8 changed files with 194 additions and 256 deletions

View File

@ -1,13 +1,14 @@
import { API } from '../utils/globals';
import KeyCloakService from '../services/KeyCloakService';
const getAllEntries = (
const getEntries = (
endpoint,
challengeName,
setDataStates,
setLoadingState,
setScoreSorted
) => {
fetch(`${API}/challenge-all-submissions/${challengeName}`, {
fetch(`${API}/${endpoint}/${challengeName}`, {
headers: { Authorization: `Bearer ${KeyCloakService.getToken()}` },
})
.then((response) => response.json())
@ -61,4 +62,4 @@ const getAllEntries = (
});
};
export default getAllEntries;
export default getEntries;

View File

@ -3,9 +3,7 @@ import KeyCloakService from '../services/KeyCloakService';
const getMyEntries = (
challengeName,
setDataOriginalState,
setDataStateForSearch,
setDataState,
setDataStates,
setLoadingState,
setScoreSorted
) => {
@ -14,7 +12,6 @@ const getMyEntries = (
})
.then((response) => response.json())
.then((data) => {
setDataOriginalState(data);
let item = {};
let result = [];
let initSetScoreSorted = [];
@ -31,18 +28,17 @@ const getMyEntries = (
};
}
for (let test of tests) {
if (item.evaluations) {
if (
!Object.hasOwn(item.evaluations, `${test.metric}.${test.name}`)
) {
item = {
...item,
evaluations: {
...item.evaluations,
[`${test.metric}.${test.name}`]: '_',
},
};
}
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 = {
@ -50,6 +46,7 @@ const getMyEntries = (
id: submission.id,
submitter: submission.submitter,
when: submission.when,
tags: submission.tags,
};
result.push(item);
item = {};
@ -58,10 +55,9 @@ const getMyEntries = (
for (let _ of tests) {
initSetScoreSorted.push(false);
}
setScoreSorted(initSetScoreSorted);
setDataStateForSearch(result);
setDataState(result);
setLoadingState(false);
for (let setDataState of setDataStates) setDataState(result);
if (setScoreSorted) setScoreSorted(initSetScoreSorted);
if (setLoadingState) setLoadingState(false);
});
};

View File

@ -3,7 +3,7 @@ import { FlexColumn } from '../../utils/containers';
import { H2 } from '../../utils/fonts';
import Pager from '../../components/generic/Pager';
import Search from '../../components/generic/Search';
import getAllEntries from '../../api/getAllEntries';
import getEntries from '../../api/getEntries';
import Table from '../../components/generic/Table';
import Loading from '../../components/generic/Loading';
import { CALC_PAGES, ELEMENTS_PER_PAGE } from '../../utils/globals';
@ -22,7 +22,8 @@ const NewTablePageTest = (props) => {
React.useMemo(() => {
if (props.challengeName) {
getAllEntries(
getEntries(
'challenge-all-submissions',
props.challengeName,
[setEntries, setEntriesAll],
setLoading,

View File

@ -5,9 +5,19 @@ const searchQueryHandler = (event, entriesAll, setPageNr, setEntries) => {
if (searchQuery === '') setEntries(entriesAll);
else {
for (let entry of entriesAll) {
const { when } = entry;
const otherKeys = Object.values(entry).join(' ');
const str = `${when.slice(11, 16)} ${when.slice(0, 10)} ${otherKeys}`;
let { when, tags } = entry;
tags = Object.values(tags)
.map((tag) => tag.name)
.join(' ');
const otherKeys = Object.values(entry)
.join(' ')
.replaceAll(-999999999, 'N/A')
.replaceAll('[object Object]', '')
.replaceAll(',', '');
const str = `${when.slice(11, 16)} ${when.slice(
0,
10
)} ${otherKeys} ${tags}`;
if (str.toLowerCase().includes(searchQuery.toLowerCase()))
submissionsToRender.push(entry);
}

View File

@ -1,220 +1,132 @@
import React from 'react';
import { FlexColumn } from '../../utils/containers';
import { H2 } from '../../utils/fonts';
import getMyEntries from '../../api/getMyEntries';
import Pager from '../../components/generic/Pager';
import {
CALC_PAGES,
EVALUATIONS_FORMAT,
IS_MOBILE,
RENDER_WHEN,
} from '../../utils/globals';
import Media from 'react-media';
import theme from '../../utils/theme';
import { CALC_PAGES } from '../../utils/globals';
import Loading from '../../components/generic/Loading';
import Table from '../../components/generic/Table/Table';
import myEntriesSearchQueryHandler from './myEntriesSearchQueryHandler';
import Search from '../../components/generic/Search';
import orderKeys from './orderKeys';
import { ELEMENTS_PER_PAGE } from '../../utils/globals';
import getEntries from '../../api/getEntries';
import searchHandler from './searchHandler';
const MyEntries = (props) => {
const [myEntriesFromAPI, setMyEntriesFromAPI] = React.useState({});
const [myEntriesAll, setMyEntriesAll] = React.useState({});
const [myEntries, setMyEntries] = React.useState({});
// const [myEntriesFromAPI, setMyEntriesFromAPI] = React.useState({});
const [myEntriesAll, setMyEntriesAll] = React.useState([]);
const [myEntries, setMyEntries] = React.useState([]);
const [loading, setLoading] = React.useState(true);
const [pageNr, setPageNr] = React.useState(1);
const [idSorted, setIdSorted] = React.useState([]);
const [whenSorted, setWhenSorted] = React.useState(false);
const [scoresSorted, setScoresSorted] = React.useState([]);
React.useEffect(() => {
challengesRequest();
// eslint-disable-next-line
}, []);
const searchQueryHandler = (event) => {
myEntriesSearchQueryHandler(event, myEntriesAll, setPageNr, setMyEntries);
};
const getPossibleMetrics = () => {
let metrics = [];
for (let test of myEntriesFromAPI.tests) {
let myEval = `${test.metric}.${test.name}`;
if (myEval && !metrics.includes(myEval)) {
metrics.push(myEval);
}
}
return metrics;
};
const getMyEntriesHeader = () => {
let header = ['#'];
if (IS_MOBILE()) header.push('when');
for (let myEval of getPossibleMetrics()) {
header.push(myEval);
}
if (!IS_MOBILE()) header.push('when');
return header;
};
const challengesRequest = () => {
getMyEntries(
React.useMemo(() => {
getEntries(
'challenge-my-submissions',
props.challengeName,
setMyEntriesFromAPI,
setMyEntriesAll,
setMyEntries,
[setMyEntries, setMyEntriesAll],
setLoading,
setScoresSorted
);
};
}, [props.challengeName]);
const sortByUpdate = (elem, i) => {
let newEntries = myEntries;
switch (elem) {
case '#':
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 = getPossibleMetrics().indexOf(elem);
// eslint-disable-next-line no-case-declarations
let newScoresSorted = scoresSorted;
if (scoresSorted[metricIndex]) {
newEntries = newEntries.sort(
(a, b) =>
(b.evaluations ? b.evaluations[elem] : -1) -
(a.evaluations ? a.evaluations[elem] : -1)
);
newScoresSorted[metricIndex] = false;
setScoresSorted(newScoresSorted);
} else {
newEntries = newEntries.sort(
(a, b) =>
(a.evaluations ? a.evaluations[elem] : -1) -
(b.evaluations ? b.evaluations[elem] : -1)
);
newScoresSorted[metricIndex] = true;
setScoresSorted(newScoresSorted);
}
break;
}
setMyEntries(newEntries);
};
const sortByUpdate = React.useCallback(
(elem) => {
let newEntries = myEntries.slice();
const possibleMetrics = orderKeys(myEntries[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 '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;
}
setMyEntries(newEntries);
},
[idSorted, myEntries, scoresSorted, whenSorted]
);
const mobileRender = () => {
return (
<FlexColumn padding="24px 12px" width="70%" as="section" id="start">
<H2 as="h2" margin="0 0 12px 0">
My Entries
</H2>
{!loading ? (
<>
<Search searchQueryHandler={searchQueryHandler} />
<Table
challengeName={props.challengeName}
headerElements={getMyEntriesHeader()}
possibleMetrics={getPossibleMetrics()}
tableType="myEntries"
gridTemplateColumns={
'1fr ' + '4fr '.repeat(getMyEntriesHeader().length - 1)
}
staticColumnElements={[
{ name: 'id', format: null, order: 1, align: 'left' },
{ name: 'when', format: RENDER_WHEN, order: 3, align: 'right' },
]}
iterableColumnElement={{
name: 'evaluations',
format: EVALUATIONS_FORMAT,
order: 2,
align: 'left',
}}
pageNr={pageNr}
elements={myEntries}
sortByUpdate={sortByUpdate}
/>
<Pager
pageNr={pageNr}
elements={myEntries}
setPageNr={setPageNr}
width="48px"
borderRadius="64px"
pages={CALC_PAGES(myEntries)}
number={`${pageNr} / ${CALC_PAGES(myEntries)}`}
/>
</>
) : (
<Loading />
)}
</FlexColumn>
);
};
const desktopRender = () => {
return (
<FlexColumn padding="24px" as="section" width="100%" maxWidth="1600px">
<FlexColumn padding="24px 12px" width="70%" as="section" id="start">
<H2 as="h2" margin="0 0 32px 0">
My Entries
</H2>
</FlexColumn>
{myEntries && !loading ? (
<>
<Search searchQueryHandler={searchQueryHandler} />
<Table
challengeName={props.challengeName}
headerElements={getMyEntriesHeader()}
possibleMetrics={getPossibleMetrics()}
gridTemplateColumns={
'1fr ' + '3fr '.repeat(getMyEntriesHeader().length - 2) + ' 4fr'
}
staticColumnElements={[
{ name: 'id', format: null, order: 1, align: 'left' },
{ name: 'when', format: RENDER_WHEN, order: 3, align: 'right' },
]}
iterableColumnElement={{
name: 'evaluations',
format: EVALUATIONS_FORMAT,
order: 2,
align: 'left',
}}
pageNr={pageNr}
elements={myEntries}
sortByUpdate={sortByUpdate}
myEntries
/>
<Pager
pageNr={pageNr}
elements={myEntries}
setPageNr={setPageNr}
width="72px"
mobileRender
borderRadius="64px"
pages={CALC_PAGES(myEntries, 2)}
number={`${pageNr} / ${CALC_PAGES(myEntries, 2)}`}
/>
</>
) : (
<Loading />
)}
</FlexColumn>
);
};
const n = (pageNr - 1) * (ELEMENTS_PER_PAGE * 2);
let elements = myEntries.slice(n, n + ELEMENTS_PER_PAGE * 2);
return (
<>
<Media query={theme.mobile}>{mobileRender()}</Media>
<Media query={theme.desktop}>{desktopRender()}</Media>
</>
<FlexColumn
padding="24px"
gap="32px"
as="section"
width="100%"
maxWidth="1600px"
>
<H2 as="h2">My Entries</H2>
{!loading ? (
<>
<Search
searchQueryHandler={(event) =>
searchHandler(event, myEntriesAll, setPageNr, setMyEntries)
}
/>
{elements.length > 0 && myEntries[0] && (
<Table
items={elements}
orderedKeys={orderKeys(myEntries[0])}
sortByUpdate={sortByUpdate}
/>
)}
<Pager
pageNr={pageNr}
elements={myEntries}
setPageNr={setPageNr}
width="72px"
borderRadius="64px"
pages={CALC_PAGES(myEntries, 2)}
number={`${pageNr} / ${CALC_PAGES(myEntries, 2)}`}
/>
</>
) : (
<Loading />
)}
</FlexColumn>
);
};

View File

@ -1,33 +0,0 @@
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 = '';
if (entry.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

@ -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;

View File

@ -0,0 +1,28 @@
const searchQueryHandler = (event, entriesAll, setPageNr, setEntries) => {
let searchQuery = event.target.value;
let submissionsToRender = [];
setPageNr(1);
if (searchQuery === '') setEntries(entriesAll);
else {
for (let entry of entriesAll) {
let { when, tags } = entry;
tags = Object.values(tags)
.map((tag) => tag.name)
.join(' ');
const otherKeys = Object.values(entry)
.join(' ')
.replaceAll(-999999999, 'N/A')
.replaceAll('[object Object]', '')
.replaceAll(',', '');
const str = `${when.slice(11, 16)} ${when.slice(
0,
10
)} ${otherKeys} ${tags}`;
if (str.toLowerCase().includes(searchQuery.toLowerCase()))
submissionsToRender.push(entry);
}
setEntries(submissionsToRender);
}
};
export default searchQueryHandler;