use redux

pull/43/head
Alexander Bentkamp 4 years ago
parent 50339da74f
commit cc6eb8c3f9

@ -14,29 +14,15 @@ import { AppBar, CssBaseline, Toolbar, Typography } from '@mui/material';
import Welcome from './components/Welcome'; import Welcome from './components/Welcome';
import Level from './components/Level'; import Level from './components/Level';
import GoodBye from './components/GoodBye'; import GoodBye from './components/GoodBye';
import useWebSocket from 'react-use-websocket';
import { LeanClient } from 'lean4web/client/src/editor/leanclient';
import { monacoSetup } from 'lean4web/client/src/monacoSetup' import { monacoSetup } from 'lean4web/client/src/monacoSetup'
import { useAppSelector } from './hooks';
const socketUrl = ((window.location.protocol === "https:") ? "wss://" : "ws://") + window.location.host + '/websocket/'
monacoSetup()
function App() { function App() {
const [title, setTitle] = useState("")
const [conclusion, setConclusion] = useState("") const [conclusion, setConclusion] = useState("")
const [levelTitle, setLevelTitle] = useState("") const [levelTitle, setLevelTitle] = useState("")
const [nbLevels, setNbLevels] = useState(0) const [nbLevels, setNbLevels] = useState(0)
const [curLevel, setCurLevel] = useState(0) const [curLevel, setCurLevel] = useState(0)
const [finished, setFinished] = useState(false) const [finished, setFinished] = useState(false)
const [leanClient, setLeanClient] = useState<null|LeanClient>(null)
useEffect(() => {
const uri = monaco.Uri.parse('file:///')
const leanClient = new LeanClient(socketUrl, undefined, uri, () => {})
setLeanClient(leanClient)
}, [])
const mathJaxConfig = { const mathJaxConfig = {
loader: { loader: {
@ -58,11 +44,13 @@ function App() {
if (finished) { if (finished) {
mainComponent = <GoodBye message={conclusion} /> mainComponent = <GoodBye message={conclusion} />
} else if (curLevel > 0) { } else if (curLevel > 0) {
mainComponent = <Level leanClient={leanClient} nbLevels={nbLevels} level={curLevel} setCurLevel={setCurLevel} setLevelTitle={setLevelTitle} setFinished={setFinished}/> mainComponent = <Level nbLevels={nbLevels} level={curLevel} setCurLevel={setCurLevel} setLevelTitle={setLevelTitle} setFinished={setFinished}/>
} else { } else {
mainComponent = <Welcome leanClient={leanClient} setNbLevels={setNbLevels} setTitle={setTitle} startGame={startGame} setConclusion={setConclusion}/> mainComponent = <Welcome setNbLevels={setNbLevels} startGame={startGame} setConclusion={setConclusion}/>
} }
const title = useAppSelector(state => state.game.title)
return ( return (
<div className="App"> <div className="App">
<MathJaxContext config={mathJaxConfig}> <MathJaxContext config={mathJaxConfig}>

@ -22,9 +22,9 @@ import 'lean4web/client/src/editor/infoview.css'
import { renderInfoview } from '@leanprover/infoview' import { renderInfoview } from '@leanprover/infoview'
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js' import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js'
import './level.css' import './level.css'
import { ConnectionContext } from '../connection';
interface LevelProps { interface LevelProps {
leanClient: null|LeanClient;
nbLevels: any; nbLevels: any;
level: any; level: any;
setCurLevel: any; setCurLevel: any;
@ -32,7 +32,7 @@ interface LevelProps {
setFinished: any setFinished: any
} }
function Level({ leanClient, nbLevels, level, setCurLevel, setLevelTitle, setFinished }: LevelProps) { function Level({ nbLevels, level, setCurLevel, setLevelTitle, setFinished }: LevelProps) {
const [index, setIndex] = useState(level) // Level number const [index, setIndex] = useState(level) // Level number
const [tacticDocs, setTacticDocs] = useState([]) const [tacticDocs, setTacticDocs] = useState([])
const [lemmaDocs, setLemmaDocs] = useState([]) const [lemmaDocs, setLemmaDocs] = useState([])
@ -72,6 +72,8 @@ function Level({ leanClient, nbLevels, level, setCurLevel, setLevelTitle, setFin
messagePanelRef.current!.scrollTo(0,0) messagePanelRef.current!.scrollTo(0,0)
}, [level]) }, [level])
const leanClient = React.useContext(ConnectionContext)
useEffect(() => { useEffect(() => {
const editor = monaco.editor.create(codeviewRef.current!, { const editor = monaco.editor.create(codeviewRef.current!, {
glyphMargin: true, glyphMargin: true,

@ -9,30 +9,25 @@ import '@fontsource/roboto/700.css';
import * as rpc from 'vscode-ws-jsonrpc'; import * as rpc from 'vscode-ws-jsonrpc';
import cytoscape from 'cytoscape' import cytoscape from 'cytoscape'
import klay from 'cytoscape-klay'; import klay from 'cytoscape-klay';
import { useSelector, useDispatch } from 'react-redux'
import { fetchGame } from '../game/gameSlice'
cytoscape.use( klay ); cytoscape.use( klay );
import { Box, Typography, Button, CircularProgress, Grid } from '@mui/material'; import { Box, Typography, Button, CircularProgress, Grid } from '@mui/material';
import { LeanClient } from 'lean4web/client/src/editor/leanclient'; import { LeanClient } from 'lean4web/client/src/editor/leanclient';
import { ConnectionContext } from '../connection';
import { useAppDispatch, useAppSelector } from '../hooks';
interface WelcomeProps { interface WelcomeProps {
leanClient: null|LeanClient;
setNbLevels: any; setNbLevels: any;
setTitle: any;
startGame: any; startGame: any;
setConclusion: any; setConclusion: any;
} }
type infoResultType = { function Welcome({ setNbLevels, startGame, setConclusion }: WelcomeProps) {
title: string, const dispatch = useAppDispatch()
nb_levels: any[],
conclusion: string
worlds: {edges: string[][], nodes: string[]}
}
function Welcome({ leanClient, setNbLevels, setTitle, startGame, setConclusion }: WelcomeProps) {
const [leanData, setLeanData] = useState<null|infoResultType>(null)
const worldsRef = useRef<HTMLDivElement>(null) const worldsRef = useRef<HTMLDivElement>(null)
const drawWorlds = (worlds) => { const drawWorlds = (worlds) => {
@ -78,43 +73,35 @@ function Welcome({ leanClient, setNbLevels, setTitle, startGame, setConclusion }
}) })
} }
useEffect(() => { useEffect(() => { dispatch(fetchGame); }, [])
if (!leanClient) return;
const getInfo = async () => { const worlds = useAppSelector(state => state.game.worlds)
await leanClient.start() // TODO: need a way to wait for start without restarting useEffect(() => { if (worlds) { drawWorlds(worlds); } }, [worlds])
leanClient.sendRequest("info", {}).then((res: infoResultType) =>{
console.log(res)
setLeanData(res)
setNbLevels(res.nb_levels)
setTitle(res.title)
document.title = res.title
setConclusion(res.conclusion)
drawWorlds(res.worlds)
});
}
getInfo()
}, [leanClient])
let content const title = useAppSelector(state => state.game.title)
if (leanData) { useEffect(() => { window.document.title = title }, [title])
content = (<Box sx={{ m: 3 }}>
const introduction = useAppSelector(state => state.game.introduction)
return <div>
{ introduction?// TODO: find a better way to mark loading state?
<div>
<Box sx={{ m: 3 }}>
<Typography variant="body1" component="div"> <Typography variant="body1" component="div">
<MathJax> <MathJax>
<ReactMarkdown>{leanData["introduction"]}</ReactMarkdown> <ReactMarkdown>{introduction}</ReactMarkdown>
</MathJax> </MathJax>
</Typography> </Typography>
</Box>
<Box textAlign='center' sx={{ m: 5 }}> <Box textAlign='center' sx={{ m: 5 }}>
<Button onClick={startGame} variant="contained">Start rescue mission</Button> <Button onClick={startGame} variant="contained">Start rescue mission</Button>
</Box> </Box>
</Box>)
} else {
content = <Box display="flex" alignItems="center" justifyContent="center" sx={{ height: "calc(100vh - 64px)" }}><CircularProgress /></Box>
}
return <div>
<div>{content}</div>
<div ref={worldsRef} style={{"width": "100%","height": "50em"}} /> <div ref={worldsRef} style={{"width": "100%","height": "50em"}} />
</div> </div>
: <Box display="flex" alignItems="center" justifyContent="center" sx={{ height: "calc(100vh - 64px)" }}><CircularProgress /></Box>
}
</div>
} }
export default Welcome export default Welcome

@ -0,0 +1,15 @@
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js'
import { LeanClient } from 'lean4web/client/src/editor/leanclient';
import * as React from 'react';
import { monacoSetup } from 'lean4web/client/src/monacoSetup';
monacoSetup()
const socketUrl = ((window.location.protocol === "https:") ? "wss://" : "ws://") + window.location.host + '/websocket/'
const uri = monaco.Uri.parse('file:///')
export const leanClient = new LeanClient(socketUrl, undefined, uri, () => {})
export const ConnectionContext = React.createContext(null);

@ -0,0 +1,59 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { LeanClient } from 'lean4web/client/src/editor/leanclient'
import type { RootState } from '../store'
interface GameState {
title: null|string,
introduction: null|string,
worlds: null|{nodes: string[], edges: string[][2]},
authors: null|string[],
conclusion: null|string,
}
const initialState : GameState = {
title: null,
introduction: null,
worlds: null,
authors: null,
conclusion: null,
}
export const gameSlice = createSlice({
name: 'game',
initialState,
reducers: {
loadedGame: (state, action: PayloadAction<any>) => {
state.title = action.payload.title
state.introduction = action.payload.introduction
state.worlds = action.payload.worlds
state.authors = action.payload.authors
state.conclusion = action.payload.conclusion
},
},
})
export const { loadedGame } = gameSlice.actions
// TODO: Move this into LeanClient?
/** Call `callback` when the leanClient has started. If not already started, start it. */
const whenLeanClientStarted = (leanClient, callback) => {
if (leanClient.isRunning()) {
callback()
} else {
if (!leanClient.isStarted()) {
leanClient.start()
}
leanClient.restarted(callback)
}
}
export const fetchGame = (dispatch, getState, extraArgument) => {
const leanClient : LeanClient = extraArgument.leanClient
whenLeanClientStarted(leanClient, () => {
leanClient.sendRequest("info", {}).then((res) =>{
dispatch(loadedGame(res))
})
})
}
export default gameSlice.reducer

@ -0,0 +1,6 @@
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import type { RootState, AppDispatch } from './store'
// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

@ -2,7 +2,19 @@ import * as React from 'react';
import { createRoot } from 'react-dom/client'; import { createRoot } from 'react-dom/client';
import './index.css'; import './index.css';
import App from './App'; import App from './App';
import { store } from './store';
import { Provider } from 'react-redux';
import { ConnectionContext, leanClient } from './connection'
const container = document.getElementById('root'); const container = document.getElementById('root');
const root = createRoot(container!); const root = createRoot(container!);
root.render(<App />); root.render(
<React.StrictMode>
<Provider store={store}>
<ConnectionContext.Provider value={leanClient}>
<App />
</ConnectionContext.Provider>
</Provider>
</React.StrictMode>
);

@ -0,0 +1,24 @@
import { configureStore } from '@reduxjs/toolkit';
import gameReducer from './game/gameSlice';
import { leanClient } from './connection'
import thunkMiddleware from 'redux-thunk'
const thunkMiddlewareWithArg = thunkMiddleware.withExtraArgument({ leanClient })
export const store = configureStore({
reducer: {
game: gameReducer,
},
middleware: getDefaultMiddleware =>
getDefaultMiddleware({
thunk: {
extraArgument: { leanClient }
}
})
});
// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch

270
package-lock.json generated

@ -12,6 +12,7 @@
"@fontsource/roboto-mono": "^4.5.8", "@fontsource/roboto-mono": "^4.5.8",
"@mui/icons-material": "^5.10.6", "@mui/icons-material": "^5.10.6",
"@mui/material": "^5.10.9", "@mui/material": "^5.10.9",
"@reduxjs/toolkit": "^1.9.0",
"@types/cytoscape": "^3.19.9", "@types/cytoscape": "^3.19.9",
"better-react-mathjax": "^2.0.2", "better-react-mathjax": "^2.0.2",
"cytoscape": "^3.23.0", "cytoscape": "^3.23.0",
@ -22,7 +23,7 @@
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-markdown": "^8.0.3", "react-markdown": "^8.0.3",
"react-use-websocket": "^4.2.0", "react-redux": "^8.0.5",
"vscode-ws-jsonrpc": "^2.0.0", "vscode-ws-jsonrpc": "^2.0.0",
"ws": "^8.9.0" "ws": "^8.9.0"
}, },
@ -33,6 +34,7 @@
"@babel/preset-react": "^7.0.0", "@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.18.6", "@babel/preset-typescript": "^7.18.6",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.8", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.8",
"@redux-devtools/core": "^3.13.1",
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
"babel-loader": "^8.2.5", "babel-loader": "^8.2.5",
"concurrently": "^7.4.0", "concurrently": "^7.4.0",
@ -2009,6 +2011,60 @@
"url": "https://opencollective.com/popperjs" "url": "https://opencollective.com/popperjs"
} }
}, },
"node_modules/@redux-devtools/core": {
"version": "3.13.1",
"resolved": "https://registry.npmjs.org/@redux-devtools/core/-/core-3.13.1.tgz",
"integrity": "sha512-VZbma4b28D7dLn6rKTxx4r1KJrgiT2EQNF4vjkpTlXTu0cQcHkEcAO9ixMBj6rZGrT/jinCHq8gBy2bWgnDvcA==",
"dev": true,
"dependencies": {
"@babel/runtime": "^7.18.3",
"@redux-devtools/instrument": "^2.1.0",
"@types/prop-types": "^15.7.5",
"lodash": "^4.17.21",
"prop-types": "^15.8.1"
},
"peerDependencies": {
"react": "^0.14.9 || ^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0",
"react-redux": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0",
"redux": "^3.5.2 || ^4.0.0"
}
},
"node_modules/@redux-devtools/instrument": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@redux-devtools/instrument/-/instrument-2.1.0.tgz",
"integrity": "sha512-e8fo88kuq/zWqfNf6S/GNfaQMjF4WSPpucmYfRhzZyyXHC3PCLd/xgz7zooPErDh9QwUXK6sTVYvrkq7hPbsFA==",
"dev": true,
"dependencies": {
"@babel/runtime": "^7.16.7",
"lodash": "^4.17.21"
},
"peerDependencies": {
"redux": "^3.4.0 || ^4.0.0"
}
},
"node_modules/@reduxjs/toolkit": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.0.tgz",
"integrity": "sha512-ak11IrjYcUXRqlhNPwnz6AcvA2ynJTu8PzDbbqQw4a3xR4KZtgiqbNblQD+10CRbfK4+5C79SOyxnT9dhBqFnA==",
"dependencies": {
"immer": "^9.0.16",
"redux": "^4.2.0",
"redux-thunk": "^2.4.2",
"reselect": "^4.1.7"
},
"peerDependencies": {
"react": "^16.9.0 || ^17.0.0 || ^18",
"react-redux": "^7.2.1 || ^8.0.2"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-redux": {
"optional": true
}
}
},
"node_modules/@testing-library/dom": { "node_modules/@testing-library/dom": {
"version": "8.19.0", "version": "8.19.0",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.19.0.tgz", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.19.0.tgz",
@ -2230,6 +2286,15 @@
"@types/unist": "*" "@types/unist": "*"
} }
}, },
"node_modules/@types/hoist-non-react-statics": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
"dependencies": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"node_modules/@types/http-proxy": { "node_modules/@types/http-proxy": {
"version": "1.17.9", "version": "1.17.9",
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz", "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz",
@ -2308,7 +2373,7 @@
"version": "18.0.6", "version": "18.0.6",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.6.tgz", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.6.tgz",
"integrity": "sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==", "integrity": "sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"@types/react": "*" "@types/react": "*"
} }
@ -2373,6 +2438,11 @@
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
"integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ=="
}, },
"node_modules/@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"node_modules/@types/ws": { "node_modules/@types/ws": {
"version": "8.5.3", "version": "8.5.3",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
@ -4501,8 +4571,6 @@
"version": "3.3.2", "version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"react-is": "^16.7.0" "react-is": "^16.7.0"
} }
@ -4510,9 +4578,7 @@
"node_modules/hoist-non-react-statics/node_modules/react-is": { "node_modules/hoist-non-react-statics/node_modules/react-is": {
"version": "16.13.1", "version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
"optional": true,
"peer": true
}, },
"node_modules/hpack.js": { "node_modules/hpack.js": {
"version": "2.1.6", "version": "2.1.6",
@ -4665,6 +4731,15 @@
"integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
"dev": true "dev": true
}, },
"node_modules/immer": {
"version": "9.0.16",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.16.tgz",
"integrity": "sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/immer"
}
},
"node_modules/import-fresh": { "node_modules/import-fresh": {
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@ -6694,6 +6769,44 @@
"react": ">=16" "react": ">=16"
} }
}, },
"node_modules/react-redux": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz",
"integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/use-sync-external-store": "^0.0.3",
"hoist-non-react-statics": "^3.3.2",
"react-is": "^18.0.0",
"use-sync-external-store": "^1.0.0"
},
"peerDependencies": {
"@types/react": "^16.8 || ^17.0 || ^18.0",
"@types/react-dom": "^16.8 || ^17.0 || ^18.0",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0",
"react-native": ">=0.59",
"redux": "^4"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
},
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
},
"redux": {
"optional": true
}
}
},
"node_modules/react-refresh": { "node_modules/react-refresh": {
"version": "0.14.0", "version": "0.14.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
@ -6730,15 +6843,6 @@
"react-dom": ">=16.6.0" "react-dom": ">=16.6.0"
} }
}, },
"node_modules/react-use-websocket": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/react-use-websocket/-/react-use-websocket-4.2.0.tgz",
"integrity": "sha512-ZovaTlc/tWX6a590fi3kMWImhyoWj46BWJWvO5oucZJzRnVVhYtes2D9g+5MKXjSdR7Es3456hB89v4/1pcBKg==",
"peerDependencies": {
"react": ">= 18.0.0",
"react-dom": ">= 18.0.0"
}
},
"node_modules/readable-stream": { "node_modules/readable-stream": {
"version": "2.3.7", "version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@ -6793,6 +6897,22 @@
"node": ">= 0.10" "node": ">= 0.10"
} }
}, },
"node_modules/redux": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz",
"integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==",
"dependencies": {
"@babel/runtime": "^7.9.2"
}
},
"node_modules/redux-thunk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
"integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==",
"peerDependencies": {
"redux": "^4"
}
},
"node_modules/regenerate": { "node_modules/regenerate": {
"version": "1.4.2", "version": "1.4.2",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
@ -6922,6 +7042,11 @@
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
"dev": true "dev": true
}, },
"node_modules/reselect": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz",
"integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A=="
},
"node_modules/resolve": { "node_modules/resolve": {
"version": "1.22.1", "version": "1.22.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
@ -8015,6 +8140,14 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"node_modules/use-sync-external-store": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/util-deprecate": { "node_modules/util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@ -10014,6 +10147,40 @@
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==" "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw=="
}, },
"@redux-devtools/core": {
"version": "3.13.1",
"resolved": "https://registry.npmjs.org/@redux-devtools/core/-/core-3.13.1.tgz",
"integrity": "sha512-VZbma4b28D7dLn6rKTxx4r1KJrgiT2EQNF4vjkpTlXTu0cQcHkEcAO9ixMBj6rZGrT/jinCHq8gBy2bWgnDvcA==",
"dev": true,
"requires": {
"@babel/runtime": "^7.18.3",
"@redux-devtools/instrument": "^2.1.0",
"@types/prop-types": "^15.7.5",
"lodash": "^4.17.21",
"prop-types": "^15.8.1"
}
},
"@redux-devtools/instrument": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@redux-devtools/instrument/-/instrument-2.1.0.tgz",
"integrity": "sha512-e8fo88kuq/zWqfNf6S/GNfaQMjF4WSPpucmYfRhzZyyXHC3PCLd/xgz7zooPErDh9QwUXK6sTVYvrkq7hPbsFA==",
"dev": true,
"requires": {
"@babel/runtime": "^7.16.7",
"lodash": "^4.17.21"
}
},
"@reduxjs/toolkit": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.0.tgz",
"integrity": "sha512-ak11IrjYcUXRqlhNPwnz6AcvA2ynJTu8PzDbbqQw4a3xR4KZtgiqbNblQD+10CRbfK4+5C79SOyxnT9dhBqFnA==",
"requires": {
"immer": "^9.0.16",
"redux": "^4.2.0",
"redux-thunk": "^2.4.2",
"reselect": "^4.1.7"
}
},
"@testing-library/dom": { "@testing-library/dom": {
"version": "8.19.0", "version": "8.19.0",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.19.0.tgz", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.19.0.tgz",
@ -10206,6 +10373,15 @@
"@types/unist": "*" "@types/unist": "*"
} }
}, },
"@types/hoist-non-react-statics": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
"requires": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"@types/http-proxy": { "@types/http-proxy": {
"version": "1.17.9", "version": "1.17.9",
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz", "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz",
@ -10284,7 +10460,7 @@
"version": "18.0.6", "version": "18.0.6",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.6.tgz", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.6.tgz",
"integrity": "sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==", "integrity": "sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==",
"dev": true, "devOptional": true,
"requires": { "requires": {
"@types/react": "*" "@types/react": "*"
} }
@ -10349,6 +10525,11 @@
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
"integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ=="
}, },
"@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"@types/ws": { "@types/ws": {
"version": "8.5.3", "version": "8.5.3",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
@ -11976,8 +12157,6 @@
"version": "3.3.2", "version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"optional": true,
"peer": true,
"requires": { "requires": {
"react-is": "^16.7.0" "react-is": "^16.7.0"
}, },
@ -11985,9 +12164,7 @@
"react-is": { "react-is": {
"version": "16.13.1", "version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
"optional": true,
"peer": true
} }
} }
}, },
@ -12103,6 +12280,11 @@
"integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
"dev": true "dev": true
}, },
"immer": {
"version": "9.0.16",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.16.tgz",
"integrity": "sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ=="
},
"import-fresh": { "import-fresh": {
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@ -13486,6 +13668,19 @@
"vfile": "^5.0.0" "vfile": "^5.0.0"
} }
}, },
"react-redux": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz",
"integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==",
"requires": {
"@babel/runtime": "^7.12.1",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/use-sync-external-store": "^0.0.3",
"hoist-non-react-statics": "^3.3.2",
"react-is": "^18.0.0",
"use-sync-external-store": "^1.0.0"
}
},
"react-refresh": { "react-refresh": {
"version": "0.14.0", "version": "0.14.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
@ -13512,12 +13707,6 @@
"prop-types": "^15.6.2" "prop-types": "^15.6.2"
} }
}, },
"react-use-websocket": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/react-use-websocket/-/react-use-websocket-4.2.0.tgz",
"integrity": "sha512-ZovaTlc/tWX6a590fi3kMWImhyoWj46BWJWvO5oucZJzRnVVhYtes2D9g+5MKXjSdR7Es3456hB89v4/1pcBKg==",
"requires": {}
},
"readable-stream": { "readable-stream": {
"version": "2.3.7", "version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@ -13568,6 +13757,20 @@
"resolve": "^1.9.0" "resolve": "^1.9.0"
} }
}, },
"redux": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz",
"integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==",
"requires": {
"@babel/runtime": "^7.9.2"
}
},
"redux-thunk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
"integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==",
"requires": {}
},
"regenerate": { "regenerate": {
"version": "1.4.2", "version": "1.4.2",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
@ -13673,6 +13876,11 @@
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
"dev": true "dev": true
}, },
"reselect": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz",
"integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A=="
},
"resolve": { "resolve": {
"version": "1.22.1", "version": "1.22.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
@ -14482,6 +14690,12 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"use-sync-external-store": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
"requires": {}
},
"util-deprecate": { "util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",

@ -8,6 +8,7 @@
"@fontsource/roboto-mono": "^4.5.8", "@fontsource/roboto-mono": "^4.5.8",
"@mui/icons-material": "^5.10.6", "@mui/icons-material": "^5.10.6",
"@mui/material": "^5.10.9", "@mui/material": "^5.10.9",
"@reduxjs/toolkit": "^1.9.0",
"@types/cytoscape": "^3.19.9", "@types/cytoscape": "^3.19.9",
"better-react-mathjax": "^2.0.2", "better-react-mathjax": "^2.0.2",
"cytoscape": "^3.23.0", "cytoscape": "^3.23.0",
@ -18,7 +19,7 @@
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-markdown": "^8.0.3", "react-markdown": "^8.0.3",
"react-use-websocket": "^4.2.0", "react-redux": "^8.0.5",
"vscode-ws-jsonrpc": "^2.0.0", "vscode-ws-jsonrpc": "^2.0.0",
"ws": "^8.9.0" "ws": "^8.9.0"
}, },
@ -29,6 +30,7 @@
"@babel/preset-react": "^7.0.0", "@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.18.6", "@babel/preset-typescript": "^7.18.6",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.8", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.8",
"@redux-devtools/core": "^3.13.1",
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
"babel-loader": "^8.2.5", "babel-loader": "^8.2.5",
"concurrently": "^7.4.0", "concurrently": "^7.4.0",

Loading…
Cancel
Save