Skip to content

Commit

Permalink
Liz gui (#360)
Browse files Browse the repository at this point in the history
* Set up development environment

* Add PyWebView window API, create basic app UI, add Zustand stores, add SocketIO, add PyPlot graphing

* Changed accordion to collapsible box

* Create drag and drop sortable list

* Add switches and conditional texfields to preprocessing section, fixed DnD

* fixed switches to work for all levels of settings

* Made preprocessing section display options based on selected options

* Added frequency settings

* fixed frequencies component

* Change from Flask to FastAPI, add loggers

* Add websockets with FastAPI, defer imports, fix Graph component

* Improve sidebar

* Layout redesign: new App bar, and other improvements (#356)

* add routing and dummy pages

* added toolbar, changed styling

* updated channels gui

* Add multiple simultaneous websocket connections

* Fix backend dependencies

* Detect if app running in WebView

* Fix some websocket issues

* update deps

* Unify TitleBar and AppToolbar into AppBar, use UserAgent to detect PyWebView

* Add App Info modal dialog when clicking on Title

* Fix handling of keyboard interrupt events, add parameter to make PyWebView optional

* hide resize handle for normal browsers

* Delete test data, add test folder to .gitignore

* Remove npm lock file, add to .gitignore

* Delete ThemedApp

* Delete and ignore uv.lock

* Undo reset.css changes

---------

Co-authored-by: Samed Rouven Vossberg <[email protected]>

* Remove SettingsPanel component

* Change toml to tomllib (python 3.11 required)

* Changed accordion to collapsible box

* Create drag and drop sortable list

* Add switches and conditional texfields to preprocessing section, fixed DnD

* prevent title word wrap

* save

* save2

* fixed frequencies component

* Massive changes to Settings page

* temporarily ignore frontend build files

* Change toml to tomllib (python 3.11 required)

* Change from Flask to FastAPI, add loggers

* Add websockets with FastAPI, defer imports, fix Graph component

* Layout redesign: new App bar, and other improvements (#356)

* add routing and dummy pages

* added toolbar, changed styling

* updated channels gui

* Add multiple simultaneous websocket connections

* Fix backend dependencies

* Detect if app running in WebView

* Fix some websocket issues

* update deps

* Unify TitleBar and AppToolbar into AppBar, use UserAgent to detect PyWebView

* Add App Info modal dialog when clicking on Title

* Fix handling of keyboard interrupt events, add parameter to make PyWebView optional

* hide resize handle for normal browsers

* Delete test data, add test folder to .gitignore

* Remove npm lock file, add to .gitignore

* Delete ThemedApp

* Delete and ignore uv.lock

* Undo reset.css changes

---------

Co-authored-by: Samed Rouven Vossberg <[email protected]>

* Add backend stream init and frontend setup page (#358)

* nm channels connected to backend and fix in backend

* debugging backend connection, adding POST to Channels

* add fastAPI call for LSL

* add LSL Stream search

* add LSL Stream setup

* Remove hardcoded backend port from websocket store and add ws proxy to vite

* Divide file and source selection into separate components and routes

* add offline Stream setup and modularize SourceSelectionSettings

* minor change: replace navigate with react-router Link

* add test file for LSL stream setup

* minor: fix routes

* Add FileBrowser component and API endpoints to access local computer file system

* debug backend and chanels

* LSLOfflineStream: run in a separate subprocess, add blocking and non-blocking modes, add context manager

* Made channels component scrollable

* Update StreamSelector, change some components to MUI, add immer to sessionStore

* Add jsconfig and Eslint jsdoc plugin

* fix option to setup LSL stream

* set port to 50001

* Filter out React 19 warnings for MUI components

* Fix JSDoc linting style

* - Update to Zustand 5, add utility functions to create stores with middleware and devtools
- Make sessionStore and uiStore persistent
- Refactor Channels page
- Add FileManager class
- Start adding JSDoc documentation and configs
- Add TitledBox component
- Remove mock data generation
- Fix backend hot-reloading (hack)
- Add dev parameter to AppManager (enables hot reloading)
- Other fixes and changes

---------

Co-authored-by: Samed Rouven Vossberg <[email protected]>
Co-authored-by: Toni M. Brotons <[email protected]>

* - Migrate many components to MUI
- Remove most module.css files
- Add recursively rendering Settings component
- Temporarily emove Sidebar from layout (component remains in codebase)
- Reorganize component and page file structure with less subfolders

* add backend stream run process

* fix imports

* fix additional imports

* add debugging file and fix another import

* WIP calling run function and setting up websocket connetion

* fix rebase errors

* add backend stream run process

* add debugging file and fix another import

---------

Co-authored-by: Antonio Martinez Brotons <[email protected]>
Co-authored-by: elizametno <[email protected]>
Co-authored-by: Samed Rouven Vossberg <[email protected]>
Co-authored-by: timonmerk <[email protected]>
Co-authored-by: timonmerk <[email protected]>
  • Loading branch information
6 people authored Sep 22, 2024
1 parent 50e3527 commit 1296a81
Show file tree
Hide file tree
Showing 99 changed files with 2,022 additions and 1,401 deletions.
13 changes: 7 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -193,14 +193,15 @@ out_per
/profiling/*
# Test output
test_data/
# Ignore npm lock files
# various lock files
package-lock.json
package-lock.json.bak
# Ignore uv lock file
uv.lock

# LSL log file
lsllog.txt

# temporarily ignore the frontend build
/gui_dev/dist
/gui/frontend
# Node modules
gui_dev/node_modules/*

# LSL log file
lsllog.txt
21 changes: 21 additions & 0 deletions gui_dev/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react/jsx-runtime',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
settings: { react: { version: '18.2' } },
plugins: ['react-refresh'],
rules: {
'react/jsx-no-target-blank': 'off',
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}
3 changes: 2 additions & 1 deletion gui_dev/jsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
"baseUrl": "./",
"target": "ES6",
"checkJs": true,
"module": "ES6",
"moduleResolution": "node",
"paths": {
"@/*": ["./src/*"]
},
"jsx": "react-jsx",
"jsx": "react-jsx"
}
}
6 changes: 4 additions & 2 deletions gui_dev/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"dependencies": {
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@mui/icons-material": "^5.16.7",
"@mui/material": "^5.16.7",
"@mui/icons-material": "latest",
"@mui/material": "latest",
"immer": "^10.1.1",
"plotly.js-basic-dist-min": "^2.35.2",
"react": "next",
Expand All @@ -28,9 +28,11 @@
"@babel/preset-react": "^7.24.7",
"@eslint/compat": "^1.1.1",
"@vitejs/plugin-react": "^4.3.1",
"@welldone-software/why-did-you-render": "^8.0.3",
"babel-plugin-react-compiler": "latest",
"eslint": "^9.10.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-jsdoc": "^50.2.3",
"eslint-plugin-react": "^7.36.1",
"eslint-plugin-react-compiler": "latest",
"eslint-plugin-react-hooks": "^4.6.2",
Expand Down
9 changes: 9 additions & 0 deletions gui_dev/scripts/wdyr.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from "react";
import whyDidYouRender from "@welldone-software/why-did-you-render";
if (process.env.NODE_ENV === "development") {
whyDidYouRender(React, {
trackAllPureComponents: true,
logOnDifferentValues: true,
collapseGroups: false,
});
}
74 changes: 33 additions & 41 deletions gui_dev/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,19 @@ import {
Routes,
Navigate,
} from "react-router-dom";
import { createTheme, ThemeProvider } from "@mui/material/styles";
import { Box, Stack, ThemeProvider } from "@mui/material";
import CssBaseline from "@mui/material/CssBaseline";
import { AppBar, StatusBar } from "@/components";
import { Dashboard, SourceSelection, Channels, Settings } from "@/pages";
import styles from "./App.module.css";
import {
Dashboard,
SourceSelection,
Channels,
Settings,
Decoding,
} from "@/pages";
import { theme } from "./theme";
import { StreamSelector } from "@/pages/SourceSelection/StreamSelector";
import { FileSelector } from "@/pages/SourceSelection/FileSelector";

/**
*
Expand Down Expand Up @@ -46,52 +54,36 @@ export const App = () => {
};
}, [connectSocket, disconnectSocket]);

const theme = createTheme({
palette: {
mode: "dark", // This sets the overall theme to dark mode
primary: {
main: "#1a73e8", // Change this to your preferred primary color
},
secondary: {
main: "#f4f4f4", // Light color for secondary elements
},
background: {
default: "#333", // Background color
paper: "#424242", // Background color for Paper components
},
text: {
primary: "#f4f4f4", // Text color
secondary: "#cccccc", // Slightly lighter text color
},
},
typography: {
fontFamily: '"Figtree", sans-serif', // Use the Figtree font globally
},
});

return (
<ThemeProvider theme={theme}>
<CssBaseline />

<Router>
<div className={styles.appContainer}>
<Stack height="100vh" width="100vw" overflow="hidden">
<AppBar />
<div className={styles.appContent}>
<Box
sx={{
height: "100%",
overflow: "auto",
width: "100%",
p: 0,
m: 0,
}}
>
<Routes>
<Route path="/" element={<Navigate to="/source" replace />} />
<Route
path="/source/"
element={<Navigate to="/source/file" replace />}
/>
<Route exact path="/source/*" element={<SourceSelection />} />
<Route exact path="/channels" element={<Channels />} />
<Route exact path="/settings" element={<Settings />} />
<Route exact path="/dashboard" element={<Dashboard />} />
<Route exact path="/decoding" element={<Dashboard />} />
<Route index element={<Navigate to="/source" replace />} />
<Route path="source" element={<SourceSelection />}>
<Route index element={<Navigate to="/source/file" replace />} />
<Route path="file" element={<FileSelector />} />
<Route path="lsl" element={<StreamSelector />} />
</Route>
<Route path="channels" element={<Channels />} />
<Route path="settings" element={<Settings />} />
<Route path="dashboard" element={<Dashboard />} />
<Route path="decoding" element={<Decoding />} />
</Routes>
</div>
</Box>
<StatusBar />
</div>
</Stack>
</Router>
</ThemeProvider>
);
Expand Down
28 changes: 0 additions & 28 deletions gui_dev/src/App.module.css

This file was deleted.

66 changes: 66 additions & 0 deletions gui_dev/src/components/AppBar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { useState } from "react";
import { WindowButtons } from "./WindowButtons";
import { AppInfoModal } from "@/components";
import { Button, Stack, Typography } from "@mui/material";
import { Link, useLocation } from "react-router-dom";
import {
Dataset,
Settings,
Dashboard,
BarChart,
Dvr,
} from "@mui/icons-material";
import { useWebviewStore } from "@/stores";

const ToolbarButton = ({ to, label, icon }) => {
const location = useLocation();
const isSelected = location.pathname.includes(to);
return (
<Button
component={Link}
to={isSelected ? null : to}
startIcon={icon}
sx={isSelected ? { color: "primary.main" } : { color: "text.primary" }}
>
{label}
</Button>
);
};

const Toolbar = () => (
<Stack direction="row" justifyContent="space-around" p={0.5}>
<ToolbarButton to="/source" icon={<Dataset />} label="Source Selection" />
<ToolbarButton to="/channels" icon={<Dvr />} label="Channels" />
<ToolbarButton to="/settings" icon={<Settings />} label="Settings" />
<ToolbarButton to="/dashboard" icon={<Dashboard />} label="Dashboard" />
<ToolbarButton to="/decoding" icon={<BarChart />} label="Decoding" />
</Stack>
);

export const AppBar = () => {
// In your JSX:
const { isWebView } = useWebviewStore((state) => state.isWebView);
const [showModal, setShowModal] = useState(false);

return (
<Stack
className="pywebview-drag-region"
direction="row"
justifyContent="space-between"
borderBottom="2px solid"
borderColor="background.level3"
bgcolor="background.paper"
>
<Typography
onClick={() => setShowModal(true)}
variant="h4"
sx={{ cursor: "pointer", ml: 2, "&:hover": { color: "primary.main" } }}
>
PyNeuromodulation
</Typography>
<Toolbar />
{isWebView && <WindowButtons />}
<AppInfoModal open={showModal} onClose={() => setShowModal(false)} />
</Stack>
);
};
30 changes: 0 additions & 30 deletions gui_dev/src/components/AppBar/AppBar.jsx

This file was deleted.

Loading

0 comments on commit 1296a81

Please sign in to comment.