diff --git a/gui/package.json b/gui/package.json index 20a2fcbf..08082a12 100644 --- a/gui/package.json +++ b/gui/package.json @@ -23,10 +23,9 @@ "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.5", "@fi-sci/misc": "^0.0.8", - "@fi-sci/modal-window": "^0.0.2", "@geoffcox/react-splitter": "^2.1.2", "@monaco-editor/react": "^4.6.0", - "@mui/icons-material": "^5.15.17", + "@mui/icons-material": "^5.16.5", "@mui/material": "^5.15.17", "@octokit/rest": "^21.0.0", "@vercel/analytics": "^1.3.1", diff --git a/gui/src/app/App.tsx b/gui/src/app/App.tsx index e7673069..7899515e 100644 --- a/gui/src/app/App.tsx +++ b/gui/src/app/App.tsx @@ -1,17 +1,23 @@ -import { BrowserRouter } from "react-router-dom"; +import { createTheme } from "@mui/material"; +import { ThemeProvider } from "@mui/system"; import ProjectContextProvider from "@SpCore/ProjectContextProvider"; import HomePage from "@SpPages/HomePage"; import { Analytics } from "@vercel/analytics/react"; +import { BrowserRouter } from "react-router-dom"; + +const theme = createTheme(); function App() { return ( -
- - - - -
+ +
+ + + + +
+
); } diff --git a/gui/src/app/CompilationServerConnectionControl/CompilationServerConnectionControl.tsx b/gui/src/app/CompilationServerConnectionControl/CompilationServerConnectionControl.tsx index 9c73ff23..175878a1 100644 --- a/gui/src/app/CompilationServerConnectionControl/CompilationServerConnectionControl.tsx +++ b/gui/src/app/CompilationServerConnectionControl/CompilationServerConnectionControl.tsx @@ -1,17 +1,20 @@ import { SmallIconButton } from "@fi-sci/misc"; -import { default as ModalWindow, useModalWindow } from "@fi-sci/modal-window"; import { Cancel, Check } from "@mui/icons-material"; -import Button from "@mui/material/Button"; import Link from "@mui/material/Link"; + +import CloseableDialog, { + useDialogControls, +} from "@SpComponents/CloseableDialog"; import { FunctionComponent, useCallback, useEffect, useState } from "react"; +import ConfigureCompilationServerDialog from "./ConfigureCompilationServerDialog"; + +export const publicUrl = "https://trom-stan-wasm-server.magland.org"; +export const localUrl = "http://localhost:8083"; type CompilationServerConnectionControlProps = { // none }; -const publicUrl = "https://trom-stan-wasm-server.magland.org"; -const localUrl = "http://localhost:8083"; - const CompilationServerConnectionControl: FunctionComponent< CompilationServerConnectionControlProps > = () => { @@ -26,8 +29,8 @@ const CompilationServerConnectionControl: FunctionComponent< const { handleOpen: openDialog, handleClose: closeDialog, - visible: dialogVisible, - } = useModalWindow(); + open, + } = useDialogControls(); const handleRetry = useCallback(() => { retryConnection(); @@ -60,7 +63,12 @@ const CompilationServerConnectionControl: FunctionComponent<    - + - + ); }; @@ -96,123 +104,4 @@ const useIsConnected = (stanWasmServerUrl: string) => { return { isConnected, retryConnection }; }; -type ConfigureCompilationServerDialogProps = { - stanWasmServerUrl: string; - setStanWasmServerUrl: (url: string) => void; - isConnected: boolean; - closeDialog: () => void; - onRetry: () => void; -}; - -const ConfigureCompilationServerDialog: FunctionComponent< - ConfigureCompilationServerDialogProps -> = ({ - stanWasmServerUrl, - setStanWasmServerUrl, - isConnected, - closeDialog, - onRetry, -}) => { - const [choice, setChoice] = useState<"public" | "local" | "custom">("custom"); - useEffect(() => { - if (stanWasmServerUrl === publicUrl) setChoice("public"); - else if (stanWasmServerUrl === localUrl) setChoice("local"); - else setChoice("custom"); - }, [stanWasmServerUrl]); - return ( -
-

Select a compilation server

-

- While the sampling is performed locally in the browser, a compilation - server is required to compile the Stan programs. -

-
-
- {isConnected ? ( - Connected - ) : ( - Not connected - )} -   - - retry - -
-
-
- { - if (choice === "custom") setChoice("public"); - setStanWasmServerUrl(publicUrl); - }} - /> - -
- - { - if (choice === "custom") setChoice("local"); - setStanWasmServerUrl(localUrl); - }} - /> - -
- - setChoice("custom")} - /> - -
- - setStanWasmServerUrl(e.target.value)} - /> -
-
- {choice === "local" && ( -
-

To start a local compilation server:

-
-
-                docker run -p 8083:8080 -it magland/stan-wasm-server:latest
-              
-
-
- )} - {choice === "public" && ( -
-

- The public server is provided for convenience, but may not be as - reliable as a local server, depending on the current load and - availability. -

-
- )} -
- -
-
- ); -}; - export default CompilationServerConnectionControl; diff --git a/gui/src/app/CompilationServerConnectionControl/ConfigureCompilationServerDialog.tsx b/gui/src/app/CompilationServerConnectionControl/ConfigureCompilationServerDialog.tsx new file mode 100644 index 00000000..b953c5a0 --- /dev/null +++ b/gui/src/app/CompilationServerConnectionControl/ConfigureCompilationServerDialog.tsx @@ -0,0 +1,124 @@ +import Button from "@mui/material/Button"; +import Link from "@mui/material/Link"; +import { FunctionComponent, useEffect, useState } from "react"; +import { localUrl, publicUrl } from "./CompilationServerConnectionControl"; + +type ConfigureCompilationServerDialogProps = { + stanWasmServerUrl: string; + setStanWasmServerUrl: (url: string) => void; + isConnected: boolean; + closeDialog: () => void; + onRetry: () => void; +}; + +const ConfigureCompilationServerDialog: FunctionComponent< + ConfigureCompilationServerDialogProps +> = ({ + stanWasmServerUrl, + setStanWasmServerUrl, + isConnected, + closeDialog, + onRetry, +}) => { + const [choice, setChoice] = useState<"public" | "local" | "custom">("custom"); + useEffect(() => { + if (stanWasmServerUrl === publicUrl) setChoice("public"); + else if (stanWasmServerUrl === localUrl) setChoice("local"); + else setChoice("custom"); + }, [stanWasmServerUrl]); + return ( +
+

+ While the sampling is performed locally in the browser, a compilation + server is required to compile the Stan programs. +

+
+
+ {isConnected ? ( + Connected + ) : ( + Not connected + )} +   + + retry + +
+
+
+ { + if (choice === "custom") setChoice("public"); + setStanWasmServerUrl(publicUrl); + }} + /> + +
+ + { + if (choice === "custom") setChoice("local"); + setStanWasmServerUrl(localUrl); + }} + /> + +
+ + setChoice("custom")} + /> + +
+ + setStanWasmServerUrl(e.target.value)} + /> +
+
+ {choice === "local" && ( +
+

To start a local compilation server:

+
+
+                docker run -p 8083:8080 -it magland/stan-wasm-server:latest
+              
+
+
+ )} + {choice === "public" && ( +
+

+ The public server is provided for convenience, but may not be as + reliable as a local server, depending on the current load and + availability. +

+
+ )} +
+ +
+
+ ); +}; + +export default ConfigureCompilationServerDialog; diff --git a/gui/src/app/components/CloseableDialog.tsx b/gui/src/app/components/CloseableDialog.tsx new file mode 100644 index 00000000..e364a017 --- /dev/null +++ b/gui/src/app/components/CloseableDialog.tsx @@ -0,0 +1,56 @@ +import CloseIcon from "@mui/icons-material/Close"; +import Dialog from "@mui/material/Dialog"; +import DialogTitle from "@mui/material/DialogTitle"; +import IconButton from "@mui/material/IconButton"; +import { FunctionComponent, PropsWithChildren, useState } from "react"; + +type CloseableDialogProps = { + title: string; + id: string; + open: boolean; + handleClose: () => void; +}; + +export const useDialogControls = () => { + const [open, setOpen] = useState(false); + + const handleOpen = () => { + setOpen(true); + }; + const handleClose = () => { + setOpen(false); + }; + + return { open, handleOpen, handleClose }; +}; + +const CloseableDialog: FunctionComponent< + PropsWithChildren +> = ({ title, id, handleClose, open, children }) => { + const theDialog = ( + + {title} + theme.palette.grey[500], + }} + > + + + {children} + + ); + + return theDialog; +}; + +export default CloseableDialog; diff --git a/gui/src/app/pages/HomePage/LoadProjectWindow.tsx b/gui/src/app/pages/HomePage/LoadProjectWindow.tsx index 27706868..a9718367 100644 --- a/gui/src/app/pages/HomePage/LoadProjectWindow.tsx +++ b/gui/src/app/pages/HomePage/LoadProjectWindow.tsx @@ -104,8 +104,7 @@ const LoadProjectWindow: FunctionComponent = ({ }, [filesUploaded, importUploadedFiles]); return ( -
-

Load project

+
You can upload:
    diff --git a/gui/src/app/pages/HomePage/SaveProjectWindow.tsx b/gui/src/app/pages/HomePage/SaveProjectWindow.tsx index 42dcd0d4..32570d47 100644 --- a/gui/src/app/pages/HomePage/SaveProjectWindow.tsx +++ b/gui/src/app/pages/HomePage/SaveProjectWindow.tsx @@ -1,8 +1,8 @@ import { FunctionComponent, useCallback, useContext, useState } from "react"; -import { serializeAsZip } from "@SpCore/ProjectSerialization"; import { FileRegistry, mapModelToFileManifest } from "@SpCore/FileMapping"; import { ProjectContext } from "@SpCore/ProjectContextProvider"; +import { serializeAsZip } from "@SpCore/ProjectSerialization"; import saveAsGitHubGist from "@SpCore/gists/saveAsGitHubGist"; import { triggerDownload } from "@SpUtil/triggerDownload"; import Button from "@mui/material/Button"; @@ -20,8 +20,7 @@ const SaveProjectWindow: FunctionComponent = ({ const [exportingToGist, setExportingToGist] = useState(false); return ( -
    -

    Save this project

    +
    diff --git a/gui/src/app/pages/HomePage/Sidebar.tsx b/gui/src/app/pages/HomePage/Sidebar.tsx index b7d63bc3..eceeb4b7 100644 --- a/gui/src/app/pages/HomePage/Sidebar.tsx +++ b/gui/src/app/pages/HomePage/Sidebar.tsx @@ -1,14 +1,15 @@ +import CloseableDialog, { + useDialogControls, +} from "@SpComponents/CloseableDialog"; import { ProjectContext } from "@SpCore/ProjectContextProvider"; import { modelHasUnsavedChanges } from "@SpCore/ProjectDataModel"; import LoadProjectWindow from "@SpPages/LoadProjectWindow"; import SaveProjectWindow from "@SpPages/SaveProjectWindow"; -import ModalWindow, { useModalWindow } from "@fi-sci/modal-window"; +import { List, ListItem } from "@mui/material"; import Button from "@mui/material/Button"; import Divider from "@mui/material/Divider"; import Drawer from "@mui/material/Drawer"; import Link from "@mui/material/Link"; -import List from "@mui/material/List"; -import ListItem from "@mui/material/ListItem"; import Toolbar from "@mui/material/Toolbar"; import { FunctionComponent, useContext, useMemo } from "react"; import { useNavigate } from "react-router-dom"; @@ -43,15 +44,15 @@ const Sidebar: FunctionComponent = ({ const dataModified = useMemo(() => modelHasUnsavedChanges(data), [data]); const { - visible: saveProjectVisible, + open: saveProjectVisible, handleOpen: saveProjectOpen, handleClose: saveProjectClose, - } = useModalWindow(); + } = useDialogControls(); const { - visible: loadProjectVisible, + open: loadProjectVisible, handleOpen: loadProjectOpen, handleClose: loadProjectClose, - } = useModalWindow(); + } = useDialogControls(); return ( = ({ - + - - + + - + ); }; diff --git a/gui/src/localStyles.css b/gui/src/localStyles.css index 993e6aa6..435a10bf 100644 --- a/gui/src/localStyles.css +++ b/gui/src/localStyles.css @@ -13,6 +13,10 @@ color: red; } +.dialogWrapper { + padding: 10px; +} + .CompilationServerConnectionPane { font-size: 12px; } diff --git a/gui/yarn.lock b/gui/yarn.lock index d923faec..9ae49ff6 100644 --- a/gui/yarn.lock +++ b/gui/yarn.lock @@ -554,14 +554,6 @@ resolved "https://registry.yarnpkg.com/@fi-sci/misc/-/misc-0.0.8.tgz#56b0c5402fc64df873c8a7b0d65966c3df3f0dd7" integrity sha512-lhbKCriIv9TxBw3xSZ/q7mlfVDc+OsJ1x6jesyeHEVMdqqYHDIRTZTdUIrnA0jdL4nMj3FbYNHE49Z7K+iouiQ== -"@fi-sci/modal-window@^0.0.2": - version "0.0.2" - resolved "https://registry.yarnpkg.com/@fi-sci/modal-window/-/modal-window-0.0.2.tgz#ab50fe92925a2efd01fd8d3ab54f8f47bf7821b3" - integrity sha512-CHeCWWLblUNUtqCWIhnR6+2TYzzcoJlKj0PGgnw5XYEOFHhV7TBDGFQ5jzc609jAPRfc3grkUYJy6lru+BnFWA== - dependencies: - "@mui/icons-material" "^5.14.19" - "@mui/material" "^5.14.20" - "@floating-ui/core@^1.6.0": version "1.6.4" resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.4.tgz#0140cf5091c8dee602bff9da5ab330840ff91df6" @@ -715,14 +707,14 @@ resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.21.tgz#15ffc56cef7009479229b55126176f988afba96b" integrity sha512-dp9lXBaJZzJYeJfQY3Ow4Rb49QaCEdkl2KKYscdQHQm6bMJ+l4XPY3Cd9PCeeJTsHPIDJ60lzXbeRgs6sx/rpw== -"@mui/icons-material@^5.14.19", "@mui/icons-material@^5.15.17": - version "5.15.21" - resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.15.21.tgz#1e29e1bdb90916be5b66c95c45951f441821f34a" - integrity sha512-yqkq1MbdkmX5ZHyvZTBuAaA6RkvoqkoAgwBSx9Oh0L0jAfj9T/Ih/NhMNjkl8PWVSonjfDUkKroBnjRyo/1M9Q== +"@mui/icons-material@^5.16.5": + version "5.16.5" + resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.16.5.tgz#53cdd03132315c8daff2200d146035f34c913470" + integrity sha512-bn88xxU/J9UV0s6+eutq7o3TTOrOlbCX+KshFb8kxgIxJZZfYz3JbAXVMivvoMF4Md6jCVUzM9HEkf4Ajab4tw== dependencies: "@babel/runtime" "^7.23.9" -"@mui/material@^5.14.20", "@mui/material@^5.15.17": +"@mui/material@^5.15.17": version "5.15.21" resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.15.21.tgz#b2c8d756af570a61cb4975acf0e71dafb110b001" integrity sha512-nTyCcgduKwHqiuQ/B03EQUa+utSMzn2sQp0QAibsnYe4tvc3zkMbO0amKpl48vhABIY3IvT6w9615BFIgMt0YA==