mirror of
https://github.com/wassname/optuna-dashboard.git
synced 2026-09-11 12:30:25 +08:00
Merge branch 'main' of github.com:porink0424/optuna-dashboard into feat/jupyterlab-optuna
This commit is contained in:
@@ -9,7 +9,14 @@ on:
|
||||
- '**.tsx'
|
||||
- 'optuna_dashboard/package.json'
|
||||
- 'optuna_dashboard/package-lock.json'
|
||||
- 'vscode/package.json'
|
||||
- 'vscode/package-lock.json'
|
||||
- 'tslib/react/package.json'
|
||||
- 'tslib/react/package-lock.json'
|
||||
- 'tslib/storage/package.json'
|
||||
- 'tslib/storage/package-lock.json'
|
||||
- 'optuna_dashboard/tsconfig.json'
|
||||
- 'optuna_dashboard/tsconfig.pkg.json'
|
||||
- 'optuna_dashboard/webpack.config.js'
|
||||
jobs:
|
||||
lint:
|
||||
@@ -112,6 +119,11 @@ jobs:
|
||||
npm run build:dev
|
||||
npm run build:prd
|
||||
|
||||
- name: Build optuna_dashboard package (for Jupyter Lab extension)
|
||||
working-directory: optuna_dashboard
|
||||
run: |
|
||||
npm run build:pkg
|
||||
|
||||
test-tslib:
|
||||
name: Run tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
pkg
|
||||
types
|
||||
Generated
+5
-30
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "optuna-dashboard",
|
||||
"name": "@optuna/optuna-dashboard",
|
||||
"version": "0.0.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "optuna-dashboard",
|
||||
"name": "@optuna/optuna-dashboard",
|
||||
"version": "0.0.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -19,7 +19,7 @@
|
||||
"@react-three/drei": "^9.96.4",
|
||||
"@react-three/fiber": "^8.15.15",
|
||||
"@tanstack/react-query": "^5.18.1",
|
||||
"@tanstack/react-table": "^8.16.0",
|
||||
"@tanstack/react-table": "file:../tslib/react/node_modules/@tanstack/react-table",
|
||||
"@tanstack/react-virtual": "^3.1.2",
|
||||
"@types/papaparse": "^5.3.14",
|
||||
"@types/three": "^0.160.0",
|
||||
@@ -14278,22 +14278,8 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/react-table": {
|
||||
"version": "8.17.3",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tanstack/table-core": "8.17.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8",
|
||||
"react-dom": ">=16.8"
|
||||
}
|
||||
"resolved": "../tslib/react/node_modules/@tanstack/react-table",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@tanstack/react-virtual": {
|
||||
"version": "3.5.1",
|
||||
@@ -14310,17 +14296,6 @@
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/table-core": {
|
||||
"version": "8.17.3",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/virtual-core": {
|
||||
"version": "3.5.1",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
{
|
||||
"name": "optuna-dashboard",
|
||||
"name": "@optuna/optuna-dashboard",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"description": "Dashboard for Optuna",
|
||||
"main": "index.js",
|
||||
"main": "pkg/pkg_index.js",
|
||||
"types": "types/pkg_index.d.ts",
|
||||
"scripts": {
|
||||
"watch": "NODE_ENV=development TYPESCRIPT_LOADER=esbuild-loader webpack --watch",
|
||||
"build": "webpack",
|
||||
"build:dev": "NODE_ENV=development TYPESCRIPT_LOADER=esbuild-loader webpack",
|
||||
"build:prd": "NODE_ENV=production webpack",
|
||||
"build:pkg": "tsc -d --project tsconfig.pkg.json",
|
||||
"type-check": "tsc --noEmit"
|
||||
},
|
||||
"author": "Masashi Shibata",
|
||||
@@ -24,7 +26,7 @@
|
||||
"@react-three/drei": "^9.96.4",
|
||||
"@react-three/fiber": "^8.15.15",
|
||||
"@tanstack/react-query": "^5.18.1",
|
||||
"@tanstack/react-table": "^8.16.0",
|
||||
"@tanstack/react-table": "file:../tslib/react/node_modules/@tanstack/react-table",
|
||||
"@tanstack/react-virtual": "^3.1.2",
|
||||
"@types/papaparse": "^5.3.14",
|
||||
"@types/three": "^0.160.0",
|
||||
|
||||
@@ -13,14 +13,10 @@ import { BrowserRouter as Router, Route, Routes } from "react-router-dom"
|
||||
import { RecoilRoot } from "recoil"
|
||||
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
|
||||
import { APIClientProvider } from "../apiClientProvider"
|
||||
import { AxiosClient } from "../axiosClient"
|
||||
import { CompareStudies } from "./CompareStudies"
|
||||
import { StudyDetail } from "./StudyDetail"
|
||||
import { StudyList } from "./StudyList"
|
||||
|
||||
const axiosAPIClient = new AxiosClient()
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
@@ -54,102 +50,100 @@ export const App: FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<APIClientProvider apiClient={axiosAPIClient}>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<RecoilRoot>
|
||||
<ThemeProvider theme={theme}>
|
||||
<CssBaseline />
|
||||
<Box
|
||||
component="div"
|
||||
sx={{
|
||||
backgroundColor: colorMode === "dark" ? "#121212" : "#ffffff",
|
||||
width: "100%",
|
||||
minHeight: "100vh",
|
||||
}}
|
||||
>
|
||||
<SnackbarProvider maxSnack={3}>
|
||||
<Router>
|
||||
<Routes>
|
||||
<Route
|
||||
path={URL_PREFIX + "/studies/:studyId/analytics"}
|
||||
element={
|
||||
<StudyDetail
|
||||
toggleColorMode={toggleColorMode}
|
||||
page={"analytics"}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={URL_PREFIX + "/studies/:studyId/trials"}
|
||||
element={
|
||||
<StudyDetail
|
||||
toggleColorMode={toggleColorMode}
|
||||
page={"trialList"}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={URL_PREFIX + "/studies/:studyId/trialTable"}
|
||||
element={
|
||||
<StudyDetail
|
||||
toggleColorMode={toggleColorMode}
|
||||
page={"trialTable"}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={URL_PREFIX + "/studies/:studyId/note"}
|
||||
element={
|
||||
<StudyDetail
|
||||
toggleColorMode={toggleColorMode}
|
||||
page={"note"}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={URL_PREFIX + "/studies/:studyId/graph"}
|
||||
element={
|
||||
<StudyDetail
|
||||
toggleColorMode={toggleColorMode}
|
||||
page={"graph"}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={URL_PREFIX + "/studies/:studyId"}
|
||||
element={
|
||||
<StudyDetail
|
||||
toggleColorMode={toggleColorMode}
|
||||
page={"top"}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={URL_PREFIX + "/studies/:studyId/preference-history"}
|
||||
element={
|
||||
<StudyDetail
|
||||
toggleColorMode={toggleColorMode}
|
||||
page={"preferenceHistory"}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={URL_PREFIX + "/compare-studies"}
|
||||
element={
|
||||
<CompareStudies toggleColorMode={toggleColorMode} />
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={URL_PREFIX + "/"}
|
||||
element={<StudyList toggleColorMode={toggleColorMode} />}
|
||||
/>
|
||||
</Routes>
|
||||
</Router>
|
||||
</SnackbarProvider>
|
||||
</Box>
|
||||
</ThemeProvider>
|
||||
</RecoilRoot>
|
||||
</QueryClientProvider>
|
||||
</APIClientProvider>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<RecoilRoot>
|
||||
<ThemeProvider theme={theme}>
|
||||
<CssBaseline />
|
||||
<Box
|
||||
component="div"
|
||||
sx={{
|
||||
backgroundColor: colorMode === "dark" ? "#121212" : "#ffffff",
|
||||
width: "100%",
|
||||
minHeight: "100vh",
|
||||
}}
|
||||
>
|
||||
<SnackbarProvider maxSnack={3}>
|
||||
<Router>
|
||||
<Routes>
|
||||
<Route
|
||||
path={URL_PREFIX + "/studies/:studyId/analytics"}
|
||||
element={
|
||||
<StudyDetail
|
||||
toggleColorMode={toggleColorMode}
|
||||
page={"analytics"}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={URL_PREFIX + "/studies/:studyId/trials"}
|
||||
element={
|
||||
<StudyDetail
|
||||
toggleColorMode={toggleColorMode}
|
||||
page={"trialList"}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={URL_PREFIX + "/studies/:studyId/trialTable"}
|
||||
element={
|
||||
<StudyDetail
|
||||
toggleColorMode={toggleColorMode}
|
||||
page={"trialTable"}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={URL_PREFIX + "/studies/:studyId/note"}
|
||||
element={
|
||||
<StudyDetail
|
||||
toggleColorMode={toggleColorMode}
|
||||
page={"note"}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={URL_PREFIX + "/studies/:studyId/graph"}
|
||||
element={
|
||||
<StudyDetail
|
||||
toggleColorMode={toggleColorMode}
|
||||
page={"graph"}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={URL_PREFIX + "/studies/:studyId"}
|
||||
element={
|
||||
<StudyDetail
|
||||
toggleColorMode={toggleColorMode}
|
||||
page={"top"}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={URL_PREFIX + "/studies/:studyId/preference-history"}
|
||||
element={
|
||||
<StudyDetail
|
||||
toggleColorMode={toggleColorMode}
|
||||
page={"preferenceHistory"}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={URL_PREFIX + "/compare-studies"}
|
||||
element={
|
||||
<CompareStudies toggleColorMode={toggleColorMode} />
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={URL_PREFIX + "/"}
|
||||
element={<StudyList toggleColorMode={toggleColorMode} />}
|
||||
/>
|
||||
</Routes>
|
||||
</Router>
|
||||
</SnackbarProvider>
|
||||
</Box>
|
||||
</ThemeProvider>
|
||||
</RecoilRoot>
|
||||
</QueryClientProvider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import ClearIcon from "@mui/icons-material/Clear"
|
||||
import { Box, Modal, useTheme } from "@mui/material"
|
||||
import IconButton from "@mui/material/IconButton"
|
||||
import { DataGrid } from "@optuna/react"
|
||||
import { useSnackbar } from "notistack"
|
||||
import Papa from "papaparse"
|
||||
import React, { useState, useEffect, ReactNode } from "react"
|
||||
import { DataGrid } from "../DataGrid"
|
||||
|
||||
import { Artifact } from "ts/types/optuna"
|
||||
|
||||
|
||||
@@ -13,12 +13,12 @@ import {
|
||||
import Chip from "@mui/material/Chip"
|
||||
import Divider from "@mui/material/Divider"
|
||||
import FormControlLabel from "@mui/material/FormControlLabel"
|
||||
import Grid from "@mui/material/Grid"
|
||||
import List from "@mui/material/List"
|
||||
import ListItem from "@mui/material/ListItem"
|
||||
import ListItemButton from "@mui/material/ListItemButton"
|
||||
import ListItemText from "@mui/material/ListItemText"
|
||||
import ListSubheader from "@mui/material/ListSubheader"
|
||||
import Grid2 from "@mui/material/Unstable_Grid2"
|
||||
import * as Optuna from "@optuna/types"
|
||||
import { useSnackbar } from "notistack"
|
||||
import React, { FC, useEffect, useMemo, useState } from "react"
|
||||
@@ -336,21 +336,21 @@ const StudiesGraph: FC<{ studies: StudySummary[] }> = ({ studies }) => {
|
||||
</CardContent>
|
||||
</Card>
|
||||
) : null}
|
||||
<Grid2 container spacing={2} sx={{ padding: theme.spacing(0, 2) }}>
|
||||
<Grid container spacing={2} sx={{ padding: theme.spacing(0, 2) }}>
|
||||
{showStudyDetails !== null &&
|
||||
showStudyDetails.length > 0 &&
|
||||
showStudyDetails.every((s) => s)
|
||||
? showStudyDetails[0].directions.map((d, i) => (
|
||||
<Grid2 xs={6} key={i}>
|
||||
<Grid item xs={6} key={i}>
|
||||
<Card>
|
||||
<CardContent>
|
||||
<GraphEdf studies={showStudyDetails} objectiveId={i} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid2>
|
||||
</Grid>
|
||||
))
|
||||
: null}
|
||||
</Grid2>
|
||||
</Grid>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,383 +0,0 @@
|
||||
import CheckBoxIcon from "@mui/icons-material/CheckBox"
|
||||
import CheckBoxOutlineBlankIcon from "@mui/icons-material/CheckBoxOutlineBlank"
|
||||
import FilterListIcon from "@mui/icons-material/FilterList"
|
||||
import FirstPageIcon from "@mui/icons-material/FirstPage"
|
||||
import KeyboardArrowLeft from "@mui/icons-material/KeyboardArrowLeft"
|
||||
import KeyboardArrowRight from "@mui/icons-material/KeyboardArrowRight"
|
||||
import LastPageIcon from "@mui/icons-material/LastPage"
|
||||
import {
|
||||
Box,
|
||||
IconButton,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TablePagination,
|
||||
TableRow,
|
||||
TableSortLabel,
|
||||
TextField,
|
||||
useTheme,
|
||||
} from "@mui/material"
|
||||
import ListItemIcon from "@mui/material/ListItemIcon"
|
||||
import Paper from "@mui/material/Paper"
|
||||
import { TablePaginationActionsProps } from "@mui/material/TablePagination/TablePaginationActions"
|
||||
import { styled } from "@mui/system"
|
||||
import React from "react"
|
||||
|
||||
import {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
Header,
|
||||
PaginationState,
|
||||
SortingState,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getFacetedRowModel,
|
||||
getFacetedUniqueValues,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table"
|
||||
|
||||
const TableHeaderCellSpan = styled("span")({
|
||||
display: "inline-flex",
|
||||
})
|
||||
|
||||
const HiddenSpan = styled("span")({
|
||||
border: 0,
|
||||
clip: "rect(0 0 0 0)",
|
||||
height: 1,
|
||||
margin: -1,
|
||||
overflow: "hidden",
|
||||
padding: 0,
|
||||
position: "absolute",
|
||||
top: 20,
|
||||
width: 1,
|
||||
})
|
||||
|
||||
function FilterMenu<T>({
|
||||
header,
|
||||
filterChoices,
|
||||
}: {
|
||||
header: Header<T, unknown>
|
||||
filterChoices: string[]
|
||||
}): React.ReactElement {
|
||||
const [filterMenuAnchorEl, setFilterMenuAnchorEl] =
|
||||
React.useState<null | HTMLElement>(null)
|
||||
return (
|
||||
<>
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={(e) => {
|
||||
setFilterMenuAnchorEl(e.currentTarget)
|
||||
}}
|
||||
>
|
||||
<FilterListIcon fontSize="small" />
|
||||
</IconButton>
|
||||
<Menu
|
||||
anchorEl={filterMenuAnchorEl}
|
||||
open={filterMenuAnchorEl !== null}
|
||||
onClose={() => {
|
||||
setFilterMenuAnchorEl(null)
|
||||
}}
|
||||
>
|
||||
{filterChoices.map((choice) => (
|
||||
<MenuItem
|
||||
key={choice}
|
||||
onClick={() => {
|
||||
const skippedValues = header.column.getFilterValue() as string[]
|
||||
const isSkipped = skippedValues.includes(choice)
|
||||
const newSkippedValues = isSkipped
|
||||
? skippedValues.filter((v) => v !== choice)
|
||||
: skippedValues.concat(choice)
|
||||
header.column.setFilterValue(newSkippedValues)
|
||||
}}
|
||||
>
|
||||
<ListItemIcon>
|
||||
{header.column.getFilterValue() !== undefined ? (
|
||||
(header.column.getFilterValue() as string[]).includes(
|
||||
choice
|
||||
) ? (
|
||||
<CheckBoxOutlineBlankIcon color="primary" />
|
||||
) : (
|
||||
<CheckBoxIcon color="primary" />
|
||||
)
|
||||
) : null}
|
||||
</ListItemIcon>
|
||||
{choice ?? "(missing value)"}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Menu>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function DataGrid<T>({
|
||||
data,
|
||||
columns,
|
||||
initialRowsPerPage,
|
||||
}: {
|
||||
data: T[]
|
||||
columns: ColumnDef<T>[]
|
||||
initialRowsPerPage?: number
|
||||
}): React.ReactElement {
|
||||
const [sorting, setSorting] = React.useState<SortingState>([])
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||
[]
|
||||
)
|
||||
const rowsPerPageOptions = [10, 50, 100, { label: "All", value: data.length }]
|
||||
|
||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize:
|
||||
initialRowsPerPage && rowsPerPageOptions.includes(initialRowsPerPage)
|
||||
? initialRowsPerPage
|
||||
: 50,
|
||||
})
|
||||
|
||||
const table = useReactTable({
|
||||
data,
|
||||
columns,
|
||||
state: {
|
||||
columnFilters,
|
||||
sorting,
|
||||
pagination,
|
||||
},
|
||||
onColumnFiltersChange: setColumnFilters,
|
||||
onSortingChange: setSorting,
|
||||
onPaginationChange: setPagination,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getFacetedRowModel: getFacetedRowModel(),
|
||||
getFacetedUniqueValues: getFacetedUniqueValues(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
autoResetPageIndex: false,
|
||||
})
|
||||
|
||||
return (
|
||||
<Box component="div" sx={{ width: "100%" }}>
|
||||
<TableContainer component={Paper}>
|
||||
<Table sx={{ minWidth: 650 }} aria-label="simple table">
|
||||
<TableHead>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id}>
|
||||
{headerGroup.headers.map((header) => {
|
||||
if (
|
||||
header.column.getCanFilter() &&
|
||||
!header.column.getIsFiltered()
|
||||
) {
|
||||
header.column.setFilterValue([])
|
||||
}
|
||||
const order = header.column.getIsSorted()
|
||||
const filterChoices = header.column.getCanFilter()
|
||||
? Array.from(
|
||||
header.column.getFacetedUniqueValues().keys()
|
||||
).sort()
|
||||
: null
|
||||
return (
|
||||
<TableCell key={header.id} colSpan={header.colSpan}>
|
||||
{header.isPlaceholder ? null : (
|
||||
<TableHeaderCellSpan>
|
||||
{header.column.getCanSort() ? (
|
||||
<TableSortLabel
|
||||
active={order !== false}
|
||||
direction={order || "asc"}
|
||||
onClick={header.column.getToggleSortingHandler()}
|
||||
>
|
||||
{flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)}
|
||||
{order !== null ? (
|
||||
<HiddenSpan>
|
||||
{order === "desc"
|
||||
? "sorted descending"
|
||||
: "sorted ascending"}
|
||||
</HiddenSpan>
|
||||
) : null}
|
||||
</TableSortLabel>
|
||||
) : (
|
||||
flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)
|
||||
)}
|
||||
{filterChoices !== null ? (
|
||||
<FilterMenu
|
||||
header={header}
|
||||
filterChoices={filterChoices}
|
||||
/>
|
||||
) : null}
|
||||
</TableHeaderCellSpan>
|
||||
)}
|
||||
</TableCell>
|
||||
)
|
||||
})}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{table.getRowModel().rows.map((row) => {
|
||||
return (
|
||||
<TableRow key={row.id}>
|
||||
{row.getVisibleCells().map((cell) => {
|
||||
return (
|
||||
<TableCell key={cell.id}>
|
||||
{flexRender(
|
||||
cell.column.columnDef.cell,
|
||||
cell.getContext()
|
||||
)}
|
||||
</TableCell>
|
||||
)
|
||||
})}
|
||||
</TableRow>
|
||||
)
|
||||
})}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
<Box component="div" display="flex" alignItems="center">
|
||||
<TablePagination
|
||||
rowsPerPageOptions={rowsPerPageOptions}
|
||||
component="div"
|
||||
count={table.getFilteredRowModel().rows.length}
|
||||
rowsPerPage={table.getState().pagination.pageSize}
|
||||
page={table.getState().pagination.pageIndex}
|
||||
slotProps={{
|
||||
select: {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
},
|
||||
}}
|
||||
onPageChange={(_, page) => {
|
||||
table.setPageIndex(page)
|
||||
}}
|
||||
onRowsPerPageChange={(e) => {
|
||||
const size = e.target.value ? Number(e.target.value) : 10
|
||||
table.setPageSize(size)
|
||||
}}
|
||||
ActionsComponent={TablePaginationActions}
|
||||
/>
|
||||
{table.getPageCount() > 2 ? (
|
||||
<PaginationForm1
|
||||
onPageNumberSubmit={(page) => table.setPageIndex(page)}
|
||||
maxPageNumber={table.getPageCount()}
|
||||
/>
|
||||
) : null}
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
const TablePaginationActions = ({
|
||||
count,
|
||||
page,
|
||||
rowsPerPage,
|
||||
onPageChange,
|
||||
}: TablePaginationActionsProps) => {
|
||||
const theme = useTheme()
|
||||
const handleFirstPageButtonClick = (
|
||||
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
|
||||
) => {
|
||||
onPageChange(event, 0)
|
||||
}
|
||||
|
||||
const handleBackButtonClick = (
|
||||
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
|
||||
) => {
|
||||
onPageChange(event, page - 1)
|
||||
}
|
||||
|
||||
const handleNextButtonClick = (
|
||||
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
|
||||
) => {
|
||||
onPageChange(event, page + 1)
|
||||
}
|
||||
|
||||
const handleLastPageButtonClick = (
|
||||
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
|
||||
) => {
|
||||
onPageChange(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1))
|
||||
}
|
||||
|
||||
return (
|
||||
<Box component="div" sx={{ flexShrink: 0, ml: 2.5 }}>
|
||||
<IconButton
|
||||
onClick={handleFirstPageButtonClick}
|
||||
disabled={page === 0}
|
||||
aria-label="first page"
|
||||
>
|
||||
{theme.direction === "rtl" ? <LastPageIcon /> : <FirstPageIcon />}
|
||||
</IconButton>
|
||||
<IconButton
|
||||
onClick={handleBackButtonClick}
|
||||
disabled={page === 0}
|
||||
aria-label="previous page"
|
||||
>
|
||||
{theme.direction === "rtl" ? (
|
||||
<KeyboardArrowRight />
|
||||
) : (
|
||||
<KeyboardArrowLeft />
|
||||
)}
|
||||
</IconButton>
|
||||
<IconButton
|
||||
onClick={handleNextButtonClick}
|
||||
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
|
||||
aria-label="next page"
|
||||
>
|
||||
{theme.direction === "rtl" ? (
|
||||
<KeyboardArrowLeft />
|
||||
) : (
|
||||
<KeyboardArrowRight />
|
||||
)}
|
||||
</IconButton>
|
||||
<IconButton
|
||||
onClick={handleLastPageButtonClick}
|
||||
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
|
||||
aria-label="last page"
|
||||
>
|
||||
{theme.direction === "rtl" ? <FirstPageIcon /> : <LastPageIcon />}
|
||||
</IconButton>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
const PaginationForm1: React.FC<{
|
||||
onPageNumberSubmit: (value: number) => void
|
||||
maxPageNumber: number
|
||||
}> = ({ onPageNumberSubmit, maxPageNumber }) => {
|
||||
// This component is separated from DataGrid to prevent `DataGrid` from re-rendering the page,
|
||||
// every time any letters are input.
|
||||
const [specifiedPageText, setSpecifiedPageText] = React.useState("")
|
||||
|
||||
const handleSubmitPageNumber = (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault()
|
||||
const newPageNumber = parseInt(specifiedPageText, 10)
|
||||
// Page is 0-indexed in `TablePagination`.
|
||||
onPageNumberSubmit(newPageNumber - 1)
|
||||
setSpecifiedPageText("") // reset the input field
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmitPageNumber}>
|
||||
<TextField
|
||||
size="small"
|
||||
label={`Go to Page: n / ${maxPageNumber}`}
|
||||
value={specifiedPageText}
|
||||
type="number"
|
||||
style={{ width: 200 }}
|
||||
inputProps={{ min: 1, max: maxPageNumber }}
|
||||
onChange={(e) => {
|
||||
setSpecifiedPageText(e.target.value)
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
export { DataGrid }
|
||||
@@ -6,12 +6,12 @@ import {
|
||||
Typography,
|
||||
useTheme,
|
||||
} from "@mui/material"
|
||||
import Grid2 from "@mui/material/Unstable_Grid2"
|
||||
import Grid from "@mui/material/Grid"
|
||||
import { DataGrid } from "@optuna/react"
|
||||
import * as Optuna from "@optuna/types"
|
||||
import React, { FC } from "react"
|
||||
import { useStudyDetailValue, useStudySummaryValue } from "../../state"
|
||||
import { BestTrialsCard } from "../BestTrialsCard"
|
||||
import { DataGrid } from "../DataGrid"
|
||||
import { Contour } from "../GraphContour"
|
||||
|
||||
import { ColumnDef, createColumnHelper } from "@tanstack/react-table"
|
||||
@@ -41,16 +41,16 @@ export const PreferentialAnalytics: FC<{ studyId: number }> = ({ studyId }) => {
|
||||
component="div"
|
||||
sx={{ display: "flex", width: "100%", flexDirection: "column" }}
|
||||
>
|
||||
<Grid2 container spacing={2} sx={{ padding: theme.spacing(0, 2) }}>
|
||||
<Grid2 xs={14}>
|
||||
<Grid container spacing={2} sx={{ padding: theme.spacing(0, 2) }}>
|
||||
<Grid item xs={14}>
|
||||
<Paper elevation={2} sx={{ padding: theme.spacing(2) }}>
|
||||
<Contour study={studyDetail} />
|
||||
</Paper>
|
||||
</Grid2>
|
||||
<Grid2 xs={6} spacing={2}>
|
||||
</Grid>
|
||||
<Grid item xs={6} spacing={2}>
|
||||
<BestTrialsCard studyDetail={studyDetail} />
|
||||
</Grid2>
|
||||
<Grid2 xs={6}>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Card>
|
||||
<CardContent
|
||||
sx={{
|
||||
@@ -70,8 +70,8 @@ export const PreferentialAnalytics: FC<{ studyId: number }> = ({ studyId }) => {
|
||||
<DataGrid data={userAttrs} columns={columns} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
Typography,
|
||||
useTheme,
|
||||
} from "@mui/material"
|
||||
import Grid2 from "@mui/material/Unstable_Grid2"
|
||||
import Grid from "@mui/material/Grid"
|
||||
import React, { FC, useEffect, useMemo } from "react"
|
||||
import { Link, useParams } from "react-router-dom"
|
||||
import { useRecoilValue } from "recoil"
|
||||
@@ -146,19 +146,19 @@ export const StudyDetail: FC<{
|
||||
>
|
||||
Empirical Distribution of the Objective Value
|
||||
</Typography>
|
||||
<Grid2 container spacing={2} sx={{ padding: theme.spacing(2) }}>
|
||||
<Grid container spacing={2} sx={{ padding: theme.spacing(2) }}>
|
||||
{studyDetail !== null
|
||||
? studyDetail.directions.map((d, i) => (
|
||||
<Grid2 xs={6} key={i}>
|
||||
<Grid item xs={6} key={i}>
|
||||
<Card>
|
||||
<CardContent>
|
||||
<GraphEdf studies={[studyDetail]} objectiveId={i} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid2>
|
||||
</Grid>
|
||||
))
|
||||
: null}
|
||||
</Grid2>
|
||||
</Grid>
|
||||
</Box>
|
||||
)
|
||||
} else if (page === "trialList") {
|
||||
|
||||
@@ -8,7 +8,8 @@ import {
|
||||
useTheme,
|
||||
} from "@mui/material"
|
||||
import FormControlLabel from "@mui/material/FormControlLabel"
|
||||
import Grid2 from "@mui/material/Unstable_Grid2"
|
||||
import Grid from "@mui/material/Grid"
|
||||
import { DataGrid } from "@optuna/react"
|
||||
import * as Optuna from "@optuna/types"
|
||||
import React, { FC, useState } from "react"
|
||||
import { useRecoilValue } from "recoil"
|
||||
@@ -21,7 +22,6 @@ import {
|
||||
import { artifactIsAvailable } from "../state"
|
||||
import { StudyArtifactCards } from "./Artifact/StudyArtifactCards"
|
||||
import { BestTrialsCard } from "./BestTrialsCard"
|
||||
import { DataGrid } from "./DataGrid"
|
||||
import { GraphHistory } from "./GraphHistory"
|
||||
import { GraphHyperparameterImportance } from "./GraphHyperparameterImportances"
|
||||
import { GraphIntermediateValues } from "./GraphIntermediateValues"
|
||||
@@ -124,31 +124,31 @@ export const StudyHistory: FC<{ studyId: number }> = ({ studyId }) => {
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Grid2 container spacing={2} sx={{ padding: theme.spacing(0, 2) }}>
|
||||
<Grid2 xs={6}>
|
||||
<Grid container spacing={2} sx={{ padding: theme.spacing(0, 2) }}>
|
||||
<Grid item xs={6}>
|
||||
<GraphHyperparameterImportance
|
||||
studyId={studyId}
|
||||
study={studyDetail}
|
||||
graphHeight="450px"
|
||||
/>
|
||||
</Grid2>
|
||||
<Grid2 xs={6}>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<GraphTimeline study={studyDetail} />
|
||||
</Grid2>
|
||||
</Grid>
|
||||
{studyDetail !== null &&
|
||||
studyDetail.plotly_graph_objects.map((go) => (
|
||||
<Grid2 xs={6} key={go.id}>
|
||||
<Grid xs={6} key={go.id}>
|
||||
<Card>
|
||||
<CardContent>
|
||||
<UserDefinedPlot graphObject={go} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid2>
|
||||
</Grid>
|
||||
))}
|
||||
<Grid2 xs={6} spacing={2}>
|
||||
<Grid item xs={6}>
|
||||
<BestTrialsCard studyDetail={studyDetail} />
|
||||
</Grid2>
|
||||
<Grid2 xs={6}>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Card>
|
||||
<CardContent
|
||||
sx={{
|
||||
@@ -168,23 +168,23 @@ export const StudyHistory: FC<{ studyId: number }> = ({ studyId }) => {
|
||||
<DataGrid data={userAttrs} columns={columns} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid2>
|
||||
</Grid>
|
||||
{studyDetail !== null &&
|
||||
studyDetail.directions.length === 1 &&
|
||||
studyDetail.has_intermediate_values ? (
|
||||
<Grid2 xs={6}>
|
||||
<Grid item xs={6}>
|
||||
<GraphIntermediateValues
|
||||
trials={trials}
|
||||
includePruned={includePruned}
|
||||
logScale={logScale}
|
||||
/>
|
||||
</Grid2>
|
||||
</Grid>
|
||||
) : null}
|
||||
</Grid2>
|
||||
</Grid>
|
||||
|
||||
{artifactEnabled && studyDetail !== null && (
|
||||
<Grid2 container spacing={2} sx={{ padding: theme.spacing(0, 2) }}>
|
||||
<Grid2 xs={6}>
|
||||
<Grid container spacing={2} sx={{ padding: theme.spacing(2) }}>
|
||||
<Grid item xs={6}>
|
||||
<Card>
|
||||
<CardContent
|
||||
sx={{
|
||||
@@ -204,8 +204,8 @@ export const StudyHistory: FC<{ studyId: number }> = ({ studyId }) => {
|
||||
<StudyArtifactCards study={studyDetail} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)}
|
||||
</Box>
|
||||
)
|
||||
|
||||
@@ -3,9 +3,10 @@ import LinkIcon from "@mui/icons-material/Link"
|
||||
import { Button, IconButton, useTheme } from "@mui/material"
|
||||
import React, { FC } from "react"
|
||||
|
||||
import { DataGrid } from "@optuna/react"
|
||||
|
||||
import { Link } from "react-router-dom"
|
||||
import { StudyDetail, Trial } from "ts/types/optuna"
|
||||
import { DataGrid } from "./DataGrid"
|
||||
|
||||
import {
|
||||
ColumnDef,
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import React from "react"
|
||||
import ReactDOM from "react-dom/client"
|
||||
import { APIClientProvider } from "./apiClientProvider"
|
||||
import { AxiosClient } from "./axiosClient"
|
||||
import { App } from "./components/App"
|
||||
|
||||
const axiosAPIClient = new AxiosClient()
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("dashboard") as HTMLElement).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
<APIClientProvider apiClient={axiosAPIClient}>
|
||||
<App />
|
||||
</APIClientProvider>
|
||||
</React.StrictMode>
|
||||
)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { APIClientProvider } from "./apiClientProvider"
|
||||
import { AxiosClient } from "./axiosClient"
|
||||
import { App } from "./components/App"
|
||||
|
||||
export { AxiosClient, APIClientProvider, App }
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./ts",
|
||||
"outDir": "./pkg",
|
||||
"declaration": true,
|
||||
"declarationDir": "./types",
|
||||
},
|
||||
"files": [
|
||||
"./ts/pkg_index.tsx",
|
||||
],
|
||||
"include": [
|
||||
"./ts/types/**/*",
|
||||
],
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
Typography,
|
||||
useTheme,
|
||||
} from "@mui/material"
|
||||
import Grid2 from "@mui/material/Unstable_Grid2"
|
||||
import Grid from "@mui/material/Grid"
|
||||
import {
|
||||
PlotHistory,
|
||||
PlotImportance,
|
||||
@@ -176,8 +176,8 @@ export const StudyDetail: FC<{
|
||||
<PlotHistory study={study} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Grid2 container spacing={0}>
|
||||
<Grid2 xs={6}>
|
||||
<Grid container spacing={0}>
|
||||
<Grid item xs={6}>
|
||||
<Card sx={{ margin: theme.spacing(2) }}>
|
||||
<CardContent>
|
||||
{!!study && (
|
||||
@@ -185,8 +185,8 @@ export const StudyDetail: FC<{
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid2>
|
||||
<Grid2 xs={6}>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Card sx={{ margin: theme.spacing(2) }}>
|
||||
<CardContent>
|
||||
{!!study && (
|
||||
@@ -198,8 +198,8 @@ export const StudyDetail: FC<{
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Card sx={{ margin: theme.spacing(2) }}>
|
||||
<CardContent>
|
||||
{!!study && <TrialTable study={study} initialRowsPerPage={10} />}
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
import CheckBoxIcon from "@mui/icons-material/CheckBox"
|
||||
import CheckBoxOutlineBlankIcon from "@mui/icons-material/CheckBoxOutlineBlank"
|
||||
import FilterListIcon from "@mui/icons-material/FilterList"
|
||||
import FirstPageIcon from "@mui/icons-material/FirstPage"
|
||||
import KeyboardArrowLeft from "@mui/icons-material/KeyboardArrowLeft"
|
||||
import KeyboardArrowRight from "@mui/icons-material/KeyboardArrowRight"
|
||||
import LastPageIcon from "@mui/icons-material/LastPage"
|
||||
import {
|
||||
CheckBox as CheckBoxIcon,
|
||||
CheckBoxOutlineBlank as CheckBoxOutlineBlankIcon,
|
||||
FilterList as FilterListIcon,
|
||||
FirstPage as FirstPageIcon,
|
||||
KeyboardArrowLeft,
|
||||
KeyboardArrowRight,
|
||||
LastPage as LastPageIcon,
|
||||
} from "@mui/icons-material"
|
||||
import {
|
||||
Box,
|
||||
IconButton,
|
||||
ListItem as ListItemIcon,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Paper,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
@@ -21,8 +25,6 @@ import {
|
||||
TextField,
|
||||
useTheme,
|
||||
} from "@mui/material"
|
||||
import ListItemIcon from "@mui/material/ListItemIcon"
|
||||
import Paper from "@mui/material/Paper"
|
||||
import { TablePaginationActionsProps } from "@mui/material/TablePagination/TablePaginationActions"
|
||||
import { styled } from "@mui/system"
|
||||
import React from "react"
|
||||
|
||||
Reference in New Issue
Block a user