Fix scrolling issue of jupyter lab

This commit is contained in:
c-bata
2024-08-08 10:23:35 +09:00
parent a7f715cb00
commit 963e58a116
17 changed files with 89 additions and 92 deletions
+5
View File
@@ -37,6 +37,11 @@ serve-browser-app: tslib $(RUSTLIB_OUT)
vscode-extension: vscode/assets/bundle.js
cd vscode && npm install && npm run vscode:prepublish && vsce package
.PHONY: jupyterlab-extension
jupyterlab-extension: tslib
cd optuna_dashboard && npm install && npm run build:pkg
cd jupyterlab && python -m build --sdist
.PHONY: sdist
sdist: pyproject.toml $(DASHBOARD_TS_OUT)
python -m build --sdist
+3 -1
View File
@@ -231,7 +231,9 @@ export class JupyterlabAPIClient extends APIClient {
})
return
}
getParamImportances = (studyId: number): Promise<Optuna.ParamImportance[][]> =>
getParamImportances = (
studyId: number
): Promise<Optuna.ParamImportance[][]> =>
requestAPI<ParamImportancesResponse>(
`/api/studies/${studyId}/param_importances`
).then((res) => {
@@ -11,7 +11,7 @@ import CircularProgress from "@mui/material/CircularProgress"
import {
APIClientProvider,
App,
ConstantsProvider,
ConstantsContext,
} from "@optuna/optuna-dashboard"
import { SnackbarProvider, enqueueSnackbar } from "notistack"
import React, { Dispatch, FC, SetStateAction, useEffect, useState } from "react"
@@ -54,14 +54,16 @@ export const JupyterLabEntrypoint: FC = () => {
)
}
return (
<ConstantsProvider
APP_BAR_TITLE="Optuna Dashboard JupyterLab"
URL_PREFIX={pathName}
<ConstantsContext.Provider
value={{
environment: "jupyterlab",
url_prefix: pathName,
}}
>
<APIClientProvider apiClient={jupyterlabAPIClient}>
<App />
</APIClientProvider>
</ConstantsProvider>
</ConstantsContext.Provider>
)
}
+10 -10
View File
@@ -50,7 +50,7 @@ export const App: FC = () => {
setColorMode(colorMode === "dark" ? "light" : "dark")
}
const { URL_PREFIX } = useConstants()
const { url_prefix } = useConstants()
return (
<QueryClientProvider client={queryClient}>
@@ -69,7 +69,7 @@ export const App: FC = () => {
<Router>
<Routes>
<Route
path={URL_PREFIX + "/studies/:studyId/analytics"}
path={url_prefix + "/studies/:studyId/analytics"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
@@ -78,7 +78,7 @@ export const App: FC = () => {
}
/>
<Route
path={URL_PREFIX + "/studies/:studyId/trials"}
path={url_prefix + "/studies/:studyId/trials"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
@@ -87,7 +87,7 @@ export const App: FC = () => {
}
/>
<Route
path={URL_PREFIX + "/studies/:studyId/trialTable"}
path={url_prefix + "/studies/:studyId/trialTable"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
@@ -96,7 +96,7 @@ export const App: FC = () => {
}
/>
<Route
path={URL_PREFIX + "/studies/:studyId/note"}
path={url_prefix + "/studies/:studyId/note"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
@@ -105,7 +105,7 @@ export const App: FC = () => {
}
/>
<Route
path={URL_PREFIX + "/studies/:studyId/graph"}
path={url_prefix + "/studies/:studyId/graph"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
@@ -114,7 +114,7 @@ export const App: FC = () => {
}
/>
<Route
path={URL_PREFIX + "/studies/:studyId"}
path={url_prefix + "/studies/:studyId"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
@@ -123,7 +123,7 @@ export const App: FC = () => {
}
/>
<Route
path={URL_PREFIX + "/studies/:studyId/preference-history"}
path={url_prefix + "/studies/:studyId/preference-history"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
@@ -132,13 +132,13 @@ export const App: FC = () => {
}
/>
<Route
path={URL_PREFIX + "/compare-studies"}
path={url_prefix + "/compare-studies"}
element={
<CompareStudies toggleColorMode={toggleColorMode} />
}
/>
<Route
path={URL_PREFIX + "/"}
path={url_prefix + "/"}
element={<StudyList toggleColorMode={toggleColorMode} />}
/>
</Routes>
+19 -10
View File
@@ -21,7 +21,7 @@ import ListItemIcon from "@mui/material/ListItemIcon"
import ListItemText from "@mui/material/ListItemText"
import Modal from "@mui/material/Modal"
import Toolbar from "@mui/material/Toolbar"
import { CSSObject, Theme, styled, useTheme } from "@mui/material/styles"
import { CSSObject, SxProps, Theme, styled, useTheme } from "@mui/material/styles"
import React, { FC } from "react"
import { Link } from "react-router-dom"
import { useRecoilState, useRecoilValue } from "recoil"
@@ -130,9 +130,10 @@ export const AppDrawer: FC<{
toolbar: React.ReactNode
children?: React.ReactNode
}> = ({ studyId, toggleColorMode, page, toolbar, children }) => {
const { URL_PREFIX } = useConstants()
const { url_prefix } = useConstants()
const theme = useTheme()
const constants = useConstants()
const action = actionCreator()
const [open, setOpen] = useRecoilState<boolean>(drawerOpenState)
const reloadInterval = useRecoilValue<number>(reloadIntervalState)
@@ -158,6 +159,14 @@ export const AppDrawer: FC<{
const styleSwitch = {
display: open ? "inherit" : "none",
}
const mainSx: SxProps = {
flexGrow: 1,
}
if (constants.environment === "jupyterlab") {
// 100vh - (the height of Optuna Dashboard toolbar) - (the height of JupyterLab toolbar)
mainSx.height = `calc(100vh - ${theme.mixins.toolbar.minHeight}px - 29px)`
mainSx.overflow = "auto"
}
const handleDrawerOpen = () => {
setOpen(true)
@@ -212,7 +221,7 @@ export const AppDrawer: FC<{
<ListItem key="Top" disablePadding sx={styleListItem}>
<ListItemButton
component={Link}
to={`${URL_PREFIX}/studies/${studyId}`}
to={`${url_prefix}/studies/${studyId}`}
sx={styleListItemButton}
selected={page === "top"}
>
@@ -233,7 +242,7 @@ export const AppDrawer: FC<{
>
<ListItemButton
component={Link}
to={`${URL_PREFIX}/studies/${studyId}/preference-history`}
to={`${url_prefix}/studies/${studyId}/preference-history`}
sx={styleListItemButton}
selected={page === "preferenceHistory"}
>
@@ -250,7 +259,7 @@ export const AppDrawer: FC<{
<ListItem key="Analytics" disablePadding sx={styleListItem}>
<ListItemButton
component={Link}
to={`${URL_PREFIX}/studies/${studyId}/analytics`}
to={`${url_prefix}/studies/${studyId}/analytics`}
sx={styleListItemButton}
selected={page === "analytics"}
>
@@ -264,7 +273,7 @@ export const AppDrawer: FC<{
<ListItem key="PreferenceGraph" disablePadding sx={styleListItem}>
<ListItemButton
component={Link}
to={`${URL_PREFIX}/studies/${studyId}/graph`}
to={`${url_prefix}/studies/${studyId}/graph`}
sx={styleListItemButton}
selected={page === "graph"}
>
@@ -281,7 +290,7 @@ export const AppDrawer: FC<{
<ListItem key="TableList" disablePadding sx={styleListItem}>
<ListItemButton
component={Link}
to={`${URL_PREFIX}/studies/${studyId}/trials`}
to={`${url_prefix}/studies/${studyId}/trials`}
sx={styleListItemButton}
selected={page === "trialList"}
>
@@ -294,7 +303,7 @@ export const AppDrawer: FC<{
<ListItem key="TrialTable" disablePadding sx={styleListItem}>
<ListItemButton
component={Link}
to={`${URL_PREFIX}/studies/${studyId}/trialTable`}
to={`${url_prefix}/studies/${studyId}/trialTable`}
sx={styleListItemButton}
selected={page === "trialTable"}
>
@@ -307,7 +316,7 @@ export const AppDrawer: FC<{
<ListItem key="Note" disablePadding sx={styleListItem}>
<ListItemButton
component={Link}
to={`${URL_PREFIX}/studies/${studyId}/note`}
to={`${url_prefix}/studies/${studyId}/note`}
sx={styleListItemButton}
selected={page === "note"}
>
@@ -419,7 +428,7 @@ export const AppDrawer: FC<{
</ListItem>
</List>
</Drawer>
<Box component="main" sx={{ flexGrow: 1 }}>
<Box component="main" sx={ mainSx }>
<DrawerHeader />
{children || null}
</Box>
@@ -24,7 +24,7 @@ const useBestTrials = (studyDetail: StudyDetail | null): Trial[] => {
export const BestTrialsCard: FC<{
studyDetail: StudyDetail | null
}> = ({ studyDetail }) => {
const { URL_PREFIX } = useConstants()
const { url_prefix } = useConstants()
const theme = useTheme()
const bestTrials = useBestTrials(studyDetail)
@@ -64,7 +64,7 @@ export const BestTrialsCard: FC<{
variant="outlined"
startIcon={<LinkIcon />}
component={Link}
to={`${URL_PREFIX}/studies/${bestTrial.study_id}/trials?numbers=${bestTrial.number}`}
to={`${url_prefix}/studies/${bestTrial.study_id}/trials?numbers=${bestTrial.number}`}
sx={{ margin: theme.spacing(1) }}
>
Details
@@ -92,7 +92,7 @@ export const BestTrialsCard: FC<{
<ListItemButton
component={Link}
to={
URL_PREFIX +
url_prefix +
`/studies/${trial.study_id}/trials?numbers=${trial.number}`
}
sx={{ flexDirection: "column", alignItems: "flex-start" }}
@@ -76,7 +76,7 @@ const isEqualDirections = (
export const CompareStudies: FC<{
toggleColorMode: () => void
}> = ({ toggleColorMode }) => {
const { URL_PREFIX } = useConstants()
const { url_prefix } = useConstants()
const { enqueueSnackbar } = useSnackbar()
const theme = useTheme()
@@ -101,7 +101,7 @@ export const CompareStudies: FC<{
<>
<IconButton
component={Link}
to={URL_PREFIX + "/"}
to={url_prefix + "/"}
sx={{ marginRight: theme.spacing(1) }}
color="inherit"
title="Return to the top page"
@@ -189,10 +189,10 @@ export const CompareStudies: FC<{
next = [...selectedIds, study.study_id]
}
}
navigate(getStudyListLink(next, URL_PREFIX))
navigate(getStudyListLink(next, url_prefix))
} else {
navigate(
getStudyListLink([study.study_id], URL_PREFIX)
getStudyListLink([study.study_id], url_prefix)
)
}
}}
@@ -40,7 +40,7 @@ export const GraphHistory: FC<{
logScale: boolean
includePruned: boolean
}> = ({ studies, logScale, includePruned }) => {
const { URL_PREFIX } = useConstants()
const { url_prefix } = useConstants()
const theme = useTheme()
const colorTheme = usePlotlyColorTheme(theme.palette.mode)
@@ -103,7 +103,7 @@ export const GraphHistory: FC<{
studyId = studies[Math.floor(data.points[0].curveNumber / 2)].id
}
navigate(
URL_PREFIX +
url_prefix +
`/studies/${studyId}/trials?numbers=${data.points[0].x}`
)
}
@@ -62,7 +62,7 @@ const GraphParetoFrontBackend: FC<{
const GraphParetoFrontFrontend: FC<{
study: StudyDetail | null
}> = ({ study = null }) => {
const { URL_PREFIX } = useConstants()
const { url_prefix } = useConstants()
const theme = useTheme()
const colorTheme = usePlotlyColorTheme(theme.palette.mode)
@@ -96,7 +96,7 @@ const GraphParetoFrontFrontend: FC<{
data.points[0].text.replace(/<br>/g, "")
)
navigate(
URL_PREFIX +
url_prefix +
`/studies/${study.id}/trials?numbers=${plotTextInfo.number}`
)
})
@@ -50,7 +50,7 @@ export const StudyDetail: FC<{
toggleColorMode: () => void
page: PageId
}> = ({ toggleColorMode, page }) => {
const { URL_PREFIX } = useConstants()
const { url_prefix } = useConstants()
const theme = useTheme()
const action = actionCreator()
@@ -226,7 +226,7 @@ export const StudyDetail: FC<{
<>
<IconButton
component={Link}
to={URL_PREFIX + "/"}
to={url_prefix + "/"}
sx={{ marginRight: theme.spacing(1) }}
color="inherit"
title="Return to the top page"
+3 -3
View File
@@ -45,7 +45,7 @@ import { useRenameStudyDialog } from "./RenameStudyDialog"
export const StudyList: FC<{
toggleColorMode: () => void
}> = ({ toggleColorMode }) => {
const { URL_PREFIX } = useConstants()
const { url_prefix } = useConstants()
const theme = useTheme()
const action = actionCreator()
@@ -155,7 +155,7 @@ export const StudyList: FC<{
>
<CardActionArea
component={Link}
to={`${URL_PREFIX}/studies/${study.study_id}`}
to={`${url_prefix}/studies/${study.study_id}`}
>
<CardContent>
<Typography variant="h5" sx={{ wordBreak: "break-all" }}>
@@ -260,7 +260,7 @@ export const StudyList: FC<{
variant="outlined"
startIcon={<CompareIcon />}
component={Link}
to={`${URL_PREFIX}/compare-studies`}
to={`${url_prefix}/compare-studies`}
sx={{ marginRight: theme.spacing(2), minWidth: "120px" }}
>
Compare
+4 -4
View File
@@ -335,7 +335,7 @@ const getTrialListLink = (
export const TrialList: FC<{ studyDetail: StudyDetail | null }> = ({
studyDetail,
}) => {
const { URL_PREFIX } = useConstants()
const { url_prefix } = useConstants()
const theme = useTheme()
const query = useQuery()
@@ -425,7 +425,7 @@ export const TrialList: FC<{ studyDetail: StudyDetail | null }> = ({
studyDetail.id,
excludedStates,
numbers,
URL_PREFIX
url_prefix
)
)
}}
@@ -489,7 +489,7 @@ export const TrialList: FC<{ studyDetail: StudyDetail | null }> = ({
trial.study_id,
excludedStates,
next,
URL_PREFIX
url_prefix
)
)
} else {
@@ -498,7 +498,7 @@ export const TrialList: FC<{ studyDetail: StudyDetail | null }> = ({
trial.study_id,
excludedStates,
[trial.number],
URL_PREFIX
url_prefix
)
)
}
@@ -28,7 +28,7 @@ const multiValueFilter: FilterFn<Trial> = <D extends object>(
export const TrialTable: FC<{
studyDetail: StudyDetail | null
}> = ({ studyDetail }) => {
const { URL_PREFIX } = useConstants()
const { url_prefix } = useConstants()
const theme = useTheme()
const trials: Trial[] = studyDetail !== null ? studyDetail.trials : []
@@ -127,7 +127,7 @@ export const TrialTable: FC<{
<IconButton
component={Link}
to={
URL_PREFIX +
url_prefix +
`/studies/${info.getValue().study_id}/trials?numbers=${
info.getValue().number
}`
+7 -31
View File
@@ -1,39 +1,15 @@
import React from "react"
type ConstantsContextType = {
APP_BAR_TITLE: string
API_ENDPOINT?: string
URL_PREFIX: string
environment: "jupyterlab" | "optuna-dashboard"
url_prefix: string
}
export const ConstantsContext = React.createContext<
ConstantsContextType | undefined
>(undefined)
export const ConstantsContext = React.createContext<ConstantsContextType>({
environment: "optuna-dashboard",
url_prefix: "",
})
export const useConstants = (): ConstantsContextType => {
const context = React.useContext(ConstantsContext)
if (context === undefined) {
throw new Error("useConstants must be used within a ConstantsProvider.")
}
return context
}
export function ConstantsProvider({
APP_BAR_TITLE,
API_ENDPOINT,
URL_PREFIX,
children,
}: {
APP_BAR_TITLE: string
API_ENDPOINT?: string
URL_PREFIX: string
children: React.ReactNode
}) {
return (
<ConstantsContext.Provider
value={{ APP_BAR_TITLE, API_ENDPOINT, URL_PREFIX }}
>
{children}
</ConstantsContext.Provider>
)
return React.useContext(ConstantsContext)
}
+14 -8
View File
@@ -1,24 +1,30 @@
import React from "react"
import React, { FC, ReactNode } from "react"
import ReactDOM from "react-dom/client"
import { APIClientProvider } from "./apiClientProvider"
import { AxiosClient } from "./axiosClient"
import { App } from "./components/App"
import { ConstantsProvider } from "./constantsProvider"
import { ConstantsContext } from "./constantsProvider"
declare const APP_BAR_TITLE: string
declare const API_ENDPOINT: string
declare const URL_PREFIX: string
const axiosAPIClient = new AxiosClient(API_ENDPOINT)
const ConstantsProvider: FC<{ children: ReactNode }> = ({ children }) => (
<ConstantsContext.Provider
value={{
environment: "optuna-dashboard",
url_prefix: URL_PREFIX,
}}
>
{children}
</ConstantsContext.Provider>
)
ReactDOM.createRoot(document.getElementById("dashboard") as HTMLElement).render(
<React.StrictMode>
<APIClientProvider apiClient={axiosAPIClient}>
<ConstantsProvider
APP_BAR_TITLE={APP_BAR_TITLE}
API_ENDPOINT={API_ENDPOINT}
URL_PREFIX={URL_PREFIX}
>
<ConstantsProvider>
<App />
</ConstantsProvider>
</APIClientProvider>
+2 -2
View File
@@ -16,7 +16,7 @@ import {
import { APIClientProvider } from "./apiClientProvider"
import { AxiosClient } from "./axiosClient"
import { App } from "./components/App"
import { ConstantsProvider } from "./constantsProvider"
import { ConstantsContext } from "./constantsProvider"
import {
Artifact,
FeedbackComponentType,
@@ -37,7 +37,7 @@ export {
APIClientProvider,
App,
APIClient,
ConstantsProvider,
ConstantsContext,
Artifact,
FeedbackComponentType,
FormWidgets,
-3
View File
@@ -54,9 +54,6 @@ var config = {
},
plugins: [
new webpack.DefinePlugin({
APP_BAR_TITLE: JSON.stringify(
process.env.APP_BAR_TITLE || "Optuna Dashboard"
),
API_ENDPOINT: JSON.stringify(process.env.API_ENDPOINT),
URL_PREFIX: JSON.stringify(process.env.URL_PREFIX || "/dashboard"),
}),