diff --git a/optuna_dashboard/static/action.ts b/optuna_dashboard/static/action.ts
index 5f1061c9..4f398497 100644
--- a/optuna_dashboard/static/action.ts
+++ b/optuna_dashboard/static/action.ts
@@ -5,6 +5,7 @@ import {
getStudySummariesAPI,
createNewStudyAPI,
deleteStudyAPI,
+ saveNoteAPI,
} from "./apiClient"
import { studyDetailsState, studySummariesState } from "./state"
@@ -95,11 +96,32 @@ export const actionCreator = () => {
})
}
+ const saveNote = (studyId: number, note: Note) => {
+ saveNoteAPI(studyId, note)
+ .then(() => {
+ const newStudy = Object.assign({}, studyDetails[studyId])
+ newStudy.note = note
+ const newStudies = Object.assign({}, studyDetails)
+ newStudies[studyId] = newStudy
+ setStudyDetails(newStudies)
+ enqueueSnackbar(`Success to save the note`, {
+ variant: "success",
+ })
+ })
+ .catch((err) => {
+ const reason = err.response?.data.reason
+ enqueueSnackbar(`Failed: ${reason}`, {
+ variant: "error",
+ })
+ })
+ }
+
return {
updateStudyDetail,
updateStudySummaries,
createNewStudy,
deleteStudy,
+ saveNote,
}
}
diff --git a/optuna_dashboard/static/components/Note.tsx b/optuna_dashboard/static/components/Note.tsx
index 2b2a7f3a..0e01d1a9 100644
--- a/optuna_dashboard/static/components/Note.tsx
+++ b/optuna_dashboard/static/components/Note.tsx
@@ -1,18 +1,91 @@
-import {Card, CardContent, useTheme, TextField} from "@mui/material";
-import React, {FC} from "react";
+import { Box, Button, TextField, Typography, useTheme } from "@mui/material"
+import React, { FC, createRef, useState, useEffect } from "react"
+import LoadingButton from "@mui/lab/LoadingButton"
+import SaveIcon from "@mui/icons-material/Save"
+import { actionCreator } from "../action"
-export const Note: FC<{studyId: number}> = ({studyId}) => {
- const theme = useTheme()
- return (
- = ({ studyId, latestNote }) => {
+ const theme = useTheme()
+ const [disable, setDisable] = useState(true)
+ const [curNote, setCurNote] = useState({ version: 0, body: "" })
+ const textAreaRef = createRef()
+ const action = actionCreator()
+ const notLatest = latestNote.version > curNote.version
+
+ useEffect(() => {
+ setCurNote(latestNote)
+ }, [])
+ const handleSave = () => {
+ const newNote = {
+ version: curNote.version + 1,
+ body: textAreaRef.current ? textAreaRef.current.value : ""
+ }
+ setCurNote(newNote)
+ action.saveNote(studyId, newNote)
+ }
+ const handleRefresh = () => {
+ if (!textAreaRef.current) {
+ console.log("Unexpectedly, textarea is not found.")
+ return
+ }
+ textAreaRef.current.value = latestNote.body
+ setCurNote(latestNote)
+ }
+
+ return (
+ <>
+ {
+ const cur = textAreaRef.current ? textAreaRef.current.value : ""
+ setDisable(cur === latestNote.body)
+ }}
+ />
+
+ {notLatest && (
+ <>
+
+ The text you are editing has updated. Do you want to discard your
+ changes and refresh the textarea?
+
+
+ >
+ )}
+
+ }
+ variant="contained"
+ disabled={disable}
>
-
-
-
-
- )
-}
\ No newline at end of file
+ Save
+
+
+ >
+ )
+}
diff --git a/optuna_dashboard/static/components/StudyDetail.tsx b/optuna_dashboard/static/components/StudyDetail.tsx
index b7f4abc4..1796bcec 100644
--- a/optuna_dashboard/static/components/StudyDetail.tsx
+++ b/optuna_dashboard/static/components/StudyDetail.tsx
@@ -37,6 +37,7 @@ import { GraphIntermediateValues } from "./GraphIntermediateValues"
import { GraphSlice } from "./GraphSlice"
import { GraphHistory } from "./GraphHistory"
import { GraphParetoFront } from "./GraphParetoFront"
+import { Note } from "./Note"
import { actionCreator } from "../action"
import { studyDetailsState } from "../state"
@@ -382,6 +383,14 @@ export const StudyDetail: FC<{
+
+
+ Note
+ {studyDetail !== null && (
+
+ )}
+
+
diff --git a/package-lock.json b/package-lock.json
index 90d2df10..4c468579 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,6 +10,7 @@
"license": "MIT",
"dependencies": {
"@mui/icons-material": "^5.4.4",
+ "@mui/lab": "^5.0.0-alpha.73",
"@mui/material": "^5.4.4",
"axios": "^0.21.2",
"notistack": "^2.0.3",
@@ -2740,6 +2741,75 @@
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
"dev": true
},
+ "node_modules/@date-io/core": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/@date-io/core/-/core-2.13.1.tgz",
+ "integrity": "sha512-pVI9nfkf2qClb2Cxdq0Q4zJhdawMG4ybWZUVGifT78FDwzRMX2SwXBb55s5NRJk0HcIicDuxktmCtemZqMH1Zg=="
+ },
+ "node_modules/@date-io/date-fns": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/@date-io/date-fns/-/date-fns-2.13.1.tgz",
+ "integrity": "sha512-8fmfwjiLMpFLD+t4NBwDx0eblWnNcgt4NgfT/uiiQTGI81fnPu9tpBMYdAcuWxaV7LLpXgzLBx1SYWAMDVUDQQ==",
+ "dependencies": {
+ "@date-io/core": "^2.13.1"
+ },
+ "peerDependencies": {
+ "date-fns": "^2.0.0"
+ },
+ "peerDependenciesMeta": {
+ "date-fns": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@date-io/dayjs": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/@date-io/dayjs/-/dayjs-2.13.1.tgz",
+ "integrity": "sha512-5bL4WWWmlI4uGZVScANhHJV7Mjp93ec2gNeUHDqqLaMZhp51S0NgD25oqj/k0LqBn1cdU2MvzNpk/ObMmVv5cQ==",
+ "dependencies": {
+ "@date-io/core": "^2.13.1"
+ },
+ "peerDependencies": {
+ "dayjs": "^1.8.17"
+ },
+ "peerDependenciesMeta": {
+ "dayjs": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@date-io/luxon": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/@date-io/luxon/-/luxon-2.13.1.tgz",
+ "integrity": "sha512-yG+uM7lXfwLyKKEwjvP8oZ7qblpmfl9gxQYae55ifbwiTs0CoCTkYkxEaQHGkYtTqGTzLqcb0O9Pzx6vgWg+yg==",
+ "dependencies": {
+ "@date-io/core": "^2.13.1"
+ },
+ "peerDependencies": {
+ "luxon": "^1.21.3 || ^2.x"
+ },
+ "peerDependenciesMeta": {
+ "luxon": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@date-io/moment": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/@date-io/moment/-/moment-2.13.1.tgz",
+ "integrity": "sha512-XX1X/Tlvl3TdqQy2j0ZUtEJV6Rl8tOyc5WOS3ki52He28Uzme4Ro/JuPWTMBDH63weSWIZDlbR7zBgp3ZA2y1A==",
+ "dependencies": {
+ "@date-io/core": "^2.13.1"
+ },
+ "peerDependencies": {
+ "moment": "^2.24.0"
+ },
+ "peerDependenciesMeta": {
+ "moment": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@discoveryjs/json-ext": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz",
@@ -3681,6 +3751,91 @@
}
}
},
+ "node_modules/@mui/lab": {
+ "version": "5.0.0-alpha.73",
+ "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.73.tgz",
+ "integrity": "sha512-10Uj0Atc7gBTXKX4VV38P6RdqTQrJZxcl3HeEcytIO1S3NAGfc7gZ3Hdpnhtj5U8kcRJZZPH9LtrBbMZzxU/1A==",
+ "dependencies": {
+ "@babel/runtime": "^7.17.2",
+ "@date-io/date-fns": "^2.13.1",
+ "@date-io/dayjs": "^2.13.1",
+ "@date-io/luxon": "^2.13.1",
+ "@date-io/moment": "^2.13.1",
+ "@mui/base": "5.0.0-alpha.72",
+ "@mui/system": "^5.5.1",
+ "@mui/utils": "^5.4.4",
+ "clsx": "^1.1.1",
+ "prop-types": "^15.7.2",
+ "react-is": "^17.0.2",
+ "react-transition-group": "^4.4.2",
+ "rifm": "^0.12.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "@mui/material": "^5.0.0",
+ "@types/react": "^16.8.6 || ^17.0.0",
+ "date-fns": "^2.25.0",
+ "dayjs": "^1.10.7",
+ "luxon": "^1.28.0 || ^2.0.0",
+ "moment": "^2.29.1",
+ "react": "^17.0.0",
+ "react-dom": "^17.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "date-fns": {
+ "optional": true
+ },
+ "dayjs": {
+ "optional": true
+ },
+ "luxon": {
+ "optional": true
+ },
+ "moment": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/lab/node_modules/@mui/base": {
+ "version": "5.0.0-alpha.72",
+ "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.72.tgz",
+ "integrity": "sha512-WCAooa9eqbsC68LhyKtDBRumH4hV1eRZ0A3SDKFHSwYG9fCOdsFv/H1dIYRJM0rwD45bMnuDiG3Qmx7YsTiptw==",
+ "dependencies": {
+ "@babel/runtime": "^7.17.2",
+ "@emotion/is-prop-valid": "^1.1.2",
+ "@mui/utils": "^5.4.4",
+ "@popperjs/core": "^2.11.3",
+ "clsx": "^1.1.1",
+ "prop-types": "^15.7.2",
+ "react-is": "^17.0.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "@types/react": "^16.8.6 || ^17.0.0",
+ "react": "^17.0.0",
+ "react-dom": "^17.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@mui/material": {
"version": "5.4.4",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.4.4.tgz",
@@ -3782,17 +3937,17 @@
}
},
"node_modules/@mui/system": {
- "version": "5.4.4",
- "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.4.4.tgz",
- "integrity": "sha512-Zjbztq2o/VRuRRCWjG44juRrPKYLQMqtQpMHmMttGu5BnvK6PAPW3WOY0r1JCAwLhbd8Kug9nyhGQYKETjo+tQ==",
+ "version": "5.5.1",
+ "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.5.1.tgz",
+ "integrity": "sha512-2hynI4hN8304hOCT8sc4knJviwUUYJ7XK3mXwQ0nagVGOPnWSOad/nYADm7K0vdlCeUXLIbDbe7oNN3Kaiu2kA==",
"dependencies": {
"@babel/runtime": "^7.17.2",
"@mui/private-theming": "^5.4.4",
"@mui/styled-engine": "^5.4.4",
- "@mui/types": "^7.1.2",
+ "@mui/types": "^7.1.3",
"@mui/utils": "^5.4.4",
"clsx": "^1.1.1",
- "csstype": "^3.0.10",
+ "csstype": "^3.0.11",
"prop-types": "^15.7.2"
},
"engines": {
@@ -3821,9 +3976,9 @@
}
},
"node_modules/@mui/types": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.1.2.tgz",
- "integrity": "sha512-SD7O1nVzqG+ckQpFjDhXPZjRceB8HQFHEvdLLrPhlJy4lLbwEBbxK74Tj4t6Jgk0fTvLJisuwOutrtYe9P/xBQ==",
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.1.3.tgz",
+ "integrity": "sha512-DDF0UhMBo4Uezlk+6QxrlDbchF79XG6Zs0zIewlR4c0Dt6GKVFfUtzPtHCH1tTbcSlq/L2bGEdiaoHBJ9Y1gSA==",
"peerDependencies": {
"@types/react": "*"
},
@@ -3891,9 +4046,9 @@
}
},
"node_modules/@popperjs/core": {
- "version": "2.11.2",
- "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz",
- "integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==",
+ "version": "2.11.4",
+ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.4.tgz",
+ "integrity": "sha512-q/ytXxO5NKvyT37pmisQAItCFqA7FD/vNb8dgaJy3/630Fsc+Mz9/9f2SziBoIZ30TJooXyTwZmhi1zjXmObYg==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
@@ -10287,6 +10442,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/rifm": {
+ "version": "0.12.1",
+ "resolved": "https://registry.npmjs.org/rifm/-/rifm-0.12.1.tgz",
+ "integrity": "sha512-OGA1Bitg/dSJtI/c4dh90svzaUPt228kzFsUkJbtA2c964IqEAwWXeL9ZJi86xWv3j5SMqRvGULl7bA6cK0Bvg==",
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
"node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
@@ -13674,6 +13837,43 @@
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
"dev": true
},
+ "@date-io/core": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/@date-io/core/-/core-2.13.1.tgz",
+ "integrity": "sha512-pVI9nfkf2qClb2Cxdq0Q4zJhdawMG4ybWZUVGifT78FDwzRMX2SwXBb55s5NRJk0HcIicDuxktmCtemZqMH1Zg=="
+ },
+ "@date-io/date-fns": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/@date-io/date-fns/-/date-fns-2.13.1.tgz",
+ "integrity": "sha512-8fmfwjiLMpFLD+t4NBwDx0eblWnNcgt4NgfT/uiiQTGI81fnPu9tpBMYdAcuWxaV7LLpXgzLBx1SYWAMDVUDQQ==",
+ "requires": {
+ "@date-io/core": "^2.13.1"
+ }
+ },
+ "@date-io/dayjs": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/@date-io/dayjs/-/dayjs-2.13.1.tgz",
+ "integrity": "sha512-5bL4WWWmlI4uGZVScANhHJV7Mjp93ec2gNeUHDqqLaMZhp51S0NgD25oqj/k0LqBn1cdU2MvzNpk/ObMmVv5cQ==",
+ "requires": {
+ "@date-io/core": "^2.13.1"
+ }
+ },
+ "@date-io/luxon": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/@date-io/luxon/-/luxon-2.13.1.tgz",
+ "integrity": "sha512-yG+uM7lXfwLyKKEwjvP8oZ7qblpmfl9gxQYae55ifbwiTs0CoCTkYkxEaQHGkYtTqGTzLqcb0O9Pzx6vgWg+yg==",
+ "requires": {
+ "@date-io/core": "^2.13.1"
+ }
+ },
+ "@date-io/moment": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/@date-io/moment/-/moment-2.13.1.tgz",
+ "integrity": "sha512-XX1X/Tlvl3TdqQy2j0ZUtEJV6Rl8tOyc5WOS3ki52He28Uzme4Ro/JuPWTMBDH63weSWIZDlbR7zBgp3ZA2y1A==",
+ "requires": {
+ "@date-io/core": "^2.13.1"
+ }
+ },
"@discoveryjs/json-ext": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz",
@@ -14375,6 +14575,42 @@
"@babel/runtime": "^7.17.2"
}
},
+ "@mui/lab": {
+ "version": "5.0.0-alpha.73",
+ "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.73.tgz",
+ "integrity": "sha512-10Uj0Atc7gBTXKX4VV38P6RdqTQrJZxcl3HeEcytIO1S3NAGfc7gZ3Hdpnhtj5U8kcRJZZPH9LtrBbMZzxU/1A==",
+ "requires": {
+ "@babel/runtime": "^7.17.2",
+ "@date-io/date-fns": "^2.13.1",
+ "@date-io/dayjs": "^2.13.1",
+ "@date-io/luxon": "^2.13.1",
+ "@date-io/moment": "^2.13.1",
+ "@mui/base": "5.0.0-alpha.72",
+ "@mui/system": "^5.5.1",
+ "@mui/utils": "^5.4.4",
+ "clsx": "^1.1.1",
+ "prop-types": "^15.7.2",
+ "react-is": "^17.0.2",
+ "react-transition-group": "^4.4.2",
+ "rifm": "^0.12.1"
+ },
+ "dependencies": {
+ "@mui/base": {
+ "version": "5.0.0-alpha.72",
+ "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.72.tgz",
+ "integrity": "sha512-WCAooa9eqbsC68LhyKtDBRumH4hV1eRZ0A3SDKFHSwYG9fCOdsFv/H1dIYRJM0rwD45bMnuDiG3Qmx7YsTiptw==",
+ "requires": {
+ "@babel/runtime": "^7.17.2",
+ "@emotion/is-prop-valid": "^1.1.2",
+ "@mui/utils": "^5.4.4",
+ "@popperjs/core": "^2.11.3",
+ "clsx": "^1.1.1",
+ "prop-types": "^15.7.2",
+ "react-is": "^17.0.2"
+ }
+ }
+ }
+ },
"@mui/material": {
"version": "5.4.4",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.4.4.tgz",
@@ -14415,24 +14651,24 @@
}
},
"@mui/system": {
- "version": "5.4.4",
- "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.4.4.tgz",
- "integrity": "sha512-Zjbztq2o/VRuRRCWjG44juRrPKYLQMqtQpMHmMttGu5BnvK6PAPW3WOY0r1JCAwLhbd8Kug9nyhGQYKETjo+tQ==",
+ "version": "5.5.1",
+ "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.5.1.tgz",
+ "integrity": "sha512-2hynI4hN8304hOCT8sc4knJviwUUYJ7XK3mXwQ0nagVGOPnWSOad/nYADm7K0vdlCeUXLIbDbe7oNN3Kaiu2kA==",
"requires": {
"@babel/runtime": "^7.17.2",
"@mui/private-theming": "^5.4.4",
"@mui/styled-engine": "^5.4.4",
- "@mui/types": "^7.1.2",
+ "@mui/types": "^7.1.3",
"@mui/utils": "^5.4.4",
"clsx": "^1.1.1",
- "csstype": "^3.0.10",
+ "csstype": "^3.0.11",
"prop-types": "^15.7.2"
}
},
"@mui/types": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.1.2.tgz",
- "integrity": "sha512-SD7O1nVzqG+ckQpFjDhXPZjRceB8HQFHEvdLLrPhlJy4lLbwEBbxK74Tj4t6Jgk0fTvLJisuwOutrtYe9P/xBQ==",
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.1.3.tgz",
+ "integrity": "sha512-DDF0UhMBo4Uezlk+6QxrlDbchF79XG6Zs0zIewlR4c0Dt6GKVFfUtzPtHCH1tTbcSlq/L2bGEdiaoHBJ9Y1gSA==",
"requires": {}
},
"@mui/utils": {
@@ -14474,9 +14710,9 @@
}
},
"@popperjs/core": {
- "version": "2.11.2",
- "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz",
- "integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA=="
+ "version": "2.11.4",
+ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.4.tgz",
+ "integrity": "sha512-q/ytXxO5NKvyT37pmisQAItCFqA7FD/vNb8dgaJy3/630Fsc+Mz9/9f2SziBoIZ30TJooXyTwZmhi1zjXmObYg=="
},
"@sinonjs/commons": {
"version": "1.8.3",
@@ -19265,6 +19501,12 @@
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
"dev": true
},
+ "rifm": {
+ "version": "0.12.1",
+ "resolved": "https://registry.npmjs.org/rifm/-/rifm-0.12.1.tgz",
+ "integrity": "sha512-OGA1Bitg/dSJtI/c4dh90svzaUPt228kzFsUkJbtA2c964IqEAwWXeL9ZJi86xWv3j5SMqRvGULl7bA6cK0Bvg==",
+ "requires": {}
+ },
"rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
diff --git a/package.json b/package.json
index 3338baf6..39663336 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
"license": "MIT",
"dependencies": {
"@mui/icons-material": "^5.4.4",
+ "@mui/lab": "^5.0.0-alpha.73",
"@mui/material": "^5.4.4",
"axios": "^0.21.2",
"notistack": "^2.0.3",