refactor: AllEntries Table replaced by new table and logic
This commit is contained in:
parent
098e865e91
commit
e5d0e50102
@ -47,10 +47,6 @@ const RoutingManager = (props) => {
|
|||||||
path={`${CHALLENGE_PAGE}/:challengeId/submit`}
|
path={`${CHALLENGE_PAGE}/:challengeId/submit`}
|
||||||
element={<Challenge section={CHALLENGE_SECTIONS.SUBMIT} />}
|
element={<Challenge section={CHALLENGE_SECTIONS.SUBMIT} />}
|
||||||
/>
|
/>
|
||||||
<Route
|
|
||||||
path={`${CHALLENGE_PAGE}/:challengeId/NewTablePageTest`}
|
|
||||||
element={<Challenge section={7} />}
|
|
||||||
/>
|
|
||||||
<Route path={CHALLENGES_PAGE} element={<Challenges />} />
|
<Route path={CHALLENGES_PAGE} element={<Challenges />} />
|
||||||
<Route
|
<Route
|
||||||
path={POLICY_PRIVACY_PAGE}
|
path={POLICY_PRIVACY_PAGE}
|
||||||
|
@ -3,8 +3,7 @@ import KeyCloakService from '../services/KeyCloakService';
|
|||||||
|
|
||||||
const getAllEntries = (
|
const getAllEntries = (
|
||||||
challengeName,
|
challengeName,
|
||||||
setDataOriginalState,
|
setDataStates,
|
||||||
setDataState,
|
|
||||||
setLoadingState,
|
setLoadingState,
|
||||||
setScoreSorted
|
setScoreSorted
|
||||||
) => {
|
) => {
|
||||||
@ -13,7 +12,6 @@ const getAllEntries = (
|
|||||||
})
|
})
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (setDataOriginalState) setDataOriginalState(data);
|
|
||||||
let item = {};
|
let item = {};
|
||||||
let result = [];
|
let result = [];
|
||||||
let initSetScoreSorted = [];
|
let initSetScoreSorted = [];
|
||||||
@ -57,7 +55,7 @@ const getAllEntries = (
|
|||||||
for (let _ of tests) {
|
for (let _ of tests) {
|
||||||
initSetScoreSorted.push(false);
|
initSetScoreSorted.push(false);
|
||||||
}
|
}
|
||||||
setDataState(result);
|
for (let setDataState of setDataStates) setDataState(result);
|
||||||
if (setScoreSorted) setScoreSorted(initSetScoreSorted);
|
if (setScoreSorted) setScoreSorted(initSetScoreSorted);
|
||||||
if (setLoadingState) setLoadingState(false);
|
if (setLoadingState) setLoadingState(false);
|
||||||
});
|
});
|
||||||
|
@ -1,222 +1,43 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import pensilIco from '../../../assets/pencil_ico.svg';
|
||||||
Container,
|
import deleteIco from '../../../assets/delete_ico.svg';
|
||||||
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 ColumnFilterIcon from '../ColumnFilterIcon';
|
|
||||||
// import deleteSubmission from '../../api/deleteSubmission';
|
|
||||||
import TableStyle from './styles/TableStyle';
|
import TableStyle from './styles/TableStyle';
|
||||||
import TableLine from './styles/TableLine';
|
import TableHeader from './components/TableHeader';
|
||||||
import MobileTableStyle from './styles/MobileTableStyle';
|
import TableRowTags from './components/TableRowTags';
|
||||||
|
import TableRowItems from './components/TableRowItems';
|
||||||
|
import TableRowButtons from './components/TableRowButtons';
|
||||||
|
import RowsBackgroundStyle from './styles/RowsBackgroundStyle';
|
||||||
|
import { FlexRow } from '../../../utils/containers';
|
||||||
|
|
||||||
const Table = (props) => {
|
const Table = ({ items, orderedKeys, sortByUpdate }) => {
|
||||||
const [, updateState] = React.useState();
|
const [, updateState] = React.useState();
|
||||||
const forceUpdate = React.useCallback(() => updateState({}), []);
|
const tableUpdate = React.useCallback(() => updateState({}), []);
|
||||||
const [activeIcon, setActiveIcon] = React.useState(null);
|
|
||||||
const [rotateActiveIcon, setRotateActiveIcon] = React.useState(false);
|
|
||||||
|
|
||||||
const metricsRender = (elem) => {
|
|
||||||
if (!props.iterableColumnElement) return <></>;
|
|
||||||
if (Array.isArray(elem[props.iterableColumnElement.name]))
|
|
||||||
elem = elem[props.iterableColumnElement.name];
|
|
||||||
else {
|
|
||||||
let newElem = [];
|
|
||||||
for (let metric of props.possibleMetrics) {
|
|
||||||
if (Object.hasOwn(elem, props.iterableColumnElement.name)) {
|
|
||||||
if (elem[props.iterableColumnElement.name][metric] === '_')
|
|
||||||
newElem.push('N/A');
|
|
||||||
else newElem.push(elem[props.iterableColumnElement.name][metric]);
|
|
||||||
} else {
|
|
||||||
newElem.push('N/A');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elem = newElem;
|
|
||||||
}
|
|
||||||
let indexModificator = 2;
|
|
||||||
if (props.tableType === 'leaderboard') indexModificator = 4;
|
|
||||||
if (props.tableType === 'allEntries') indexModificator = 3;
|
|
||||||
|
|
||||||
return elem.map((iterableElem, i) => {
|
|
||||||
return (
|
|
||||||
<Body
|
|
||||||
key={`metric-result-${i}`}
|
|
||||||
as="td"
|
|
||||||
order={props.iterableColumnElement.order}
|
|
||||||
textAlign={props.iterableColumnElement.align}
|
|
||||||
minWidth="88px"
|
|
||||||
margin="auto 0"
|
|
||||||
overflowWrap="anywhere"
|
|
||||||
>
|
|
||||||
{IS_MOBILE() && (
|
|
||||||
<Container className="mobile-table-header">
|
|
||||||
{props.headerElements[indexModificator + i]}
|
|
||||||
</Container>
|
|
||||||
)}
|
|
||||||
{props.iterableColumnElement.format
|
|
||||||
? props.iterableColumnElement.format(iterableElem)
|
|
||||||
: iterableElem}
|
|
||||||
</Body>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const rowRender = (elem) => {
|
|
||||||
let RowStyle = Body;
|
|
||||||
if (elem.submitter === props.user) RowStyle = Medium;
|
|
||||||
return props.staticColumnElements.map((elemName, i) => {
|
|
||||||
return (
|
|
||||||
<RowStyle
|
|
||||||
key={`leaderboard-static-elemName-${i}-${elem[elemName.name]}`}
|
|
||||||
as="td"
|
|
||||||
order={elemName.order}
|
|
||||||
textAlign={elemName.align}
|
|
||||||
margin="auto 0"
|
|
||||||
minWidth="88px"
|
|
||||||
overflowWrap="anywhere"
|
|
||||||
cursor="pointer"
|
|
||||||
// onClick={props.myEntries && (() => deleteSubmission(elem.id))}
|
|
||||||
>
|
|
||||||
{IS_MOBILE() && (
|
|
||||||
<Container className="mobile-table-header">
|
|
||||||
{props.headerElements[i]}
|
|
||||||
</Container>
|
|
||||||
)}
|
|
||||||
{elemName.format
|
|
||||||
? elemName.format(elem[elemName.name])
|
|
||||||
: elem[elemName.name]}
|
|
||||||
</RowStyle>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const desktopRender = () => {
|
|
||||||
const n = (props.pageNr - 1) * (ELEMENTS_PER_PAGE * 2);
|
|
||||||
let elementsToMap = props.elements.slice(n, n + ELEMENTS_PER_PAGE * 2);
|
|
||||||
if (elementsToMap.length > 0) {
|
|
||||||
return (
|
|
||||||
<TableStyle as="table" margin="32px 0 72px 0" width="100%">
|
|
||||||
<FlexColumn as="tbody" width="100%">
|
|
||||||
<Grid
|
|
||||||
as="tr"
|
|
||||||
gridGap="20px"
|
|
||||||
position="relative"
|
|
||||||
width="100%"
|
|
||||||
padding="0 6px"
|
|
||||||
minHeight="44px"
|
|
||||||
margin="0 0 6px 0"
|
|
||||||
gridTemplateColumns={props.gridTemplateColumns}
|
|
||||||
>
|
|
||||||
{props.headerElements.map((elem, i) => {
|
|
||||||
return (
|
|
||||||
<FlexRow
|
|
||||||
key={`table-header-${i}`}
|
|
||||||
alignmentX="flex-start"
|
|
||||||
as="td"
|
|
||||||
cursor="pointer"
|
|
||||||
onClick={() => {
|
|
||||||
if (activeIcon === i) {
|
|
||||||
let newRotateActiveIcon = !rotateActiveIcon;
|
|
||||||
setRotateActiveIcon(newRotateActiveIcon);
|
|
||||||
} else {
|
|
||||||
setRotateActiveIcon(false);
|
|
||||||
}
|
|
||||||
setActiveIcon(i);
|
|
||||||
props.sortByUpdate(elem, i);
|
|
||||||
forceUpdate();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Medium
|
|
||||||
cursor={elem !== '#' ? 'pointer' : ''}
|
|
||||||
textAlign={elem === 'when' ? 'right' : 'left'}
|
|
||||||
width={elem === 'when' ? '100%' : 'auto'}
|
|
||||||
padding="0 4px 0 0"
|
|
||||||
overflowWrap="anywhere"
|
|
||||||
minWidth="72px"
|
|
||||||
>
|
|
||||||
{elem.replace('.', ' ')}
|
|
||||||
</Medium>
|
|
||||||
{elem !== '#' && (
|
|
||||||
<ColumnFilterIcon
|
|
||||||
cursor="pointer"
|
|
||||||
index={i}
|
|
||||||
active={activeIcon}
|
|
||||||
rotateIcon={rotateActiveIcon}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</FlexRow>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
<TableLine
|
|
||||||
height="2px"
|
|
||||||
top="calc(100% + 2px)"
|
|
||||||
as="td"
|
|
||||||
shadow={theme.shadow}
|
|
||||||
/>
|
|
||||||
</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"
|
|
||||||
minHeight="48px"
|
|
||||||
>
|
|
||||||
{rowRender(elem)}
|
|
||||||
{props.headerElements ? metricsRender(elem) : ''}
|
|
||||||
</Grid>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</FlexColumn>
|
|
||||||
</TableStyle>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return <Medium margin="72px 0">No results ;c</Medium>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const mobileRender = () => {
|
|
||||||
const n = (props.pageNr - 1) * ELEMENTS_PER_PAGE;
|
|
||||||
let elementsToMap = props.elements.slice(n, n + ELEMENTS_PER_PAGE);
|
|
||||||
if (elementsToMap.length > 0) {
|
|
||||||
return (
|
|
||||||
<MobileTableStyle
|
|
||||||
as="table"
|
|
||||||
staticColumnElements={props.staticColumnElements}
|
|
||||||
headerElements={props.headerElements}
|
|
||||||
>
|
|
||||||
<Container as="tbody">
|
|
||||||
{elementsToMap.map((elem, index) => {
|
|
||||||
return (
|
|
||||||
<Grid as="tr" key={`leaderboard-row-${index}`}>
|
|
||||||
{rowRender(elem)}
|
|
||||||
{props.headerElements ? metricsRender(elem) : ''}
|
|
||||||
</Grid>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Container>
|
|
||||||
</MobileTableStyle>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return <Medium margin="72px 0">No results ;c</Medium>;
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<TableStyle>
|
||||||
<Media query={theme.mobile}>{mobileRender()}</Media>
|
<TableHeader
|
||||||
<Media query={theme.desktop}>{desktopRender()}</Media>
|
orderedKeys={orderedKeys}
|
||||||
</>
|
sortByUpdate={sortByUpdate}
|
||||||
|
tableUpdate={tableUpdate}
|
||||||
|
/>
|
||||||
|
{items.map((item, i) => {
|
||||||
|
return (
|
||||||
|
<tr key={`table-row-${i}`} className="TableStyle__tr">
|
||||||
|
<TableRowItems orderedKeys={orderedKeys} item={item} i={i} />
|
||||||
|
<FlexRow className="TableStyle__row-footer">
|
||||||
|
<TableRowTags item={item} i={i} />
|
||||||
|
<TableRowButtons
|
||||||
|
buttons={[
|
||||||
|
{ icon: pensilIco, handler: () => console.log('edit') },
|
||||||
|
{ icon: deleteIco, handler: () => console.log('delete') },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</FlexRow>
|
||||||
|
<RowsBackgroundStyle i={i} />
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TableStyle>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,19 +1,18 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import SortButtonContainerStyle from '../../styles/SortButtonContainerStyle';
|
import { FlexRow } from '../../../../../utils/containers';
|
||||||
import ColumnFilterIcon from '../../../../components/generic/ColumnFilterIcon';
|
import ColumnFilterIcon from '../../../ColumnFilterIcon';
|
||||||
import { FlexRow } from '../../../../utils/containers';
|
|
||||||
|
|
||||||
const TableHeader = (props) => {
|
const TableHeader = (props) => {
|
||||||
const [activeIcon, setActiveIcon] = React.useState(null);
|
const [activeIcon, setActiveIcon] = React.useState(null);
|
||||||
const [rotateActiveIcon, setRotateActiveIcon] = React.useState(false);
|
const [rotateActiveIcon, setRotateActiveIcon] = React.useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr className="NewTableStyle__tr-header">
|
<tr className="TableStyle__tr-header">
|
||||||
{props.orderedKeys.map((keyValue, i) => {
|
{props.orderedKeys.map((keyValue, i) => {
|
||||||
return (
|
return (
|
||||||
<th
|
<th
|
||||||
key={`table-header-${i}`}
|
key={`table-header-${i}`}
|
||||||
className="NewTableStyle__th"
|
className="TableStyle__th"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (activeIcon === i) {
|
if (activeIcon === i) {
|
||||||
let newRotateActiveIcon = !rotateActiveIcon;
|
let newRotateActiveIcon = !rotateActiveIcon;
|
||||||
@ -27,17 +26,21 @@ const TableHeader = (props) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{keyValue}
|
{keyValue}
|
||||||
<SortButtonContainerStyle as="span" column={keyValue}>
|
<FlexRow
|
||||||
|
as="span"
|
||||||
|
className="TableStyle__sort-button"
|
||||||
|
column={keyValue}
|
||||||
|
>
|
||||||
<ColumnFilterIcon
|
<ColumnFilterIcon
|
||||||
index={i}
|
index={i}
|
||||||
active={activeIcon}
|
active={activeIcon}
|
||||||
rotateIcon={rotateActiveIcon}
|
rotateIcon={rotateActiveIcon}
|
||||||
/>
|
/>
|
||||||
</SortButtonContainerStyle>
|
</FlexRow>
|
||||||
</th>
|
</th>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<FlexRow className="NewTableStyle__line" as="td" />
|
<FlexRow className="TableStyle__line" as="td" />
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
};
|
};
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FlexRow, Svg } from '../../../../utils/containers';
|
import { FlexRow, Svg } from '../../../../../utils/containers';
|
||||||
import theme from '../../../../utils/theme';
|
import theme from '../../../../../utils/theme';
|
||||||
|
|
||||||
const TableRowButtons = ({ buttons, i }) => {
|
const TableRowButtons = ({ buttons, i }) => {
|
||||||
return (
|
return (
|
@ -1,12 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { RENDER_WHEN, RENDER_METRIC_VALUE } from '../../../../utils/globals';
|
import { RENDER_WHEN, RENDER_METRIC_VALUE } from '../../../../../utils/globals';
|
||||||
|
|
||||||
const TableRowItems = ({ orderedKeys, item, i }) => {
|
const TableRowItems = ({ orderedKeys, item, i }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{orderedKeys.map((keyValue, j) => {
|
{orderedKeys.map((keyValue, j) => {
|
||||||
return (
|
return (
|
||||||
<td key={`table-item-${i}-${j}`} className="NewTableStyle__td">
|
<td key={`table-item-${i}-${j}`} className="TableStyle__td">
|
||||||
{keyValue === 'when'
|
{keyValue === 'when'
|
||||||
? RENDER_WHEN(item[keyValue])
|
? RENDER_WHEN(item[keyValue])
|
||||||
: RENDER_METRIC_VALUE(item[keyValue])}
|
: RENDER_METRIC_VALUE(item[keyValue])}
|
@ -1,9 +1,9 @@
|
|||||||
import { FlexRow } from '../../../../utils/containers';
|
|
||||||
import renderTags from './renderTags';
|
import renderTags from './renderTags';
|
||||||
|
import { FlexRow } from '../../../../../utils/containers';
|
||||||
|
|
||||||
const TableRowTags = ({ item, i }) => {
|
const TableRowTags = ({ item, i }) => {
|
||||||
return (
|
return (
|
||||||
<FlexRow className="NewTableStyle__tags-container">
|
<FlexRow className="TableStyle__tags-container">
|
||||||
{renderTags(item.tags)}
|
{renderTags(item.tags)}
|
||||||
</FlexRow>
|
</FlexRow>
|
||||||
);
|
);
|
@ -0,0 +1,16 @@
|
|||||||
|
import { FlexRow } from '../../../../../utils/containers';
|
||||||
|
|
||||||
|
const renderTags = (tags, i) => {
|
||||||
|
if (tags.length > 0) {
|
||||||
|
return tags.map((tag, j) => {
|
||||||
|
return (
|
||||||
|
<FlexRow className="TableStyle__tag" key={`submissionTag-${i}-${j}`}>
|
||||||
|
{tag.name}
|
||||||
|
</FlexRow>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return <FlexRow className="TableStyle__tag">submission without tags</FlexRow>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default renderTags;
|
@ -1,58 +0,0 @@
|
|||||||
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;
|
|
@ -1,5 +1,5 @@
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { FlexRow } from '../../../utils/containers';
|
import { FlexRow } from '../../../../utils/containers';
|
||||||
|
|
||||||
const RowsBackgroundStyle = styled(FlexRow)`
|
const RowsBackgroundStyle = styled(FlexRow)`
|
||||||
width: calc(100% + 12px);
|
width: calc(100% + 12px);
|
@ -1,14 +0,0 @@
|
|||||||
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;
|
|
@ -1,8 +1,71 @@
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { FlexColumn } from '../../../../utils/containers';
|
|
||||||
|
|
||||||
const TableStyle = styled(FlexColumn)`
|
const TableStyle = styled.table`
|
||||||
overflow-x: ${({ metrics }) => (metrics > 10 ? 'scroll' : 'auto')};
|
border-collapse: separate;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.TableStyle__th {
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
* {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.TableStyle__tr-header {
|
||||||
|
height: 48px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.TableStyle__tr {
|
||||||
|
position: relative;
|
||||||
|
height: 72px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.TableStyle__td {
|
||||||
|
padding: 0 0 32px 0;
|
||||||
|
margin: 0 0 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.TableStyle_line {
|
||||||
|
position: absolute;
|
||||||
|
top: 94%;
|
||||||
|
bottom: ${({ bottom }) => (bottom ? bottom : 'auto')};
|
||||||
|
left: -6px;
|
||||||
|
width: calc(100% + 12px);
|
||||||
|
background-color: ${({ theme }) => theme.colors.dark04};
|
||||||
|
height: 3px;
|
||||||
|
box-shadow: ${({ theme }) => theme.shadow};
|
||||||
|
}
|
||||||
|
|
||||||
|
.TableStyle__tag {
|
||||||
|
color: ${({ theme }) => theme.colors.white};
|
||||||
|
background-color: ${({ theme }) => theme.colors.green08};
|
||||||
|
padding: 4px;
|
||||||
|
border-radius: 2px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.TableStyle__row-footer {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
position: absolute;
|
||||||
|
top: 55%;
|
||||||
|
left: 0;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.TableStyle__tags-container {
|
||||||
|
gap: 4px;
|
||||||
|
padding: 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.TableStyle__sort-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 15px;
|
||||||
|
right: 16%;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default TableStyle;
|
export default TableStyle;
|
||||||
|
@ -1,244 +1,154 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import theme from '../../utils/theme';
|
|
||||||
import Media from 'react-media';
|
|
||||||
import { FlexColumn } from '../../utils/containers';
|
import { FlexColumn } from '../../utils/containers';
|
||||||
import { H2 } from '../../utils/fonts';
|
import { H2 } from '../../utils/fonts';
|
||||||
import {
|
|
||||||
CALC_PAGES,
|
|
||||||
EVALUATIONS_FORMAT,
|
|
||||||
RENDER_WHEN,
|
|
||||||
IS_MOBILE,
|
|
||||||
} from '../../utils/globals';
|
|
||||||
import Loading from '../../components/generic/Loading';
|
|
||||||
import Pager from '../../components/generic/Pager';
|
import Pager from '../../components/generic/Pager';
|
||||||
import Table from '../../components/generic/Table/Table';
|
|
||||||
import Search from '../../components/generic/Search';
|
import Search from '../../components/generic/Search';
|
||||||
import allEntriesSearchQueryHandler from './allEntriesSearchQueryHandler';
|
|
||||||
import getAllEntries from '../../api/getAllEntries';
|
import getAllEntries from '../../api/getAllEntries';
|
||||||
|
import Table from '../../components/generic/Table';
|
||||||
|
import Loading from '../../components/generic/Loading';
|
||||||
|
import { CALC_PAGES, ELEMENTS_PER_PAGE } from '../../utils/globals';
|
||||||
|
import searchQueryHandler from './searchHandler';
|
||||||
|
import orderKeys from './orderKeys';
|
||||||
|
|
||||||
const AllEntries = (props) => {
|
const NewTablePageTest = (props) => {
|
||||||
const [entriesFromApi, setEntriesFromApi] = React.useState([]);
|
|
||||||
const [entriesAll, setEntriesAll] = React.useState([]);
|
const [entriesAll, setEntriesAll] = React.useState([]);
|
||||||
const [entries, setEntries] = React.useState([]);
|
const [entries, setEntries] = React.useState([]);
|
||||||
const [pageNr, setPageNr] = React.useState(1);
|
const [pageNr, setPageNr] = React.useState(1);
|
||||||
const [loading, setLoading] = React.useState(true);
|
const [loading, setLoading] = React.useState(true);
|
||||||
|
const [idSorted, setIdSorted] = React.useState([]);
|
||||||
const [scoresSorted, setScoresSorted] = React.useState([]);
|
const [scoresSorted, setScoresSorted] = React.useState([]);
|
||||||
const [submitterSorted, setSubmitterSorted] = React.useState(false);
|
const [submitterSorted, setSubmitterSorted] = React.useState(false);
|
||||||
const [whenSorted, setWhenSorted] = React.useState(false);
|
const [whenSorted, setWhenSorted] = React.useState(false);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useMemo(() => {
|
||||||
if (props.challengeName) challengeDataRequest(props.challengeName);
|
if (props.challengeName) {
|
||||||
|
getAllEntries(
|
||||||
|
props.challengeName,
|
||||||
|
[setEntries, setEntriesAll],
|
||||||
|
setLoading,
|
||||||
|
setScoresSorted
|
||||||
|
);
|
||||||
|
}
|
||||||
}, [props.challengeName]);
|
}, [props.challengeName]);
|
||||||
|
|
||||||
const challengeDataRequest = (challengeName) => {
|
const sortByUpdate = React.useCallback(
|
||||||
getAllEntries(challengeName, setEntriesFromApi, setEntriesAll);
|
(elem) => {
|
||||||
getAllEntries(
|
let newEntries = entries.slice();
|
||||||
challengeName,
|
const possibleMetrics = orderKeys(entries[0]).filter(
|
||||||
undefined,
|
(key) => !['id', 'submitter', 'when'].includes(key)
|
||||||
setEntries,
|
);
|
||||||
setLoading,
|
let metricIndex = possibleMetrics.indexOf(elem);
|
||||||
setScoresSorted
|
let newScoresSorted = scoresSorted.slice();
|
||||||
);
|
switch (elem) {
|
||||||
};
|
case 'id':
|
||||||
|
if (idSorted) {
|
||||||
const getPossibleMetrics = () => {
|
setIdSorted(false);
|
||||||
let metrics = [];
|
newEntries = newEntries.sort((a, b) =>
|
||||||
if (entriesFromApi.tests) {
|
a.id > b.id ? 1 : b.id > a.id ? -1 : 0
|
||||||
for (let test of entriesFromApi.tests) {
|
);
|
||||||
let myEval = `${test.metric}.${test.name}`;
|
} else {
|
||||||
if (myEval && !metrics.includes(myEval)) {
|
setIdSorted(true);
|
||||||
metrics.push(myEval);
|
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;
|
||||||
}
|
}
|
||||||
}
|
setEntries(newEntries);
|
||||||
return metrics;
|
},
|
||||||
};
|
[entries, idSorted, scoresSorted, submitterSorted, whenSorted]
|
||||||
|
);
|
||||||
|
|
||||||
const getAllEntriesHeader = () => {
|
const n = (pageNr - 1) * (ELEMENTS_PER_PAGE * 2);
|
||||||
let header = ['#', 'submitter'];
|
let elements = entries.slice(n, n + ELEMENTS_PER_PAGE * 2);
|
||||||
if (IS_MOBILE()) header.push('when');
|
|
||||||
for (let metric of getPossibleMetrics()) {
|
|
||||||
header.push(metric);
|
|
||||||
}
|
|
||||||
if (!IS_MOBILE()) header.push('when');
|
|
||||||
return header;
|
|
||||||
};
|
|
||||||
|
|
||||||
const searchQueryHandler = (event) => {
|
|
||||||
allEntriesSearchQueryHandler(event, entriesAll, setPageNr, setEntries);
|
|
||||||
};
|
|
||||||
|
|
||||||
const sortByUpdate = (elem, i) => {
|
|
||||||
let newEntries = entries;
|
|
||||||
switch (elem) {
|
|
||||||
case '#':
|
|
||||||
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:
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
setEntries(newEntries);
|
|
||||||
};
|
|
||||||
|
|
||||||
const mobileRender = () => {
|
|
||||||
return (
|
|
||||||
<FlexColumn padding="24px 12px" width="70%" as="section" id="start">
|
|
||||||
<H2 as="h2" margin="0 0 12px 0">
|
|
||||||
All Entries
|
|
||||||
</H2>
|
|
||||||
{!loading ? (
|
|
||||||
<>
|
|
||||||
<Search searchQueryHandler={searchQueryHandler} />
|
|
||||||
<Table
|
|
||||||
challengeName={props.challengeName}
|
|
||||||
headerElements={getAllEntriesHeader()}
|
|
||||||
possibleMetrics={getPossibleMetrics()}
|
|
||||||
tableType="allEntries"
|
|
||||||
gridTemplateColumns={
|
|
||||||
'1fr ' + '4fr '.repeat(getAllEntriesHeader().length - 1)
|
|
||||||
}
|
|
||||||
staticColumnElements={[
|
|
||||||
{ name: 'id', format: null, order: 1, align: 'left' },
|
|
||||||
{ name: 'submitter', format: null, order: 2, align: 'left' },
|
|
||||||
{ name: 'when', format: RENDER_WHEN, order: 5, align: 'right' },
|
|
||||||
]}
|
|
||||||
iterableColumnElement={{
|
|
||||||
name: 'evaluations',
|
|
||||||
format: EVALUATIONS_FORMAT,
|
|
||||||
order: 3,
|
|
||||||
align: 'left',
|
|
||||||
}}
|
|
||||||
pageNr={pageNr}
|
|
||||||
elements={entries}
|
|
||||||
sortByUpdate={sortByUpdate}
|
|
||||||
/>
|
|
||||||
<Pager
|
|
||||||
pageNr={pageNr}
|
|
||||||
elements={entries}
|
|
||||||
setPageNr={setPageNr}
|
|
||||||
width="48px"
|
|
||||||
borderRadius="64px"
|
|
||||||
pages={CALC_PAGES(entries)}
|
|
||||||
number={`${pageNr} / ${CALC_PAGES(entries)}`}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<Loading />
|
|
||||||
)}
|
|
||||||
</FlexColumn>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const desktopRender = () => {
|
|
||||||
return (
|
|
||||||
<FlexColumn padding="24px" as="section" width="100%" maxWidth="1600px">
|
|
||||||
<H2 as="h2" margin="0 0 32px 0">
|
|
||||||
All Entries
|
|
||||||
</H2>
|
|
||||||
{!loading ? (
|
|
||||||
<>
|
|
||||||
<Search searchQueryHandler={searchQueryHandler} />
|
|
||||||
<Table
|
|
||||||
challengeName={props.challengeName}
|
|
||||||
headerElements={getAllEntriesHeader()}
|
|
||||||
possibleMetrics={getPossibleMetrics()}
|
|
||||||
gridTemplateColumns={
|
|
||||||
'1fr 3fr ' + '3fr '.repeat(getPossibleMetrics().length) + ' 3fr'
|
|
||||||
}
|
|
||||||
user={props.user}
|
|
||||||
staticColumnElements={[
|
|
||||||
{ name: 'id', format: null, order: 1, align: 'left' },
|
|
||||||
{ name: 'submitter', format: null, order: 2, align: 'left' },
|
|
||||||
{ name: 'when', format: RENDER_WHEN, order: 5, align: 'right' },
|
|
||||||
]}
|
|
||||||
metrics={getPossibleMetrics()}
|
|
||||||
iterableColumnElement={{
|
|
||||||
name: 'evaluations',
|
|
||||||
format: EVALUATIONS_FORMAT,
|
|
||||||
order: 3,
|
|
||||||
align: 'left',
|
|
||||||
}}
|
|
||||||
pageNr={pageNr}
|
|
||||||
elements={entries}
|
|
||||||
setPageNr={setPageNr}
|
|
||||||
sortByUpdate={sortByUpdate}
|
|
||||||
/>
|
|
||||||
<Pager
|
|
||||||
pageNr={pageNr}
|
|
||||||
elements={entries}
|
|
||||||
setPageNr={setPageNr}
|
|
||||||
width="72px"
|
|
||||||
borderRadius="64px"
|
|
||||||
pages={CALC_PAGES(entries, 2)}
|
|
||||||
number={`${pageNr} / ${CALC_PAGES(entries, 2)}`}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<Loading />
|
|
||||||
)}
|
|
||||||
</FlexColumn>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
return (
|
return (
|
||||||
<>
|
<FlexColumn
|
||||||
<Media query={theme.mobile}>{mobileRender()}</Media>
|
padding="24px"
|
||||||
<Media query={theme.desktop}>{desktopRender()}</Media>
|
gap="32px"
|
||||||
</>
|
as="section"
|
||||||
|
width="100%"
|
||||||
|
maxWidth="1600px"
|
||||||
|
>
|
||||||
|
<H2 as="h2">All Entries</H2>
|
||||||
|
{!loading ? (
|
||||||
|
<>
|
||||||
|
<Search
|
||||||
|
searchQueryHandler={(event) =>
|
||||||
|
searchQueryHandler(event, entriesAll, setPageNr, setEntries)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{elements.length > 0 && entries[0] && (
|
||||||
|
<Table
|
||||||
|
items={elements}
|
||||||
|
orderedKeys={orderKeys(entries[0])}
|
||||||
|
sortByUpdate={sortByUpdate}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Pager
|
||||||
|
pageNr={pageNr}
|
||||||
|
elements={entries}
|
||||||
|
setPageNr={setPageNr}
|
||||||
|
width="72px"
|
||||||
|
borderRadius="64px"
|
||||||
|
pages={CALC_PAGES(entries, 2)}
|
||||||
|
number={`${pageNr} / ${CALC_PAGES(entries, 2)}`}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Loading />
|
||||||
|
)}
|
||||||
|
</FlexColumn>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AllEntries;
|
export default NewTablePageTest;
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
const allEntriesSearchQueryHandler = (
|
|
||||||
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, submitter } = entry;
|
|
||||||
let evaluations = '';
|
|
||||||
if (entry.evaluations) {
|
|
||||||
for (let evaluation of Object.values(entry.evaluations)) {
|
|
||||||
evaluations += ` ${evaluation}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const str = `${id} ${submitter} ${when.slice(11, 16)} ${when.slice(
|
|
||||||
0,
|
|
||||||
10
|
|
||||||
)} ${evaluations}`;
|
|
||||||
if (str.toLowerCase().includes(searchQuery.toLowerCase()))
|
|
||||||
submissionsToRender.push(entry);
|
|
||||||
}
|
|
||||||
setEntries(submissionsToRender);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default allEntriesSearchQueryHandler;
|
|
23
src/pages/AllEntries/orderKeys.js
Normal file
23
src/pages/AllEntries/orderKeys.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
const orderKeys = (elem) => {
|
||||||
|
if (elem) {
|
||||||
|
let result = ['id', 'submitter'];
|
||||||
|
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;
|
@ -17,7 +17,6 @@ import getChallengeInfo from '../../api/getChallengeInfo';
|
|||||||
import Loading from '../../components/generic/Loading';
|
import Loading from '../../components/generic/Loading';
|
||||||
import getUser from '../../api/getUser';
|
import getUser from '../../api/getUser';
|
||||||
import AllEntries from '../AllEntries/AllEntries';
|
import AllEntries from '../AllEntries/AllEntries';
|
||||||
import NewTablePageTest from '../NewTable/NewTablePageTest';
|
|
||||||
|
|
||||||
const Challenge = (props) => {
|
const Challenge = (props) => {
|
||||||
const challengeName = useParams().challengeId;
|
const challengeName = useParams().challengeId;
|
||||||
@ -65,8 +64,6 @@ const Challenge = (props) => {
|
|||||||
return <MyEntries challengeName={challengeName} />;
|
return <MyEntries challengeName={challengeName} />;
|
||||||
case CHALLENGE_SECTIONS.SUBMIT:
|
case CHALLENGE_SECTIONS.SUBMIT:
|
||||||
return <Submit challengeName={challengeName} setLoading={setLoading} />;
|
return <Submit challengeName={challengeName} setLoading={setLoading} />;
|
||||||
case 7:
|
|
||||||
return <NewTablePageTest challengeName={challengeName} />;
|
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<Leaderboard
|
<Leaderboard
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { FlexRow } from '../../utils/containers';
|
|
||||||
import pensilIco from '../../assets/pencil_ico.svg';
|
|
||||||
import deleteIco from '../../assets/delete_ico.svg';
|
|
||||||
import NewTableStyle from './styles/NewTableStyle';
|
|
||||||
import RowsBackgroundStyle from './styles/RowsBackgroundStyle';
|
|
||||||
import TableHeader from './components/TableHeader';
|
|
||||||
import TableRowTags from './components/TableRowTags';
|
|
||||||
import TableRowItems from './components/TableRowItems';
|
|
||||||
import TableRowButtons from './components/TableRowButtons';
|
|
||||||
|
|
||||||
const NewTable = ({ items, orderedKeys, sortByUpdate }) => {
|
|
||||||
const [, updateState] = React.useState();
|
|
||||||
const tableUpdate = React.useCallback(() => updateState({}), []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<NewTableStyle>
|
|
||||||
<TableHeader
|
|
||||||
orderedKeys={orderedKeys}
|
|
||||||
sortByUpdate={sortByUpdate}
|
|
||||||
tableUpdate={tableUpdate}
|
|
||||||
/>
|
|
||||||
{items.map((item, i) => {
|
|
||||||
return (
|
|
||||||
<tr key={`table-row-${i}`} className="NewTableStyle__tr">
|
|
||||||
<TableRowItems orderedKeys={orderedKeys} item={item} i={i} />
|
|
||||||
<FlexRow className="NewTableStyle__row-footer">
|
|
||||||
<TableRowTags item={item} i={i} />
|
|
||||||
<TableRowButtons
|
|
||||||
buttons={[
|
|
||||||
{ icon: pensilIco, handler: () => console.log('edit') },
|
|
||||||
{ icon: deleteIco, handler: () => console.log('delete') },
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</FlexRow>
|
|
||||||
<RowsBackgroundStyle i={i} />
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</NewTableStyle>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default NewTable;
|
|
@ -1,174 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
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 NewTable from './NewTable';
|
|
||||||
import Loading from '../../components/generic/Loading';
|
|
||||||
import { CALC_PAGES, ELEMENTS_PER_PAGE } from '../../utils/globals';
|
|
||||||
import searchQueryHandler from './searchHandler';
|
|
||||||
|
|
||||||
const NewTablePageTest = (props) => {
|
|
||||||
// eslint-disable-next-line
|
|
||||||
const [entriesFromApi, setEntriesFromApi] = React.useState([]);
|
|
||||||
const [entriesAll, setEntriesAll] = React.useState([]);
|
|
||||||
const [entries, setEntries] = React.useState([]);
|
|
||||||
const [pageNr, setPageNr] = React.useState(1);
|
|
||||||
const [loading, setLoading] = React.useState(true);
|
|
||||||
const [idSorted, setIdSorted] = React.useState([]);
|
|
||||||
const [scoresSorted, setScoresSorted] = React.useState([]);
|
|
||||||
const [submitterSorted, setSubmitterSorted] = React.useState(false);
|
|
||||||
const [whenSorted, setWhenSorted] = React.useState(false);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (props.challengeName) challengeDataRequest(props.challengeName);
|
|
||||||
}, [props.challengeName]);
|
|
||||||
|
|
||||||
const challengeDataRequest = (challengeName) => {
|
|
||||||
getAllEntries(challengeName, setEntriesFromApi, setEntriesAll);
|
|
||||||
getAllEntries(
|
|
||||||
challengeName,
|
|
||||||
undefined,
|
|
||||||
setEntries,
|
|
||||||
setLoading,
|
|
||||||
setScoresSorted
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const sortByUpdate = (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;
|
|
||||||
}
|
|
||||||
setEntries(newEntries);
|
|
||||||
};
|
|
||||||
|
|
||||||
const orderKeys = (elem) => {
|
|
||||||
if (elem) {
|
|
||||||
let result = ['id', 'submitter'];
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
const n = (pageNr - 1) * (ELEMENTS_PER_PAGE * 2);
|
|
||||||
let elements = entries.slice(n, n + ELEMENTS_PER_PAGE * 2);
|
|
||||||
|
|
||||||
if (!loading) {
|
|
||||||
return (
|
|
||||||
<FlexColumn
|
|
||||||
padding="24px"
|
|
||||||
gap="32px"
|
|
||||||
as="section"
|
|
||||||
width="100%"
|
|
||||||
maxWidth="1600px"
|
|
||||||
>
|
|
||||||
<H2 as="h2">New Table Test</H2>
|
|
||||||
<Search
|
|
||||||
searchQueryHandler={(event) =>
|
|
||||||
searchQueryHandler(event, entriesAll, setPageNr, setEntries)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
{elements.length > 0 && entries[0] && (
|
|
||||||
<NewTable
|
|
||||||
items={elements}
|
|
||||||
orderedKeys={orderKeys(entries[0])}
|
|
||||||
sortByUpdate={sortByUpdate}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<Pager
|
|
||||||
pageNr={pageNr}
|
|
||||||
elements={entries}
|
|
||||||
setPageNr={setPageNr}
|
|
||||||
width="72px"
|
|
||||||
borderRadius="64px"
|
|
||||||
pages={CALC_PAGES(entries, 2)}
|
|
||||||
number={`${pageNr} / ${CALC_PAGES(entries, 2)}`}
|
|
||||||
/>
|
|
||||||
</FlexColumn>
|
|
||||||
);
|
|
||||||
} else return <Loading />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default NewTablePageTest;
|
|
@ -1,18 +0,0 @@
|
|||||||
import { FlexRow } from '../../../../utils/containers';
|
|
||||||
|
|
||||||
const renderTags = (tags, i) => {
|
|
||||||
if (tags.length > 0) {
|
|
||||||
return tags.map((tag, j) => {
|
|
||||||
return (
|
|
||||||
<FlexRow className="NewTableStyle__tag" key={`submissionTag-${i}-${j}`}>
|
|
||||||
{tag.name}
|
|
||||||
</FlexRow>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<FlexRow className="NewTableStyle__tag">submission without tags</FlexRow>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default renderTags;
|
|
@ -1 +0,0 @@
|
|||||||
export { default } from './NewTablePageTest';
|
|
@ -1,65 +0,0 @@
|
|||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
const NewTableStyle = styled.table`
|
|
||||||
border-collapse: separate;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.NewTableStyle__th {
|
|
||||||
position: relative;
|
|
||||||
cursor: pointer;
|
|
||||||
* {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.NewTableStyle__tr-header {
|
|
||||||
height: 48px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.NewTableStyle__tr {
|
|
||||||
position: relative;
|
|
||||||
height: 72px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.NewTableStyle__td {
|
|
||||||
padding: 0 0 32px 0;
|
|
||||||
margin: 0 0 0 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.NewTableStyle__line {
|
|
||||||
position: absolute;
|
|
||||||
top: 94%;
|
|
||||||
bottom: ${({ bottom }) => (bottom ? bottom : 'auto')};
|
|
||||||
left: -6px;
|
|
||||||
width: calc(100% + 12px);
|
|
||||||
background-color: ${({ theme }) => theme.colors.dark04};
|
|
||||||
height: 3px;
|
|
||||||
box-shadow: ${({ theme }) => theme.shadow};
|
|
||||||
}
|
|
||||||
|
|
||||||
.NewTableStyle__tag {
|
|
||||||
color: ${({ theme }) => theme.colors.white};
|
|
||||||
background-color: ${({ theme }) => theme.colors.green08};
|
|
||||||
padding: 4px;
|
|
||||||
border-radius: 2px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.NewTableStyle__row-footer {
|
|
||||||
width: 100%;
|
|
||||||
justify-content: space-between;
|
|
||||||
position: absolute;
|
|
||||||
top: 55%;
|
|
||||||
left: 0;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.NewTableStyle__tags-container {
|
|
||||||
gap: 4px;
|
|
||||||
padding: 0 2px;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default NewTableStyle;
|
|
@ -1,10 +0,0 @@
|
|||||||
import styled from 'styled-components';
|
|
||||||
import { FlexRow } from '../../../utils/containers';
|
|
||||||
|
|
||||||
const SortButtonContainerStyle = styled(FlexRow)`
|
|
||||||
position: absolute;
|
|
||||||
top: 15px;
|
|
||||||
right: 16%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default SortButtonContainerStyle;
|
|
Loading…
Reference in New Issue
Block a user