add loading status to block user action when doing api call; add error message when fail to do api call
This commit is contained in:
parent
882e0d0289
commit
b6711547b0
|
@ -15,11 +15,10 @@ import Button from "@material-ui/core/Button";
|
||||||
import Dialog from "@material-ui/core/Dialog";
|
import Dialog from "@material-ui/core/Dialog";
|
||||||
import DialogTitle from "@material-ui/core/DialogTitle";
|
import DialogTitle from "@material-ui/core/DialogTitle";
|
||||||
import DialogContent from "@material-ui/core/DialogContent";
|
import DialogContent from "@material-ui/core/DialogContent";
|
||||||
import DialogContentText from "@material-ui/core/DialogContentText";
|
|
||||||
import TextField from "@material-ui/core/TextField";
|
import TextField from "@material-ui/core/TextField";
|
||||||
import DialogActions from "@material-ui/core/DialogActions";
|
import DialogActions from "@material-ui/core/DialogActions";
|
||||||
|
|
||||||
import {Message, Upload} from 'element-react';
|
import {Message, Upload, Loading} from 'element-react';
|
||||||
import {apiUrl} from "../utils/config";
|
import {apiUrl} from "../utils/config";
|
||||||
|
|
||||||
const drawerWidth = 250;
|
const drawerWidth = 250;
|
||||||
|
@ -78,6 +77,7 @@ const useStyles = makeStyles((theme) => ({
|
||||||
|
|
||||||
function MenuBar (props) {
|
function MenuBar (props) {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
const [uploadDialogLoading, setUploadDialogLoading] = React.useState(false);
|
||||||
|
|
||||||
const [open, setOpen] = React.useState({game: true, agent: true});
|
const [open, setOpen] = React.useState({game: true, agent: true});
|
||||||
|
|
||||||
|
@ -114,9 +114,10 @@ function MenuBar (props) {
|
||||||
bodyFormData.append('entry', uploadForm.entry);
|
bodyFormData.append('entry', uploadForm.entry);
|
||||||
bodyFormData.append('game', uploadForm.game);
|
bodyFormData.append('game', uploadForm.game);
|
||||||
bodyFormData.append('model', uploadRef.current.state.fileList[0].raw);
|
bodyFormData.append('model', uploadRef.current.state.fileList[0].raw);
|
||||||
|
setUploadDialogLoading(true);
|
||||||
axios.post(`${apiUrl}/tournament/upload_agent`, bodyFormData, {headers: {'Content-Type': 'multipart/form-data'}})
|
axios.post(`${apiUrl}/tournament/upload_agent`, bodyFormData, {headers: {'Content-Type': 'multipart/form-data'}})
|
||||||
.then(res => {
|
.then(res => {
|
||||||
|
setTimeout(() => {setUploadDialogLoading(false)}, 250);
|
||||||
Message({
|
Message({
|
||||||
message: "Successfully uploaded model",
|
message: "Successfully uploaded model",
|
||||||
type: "success",
|
type: "success",
|
||||||
|
@ -126,6 +127,15 @@ function MenuBar (props) {
|
||||||
setUploadDialogOpen(false);
|
setUploadDialogOpen(false);
|
||||||
setUploadForm({...uploadFormInitValue});
|
setUploadForm({...uploadFormInitValue});
|
||||||
})
|
})
|
||||||
|
.catch(err => {
|
||||||
|
setTimeout(() => {setUploadDialogLoading(false)}, 250);
|
||||||
|
Message({
|
||||||
|
message: "Failed to upload model",
|
||||||
|
type: "error",
|
||||||
|
showClose: true,
|
||||||
|
});
|
||||||
|
console.log(err);
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
@ -196,7 +206,13 @@ function MenuBar (props) {
|
||||||
<Button variant="contained" color="primary" onClick={openUploadDialog} className={classes.button}>
|
<Button variant="contained" color="primary" onClick={openUploadDialog} className={classes.button}>
|
||||||
Upload Model
|
Upload Model
|
||||||
</Button>
|
</Button>
|
||||||
<Dialog open={uploadDialogOpen} onClose={handleUploadDialogClose} aria-labelledby="form-dialog-title">
|
<Dialog
|
||||||
|
open={uploadDialogOpen}
|
||||||
|
onClose={handleUploadDialogClose}
|
||||||
|
aria-labelledby="form-dialog-title"
|
||||||
|
disableBackdropClick={true}
|
||||||
|
>
|
||||||
|
<Loading loading={uploadDialogLoading}>
|
||||||
<DialogTitle id="form-dialog-title">Upload Model</DialogTitle>
|
<DialogTitle id="form-dialog-title">Upload Model</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<Upload
|
<Upload
|
||||||
|
@ -247,6 +263,7 @@ function MenuBar (props) {
|
||||||
Upload
|
Upload
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
|
</Loading>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
)
|
)
|
||||||
|
|
|
@ -21,7 +21,7 @@ import withStyles from "@material-ui/core/styles/withStyles";
|
||||||
import PlayCircleOutlineIcon from '@material-ui/icons/PlayCircleOutline';
|
import PlayCircleOutlineIcon from '@material-ui/icons/PlayCircleOutline';
|
||||||
import Button from "@material-ui/core/Button";
|
import Button from "@material-ui/core/Button";
|
||||||
import {useHistory} from "react-router-dom";
|
import {useHistory} from "react-router-dom";
|
||||||
import {Message} from "element-react";
|
import {Message, Loading} from "element-react";
|
||||||
|
|
||||||
const gameList = [
|
const gameList = [
|
||||||
{game: 'leduc-holdem', dispName: 'Leduc Hold\'em'},
|
{game: 'leduc-holdem', dispName: 'Leduc Hold\'em'},
|
||||||
|
@ -224,33 +224,48 @@ const EnhancedTableToolbar = (props) => {
|
||||||
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
const functionalButton = () => {
|
const FunctionalButton = () => {
|
||||||
|
const [buttonLoading, setButtonLoading] = React.useState(false);
|
||||||
if (routeInfo.type === 'game'){
|
if (routeInfo.type === 'game'){
|
||||||
const handleLaunchTournament = (gameName) => {
|
const handleLaunchTournament = (gameName) => {
|
||||||
// todo: customize eval num
|
// todo: customize eval num
|
||||||
// todo: add global loading when waiting for API response
|
setButtonLoading(true);
|
||||||
axios.get(`${apiUrl}/tournament/launch?eval_num=200&name=${gameName}`)
|
axios.get(`${apiUrl}/tournament/launch?eval_num=200&name=${gameName}`)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
Message({
|
setTimeout(() => {setButtonLoading(false)}, 250);
|
||||||
message: "Successfully launched tournament",
|
Message({
|
||||||
type: "success",
|
message: "Successfully launched tournament",
|
||||||
showClose: true
|
type: "success",
|
||||||
});
|
showClose: true
|
||||||
})
|
});
|
||||||
}
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log(err);
|
||||||
|
Message({
|
||||||
|
message: "Failed to launch tournament",
|
||||||
|
type: "error",
|
||||||
|
showClose: true,
|
||||||
|
});
|
||||||
|
setTimeout(() => {setButtonLoading(false)}, 250);
|
||||||
|
})
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div className={classes.button}>
|
<div className={classes.button}>
|
||||||
<Button variant="contained" color="primary" onClick={() => handleLaunchTournament(routeInfo.name)}>
|
<Loading loading={buttonLoading}>
|
||||||
Launch Tournament
|
<Button variant="contained" color="primary" onClick={() => handleLaunchTournament(routeInfo.name)}>
|
||||||
</Button>
|
Launch Tournament
|
||||||
|
</Button>
|
||||||
|
</Loading>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
else if (routeInfo.type ==='agent') {
|
else if (routeInfo.type ==='agent') {
|
||||||
const delButtonDisabled = defaultModelList.includes(routeInfo.name);
|
const delButtonDisabled = defaultModelList.includes(routeInfo.name);
|
||||||
const handleDelModel = (agentName) => {
|
const handleDelModel = (agentName) => {
|
||||||
|
setButtonLoading(true);
|
||||||
axios.get(`${apiUrl}/tournament/delete_agent?name=${agentName}`)
|
axios.get(`${apiUrl}/tournament/delete_agent?name=${agentName}`)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
|
setTimeout(() => {setButtonLoading(false)}, 250);
|
||||||
Message({
|
Message({
|
||||||
message: "Successfully deleted model",
|
message: "Successfully deleted model",
|
||||||
type: "success",
|
type: "success",
|
||||||
|
@ -259,12 +274,22 @@ const EnhancedTableToolbar = (props) => {
|
||||||
setReloadMenu(reloadMenu+1);
|
setReloadMenu(reloadMenu+1);
|
||||||
history.push(`/leaderboard?type=game&name=leduc-holdem`);
|
history.push(`/leaderboard?type=game&name=leduc-holdem`);
|
||||||
})
|
})
|
||||||
|
.catch(err => {
|
||||||
|
Message({
|
||||||
|
message: "Failed to delete model",
|
||||||
|
type: "error",
|
||||||
|
showClose: true,
|
||||||
|
});
|
||||||
|
setTimeout(() => {setButtonLoading(false)}, 250);
|
||||||
|
})
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className={classes.button}>
|
<div className={classes.button}>
|
||||||
<Button variant="contained" onClick={() => handleDelModel(routeInfo.name)} color="primary" disabled={delButtonDisabled}>
|
<Loading loading={buttonLoading}>
|
||||||
Delete Model
|
<Button variant="contained" onClick={() => handleDelModel(routeInfo.name)} color="primary" disabled={delButtonDisabled}>
|
||||||
</Button>
|
Delete Model
|
||||||
|
</Button>
|
||||||
|
</Loading>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -284,7 +309,7 @@ const EnhancedTableToolbar = (props) => {
|
||||||
<Typography color="textPrimary">{name}</Typography>
|
<Typography color="textPrimary">{name}</Typography>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
<div className={classes.button}>
|
<div className={classes.button}>
|
||||||
{functionalButton()}
|
<FunctionalButton />
|
||||||
</div>
|
</div>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue