fetch leaderboard table data from backend; optimize table style
This commit is contained in:
parent
362da09294
commit
d7daa1da05
|
@ -10,19 +10,6 @@ import ExpandMore from '@material-ui/icons/ExpandMore';
|
||||||
import {makeStyles} from "@material-ui/core/styles";
|
import {makeStyles} from "@material-ui/core/styles";
|
||||||
import qs from 'query-string';
|
import qs from 'query-string';
|
||||||
|
|
||||||
const gameList = [
|
|
||||||
{game: 'leduc-holdem', dispName: 'Leduc Hold\'em'},
|
|
||||||
{game: 'doudizhu', dispName: 'Dou Dizhu'},
|
|
||||||
];
|
|
||||||
|
|
||||||
const modelList = [
|
|
||||||
{model: 'leduc-holdem-random', dispName: 'Leduc Hold\'em Random'},
|
|
||||||
{model: 'leduc-holdem-cfr', dispName: 'Leduc Hold\'em CFR'},
|
|
||||||
{model: 'leduc-holdem-rule-v1', dispName: 'Leduc Hold\'em Rule V1'},
|
|
||||||
{model: 'doudizhu-random', dispName: 'Dou Dizhu Random'},
|
|
||||||
{model: 'doudizhu-rule-v1', dispName: 'Dou Dizhu Rule V1'}
|
|
||||||
];
|
|
||||||
|
|
||||||
const drawerWidth = 250;
|
const drawerWidth = 250;
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
|
@ -60,7 +47,7 @@ const useStyles = makeStyles((theme) => ({
|
||||||
active: {}
|
active: {}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function MenuBar () {
|
function MenuBar (props) {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
const [open, setOpen] = React.useState({game: true, agent: true});
|
const [open, setOpen] = React.useState({game: true, agent: true});
|
||||||
|
@ -80,7 +67,7 @@ function MenuBar () {
|
||||||
}
|
}
|
||||||
|
|
||||||
const { type, name } = qs.parse(window.location.search);
|
const { type, name } = qs.parse(window.location.search);
|
||||||
const gameMenu = gameList.map(game => {
|
const gameMenu = props.gameList.map(game => {
|
||||||
return <List component="div" disablePadding key={"game-menu-"+game.game}>
|
return <List component="div" disablePadding key={"game-menu-"+game.game}>
|
||||||
<ListItem button className={classes.nested} onClick={() => {handleGameJump(game.game)}}>
|
<ListItem button className={classes.nested} onClick={() => {handleGameJump(game.game)}}>
|
||||||
<ListItemText primary={game.dispName} className={`${classes.menuLayer2} ${(type === 'game' && name === game.game) ? classes.active : classes.inactive}`} />
|
<ListItemText primary={game.dispName} className={`${classes.menuLayer2} ${(type === 'game' && name === game.game) ? classes.active : classes.inactive}`} />
|
||||||
|
@ -88,7 +75,7 @@ function MenuBar () {
|
||||||
</List>
|
</List>
|
||||||
});
|
});
|
||||||
|
|
||||||
const agentMenu = modelList.map(model => {
|
const agentMenu = props.modelList.map(model => {
|
||||||
return <List component="div" disablePadding key={"game-menu-"+model.model}>
|
return <List component="div" disablePadding key={"game-menu-"+model.model}>
|
||||||
<ListItem button className={classes.nested} onClick={() => {handleAgentJump(model.model)}}>
|
<ListItem button className={classes.nested} onClick={() => {handleAgentJump(model.model)}}>
|
||||||
<ListItemText primary={model.dispName} className={`${classes.menuLayer2} ${(type === 'agent' && name === model.model) ? classes.active : classes.inactive}`} />
|
<ListItemText primary={model.dispName} className={`${classes.menuLayer2} ${(type === 'agent' && name === model.model) ? classes.active : classes.inactive}`} />
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react';
|
import React, {useEffect} from 'react';
|
||||||
|
import qs from 'query-string';
|
||||||
import MenuBar from "../components/MenuBar";
|
import MenuBar from "../components/MenuBar";
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
@ -14,73 +15,97 @@ import Typography from '@material-ui/core/Typography';
|
||||||
import Paper from '@material-ui/core/Paper';
|
import Paper from '@material-ui/core/Paper';
|
||||||
import { apiUrl } from "../utils/config";
|
import { apiUrl } from "../utils/config";
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import TablePagination from "@material-ui/core/TablePagination";
|
||||||
|
import Breadcrumbs from "@material-ui/core/Breadcrumbs";
|
||||||
|
import withStyles from "@material-ui/core/styles/withStyles";
|
||||||
|
|
||||||
|
const gameList = [
|
||||||
|
{game: 'leduc-holdem', dispName: 'Leduc Hold\'em'},
|
||||||
|
{game: 'doudizhu', dispName: 'Dou Dizhu'},
|
||||||
|
];
|
||||||
|
|
||||||
|
const modelList = [
|
||||||
|
{model: 'leduc-holdem-random', dispName: 'Leduc Hold\'em Random'},
|
||||||
|
{model: 'leduc-holdem-cfr', dispName: 'Leduc Hold\'em CFR'},
|
||||||
|
{model: 'leduc-holdem-rule-v1', dispName: 'Leduc Hold\'em Rule V1'},
|
||||||
|
{model: 'doudizhu-random', dispName: 'Dou Dizhu Random'},
|
||||||
|
{model: 'doudizhu-rule-v1', dispName: 'Dou Dizhu Rule V1'}
|
||||||
|
];
|
||||||
|
|
||||||
function LeaderBoard () {
|
function LeaderBoard () {
|
||||||
console.log(`${apiUrl}/tournament/query_game?name=doudizhu`);
|
const [rows, setRows] = React.useState([]);
|
||||||
axios.get(`${apiUrl}/tournament/query_game?name=doudizhu`)
|
|
||||||
|
const { type, name } = qs.parse(window.location.search);
|
||||||
|
let requestUrl = `${apiUrl}/tournament/`;
|
||||||
|
if (type === 'game') {
|
||||||
|
requestUrl += `query_game?name=${name}`
|
||||||
|
} else if (type === 'agent') {
|
||||||
|
requestUrl += `query_game?agent0=${name}`
|
||||||
|
}
|
||||||
|
console.log(requestUrl);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function fetchData() {
|
||||||
|
const res = await axios.get(requestUrl);
|
||||||
|
console.log('wdnmd', res);
|
||||||
|
setRows(res.data.map((resRow) => {return createData(resRow);}));
|
||||||
|
}
|
||||||
|
fetchData();
|
||||||
|
}, [requestUrl])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<MenuBar />
|
<MenuBar gameList={gameList} modelList={modelList} />
|
||||||
<div style={{marginLeft: '250px'}}>
|
<div style={{marginLeft: '250px'}}>
|
||||||
<div style={{padding: 20}}>
|
<div style={{padding: 20}}>
|
||||||
{EnhancedTable()}
|
<EnhancedTable tableRows={rows} routeInfo={{type, name}}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function createData(name, calories, fat, carbs, protein) {
|
function createData(resData) {
|
||||||
return { name, calories, fat, carbs, protein };
|
return {
|
||||||
|
id: resData.pk,
|
||||||
|
game: resData.fields.name,
|
||||||
|
agent0: resData.fields.agent0,
|
||||||
|
agent1: resData.fields.agent1,
|
||||||
|
win: resData.fields.win ? 'Win' : 'Lose',
|
||||||
|
payoff: resData.fields.payoff
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const rows = [
|
const headCells = [
|
||||||
createData('Cupcake', 305, 3.7, 67, 4.3),
|
{ id: 'id', numeric: false, disablePadding: false, label: 'ID' },
|
||||||
createData('Donut', 452, 25.0, 51, 4.9),
|
{ id: 'game', numeric: false, disablePadding: false, label: 'Game' },
|
||||||
createData('Eclair', 262, 16.0, 24, 6.0),
|
{ id: 'agent0', numeric: false, disablePadding: false, label: 'Agent 0' },
|
||||||
createData('Frozen yoghurt', 159, 6.0, 24, 4.0),
|
{ id: 'agent1', numeric: false, disablePadding: false, label: 'Agent 1' },
|
||||||
createData('Gingerbread', 356, 16.0, 49, 3.9),
|
{ id: 'win', numeric: false, disablePadding: false, label: 'Result' },
|
||||||
createData('Honeycomb', 408, 3.2, 87, 6.5),
|
{ id: 'payoff', numeric: false, disablePadding: false, label: 'Payoff' }
|
||||||
createData('Ice cream sandwich', 237, 9.0, 37, 4.3),
|
|
||||||
createData('Jelly Bean', 375, 0.0, 94, 0.0),
|
|
||||||
createData('KitKat', 518, 26.0, 65, 7.0),
|
|
||||||
createData('Lollipop', 392, 0.2, 98, 0.0),
|
|
||||||
createData('Marshmallow', 318, 0, 81, 2.0),
|
|
||||||
createData('Nougat', 360, 19.0, 9, 37.0),
|
|
||||||
createData('Oreo1', 437, 18.0, 63, 4.0),
|
|
||||||
createData('Oreo2', 437, 18.0, 63, 4.0),
|
|
||||||
createData('Oreo3', 437, 18.0, 63, 4.0),
|
|
||||||
createData('Oreo4', 437, 18.0, 63, 4.0),
|
|
||||||
createData('Oreo5', 437, 18.0, 63, 4.0),
|
|
||||||
createData('Oreo6', 437, 18.0, 63, 4.0),
|
|
||||||
createData('Oreo7', 437, 18.0, 63, 4.0),
|
|
||||||
createData('Oreo8', 437, 18.0, 63, 4.0),
|
|
||||||
createData('Oreo9', 437, 18.0, 63, 4.0),
|
|
||||||
createData('Oreo10', 437, 18.0, 63, 4.0),
|
|
||||||
createData('Oreo11', 437, 18.0, 63, 4.0)
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const headCells = [
|
const StyledTableCell = withStyles((theme) => ({
|
||||||
{ id: 'name', numeric: false, disablePadding: false, label: 'Dessert (100g serving)' },
|
head: {
|
||||||
{ id: 'calories', numeric: true, disablePadding: false, label: 'Calories' },
|
backgroundColor: '#373538',
|
||||||
{ id: 'fat', numeric: true, disablePadding: false, label: 'Fat (g)' },
|
color: theme.palette.common.white,
|
||||||
{ id: 'carbs', numeric: true, disablePadding: false, label: 'Carbs (g)' },
|
fontWeight: 600,
|
||||||
{ id: 'protein', numeric: true, disablePadding: false, label: 'Protein (g)' },
|
fontSize: 15
|
||||||
];
|
}
|
||||||
|
}))(TableCell);
|
||||||
|
|
||||||
function EnhancedTableHead() {
|
function EnhancedTableHead() {
|
||||||
return (
|
return (
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
{headCells.map((headCell) => (
|
{headCells.map((headCell) => (
|
||||||
<TableCell
|
<StyledTableCell
|
||||||
key={headCell.id}
|
key={headCell.id}
|
||||||
align={headCell.numeric ? 'right' : 'left'}
|
align={headCell.numeric ? 'right' : 'left'}
|
||||||
padding={headCell.disablePadding ? 'none' : 'default'}
|
padding={headCell.disablePadding ? 'none' : 'default'}
|
||||||
>
|
>
|
||||||
{headCell.label}
|
{headCell.label}
|
||||||
</TableCell>
|
</StyledTableCell>
|
||||||
))}
|
))}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
|
@ -96,6 +121,7 @@ const useToolbarStyles = makeStyles((theme) => ({
|
||||||
root: {
|
root: {
|
||||||
paddingLeft: theme.spacing(2),
|
paddingLeft: theme.spacing(2),
|
||||||
paddingRight: theme.spacing(1),
|
paddingRight: theme.spacing(1),
|
||||||
|
minHeight: 52,
|
||||||
},
|
},
|
||||||
highlight:
|
highlight:
|
||||||
theme.palette.type === 'light'
|
theme.palette.type === 'light'
|
||||||
|
@ -110,22 +136,49 @@ const useToolbarStyles = makeStyles((theme) => ({
|
||||||
title: {
|
title: {
|
||||||
flex: '1 1 100%',
|
flex: '1 1 100%',
|
||||||
},
|
},
|
||||||
|
capitalize: {
|
||||||
|
textTransform: 'capitalize'
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const EnhancedTableToolbar = () => {
|
const EnhancedTableToolbar = (props) => {
|
||||||
|
const { routeInfo } = props;
|
||||||
const classes = useToolbarStyles();
|
const classes = useToolbarStyles();
|
||||||
|
|
||||||
|
let name = '';
|
||||||
|
if (routeInfo.type === 'game') {
|
||||||
|
const foundItem = gameList.find(game => {
|
||||||
|
return game.game === routeInfo.name;
|
||||||
|
});
|
||||||
|
name = foundItem.dispName;
|
||||||
|
} else if (routeInfo.type === 'agent') {
|
||||||
|
const foundItem = modelList.find(model => {
|
||||||
|
return model.model === routeInfo.name;
|
||||||
|
});
|
||||||
|
name = foundItem.dispName;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Toolbar
|
<Toolbar
|
||||||
className={classes.root}
|
className={classes.root}
|
||||||
>
|
>
|
||||||
<Typography className={classes.title} variant="h6" id="tableTitle" component="div">
|
<Breadcrumbs aria-label="breadcrumb">
|
||||||
Nutrition
|
<Typography color="inherit">
|
||||||
</Typography>
|
LeaderBoards
|
||||||
|
</Typography>
|
||||||
|
<Typography color="inherit" className={classes.capitalize}>
|
||||||
|
{routeInfo.type}
|
||||||
|
</Typography>
|
||||||
|
<Typography color="textPrimary">{name}</Typography>
|
||||||
|
</Breadcrumbs>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EnhancedTableToolbar.propTypes = {
|
||||||
|
routeInfo: PropTypes.object.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
root: {
|
root: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
@ -135,7 +188,7 @@ const useStyles = makeStyles((theme) => ({
|
||||||
marginBottom: theme.spacing(2),
|
marginBottom: theme.spacing(2),
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
minWidth: 750,
|
minWidth: 900,
|
||||||
},
|
},
|
||||||
visuallyHidden: {
|
visuallyHidden: {
|
||||||
border: 0,
|
border: 0,
|
||||||
|
@ -150,13 +203,33 @@ const useStyles = makeStyles((theme) => ({
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function EnhancedTable() {
|
const EnhancedTable = (props) => {
|
||||||
|
const initRowsPerPage = 10;
|
||||||
|
const { tableRows, routeInfo } = props;
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
const [rowsPerPage, setRowsPerPage] = React.useState(initRowsPerPage);
|
||||||
|
const [page, setPage] = React.useState(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setRowsPerPage(initRowsPerPage);
|
||||||
|
setPage(0);
|
||||||
|
}, [tableRows]);
|
||||||
|
|
||||||
|
const handleChangePage = (event, newPage) => {
|
||||||
|
setPage(newPage);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChangeRowsPerPage = (event) => {
|
||||||
|
setRowsPerPage(parseInt(event.target.value, 10));
|
||||||
|
setPage(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
const emptyRows = rowsPerPage - Math.min(rowsPerPage, tableRows.length - page * rowsPerPage);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
<Paper className={classes.paper}>
|
<Paper className={classes.paper}>
|
||||||
<EnhancedTableToolbar />
|
<EnhancedTableToolbar routeInfo={routeInfo}/>
|
||||||
<TableContainer>
|
<TableContainer>
|
||||||
<Table
|
<Table
|
||||||
className={classes.table}
|
className={classes.table}
|
||||||
|
@ -166,35 +239,56 @@ function EnhancedTable() {
|
||||||
>
|
>
|
||||||
<EnhancedTableHead
|
<EnhancedTableHead
|
||||||
classes={classes}
|
classes={classes}
|
||||||
rowCount={rows.length}
|
rowCount={tableRows.length}
|
||||||
/>
|
/>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{rows.map((row, index) => {
|
{tableRows
|
||||||
|
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
|
||||||
|
.map((row, index) => {
|
||||||
const labelId = `enhanced-table-checkbox-${index}`;
|
const labelId = `enhanced-table-checkbox-${index}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableRow
|
<TableRow
|
||||||
hover
|
hover
|
||||||
role="checkbox"
|
role="checkbox"
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
key={row.name}
|
key={row.id}
|
||||||
>
|
>
|
||||||
<TableCell component="th" id={labelId} scope="row">
|
<TableCell component="th" id={labelId} scope="row">
|
||||||
{row.name}
|
{row.id}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell align="right">{row.calories}</TableCell>
|
<TableCell>{row.game}</TableCell>
|
||||||
<TableCell align="right">{row.fat}</TableCell>
|
<TableCell>{row.agent0}</TableCell>
|
||||||
<TableCell align="right">{row.carbs}</TableCell>
|
<TableCell>{row.agent1}</TableCell>
|
||||||
<TableCell align="right">{row.protein}</TableCell>
|
<TableCell>{row.win}</TableCell>
|
||||||
|
<TableCell>{row.payoff}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
{emptyRows > 0 && (
|
||||||
|
<TableRow style={{ height: 53 * emptyRows }}>
|
||||||
|
<TableCell colSpan={6} />
|
||||||
|
</TableRow>
|
||||||
|
)}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</TableContainer>
|
</TableContainer>
|
||||||
|
<TablePagination
|
||||||
|
rowsPerPageOptions={[10, 50, 100]}
|
||||||
|
component="div"
|
||||||
|
count={tableRows.length}
|
||||||
|
rowsPerPage={rowsPerPage}
|
||||||
|
page={page}
|
||||||
|
onChangePage={handleChangePage}
|
||||||
|
onChangeRowsPerPage={handleChangeRowsPerPage}
|
||||||
|
/>
|
||||||
</Paper>
|
</Paper>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EnhancedTable.propTypes = {
|
||||||
|
routeInfo: PropTypes.object.isRequired,
|
||||||
|
tableRows: PropTypes.array.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
export default LeaderBoard;
|
export default LeaderBoard;
|
||||||
|
|
Loading…
Reference in New Issue