mirror of
https://github.com/wassname/optuna-dashboard.git
synced 2026-09-09 11:28:14 +08:00
Merge pull request #851 from porink0424/feat/tslib
Separated some UI components into `@optuna/react`
This commit is contained in:
@@ -22,6 +22,7 @@ $(DASHBOARD_TS_OUT): $(DASHBOARD_TS_SRC)
|
||||
tslib:
|
||||
cd tslib/types && npm i && npm run build
|
||||
cd tslib/storage && npm i && npm run build
|
||||
cd tslib/react && npm i && npm run build
|
||||
|
||||
.PHONY: serve-browser-app
|
||||
serve-browser-app: tslib $(RUSTLIB_OUT)
|
||||
@@ -51,6 +52,6 @@ fmt:
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf tslib/types/pkg tslib/storage/pkg
|
||||
rm -rf tslib/types/pkg tslib/storage/pkg tslib/react/pkg tslib/react/types
|
||||
rm -rf optuna_dashboard/public/ doc/_build/
|
||||
rm -rf rustlib/pkg standalone_app/public/ vscode/assets/ vscode/*.vsix
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
],
|
||||
"ignore": [
|
||||
"optuna_dashboard/ts/components/PlotlyColorTemplates.ts",
|
||||
"standalone_app/src/PlotlyDarkMode.ts",
|
||||
"tslib/react/src/components/PlotlyDarkMode.ts",
|
||||
"tslib/**/pkg/*"
|
||||
]
|
||||
},
|
||||
|
||||
Generated
+629
-3143
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,7 @@
|
||||
"@mui/icons-material": "^5.15.12",
|
||||
"@mui/lab": "^5.0.0-alpha.167",
|
||||
"@mui/material": "^5.15.12",
|
||||
"@optuna/react": "../tslib/react",
|
||||
"@optuna/storage": "../tslib/storage",
|
||||
"module-workers-polyfill": "^0.3.2",
|
||||
"notistack": "^3.0.1",
|
||||
@@ -33,5 +34,8 @@
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.22.3"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-linux-x64-gnu": "^4.13.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Box, Typography, useTheme } from "@mui/material"
|
||||
import { plotlyDarkTemplate } from "@optuna/react"
|
||||
import init, { wasm_fanova_calculate } from "optuna"
|
||||
import * as plotly from "plotly.js-dist-min"
|
||||
import React, { FC, useEffect, useState } from "react"
|
||||
|
||||
import { plotlyDarkTemplate } from "../PlotlyDarkMode"
|
||||
const plotDomId = "graph-hyperparameter-importances"
|
||||
|
||||
export const PlotImportance: FC<{ study: Study }> = ({ study }) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Box, Typography, useTheme } from "@mui/material"
|
||||
import { plotlyDarkTemplate } from "@optuna/react"
|
||||
import * as plotly from "plotly.js-dist-min"
|
||||
import React, { FC, useEffect } from "react"
|
||||
import { plotlyDarkTemplate } from "../PlotlyDarkMode"
|
||||
|
||||
const plotDomId = "graph-intermediate-values"
|
||||
|
||||
|
||||
@@ -13,13 +13,12 @@ import {
|
||||
useTheme,
|
||||
} from "@mui/material"
|
||||
import Grid2 from "@mui/material/Unstable_Grid2"
|
||||
import { PlotHistory, TrialTable } from "@optuna/react"
|
||||
import React, { FC, useContext, useState, useEffect } from "react"
|
||||
import { Link, useParams } from "react-router-dom"
|
||||
import { PlotHistory } from "./PlotHistory"
|
||||
import { PlotImportance } from "./PlotImportance"
|
||||
import { PlotIntermediateValues } from "./PlotIntermediateValues"
|
||||
import { StorageContext } from "./StorageProvider"
|
||||
import { TrialTable } from "./TrialTable"
|
||||
|
||||
export const StudyDetail: FC<{
|
||||
toggleColorMode: () => void
|
||||
|
||||
Vendored
+1
-1
@@ -2,7 +2,7 @@ declare const IS_VSCODE: boolean
|
||||
|
||||
type TrialState = "Running" | "Complete" | "Pruned" | "Fail" | "Waiting"
|
||||
type TrialStateFinished = "Complete" | "Fail" | "Pruned"
|
||||
type StudyDirection = "maximize" | "minimize" | "not_set"
|
||||
type StudyDirection = "maximize" | "minimize"
|
||||
|
||||
type OptunaStorage = {
|
||||
getStudies: () => Promise<StudySummary[]>
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
pkg
|
||||
types
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
# sample db
|
||||
!public/sample_db.sqlite3
|
||||
@@ -0,0 +1,29 @@
|
||||
import type { StorybookConfig } from "@storybook/react-vite"
|
||||
|
||||
const config: StorybookConfig = {
|
||||
stories: ["../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
|
||||
addons: [
|
||||
"@storybook/addon-links",
|
||||
"@storybook/addon-essentials",
|
||||
"@storybook/addon-interactions",
|
||||
],
|
||||
framework: {
|
||||
name: "@storybook/react-vite",
|
||||
options: {},
|
||||
},
|
||||
docs: {
|
||||
autodocs: "tag",
|
||||
},
|
||||
async viteFinal(config) {
|
||||
const { mergeConfig } = await import("vite")
|
||||
return mergeConfig(config, {
|
||||
server: {
|
||||
fs: {
|
||||
// Since storybook overwrites the `allow` option, here we set it for sqlite-wasm
|
||||
allow: [...(config.server?.fs?.allow ?? []), ".."],
|
||||
},
|
||||
},
|
||||
})
|
||||
},
|
||||
}
|
||||
export default config
|
||||
@@ -0,0 +1,14 @@
|
||||
import type { Preview } from "@storybook/react"
|
||||
|
||||
const preview: Preview = {
|
||||
parameters: {
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/i,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export default preview
|
||||
Generated
+10405
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "@optuna/react",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"description": "UI packages for Optuna-Dashboard",
|
||||
"main": "pkg/index.js",
|
||||
"types": "types/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc -d",
|
||||
"storybook": "storybook dev -p 6006"
|
||||
},
|
||||
"files": [
|
||||
"pkg",
|
||||
"types"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/optuna/optuna-dashboard.git"
|
||||
},
|
||||
"author": "Optuna Development Team",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/optuna/optuna-dashboard/issues"
|
||||
},
|
||||
"homepage": "https://github.com/optuna/optuna-dashboard#readme",
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.11.3",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@mui/icons-material": "^5.15.10",
|
||||
"@mui/material": "^5.15.10",
|
||||
"@mui/system": "^5.15.9",
|
||||
"@optuna/storage": "../storage/",
|
||||
"plotly.js-dist-min": "^2.30.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"recoil": "^0.7.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@optuna/types": "../types/",
|
||||
"@storybook/addon-essentials": "^8.0.4",
|
||||
"@storybook/addon-interactions": "^8.0.4",
|
||||
"@storybook/addon-links": "^8.0.4",
|
||||
"@storybook/blocks": "^8.0.4",
|
||||
"@storybook/react": "^8.0.4",
|
||||
"@storybook/react-vite": "^8.0.4",
|
||||
"@storybook/test": "^8.0.4",
|
||||
"@types/plotly.js-dist-min": "^2.3.4",
|
||||
"@types/react": "^18.2.55",
|
||||
"@types/react-dom": "^18.2.19",
|
||||
"@vitejs/plugin-react-swc": "^3.5.0",
|
||||
"storybook": "^8.0.4",
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^5.1.0"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,32 @@
|
||||
import * as Optuna from "@optuna/types"
|
||||
import { useEffect, useState } from "react"
|
||||
import { loadStorageFromFile } from "./utils/loadStorageFromFile"
|
||||
|
||||
const fetchMockStudies = async () => {
|
||||
const filePath = "sample_db.sqlite3"
|
||||
const res = await fetch(filePath)
|
||||
const blob = await res.blob()
|
||||
const file = new File([blob], filePath)
|
||||
const mockStudies: Optuna.Study[] = []
|
||||
await loadStorageFromFile(file, (value) => {
|
||||
if (Array.isArray(value)) {
|
||||
mockStudies.push(...value)
|
||||
} else {
|
||||
mockStudies.push(...value([]))
|
||||
}
|
||||
})
|
||||
return mockStudies
|
||||
}
|
||||
|
||||
const useMockStudies = () => {
|
||||
const [mockStudies, setMockStudies] = useState<Optuna.Study[]>([])
|
||||
useEffect(() => {
|
||||
fetchMockStudies().then((studies) => setMockStudies(studies))
|
||||
}, [])
|
||||
return mockStudies
|
||||
}
|
||||
|
||||
export const useMockStudy = (studyId: number | undefined) => {
|
||||
const mockStudies = useMockStudies()
|
||||
return mockStudies.find((study) => study.study_id === studyId)
|
||||
}
|
||||
+1
-1
@@ -69,7 +69,7 @@ function DataGrid<T>(props: {
|
||||
: rowsPerPageOption[0].value
|
||||
const [rowsPerPage, setRowsPerPage] = React.useState(initialRowsPerPage)
|
||||
|
||||
const handleChangePage = (event: unknown, newPage: number) => {
|
||||
const handleChangePage = (_event: unknown, newPage: number) => {
|
||||
setPage(newPage)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Meta, StoryObj } from "@storybook/react"
|
||||
import { useMockStudy } from "../MockStudies"
|
||||
import { PlotHistory } from "./PlotHistory"
|
||||
|
||||
const meta: Meta<typeof PlotHistory> = {
|
||||
component: PlotHistory,
|
||||
title: "PlotHistory",
|
||||
tags: ["autodocs"],
|
||||
decorators: [
|
||||
(Story, storyContext) => {
|
||||
const study = useMockStudy(storyContext.parameters?.studyId)
|
||||
if (!study) return <p>loading...</p>
|
||||
return (
|
||||
<Story
|
||||
args={{
|
||||
study,
|
||||
}}
|
||||
/>
|
||||
)
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof PlotHistory>
|
||||
|
||||
export const MockStudy1: Story = {
|
||||
parameters: {
|
||||
studyId: 1,
|
||||
},
|
||||
}
|
||||
+13
-9
@@ -13,14 +13,15 @@ import {
|
||||
Typography,
|
||||
useTheme,
|
||||
} from "@mui/material"
|
||||
import * as Optuna from "@optuna/types"
|
||||
import * as plotly from "plotly.js-dist-min"
|
||||
import React, { ChangeEvent, FC, useEffect, useState } from "react"
|
||||
import { plotlyDarkTemplate } from "../PlotlyDarkMode"
|
||||
import { ChangeEvent, FC, useEffect, useState } from "react"
|
||||
import { plotlyDarkTemplate } from "./PlotlyDarkMode"
|
||||
|
||||
const plotDomId = "plot-history"
|
||||
|
||||
export const PlotHistory: FC<{
|
||||
study: Study | null
|
||||
study: Optuna.Study | null
|
||||
}> = ({ study = null }) => {
|
||||
const theme = useTheme()
|
||||
const [xAxis, setXAxis] = useState<string>("number")
|
||||
@@ -90,7 +91,7 @@ export const PlotHistory: FC<{
|
||||
>
|
||||
<FormLabel component="legend">Objective ID:</FormLabel>
|
||||
<Select value={objectiveId} onChange={handleObjectiveChange}>
|
||||
{study.directions.map((d, i) => (
|
||||
{study.directions.map((_d, i) => (
|
||||
// biome-ignore lint/suspicious/noArrayIndexKey: <explanation>
|
||||
<MenuItem value={i} key={i}>
|
||||
{i}
|
||||
@@ -170,7 +171,7 @@ export const PlotHistory: FC<{
|
||||
)
|
||||
}
|
||||
|
||||
const filterFunc = (trial: Trial, objectiveId: number): boolean => {
|
||||
const filterFunc = (trial: Optuna.Trial, objectiveId: number): boolean => {
|
||||
if (trial.state !== "Complete" && trial.state !== "Pruned") {
|
||||
return false
|
||||
}
|
||||
@@ -185,7 +186,7 @@ const filterFunc = (trial: Trial, objectiveId: number): boolean => {
|
||||
}
|
||||
|
||||
const plotHistory = (
|
||||
study: Study,
|
||||
study: Optuna.Study,
|
||||
objectiveId: number,
|
||||
xAxis: string,
|
||||
logScale: boolean,
|
||||
@@ -228,7 +229,7 @@ const plotHistory = (
|
||||
return
|
||||
}
|
||||
|
||||
const getAxisX = (trial: Trial): number | Date => {
|
||||
const getAxisX = (trial: Optuna.Trial): number | Date => {
|
||||
return xAxis === "number"
|
||||
? trial.number
|
||||
: xAxis === "datetime_start"
|
||||
@@ -236,7 +237,10 @@ const plotHistory = (
|
||||
: trial.datetime_complete ?? new Date()
|
||||
}
|
||||
|
||||
const getValue = (trial: Trial, objectiveId: number): number | null => {
|
||||
const getValue = (
|
||||
trial: Optuna.Trial,
|
||||
objectiveId: number
|
||||
): number | null => {
|
||||
if (
|
||||
objectiveId === null ||
|
||||
trial.values === undefined ||
|
||||
@@ -294,7 +298,7 @@ const plotHistory = (
|
||||
{
|
||||
x: filteredTrials.map(getAxisX),
|
||||
y: filteredTrials.map(
|
||||
(t: Trial): number => getValue(t, objectiveId) as number
|
||||
(t: Optuna.Trial): number => getValue(t, objectiveId) as number
|
||||
),
|
||||
name: "Objective Value",
|
||||
mode: "markers",
|
||||
@@ -0,0 +1,38 @@
|
||||
import { ThemeProvider } from "@mui/material"
|
||||
import { Meta, StoryObj } from "@storybook/react"
|
||||
import { useMockStudy } from "../MockStudies"
|
||||
import { darkTheme } from "../styles/darkTheme"
|
||||
import { PlotHistory } from "./PlotHistory"
|
||||
|
||||
const meta: Meta<typeof PlotHistory> = {
|
||||
component: PlotHistory,
|
||||
title: "PlotHistoryDark",
|
||||
tags: ["autodocs"],
|
||||
decorators: [
|
||||
(Story, storyContext) => {
|
||||
const study = useMockStudy(storyContext.parameters?.studyId)
|
||||
if (!study) return <p>loading...</p>
|
||||
return (
|
||||
<ThemeProvider theme={darkTheme}>
|
||||
<Story
|
||||
args={{
|
||||
study,
|
||||
}}
|
||||
/>
|
||||
</ThemeProvider>
|
||||
)
|
||||
},
|
||||
],
|
||||
parameters: {
|
||||
backgrounds: { default: "dark" },
|
||||
},
|
||||
}
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof PlotHistory>
|
||||
|
||||
export const MockStudy1: Story = {
|
||||
parameters: {
|
||||
studyId: 1,
|
||||
},
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,31 @@
|
||||
import { Meta, StoryObj } from "@storybook/react"
|
||||
import { useMockStudy } from "../MockStudies"
|
||||
import { TrialTable } from "./TrialTable"
|
||||
|
||||
const meta: Meta<typeof TrialTable> = {
|
||||
component: TrialTable,
|
||||
title: "TrialTable",
|
||||
tags: ["autodocs"],
|
||||
decorators: [
|
||||
(Story, storyContext) => {
|
||||
const study = useMockStudy(storyContext.parameters?.studyId)
|
||||
if (!study) return <p>loading...</p>
|
||||
return (
|
||||
<Story
|
||||
args={{
|
||||
study,
|
||||
}}
|
||||
/>
|
||||
)
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof TrialTable>
|
||||
|
||||
export const MockStudy1: Story = {
|
||||
parameters: {
|
||||
studyId: 1,
|
||||
},
|
||||
}
|
||||
+13
-15
@@ -1,14 +1,15 @@
|
||||
import React, { FC } from "react"
|
||||
import { FC } from "react"
|
||||
|
||||
import * as Optuna from "@optuna/types"
|
||||
import { DataGrid, DataGridColumn } from "./DataGrid"
|
||||
|
||||
export const TrialTable: FC<{
|
||||
study: Study
|
||||
study: Optuna.Study
|
||||
initialRowsPerPage?: number
|
||||
}> = ({ study, initialRowsPerPage }) => {
|
||||
const trials: Trial[] = study.trials
|
||||
const trials: Optuna.Trial[] = study.trials
|
||||
|
||||
const columns: DataGridColumn<Trial>[] = [
|
||||
const columns: DataGridColumn<Optuna.Trial>[] = [
|
||||
{ field: "number", label: "Number", sortable: true, padding: "none" },
|
||||
{
|
||||
field: "state",
|
||||
@@ -48,8 +49,8 @@ export const TrialTable: FC<{
|
||||
},
|
||||
})
|
||||
} else {
|
||||
const objectiveColumns: DataGridColumn<Trial>[] = study.directions.map(
|
||||
(s, objectiveId) => ({
|
||||
const objectiveColumns: DataGridColumn<Optuna.Trial>[] =
|
||||
study.directions.map((_s, objectiveId) => ({
|
||||
field: "values",
|
||||
label: `Objective ${objectiveId}`,
|
||||
sortable: true,
|
||||
@@ -74,13 +75,11 @@ export const TrialTable: FC<{
|
||||
}
|
||||
return trials[i].values?.[objectiveId]
|
||||
},
|
||||
})
|
||||
)
|
||||
}))
|
||||
columns.push(...objectiveColumns)
|
||||
}
|
||||
|
||||
// biome-ignore lint/complexity/noForEach: <explanation>
|
||||
study.union_search_space.forEach((s) => {
|
||||
for (const s of study.union_search_space) {
|
||||
columns.push({
|
||||
field: "params",
|
||||
label: `Param ${s.name}`,
|
||||
@@ -109,10 +108,9 @@ export const TrialTable: FC<{
|
||||
return 1
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// biome-ignore lint/complexity/noForEach: <explanation>
|
||||
study.union_user_attrs.forEach((attr_spec) => {
|
||||
for (const attr_spec of study.union_user_attrs) {
|
||||
columns.push({
|
||||
field: "user_attrs",
|
||||
label: `UserAttribute ${attr_spec.key}`,
|
||||
@@ -141,10 +139,10 @@ export const TrialTable: FC<{
|
||||
return 1
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<DataGrid<Trial>
|
||||
<DataGrid<Optuna.Trial>
|
||||
columns={columns}
|
||||
rows={trials}
|
||||
keyField={"trial_id"}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { ThemeProvider } from "@mui/material"
|
||||
import { Meta, StoryObj } from "@storybook/react"
|
||||
import { useMockStudy } from "../MockStudies"
|
||||
import { darkTheme } from "../styles/darkTheme"
|
||||
import { TrialTable } from "./TrialTable"
|
||||
|
||||
const meta: Meta<typeof TrialTable> = {
|
||||
component: TrialTable,
|
||||
title: "TrialTableDark",
|
||||
tags: ["autodocs"],
|
||||
decorators: [
|
||||
(Story, storyContext) => {
|
||||
const study = useMockStudy(storyContext.parameters?.studyId)
|
||||
if (!study) return <p>loading...</p>
|
||||
return (
|
||||
<ThemeProvider theme={darkTheme}>
|
||||
<Story
|
||||
args={{
|
||||
study,
|
||||
}}
|
||||
/>
|
||||
</ThemeProvider>
|
||||
)
|
||||
},
|
||||
],
|
||||
parameters: {
|
||||
backgrounds: { default: "dark" },
|
||||
},
|
||||
}
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof TrialTable>
|
||||
|
||||
export const MockStudy1: Story = {
|
||||
parameters: {
|
||||
studyId: 1,
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export { DataGrid } from "./components/DataGrid"
|
||||
export type { DataGridColumn } from "./components/DataGrid"
|
||||
export { PlotHistory } from "./components/PlotHistory"
|
||||
export { TrialTable } from "./components/TrialTable"
|
||||
export { plotlyDarkTemplate } from "./components/PlotlyDarkMode"
|
||||
@@ -0,0 +1,7 @@
|
||||
import { createTheme } from "@mui/material"
|
||||
|
||||
export const darkTheme = createTheme({
|
||||
palette: {
|
||||
mode: "dark",
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,45 @@
|
||||
import { JournalFileStorage, SQLite3Storage } from "@optuna/storage"
|
||||
import * as Optuna from "@optuna/types"
|
||||
import { SetterOrUpdater } from "recoil"
|
||||
|
||||
const readFile = async (file: File) => {
|
||||
return new Promise<ArrayBuffer>((resolve, reject) => {
|
||||
const reader = new FileReader()
|
||||
reader.addEventListener("load", () => {
|
||||
const arrayBuffer = reader.result as ArrayBuffer | null
|
||||
if (arrayBuffer !== null) {
|
||||
resolve(arrayBuffer)
|
||||
} else {
|
||||
reject(new Error("Failed to load file"))
|
||||
}
|
||||
})
|
||||
reader.readAsArrayBuffer(file)
|
||||
})
|
||||
}
|
||||
|
||||
const loadStudiesFromStorage = async (
|
||||
storage: SQLite3Storage | JournalFileStorage,
|
||||
setter: SetterOrUpdater<Optuna.Study[]>
|
||||
) => {
|
||||
const studySummaries = await storage.getStudies()
|
||||
const studies = (
|
||||
await Promise.all(
|
||||
studySummaries.map((_summary, index) => storage.getStudy(index))
|
||||
)
|
||||
).filter((s) => s !== null) as Optuna.Study[]
|
||||
setter((prev) => [...prev, ...studies])
|
||||
}
|
||||
|
||||
export const loadStorageFromFile = async (
|
||||
file: File,
|
||||
setStudies: SetterOrUpdater<Optuna.Study[]>
|
||||
) => {
|
||||
const arrayBuf = await readFile(file)
|
||||
const header = new Uint8Array(arrayBuf, 0, 16)
|
||||
const headerString = new TextDecoder().decode(header)
|
||||
if (headerString === "SQLite format 3\u0000") {
|
||||
await loadStudiesFromStorage(new SQLite3Storage(arrayBuf), setStudies)
|
||||
} else {
|
||||
await loadStudiesFromStorage(new JournalFileStorage(arrayBuf), setStudies)
|
||||
}
|
||||
}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"isolatedModules": true,
|
||||
"skipLibCheck": true,
|
||||
"strictNullChecks": true,
|
||||
"moduleResolution": "Node",
|
||||
"noUnusedLocals": true,
|
||||
"noImplicitThis": true,
|
||||
"alwaysStrict": true,
|
||||
"noImplicitAny": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"esModuleInterop": true,
|
||||
"rootDir": "./src",
|
||||
"outDir": "./pkg",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"target": "ES2020",
|
||||
"sourceMap": true,
|
||||
"declaration": true,
|
||||
"declarationDir": "./types",
|
||||
"strict": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx"],
|
||||
"exclude": [
|
||||
"src/**/*.stories.tsx",
|
||||
"src/**/*.stories.ts",
|
||||
"src/MockStudies.ts",
|
||||
"src/utils/loadStorageFromFile.ts"
|
||||
],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import react from "@vitejs/plugin-react-swc"
|
||||
import { defineConfig } from "vite"
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
optimizeDeps: {
|
||||
exclude: ["@sqlite.org/sqlite-wasm"],
|
||||
},
|
||||
server: {
|
||||
headers: {
|
||||
"Cross-Origin-Opener-Policy": "same-origin",
|
||||
"Cross-Origin-Embedder-Policy": "require-corp",
|
||||
},
|
||||
},
|
||||
})
|
||||
Reference in New Issue
Block a user