mirror of
https://github.com/wassname/optuna-dashboard.git
synced 2026-09-10 12:23:22 +08:00
Delete trial button
This commit is contained in:
@@ -115,6 +115,15 @@ def create_app(storage):
|
||||
{"study_summary": serializer.serialize_study_summary(summary)}
|
||||
)
|
||||
|
||||
@app.delete("/api/studies/<study_id:int>")
|
||||
@handle_json_api_exception
|
||||
def create_study(study_id: int):
|
||||
response.content_type = "application/json"
|
||||
|
||||
storage.delete_study(study_id)
|
||||
response.status = 204 # No content
|
||||
return ""
|
||||
|
||||
@app.get("/api/studies/<study_id:int>")
|
||||
@handle_json_api_exception
|
||||
def get_study_detail(study_id: int):
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
getStudyDetailAPI,
|
||||
getStudySummariesAPI,
|
||||
createNewStudyAPI,
|
||||
deleteStudyAPI,
|
||||
} from "./apiClient"
|
||||
import { studyDetailsState, studySummariesState } from "./state"
|
||||
|
||||
@@ -65,10 +66,27 @@ export const actionCreator = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const deleteStudy = (studyId: number) => {
|
||||
deleteStudyAPI(studyId)
|
||||
.then((study) => {
|
||||
setStudySummaries(studySummaries.filter((s) => s.study_id !== studyId))
|
||||
enqueueSnackbar(`Success to delete a study (study_name=${studyId})`, {
|
||||
variant: "success",
|
||||
})
|
||||
})
|
||||
.catch((err) => {
|
||||
enqueueSnackbar(`Failed to delete study (id=${studyId})`, {
|
||||
variant: "error",
|
||||
})
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
updateStudyDetail,
|
||||
updateStudySummaries,
|
||||
createNewStudy,
|
||||
deleteStudy,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -160,3 +160,9 @@ export const createNewStudyAPI = (
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteStudyAPI = (studyId: number): Promise<{}> => {
|
||||
return axiosInstance.delete<{}>(`/api/studies/${studyId}`).then((res) => {
|
||||
return {}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ interface DataGridColumn<T> {
|
||||
sortable?: boolean
|
||||
filterable?: boolean
|
||||
toCellValue?: (rowIndex: number) => string | React.ReactNode
|
||||
padding?: "default" | "checkbox" | "none"
|
||||
}
|
||||
|
||||
interface RowFilter<T> {
|
||||
@@ -152,6 +153,7 @@ function DataGrid<T>(props: {
|
||||
{columns.map((column, index) => (
|
||||
<TableCell
|
||||
key={index}
|
||||
padding={column.padding || "default"}
|
||||
sortDirection={orderBy === column.field ? order : false}
|
||||
>
|
||||
{column.sortable ? (
|
||||
@@ -241,7 +243,7 @@ function DataGridRow<T>(props: {
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<TableRow hover role="checkbox" tabIndex={-1}>
|
||||
<TableRow hover tabIndex={-1}>
|
||||
{collapseBody ? (
|
||||
<TableCell>
|
||||
<IconButton
|
||||
@@ -253,14 +255,15 @@ function DataGridRow<T>(props: {
|
||||
</IconButton>
|
||||
</TableCell>
|
||||
) : null}
|
||||
{columns.map((column) => {
|
||||
{columns.map((column, columnIndex) => {
|
||||
const cellItem = column.toCellValue
|
||||
? column.toCellValue(rowIndex)
|
||||
: row[column.field]
|
||||
|
||||
return column.filterable ? (
|
||||
<TableCell
|
||||
key={`${row[keyField]}:${column.field}`}
|
||||
key={`${row[keyField]}:${column.field}:${columnIndex}`}
|
||||
padding={column.padding || "default"}
|
||||
onClick={(e) => {
|
||||
handleClickFilterCell(column.field, row[column.field])
|
||||
}}
|
||||
@@ -268,7 +271,10 @@ function DataGridRow<T>(props: {
|
||||
<div className={classes.filterable}>{cellItem}</div>
|
||||
</TableCell>
|
||||
) : (
|
||||
<TableCell key={`${row[keyField]}:${column.field}`}>
|
||||
<TableCell
|
||||
key={`${row[keyField]}:${column.field}:${columnIndex}`}
|
||||
padding={column.padding || "default"}
|
||||
>
|
||||
{cellItem}
|
||||
</TableCell>
|
||||
)
|
||||
|
||||
@@ -125,12 +125,13 @@ export const StudyDetail: FC<{}> = () => {
|
||||
|
||||
const TrialTable: FC<{ trials: Trial[] }> = ({ trials = [] }) => {
|
||||
const columns: DataGridColumn<Trial>[] = [
|
||||
{ field: "number", label: "Number", sortable: true },
|
||||
{ field: "number", label: "Number", sortable: true, padding: "none" },
|
||||
{
|
||||
field: "state",
|
||||
label: "State",
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
padding: "none",
|
||||
toCellValue: (i) => trials[i].state.toString(),
|
||||
},
|
||||
{ field: "value", label: "Value", sortable: true },
|
||||
@@ -141,9 +142,7 @@ const TrialTable: FC<{ trials: Trial[] }> = ({ trials = [] }) => {
|
||||
trials[i].params.map((p) => p.name + ": " + p.value).join(", "),
|
||||
},
|
||||
]
|
||||
const collapseParamColumns: DataGridColumn<
|
||||
TrialParam
|
||||
>[] = [
|
||||
const collapseParamColumns: DataGridColumn<TrialParam>[] = [
|
||||
{ field: "name", label: "Name", sortable: true },
|
||||
{ field: "value", label: "Value", sortable: true },
|
||||
]
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
FormControlLabel,
|
||||
Checkbox,
|
||||
} from "@material-ui/core"
|
||||
import { AddBox, Refresh } from "@material-ui/icons"
|
||||
import { AddBox, Delete, Refresh } from "@material-ui/icons"
|
||||
|
||||
import { actionCreator } from "../action"
|
||||
import { DataGrid, DataGridColumn } from "./DataGrid"
|
||||
@@ -40,7 +40,11 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||
|
||||
export const StudyList: FC<{}> = () => {
|
||||
const classes = useStyles()
|
||||
const [openDialog, setOpenDialog] = React.useState(false)
|
||||
const [openNewStudyDialog, setOpenNewStudyDialog] = React.useState(false)
|
||||
const [openDeleteStudyDialog, setOpenDeleteStudyDialog] = React.useState(
|
||||
false
|
||||
)
|
||||
const [deleteStudyID, setDeleteStudyID] = React.useState(-1)
|
||||
const [newStudyName, setNewStudyName] = React.useState("")
|
||||
const [maximize, setMaximize] = React.useState<boolean>(false)
|
||||
|
||||
@@ -83,6 +87,25 @@ export const StudyList: FC<{}> = () => {
|
||||
sortable: false,
|
||||
toCellValue: (i) => studies[i].best_trial?.value || null,
|
||||
},
|
||||
{
|
||||
field: "study_name",
|
||||
label: "",
|
||||
sortable: false,
|
||||
padding: "none",
|
||||
toCellValue: (i) => (
|
||||
<IconButton
|
||||
aria-label="delete study"
|
||||
size="small"
|
||||
color="inherit"
|
||||
onClick={(e) => {
|
||||
setDeleteStudyID(studies[i].study_id)
|
||||
setOpenDeleteStudyDialog(true)
|
||||
}}
|
||||
>
|
||||
<Delete />
|
||||
</IconButton>
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
const collapseAttrColumns: DataGridColumn<Attribute>[] = [
|
||||
@@ -92,16 +115,27 @@ export const StudyList: FC<{}> = () => {
|
||||
|
||||
const handleCloseNewStudyDialog = () => {
|
||||
setNewStudyName("")
|
||||
setOpenDialog(false)
|
||||
setOpenNewStudyDialog(false)
|
||||
}
|
||||
|
||||
const handleCreateNewStudy = () => {
|
||||
const direction = maximize ? "maximize" : "minimize"
|
||||
action.createNewStudy(newStudyName, direction)
|
||||
setOpenDialog(false)
|
||||
setOpenNewStudyDialog(false)
|
||||
setNewStudyName("")
|
||||
}
|
||||
|
||||
const handleCloseDeleteStudyDialog = () => {
|
||||
setOpenDeleteStudyDialog(false)
|
||||
setDeleteStudyID(-1)
|
||||
}
|
||||
|
||||
const handleDeleteStudy = () => {
|
||||
action.deleteStudy(deleteStudyID)
|
||||
setOpenDeleteStudyDialog(false)
|
||||
setDeleteStudyID(-1)
|
||||
}
|
||||
|
||||
const collapseBody = (index: number) => {
|
||||
return (
|
||||
<Grid container direction="row">
|
||||
@@ -160,7 +194,7 @@ export const StudyList: FC<{}> = () => {
|
||||
aria-controls="menu-appbar"
|
||||
aria-haspopup="true"
|
||||
onClick={(e) => {
|
||||
setOpenDialog(true)
|
||||
setOpenNewStudyDialog(true)
|
||||
}}
|
||||
color="inherit"
|
||||
>
|
||||
@@ -182,11 +216,13 @@ export const StudyList: FC<{}> = () => {
|
||||
</Card>
|
||||
</Container>
|
||||
<Dialog
|
||||
open={openDialog}
|
||||
onClose={(e) => handleCloseNewStudyDialog}
|
||||
aria-labelledby="form-dialog-title"
|
||||
open={openNewStudyDialog}
|
||||
onClose={(e) => {
|
||||
handleCloseNewStudyDialog()
|
||||
}}
|
||||
aria-labelledby="create-study-form-dialog-title"
|
||||
>
|
||||
<DialogTitle id="form-dialog-title">New study</DialogTitle>
|
||||
<DialogTitle id="create-study-form-dialog-title">New study</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
To create a new study, please enter the study name here.
|
||||
@@ -230,6 +266,28 @@ export const StudyList: FC<{}> = () => {
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
<Dialog
|
||||
open={openDeleteStudyDialog}
|
||||
onClose={(e) => {
|
||||
handleCloseDeleteStudyDialog()
|
||||
}}
|
||||
aria-labelledby="delete-study-dialog-title"
|
||||
>
|
||||
<DialogTitle id="delete-study-dialog-title">Delete study</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
Are you sure to delete a study (study_id={deleteStudyID})?
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={handleCloseDeleteStudyDialog} color="primary">
|
||||
No
|
||||
</Button>
|
||||
<Button onClick={handleDeleteStudy} color="primary">
|
||||
Yes
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user