Rename components

This commit is contained in:
c-bata
2023-05-10 12:07:23 +09:00
parent ddd6492c8d
commit a0c3240701
5 changed files with 33 additions and 465 deletions
+9 -9
View File
@@ -13,8 +13,8 @@ import {
} from "@mui/material"
import { CompareStudies } from "./CompareStudies"
import { StudyDetailBeta } from "./StudyDetailBeta"
import { StudyListBeta } from "./StudyListBeta"
import { StudyDetail } from "./StudyDetail"
import { StudyList } from "./StudyList"
export const App: FC = () => {
const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)")
@@ -54,7 +54,7 @@ export const App: FC = () => {
<Route
path={URL_PREFIX + "/studies/:studyId/analytics"}
children={
<StudyDetailBeta
<StudyDetail
toggleColorMode={toggleColorMode}
page={"analytics"}
/>
@@ -63,7 +63,7 @@ export const App: FC = () => {
<Route
path={URL_PREFIX + "/studies/:studyId/trials"}
children={
<StudyDetailBeta
<StudyDetail
toggleColorMode={toggleColorMode}
page={"trialList"}
/>
@@ -72,7 +72,7 @@ export const App: FC = () => {
<Route
path={URL_PREFIX + "/studies/:studyId/trials"}
children={
<StudyDetailBeta
<StudyDetail
toggleColorMode={toggleColorMode}
page={"trialList"}
/>
@@ -81,7 +81,7 @@ export const App: FC = () => {
<Route
path={URL_PREFIX + "/studies/:studyId/trialTable"}
children={
<StudyDetailBeta
<StudyDetail
toggleColorMode={toggleColorMode}
page={"trialTable"}
/>
@@ -90,7 +90,7 @@ export const App: FC = () => {
<Route
path={URL_PREFIX + "/studies/:studyId/note"}
children={
<StudyDetailBeta
<StudyDetail
toggleColorMode={toggleColorMode}
page={"note"}
/>
@@ -99,7 +99,7 @@ export const App: FC = () => {
<Route
path={URL_PREFIX + "/studies/:studyId"}
children={
<StudyDetailBeta
<StudyDetail
toggleColorMode={toggleColorMode}
page={"history"}
/>
@@ -113,7 +113,7 @@ export const App: FC = () => {
/>
<Route
path={URL_PREFIX + "/"}
children={<StudyListBeta toggleColorMode={toggleColorMode} />}
children={<StudyList toggleColorMode={toggleColorMode} />}
/>
</Switch>
</Router>
@@ -39,7 +39,7 @@ export const useURLVars = (): number => {
return useMemo(() => parseInt(studyId, 10), [studyId])
}
export const StudyDetailBeta: FC<{
export const StudyDetail: FC<{
toggleColorMode: () => void
page: PageId
}> = ({ toggleColorMode, page }) => {
@@ -126,11 +126,7 @@ export const StudyDetailBeta: FC<{
content = (
<Card sx={{ margin: theme.spacing(2) }}>
<CardContent>
<TrialTable
studyDetail={studyDetail}
isBeta={true}
initialRowsPerPage={50}
/>
<TrialTable studyDetail={studyDetail} initialRowsPerPage={50} />
</CardContent>
</Card>
)
@@ -33,7 +33,7 @@ import { useCreateStudyDialog } from "./CreateStudyDialog"
import { useDeleteStudyDialog } from "./DeleteStudyDialog"
import { useRenameStudyDialog } from "./RenameStudyDialog"
export const StudyListBeta: FC<{
export const StudyList: FC<{
toggleColorMode: () => void
}> = ({ toggleColorMode }) => {
const theme = useTheme()
+21 -227
View File
@@ -1,28 +1,16 @@
import React, { createRef, FC, FormEvent, MouseEvent } from "react"
import {
Typography,
Grid,
Box,
Button,
IconButton,
Stack,
TextField,
} from "@mui/material"
import React, { FC } from "react"
import { IconButton } from "@mui/material"
import LinkIcon from "@mui/icons-material/Link"
import { DataGridColumn, DataGrid } from "./DataGrid"
import { Link } from "react-router-dom"
import { actionCreator } from "../action"
export const TrialTable: FC<{
studyDetail: StudyDetail | null
isBeta: boolean
initialRowsPerPage?: number
}> = ({ studyDetail, isBeta, initialRowsPerPage }) => {
}> = ({ studyDetail, initialRowsPerPage }) => {
const trials: Trial[] = studyDetail !== null ? studyDetail.trials : []
const objectiveNames: string[] = studyDetail?.objective_names || []
const action = actionCreator()
const columns: DataGridColumn<Trial>[] = [
{ field: "number", label: "Number", sortable: true, padding: "none" },
@@ -103,48 +91,6 @@ export const TrialTable: FC<{
}))
columns.push(...objectiveColumns)
}
if (!isBeta) {
columns.push({
field: "datetime_start",
label: "Duration(ms)",
toCellValue: (i) => {
const startMs = trials[i].datetime_start?.getTime()
const completeMs = trials[i].datetime_complete?.getTime()
if (startMs !== undefined && completeMs !== undefined) {
return (completeMs - startMs).toString()
}
return null
},
sortable: true,
less: (firstEl, secondEl): number => {
const firstStartMs = firstEl.datetime_start?.getTime()
const firstCompleteMs = firstEl.datetime_complete?.getTime()
const firstDurationMs =
firstStartMs !== undefined && firstCompleteMs !== undefined
? firstCompleteMs - firstStartMs
: undefined
const secondStartMs = secondEl.datetime_start?.getTime()
const secondCompleteMs = secondEl.datetime_complete?.getTime()
const secondDurationMs =
secondStartMs !== undefined && secondCompleteMs !== undefined
? secondCompleteMs - secondStartMs
: undefined
if (firstDurationMs === secondDurationMs) {
return 0
} else if (
firstDurationMs !== undefined &&
secondDurationMs !== undefined
) {
return firstDurationMs < secondDurationMs ? 1 : -1
} else if (firstDurationMs !== undefined) {
return -1
} else {
return 1
}
},
})
}
if (
studyDetail?.union_search_space.length ===
studyDetail?.intersection_search_space.length
@@ -220,175 +166,24 @@ export const TrialTable: FC<{
},
})
})
if (isBeta) {
columns.push({
field: "trial_id",
label: "Detail",
toCellValue: (i) => (
<IconButton
component={Link}
to={
URL_PREFIX +
`/studies/${trials[i].study_id}/trials?numbers=${trials[i].number}`
}
color="inherit"
title="Go to the trial's detail page"
size="small"
>
<LinkIcon />
</IconButton>
),
})
}
const collapseIntermediateValueColumns: DataGridColumn<TrialIntermediateValue>[] =
[
{ field: "step", label: "Step", sortable: true },
{
field: "value",
label: "Value",
sortable: true,
less: (firstEl, secondEl): number => {
const firstVal = firstEl.value
const secondVal = secondEl.value
if (firstVal === secondVal) {
return 0
}
if (firstVal === "nan") {
return -1
} else if (secondVal === "nan") {
return 1
}
if (firstVal === "-inf" || secondVal === "inf") {
return 1
} else if (secondVal === "-inf" || firstVal === "inf") {
return -1
}
return firstVal < secondVal ? 1 : -1
},
},
]
const collapseAttrColumns: DataGridColumn<Attribute>[] = [
{ field: "key", label: "Key", sortable: true },
{ field: "value", label: "Value", sortable: true },
]
const collapseBody = (index: number) => {
const objectiveFormRefs = studyDetail?.directions.map((d) =>
createRef<HTMLInputElement>()
)
const handleSubmit = (e: FormEvent<HTMLFormElement>): void => {
if (objectiveFormRefs === undefined) {
return
}
if (studyDetail === null) {
return
}
e.preventDefault()
const studyId = studyDetail.id
const trialId = trials[index].trial_id
const objectiveValues = objectiveFormRefs.map((ref) =>
ref.current ? Number(ref.current.value) : NaN
)
if (objectiveValues.includes(NaN)) {
return
}
action.makeTrialComplete(studyId, trialId, objectiveValues)
}
const handleFailTrial = (e: MouseEvent<HTMLButtonElement>): void => {
if (studyDetail === null) {
return
}
const studyId = studyDetail.id
const trialId = trials[index].trial_id
action.makeTrialFail(studyId, trialId)
}
return (
<Grid container direction="row">
<Grid item xs={6}>
<Box margin={1}>
<Typography variant="h6" gutterBottom component="div">
Intermediate values
</Typography>
<DataGrid<TrialIntermediateValue>
columns={collapseIntermediateValueColumns}
rows={trials[index].intermediate_values}
keyField={"step"}
dense={true}
rowsPerPageOption={[5, 10, { label: "All", value: -1 }]}
/>
</Box>
</Grid>
<Grid item xs={6}>
<Box margin={1}>
<Typography variant="h6" gutterBottom component="div">
Trial system attributes
</Typography>
<DataGrid<Attribute>
columns={collapseAttrColumns}
rows={trials[index].system_attrs}
keyField={"key"}
dense={true}
rowsPerPageOption={[5, 10, { label: "All", value: -1 }]}
/>
</Box>
</Grid>
{trials[index].state === "Running" ? (
<Grid item xs={12}>
<Box margin={1}>
<Typography variant="h6" gutterBottom component="div">
Trial tell
</Typography>
<form onSubmit={handleSubmit}>
<Box margin={1}>
<Stack direction="row" spacing={1}>
{objectiveFormRefs !== undefined &&
objectiveFormRefs.map((ref, i) => (
<TextField
required
id={`objective-${i}`}
key={`objective-${i}`}
label={
objectiveNames.length ===
studyDetail?.directions.length
? objectiveNames[i]
: `Objective ${i}`
}
inputProps={{
inputMode: "numeric",
pattern: "[-+]?[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?",
title: "Please input a float number",
}}
inputRef={ref}
/>
))}
</Stack>
</Box>
<Box margin={1}>
<Stack direction="row" spacing={1}>
<Button variant="contained" type="submit">
Submit
</Button>
<Button
variant="outlined"
color="error"
onClick={handleFailTrial}
>
Fail Trial
</Button>
</Stack>
</Box>
</form>
</Box>
</Grid>
) : null}
</Grid>
)
}
columns.push({
field: "trial_id",
label: "Detail",
toCellValue: (i) => (
<IconButton
component={Link}
to={
URL_PREFIX +
`/studies/${trials[i].study_id}/trials?numbers=${trials[i].number}`
}
color="inherit"
title="Go to the trial's detail page"
size="small"
>
<LinkIcon />
</IconButton>
),
})
return (
<DataGrid<Trial>
@@ -396,7 +191,6 @@ export const TrialTable: FC<{
rows={trials}
keyField={"trial_id"}
dense={true}
collapseBody={isBeta ? undefined : collapseBody}
initialRowsPerPage={initialRowsPerPage}
/>
)
-222
View File
@@ -1,222 +0,0 @@
import React from "react"
global.URL.createObjectURL = jest.fn()
import { SnackbarProvider } from "notistack"
import { RecoilRoot } from "recoil"
import { cleanup, render, within, fireEvent } from "@testing-library/react"
import { TrialTable } from "../optuna_dashboard/ts/components/TrialTable"
afterEach(cleanup)
const dummyDistribution: FloatDistribution = {
type: "FloatDistribution",
low: 0,
high: 10,
step: 1,
log: false,
}
const trials: Trial[] = [
{
trial_id: 1,
study_id: 0,
number: 0,
state: "Complete" as TrialState,
values: [-1],
intermediate_values: [],
datetime_start: new Date("2021-06-15T00:00:00"),
datetime_complete: new Date("2021-06-15T00:00:01"),
params: [
{
name: "x",
param_internal_value: 1,
param_external_value: "1",
param_external_type: "float",
distribution: dummyDistribution,
},
{
name: "y",
param_internal_value: 2,
param_external_value: "2",
param_external_type: "float",
distribution: dummyDistribution,
},
],
fixed_params: [],
user_attrs: [],
system_attrs: [],
note: {
body: "",
version: 0,
},
artifacts: [],
},
{
trial_id: 2,
study_id: 0,
number: 1,
state: "Fail" as TrialState,
values: [-2],
intermediate_values: [],
datetime_start: new Date("2021-06-15T00:00:01"),
datetime_complete: new Date("2021-06-15T00:00:03"),
params: [
{
name: "x",
param_internal_value: 1,
param_external_value: "1",
param_external_type: "float",
distribution: dummyDistribution,
},
{
name: "y",
param_internal_value: 2,
param_external_value: "2",
param_external_type: "float",
distribution: dummyDistribution,
},
],
fixed_params: [],
user_attrs: [],
system_attrs: [],
note: {
body: "",
version: 0,
},
artifacts: [],
},
]
const study_direction: StudyDirection = "minimize" as StudyDirection
const studyDetail: StudyDetail = {
id: 1,
name: "study_0",
directions: [study_direction],
datetime_start: new Date("2021-06-15T00:00:00"),
best_trials: [trials[1]],
trials: trials,
intersection_search_space: [
{
name: "x",
distribution: dummyDistribution,
},
{
name: "y",
distribution: dummyDistribution,
},
],
union_search_space: [
{
name: "x",
distribution: dummyDistribution,
},
{
name: "y",
distribution: dummyDistribution,
},
],
union_user_attrs: [
{ key: "foo", sortable: false },
{ key: "bar", sortable: false },
],
has_intermediate_values: false,
note: {
version: 0,
body: "",
},
}
it("Sort TrialTable by trial number", () => {
const { getAllByRole, getByText } = render(
<RecoilRoot>
<SnackbarProvider>
<TrialTable studyDetail={studyDetail} isBeta={false} />
</SnackbarProvider>
</RecoilRoot>
)
const rows = getAllByRole("row")
expect(within(rows[1]).getByText("0")).toBeTruthy()
expect(within(rows[3]).getAllByText("1")[0]).toBeTruthy()
fireEvent.click(getByText("Number"))
const rows_updated = getAllByRole("row")
expect(within(rows_updated[1]).getAllByText("1")[0]).toBeTruthy()
expect(within(rows_updated[3]).getByText("0")).toBeTruthy()
})
it("Sort TrialTable by value", () => {
const { getAllByRole, getByText } = render(
<RecoilRoot>
<SnackbarProvider>
<TrialTable studyDetail={studyDetail} isBeta={false} />
</SnackbarProvider>
</RecoilRoot>
)
fireEvent.click(getByText("Value"))
const rows = getAllByRole("row")
expect(within(rows[1]).getByText("-2")).toBeTruthy()
expect(within(rows[3]).getByText("-1")).toBeTruthy()
fireEvent.click(getByText("Value"))
const rows_updated = getAllByRole("row")
expect(within(rows_updated[1]).getByText("-1")).toBeTruthy()
expect(within(rows_updated[3]).getByText("-2")).toBeTruthy()
})
it("Sort TrialTable by duration", () => {
const { getAllByRole, getByText } = render(
<RecoilRoot>
<SnackbarProvider>
<TrialTable studyDetail={studyDetail} isBeta={false} />
</SnackbarProvider>
</RecoilRoot>
)
fireEvent.click(getByText("Duration(ms)"))
const rows = getAllByRole("row")
expect(within(rows[1]).getByText("1000")).toBeTruthy()
expect(within(rows[3]).getByText("2000")).toBeTruthy()
fireEvent.click(getByText("Duration(ms)"))
const rows_updated = getAllByRole("row")
expect(within(rows_updated[1]).getByText("2000")).toBeTruthy()
expect(within(rows_updated[3]).getByText("1000")).toBeTruthy()
})
it("Sort TrialTable by state", () => {
const { getAllByRole, getByText } = render(
<RecoilRoot>
<SnackbarProvider>
<TrialTable studyDetail={studyDetail} isBeta={false} />
</SnackbarProvider>
</RecoilRoot>
)
fireEvent.click(getByText("State"))
const rows = getAllByRole("row")
expect(within(rows[1]).getByText("Complete")).toBeTruthy()
expect(within(rows[3]).getByText("Fail")).toBeTruthy()
fireEvent.click(getByText("State"))
const rows_updated = getAllByRole("row")
expect(within(rows_updated[1]).getByText("Fail")).toBeTruthy()
expect(within(rows_updated[3]).getByText("Complete")).toBeTruthy()
})
it("Filter trials by state", () => {
const { queryAllByText } = render(
<RecoilRoot>
<SnackbarProvider>
<TrialTable studyDetail={studyDetail} isBeta={false} />
</SnackbarProvider>
</RecoilRoot>
)
expect(queryAllByText("Fail").length).toBe(1)
// Click 'Complete' state
const completedRows = queryAllByText("Complete")
expect(completedRows.length).toBe(1)
fireEvent.click(completedRows[0])
expect(queryAllByText("Fail").length).toBe(0)
})