Merge remote-tracking branch 'upstream/main'

This commit is contained in:
Harman Waseer committed 2021-02-23 18:17:05 +05:30
commit f762c49cbe
19 files changed
+1059 -70

No files matched your search

+14
View File
@@ -0,0 +1,14 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint',
],
rules: {
"@typescript-eslint/ban-ts-comment": "off"
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
],
};
+1 -1
View File
@@ -1,7 +1,7 @@
---
name: "Bug report"
about: Create a bug report to improve optuna-dashboard
title: "[Bug]"
title: ""
labels: bug
assignees: ''
+1 -1
View File
@@ -1,7 +1,7 @@
---
name: "Feature request"
about: Suggest an idea for new features in optuna-dashboard.
title: "[Feature]"
title: ""
labels: enhancement
assignees: ''
+1
View File
@@ -3,6 +3,7 @@ on:
pull_request:
paths:
- '.github/workflows/typescript-checks.yml'
- '.eslintrc.js'
- '**.ts'
- '**.tsx'
jobs:
-6
View File
@@ -68,9 +68,3 @@ You can walk-through trials by filtering and sorting.
## Submitting patches
If you want to contribute, please check [Developers Guide](./DEVELOPMENT.md).
## Alternatives
* ['optuna dashboard' subcommand](https://optuna.readthedocs.io/en/stable/reference/cli.html#dashboard): Official Optuna dashboard based on Bokeh CLI.
* [ytsmiling/optdash](https://github.com/ytsmiling/optdash): a third-party dashboard for optuna.
+1 -1
View File
@@ -37,7 +37,7 @@ export const actionCreator = () => {
const updateStudyDetail = (studyId: number) => {
getStudyDetailAPI(studyId)
.then((study) => {
let newVal = Object.assign({}, studyDetails)
const newVal = Object.assign({}, studyDetails)
newVal[studyId] = study
setStudyDetails(newVal)
})
+2 -2
View File
@@ -161,8 +161,8 @@ export const createNewStudyAPI = (
})
}
export const deleteStudyAPI = (studyId: number): Promise<{}> => {
return axiosInstance.delete<{}>(`/api/studies/${studyId}`).then((res) => {
export const deleteStudyAPI = (studyId: number) => {
return axiosInstance.delete(`/api/studies/${studyId}`).then((res) => {
return {}
})
}
+1 -1
View File
@@ -6,7 +6,7 @@ import { SnackbarProvider } from "notistack"
import { StudyDetail } from "./StudyDetail"
import { StudyList } from "./StudyList"
export const App: FC<{}> = () => {
export const App: FC = () => {
return (
<RecoilRoot>
<SnackbarProvider maxSnack={3}>
+38 -17
View File
@@ -48,6 +48,7 @@ interface DataGridColumn<T> {
field: keyof T
label: string
sortable?: boolean
less?: (i: number, j: number) => number
filterable?: boolean
toCellValue?: (rowIndex: number) => string | React.ReactNode
padding?: "default" | "checkbox" | "none"
@@ -71,7 +72,7 @@ function DataGrid<T>(props: {
const { columns, rows, keyField, dense, collapseBody } = props
let { initialRowsPerPage, rowsPerPageOption } = props
const [order, setOrder] = React.useState<Order>("asc")
const [orderBy, setOrderBy] = React.useState<keyof T>(keyField)
const [orderBy, setOrderBy] = React.useState<number>(0) // index of columns
const [page, setPage] = React.useState(0)
const [filters, setFilters] = React.useState<RowFilter<T>[]>([])
@@ -124,14 +125,14 @@ function DataGrid<T>(props: {
)
// Sorting
const createSortHandler = (property: keyof T) => (
const createSortHandler = (columnId: number) => (
event: React.MouseEvent<unknown>
) => {
const isAsc = orderBy === property && order === "asc"
const isAsc = orderBy === columnId && order === "asc"
setOrder(isAsc ? "desc" : "asc")
setOrderBy(property)
setOrderBy(columnId)
}
const sortedRows = stableSort<T>(filteredRows, getComparator(order, orderBy))
const sortedRows = stableSort<T>(filteredRows, order, orderBy, columns)
const currentPageRows =
rowsPerPage > 0
? sortedRows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
@@ -158,9 +159,9 @@ function DataGrid<T>(props: {
>
{column.sortable ? (
<TableSortLabel
active={orderBy === column.field}
direction={orderBy === column.field ? order : "asc"}
onClick={createSortHandler(column.field)}
active={orderBy === index}
direction={orderBy === index ? order : "asc"}
onClick={createSortHandler(index)}
>
{column.label}
{orderBy === column.field ? (
@@ -300,28 +301,48 @@ function DataGridRow<T>(props: {
function getComparator<T>(
order: Order,
orderBy: keyof T
columns: DataGridColumn<T>[],
orderBy: number
): (a: T, b: T) => number {
return order === "desc"
? (a, b) => descendingComparator<T>(a, b, orderBy)
: (a, b) => -descendingComparator<T>(a, b, orderBy)
? (a, b) => descendingComparator<T>(a, b, columns, orderBy)
: (a, b) => -descendingComparator<T>(a, b, columns, orderBy)
}
function descendingComparator<T>(a: T, b: T, orderBy: keyof T) {
if (b[orderBy] < a[orderBy]) {
function descendingComparator<T>(
a: T,
b: T,
columns: DataGridColumn<T>[],
orderBy: number
): number {
const field = columns[orderBy].field
if (b[field] < a[field]) {
return -1
}
if (b[orderBy] > a[orderBy]) {
if (b[field] > a[field]) {
return 1
}
return 0
}
function stableSort<T>(array: T[], comparator: (a: T, b: T) => number) {
function stableSort<T>(
array: T[],
order: Order,
orderBy: number,
columns: DataGridColumn<T>[]
) {
// TODO(c-bata): Refactor here by implementing as the same comparator interface.
const less = columns[orderBy].less
const comparator = getComparator(order, columns, orderBy)
const stabilizedThis = array.map((el, index) => [el, index] as [T, number])
stabilizedThis.sort((a, b) => {
const order = comparator(a[0], b[0])
if (order !== 0) return order
if (less) {
const result = order == "asc" ? -less(a[1], b[1]) : less(a[1], b[1])
if (result !== 0) return result
} else {
const result = comparator(a[0], b[0])
if (result !== 0) return result
}
return a[1] - b[1]
})
return stabilizedThis.map((el) => el[0])
@@ -1,4 +1,4 @@
import * as plotly from "plotly.js-dist"
import * as plotly from "plotly.js-basic-dist"
import React, { ChangeEvent, FC, useEffect, useState } from "react"
import {
Grid,
@@ -199,7 +199,7 @@ const plotHistory = (
plotly.react(plotDomId, [])
return
}
let trialsForLinePlot: Trial[] = []
const trialsForLinePlot: Trial[] = []
let currentBest: number | null = null
filteredTrials.forEach((item) => {
if (currentBest === null) {
@@ -228,9 +228,9 @@ const plotHistory = (
: trial.datetime_complete!
}
let xForLinePlot = trialsForLinePlot.map(getAxisX)
const xForLinePlot = trialsForLinePlot.map(getAxisX)
xForLinePlot.push(getAxisX(filteredTrials[filteredTrials.length - 1]))
let yForLinePlot = trialsForLinePlot.map(
const yForLinePlot = trialsForLinePlot.map(
(t: Trial): number => t.values![objectiveId]
)
yForLinePlot.push(yForLinePlot[yForLinePlot.length - 1])
@@ -1,4 +1,4 @@
import * as plotly from "plotly.js-dist"
import * as plotly from "plotly.js-basic-dist"
import React, { FC, useEffect } from "react"
const plotDomId = "graph-intermediate-values"
@@ -30,7 +30,7 @@ const plotIntermediateValue = (trials: Trial[]) => {
return
}
let filteredTrials = trials.filter(
const filteredTrials = trials.filter(
(t) => t.state === "Complete" || t.state === "Pruned"
)
const plotData: Partial<plotly.PlotData>[] = filteredTrials.map((trial) => {
@@ -1,4 +1,4 @@
import * as plotly from "plotly.js-dist"
import * as plotly from "plotly.js-basic-dist"
import React, { FC, useEffect } from "react"
const plotDomId = "graph-parallel-coordinate"
@@ -30,7 +30,7 @@ const plotCoordinate = (trials: Trial[], objectiveId: number) => {
plotly.react(plotDomId, [])
return
}
let filteredTrials = trials.filter(
const filteredTrials = trials.filter(
(t) => t.state === "Complete" || t.state === "Pruned"
)
@@ -50,7 +50,7 @@ const plotCoordinate = (trials: Trial[], objectiveId: number) => {
const objectiveValues: number[] = filteredTrials.map(
(t) => t.values![objectiveId]
)
let dimensions = [
const dimensions = [
{
label: "Objective value",
values: objectiveValues,
@@ -92,7 +92,7 @@ export const useStudyDetailValue = (studyId: number): StudyDetail | null => {
return studyDetails[studyId] || null
}
export const StudyDetail: FC<{}> = () => {
export const StudyDetail: FC = () => {
const classes = useStyles()
const action = actionCreator()
const { studyId } = useParams<ParamTypes>()
@@ -129,7 +129,7 @@ export const StudyDetail: FC<{}> = () => {
<div className={classes.grow} />
<div
className={classes.reload}
onClick={(e) => {
onClick={() => {
setOpenReloadIntervalSelect(!openReloadIntervalSelect)
}}
>
@@ -221,7 +221,7 @@ const TrialTable: FC<{ studyDetail: StudyDetail | null }> = ({
}) => {
const trials: Trial[] = studyDetail !== null ? studyDetail.trials : []
let columns: DataGridColumn<Trial>[] = [
const columns: DataGridColumn<Trial>[] = [
{ field: "number", label: "Number", sortable: true, padding: "none" },
{
field: "state",
@@ -237,7 +237,26 @@ const TrialTable: FC<{ studyDetail: StudyDetail | null }> = ({
field: "values",
label: "Value",
sortable: true,
toCellValue: (i) => trials[i].values?.[0] || null,
less: (i, j): number => {
const firstVal = trials[i].values?.[0]
const secondVal = trials[j].values?.[0]
if (firstVal === secondVal) {
return 0
} else if (firstVal && secondVal) {
return firstVal < secondVal ? 1 : -1
} else if (firstVal) {
return -1
} else {
return 1
}
},
toCellValue: (i) => {
if (trials[i].values === undefined) {
return null
}
return trials[i].values?.[0]
},
})
} else {
const objectiveColumns: DataGridColumn<
@@ -246,7 +265,26 @@ const TrialTable: FC<{ studyDetail: StudyDetail | null }> = ({
field: "values",
label: `Objective ${objectiveId}`,
sortable: true,
toCellValue: (i) => trials[i].values?.[objectiveId] || null,
less: (i, j): number => {
const firstVal = trials[i].values?.[objectiveId]
const secondVal = trials[j].values?.[objectiveId]
if (firstVal === secondVal) {
return 0
} else if (firstVal && secondVal) {
return firstVal < secondVal ? 1 : -1
} else if (firstVal) {
return -1
} else {
return 1
}
},
toCellValue: (i) => {
if (trials[i].values === undefined) {
return null
}
return trials[i].values?.[objectiveId]
},
}))
columns.push(...objectiveColumns)
}
@@ -46,7 +46,7 @@ const useStyles = makeStyles((theme: Theme) =>
})
)
export const StudyList: FC<{}> = () => {
export const StudyList: FC = () => {
const classes = useStyles()
const [
@@ -127,7 +127,7 @@ export const StudyList: FC<{}> = () => {
aria-label="delete study"
size="small"
color="inherit"
onClick={(e) => {
onClick={() => {
setDeleteStudyID(studies[i].study_id)
setOpenDeleteStudyDialog(true)
}}
@@ -226,7 +226,7 @@ export const StudyList: FC<{}> = () => {
<IconButton
aria-controls="menu-appbar"
aria-haspopup="true"
onClick={(e) => {
onClick={() => {
action.updateStudySummaries("Success to reload")
}}
color="inherit"
@@ -256,12 +256,12 @@ export const StudyList: FC<{}> = () => {
horizontal: "right",
}}
open={openNewStudySelection}
onClose={(e) => {
onClose={() => {
setNewStudySelectionAnchorEl(null)
}}
>
<MenuItem
onClick={(e) => {
onClick={() => {
setNewStudySelectionAnchorEl(null)
setOpenNewSingleObjectiveStudyDialog(true)
}}
@@ -269,7 +269,7 @@ export const StudyList: FC<{}> = () => {
Single-objective
</MenuItem>
<MenuItem
onClick={(e) => {
onClick={() => {
setNewStudySelectionAnchorEl(null)
setOpenNewMultiObjectiveStudyDialog(true)
}}
@@ -294,7 +294,7 @@ export const StudyList: FC<{}> = () => {
</Container>
<Dialog
open={openNewSingleObjectiveStudyDialog}
onClose={(e) => {
onClose={() => {
handleCloseNewSingleObjectiveStudyDialog()
}}
aria-labelledby="create-single-objective-study-form-dialog-title"
@@ -323,7 +323,7 @@ export const StudyList: FC<{}> = () => {
control={
<Checkbox
checked={maximize}
onChange={(e) => {
onChange={() => {
setMaximize(!maximize)
}}
color="primary"
@@ -350,7 +350,7 @@ export const StudyList: FC<{}> = () => {
</Dialog>
<Dialog
open={openNewMultiObjectiveStudyDialog}
onClose={(e) => {
onClose={() => {
handleCloseNewMultiObjectiveStudyDialog()
}}
aria-labelledby="create-multi-objective-study-form-dialog-title"
@@ -384,7 +384,7 @@ export const StudyList: FC<{}> = () => {
<Select
value={directions[i]}
onChange={(e) => {
let newVal: StudyDirection[] = [...directions]
const newVal: StudyDirection[] = [...directions]
newVal[i] = e.target.value as StudyDirection
setDirections(newVal)
}}
@@ -400,7 +400,7 @@ export const StudyList: FC<{}> = () => {
variant="outlined"
startIcon={<Add />}
className={classes.objectiveButton}
onClick={(e) => {
onClick={() => {
const newVal: StudyDirection[] = [...directions, "minimize"]
setDirections(newVal)
}}
@@ -412,8 +412,8 @@ export const StudyList: FC<{}> = () => {
startIcon={<Remove />}
className={classes.objectiveButton}
disabled={directions.length <= 1}
onClick={(e) => {
let newVal: StudyDirection[] = [...directions]
onClick={() => {
const newVal: StudyDirection[] = [...directions]
newVal.pop()
setDirections(newVal)
}}
@@ -443,7 +443,7 @@ export const StudyList: FC<{}> = () => {
</Dialog>
<Dialog
open={openDeleteStudyDialog}
onClose={(e) => {
onClose={() => {
handleCloseDeleteStudyDialog()
}}
aria-labelledby="delete-study-dialog-title"
+1 -1
View File
@@ -1 +1 @@
__version__ = "0.2.2"
__version__ = "0.2.3"
+925 -7
View File
File diff suppressed because it is too large. Load diff
+6 -3
View File
@@ -6,7 +6,7 @@
"main": "index.js",
"scripts": {
"fmt": "prettier --write \"optuna_dashboard/static/**/*.{ts,tsx}\"",
"lint": "prettier --list-different \"optuna_dashboard/static/**/*.{ts,tsx}\"",
"lint": "eslint . --ext .ts,.tsx && prettier --list-different \"optuna_dashboard/static/**/*.{ts,tsx}\"",
"watch": "webpack --watch",
"build": "webpack",
"build:dev": "NODE_ENV=development webpack",
@@ -19,7 +19,7 @@
"@material-ui/icons": "^4.9.1",
"axios": "^0.21.1",
"notistack": "^1.0.1",
"plotly.js-dist": "^1.57.0",
"plotly.js-basic-dist": "^1.58.4",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"react-router-dom": "^5.2.0",
@@ -31,9 +31,12 @@
"@types/react": "^16.9.53",
"@types/react-dom": "^16.9.8",
"@types/react-router-dom": "^5.1.6",
"@typescript-eslint/eslint-plugin": "^4.15.0",
"@typescript-eslint/parser": "^4.15.0",
"eslint": "^7.19.0",
"prettier": "^2.1.2",
"ts-loader": "^8.0.6",
"typescript": "^4.0.3",
"typescript": "^4.1.4",
"webpack": "^5.1.3",
"webpack-cli": "^4.1.0"
}
+1 -1
View File
@@ -38,7 +38,7 @@ setup(
long_description_content_type="text/markdown",
author="Masashi Shibata",
author_email="m.shibata1020@gmail.com",
url="https://github.com/c-bata/optuna-dashboard",
url="https://github.com/optuna/optuna-dashboard",
packages=find_packages(),
install_requires=get_install_requires(),
extras_require={
+1 -1
View File
@@ -8,7 +8,7 @@
"alwaysStrict": true,
"outDir": "./optuna_dashboard/public/",
"paths": {
"plotly.js-dist": ["node_modules/@types/plotly.js"]
"plotly.js-basic-dist": ["node_modules/@types/plotly.js"]
},
"noImplicitAny": true,
"lib": ["dom", "esnext"],