use redux
This commit is contained in:
+5
-17
@@ -14,29 +14,15 @@ import { AppBar, CssBaseline, Toolbar, Typography } from '@mui/material';
|
||||
import Welcome from './components/Welcome';
|
||||
import Level from './components/Level';
|
||||
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'
|
||||
|
||||
const socketUrl = ((window.location.protocol === "https:") ? "wss://" : "ws://") + window.location.host + '/websocket/'
|
||||
|
||||
monacoSetup()
|
||||
import { useAppSelector } from './hooks';
|
||||
|
||||
function App() {
|
||||
const [title, setTitle] = useState("")
|
||||
const [conclusion, setConclusion] = useState("")
|
||||
const [levelTitle, setLevelTitle] = useState("")
|
||||
const [nbLevels, setNbLevels] = useState(0)
|
||||
const [curLevel, setCurLevel] = useState(0)
|
||||
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 = {
|
||||
loader: {
|
||||
@@ -58,11 +44,13 @@ function App() {
|
||||
if (finished) {
|
||||
mainComponent = <GoodBye message={conclusion} />
|
||||
} 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 {
|
||||
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 (
|
||||
<div className="App">
|
||||
<MathJaxContext config={mathJaxConfig}>
|
||||
|
||||
@@ -22,9 +22,9 @@ import 'lean4web/client/src/editor/infoview.css'
|
||||
import { renderInfoview } from '@leanprover/infoview'
|
||||
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js'
|
||||
import './level.css'
|
||||
import { ConnectionContext } from '../connection';
|
||||
|
||||
interface LevelProps {
|
||||
leanClient: null|LeanClient;
|
||||
nbLevels: any;
|
||||
level: any;
|
||||
setCurLevel: any;
|
||||
@@ -32,7 +32,7 @@ interface LevelProps {
|
||||
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 [tacticDocs, setTacticDocs] = useState([])
|
||||
const [lemmaDocs, setLemmaDocs] = useState([])
|
||||
@@ -72,6 +72,8 @@ function Level({ leanClient, nbLevels, level, setCurLevel, setLevelTitle, setFin
|
||||
messagePanelRef.current!.scrollTo(0,0)
|
||||
}, [level])
|
||||
|
||||
const leanClient = React.useContext(ConnectionContext)
|
||||
|
||||
useEffect(() => {
|
||||
const editor = monaco.editor.create(codeviewRef.current!, {
|
||||
glyphMargin: true,
|
||||
|
||||
@@ -9,30 +9,25 @@ import '@fontsource/roboto/700.css';
|
||||
import * as rpc from 'vscode-ws-jsonrpc';
|
||||
import cytoscape from 'cytoscape'
|
||||
import klay from 'cytoscape-klay';
|
||||
import { useSelector, useDispatch } from 'react-redux'
|
||||
import { fetchGame } from '../game/gameSlice'
|
||||
|
||||
cytoscape.use( klay );
|
||||
|
||||
import { Box, Typography, Button, CircularProgress, Grid } from '@mui/material';
|
||||
import { LeanClient } from 'lean4web/client/src/editor/leanclient';
|
||||
import { ConnectionContext } from '../connection';
|
||||
import { useAppDispatch, useAppSelector } from '../hooks';
|
||||
|
||||
interface WelcomeProps {
|
||||
leanClient: null|LeanClient;
|
||||
setNbLevels: any;
|
||||
setTitle: any;
|
||||
startGame: any;
|
||||
setConclusion: any;
|
||||
}
|
||||
|
||||
type infoResultType = {
|
||||
title: string,
|
||||
nb_levels: any[],
|
||||
conclusion: string
|
||||
worlds: {edges: string[][], nodes: string[]}
|
||||
}
|
||||
function Welcome({ setNbLevels, startGame, setConclusion }: WelcomeProps) {
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
function Welcome({ leanClient, setNbLevels, setTitle, startGame, setConclusion }: WelcomeProps) {
|
||||
|
||||
const [leanData, setLeanData] = useState<null|infoResultType>(null)
|
||||
const worldsRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const drawWorlds = (worlds) => {
|
||||
@@ -78,42 +73,34 @@ function Welcome({ leanClient, setNbLevels, setTitle, startGame, setConclusion }
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!leanClient) return;
|
||||
useEffect(() => { dispatch(fetchGame); }, [])
|
||||
|
||||
const getInfo = async () => {
|
||||
await leanClient.start() // TODO: need a way to wait for start without restarting
|
||||
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])
|
||||
const worlds = useAppSelector(state => state.game.worlds)
|
||||
useEffect(() => { if (worlds) { drawWorlds(worlds); } }, [worlds])
|
||||
|
||||
let content
|
||||
if (leanData) {
|
||||
content = (<Box sx={{ m: 3 }}>
|
||||
<Typography variant="body1" component="div">
|
||||
<MathJax>
|
||||
<ReactMarkdown>{leanData["introduction"]}</ReactMarkdown>
|
||||
</MathJax>
|
||||
</Typography>
|
||||
const title = useAppSelector(state => state.game.title)
|
||||
useEffect(() => { window.document.title = title }, [title])
|
||||
|
||||
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">
|
||||
<MathJax>
|
||||
<ReactMarkdown>{introduction}</ReactMarkdown>
|
||||
</MathJax>
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box textAlign='center' sx={{ m: 5 }}>
|
||||
<Button onClick={startGame} variant="contained">Start rescue mission</Button>
|
||||
</Box>
|
||||
</Box>)
|
||||
} else {
|
||||
content = <Box display="flex" alignItems="center" justifyContent="center" sx={{ height: "calc(100vh - 64px)" }}><CircularProgress /></Box>
|
||||
<div ref={worldsRef} style={{"width": "100%","height": "50em"}} />
|
||||
</div>
|
||||
: <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>
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
+13
-1
@@ -2,7 +2,19 @@ import * as React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import { store } from './store';
|
||||
import { Provider } from 'react-redux';
|
||||
import { ConnectionContext, leanClient } from './connection'
|
||||
|
||||
|
||||
const container = document.getElementById('root');
|
||||
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
|
||||
Generated
+242
-28
@@ -12,6 +12,7 @@
|
||||
"@fontsource/roboto-mono": "^4.5.8",
|
||||
"@mui/icons-material": "^5.10.6",
|
||||
"@mui/material": "^5.10.9",
|
||||
"@reduxjs/toolkit": "^1.9.0",
|
||||
"@types/cytoscape": "^3.19.9",
|
||||
"better-react-mathjax": "^2.0.2",
|
||||
"cytoscape": "^3.23.0",
|
||||
@@ -22,7 +23,7 @@
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-markdown": "^8.0.3",
|
||||
"react-use-websocket": "^4.2.0",
|
||||
"react-redux": "^8.0.5",
|
||||
"vscode-ws-jsonrpc": "^2.0.0",
|
||||
"ws": "^8.9.0"
|
||||
},
|
||||
@@ -33,6 +34,7 @@
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@babel/preset-typescript": "^7.18.6",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.8",
|
||||
"@redux-devtools/core": "^3.13.1",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"babel-loader": "^8.2.5",
|
||||
"concurrently": "^7.4.0",
|
||||
@@ -2009,6 +2011,60 @@
|
||||
"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": {
|
||||
"version": "8.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.19.0.tgz",
|
||||
@@ -2230,6 +2286,15 @@
|
||||
"@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": {
|
||||
"version": "1.17.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz",
|
||||
@@ -2308,7 +2373,7 @@
|
||||
"version": "18.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.6.tgz",
|
||||
"integrity": "sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
@@ -2373,6 +2438,11 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
|
||||
"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": {
|
||||
"version": "8.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
|
||||
@@ -4501,8 +4571,6 @@
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
|
||||
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"react-is": "^16.7.0"
|
||||
}
|
||||
@@ -4510,9 +4578,7 @@
|
||||
"node_modules/hoist-non-react-statics/node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
},
|
||||
"node_modules/hpack.js": {
|
||||
"version": "2.1.6",
|
||||
@@ -4665,6 +4731,15 @@
|
||||
"integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
|
||||
"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": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||
@@ -6694,6 +6769,44 @@
|
||||
"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": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
|
||||
@@ -6730,15 +6843,6 @@
|
||||
"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": {
|
||||
"version": "2.3.7",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||
@@ -6793,6 +6897,22 @@
|
||||
"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": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
||||
@@ -6922,6 +7042,11 @@
|
||||
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
|
||||
"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": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
|
||||
@@ -8015,6 +8140,14 @@
|
||||
"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": {
|
||||
"version": "1.0.2",
|
||||
"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",
|
||||
"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": {
|
||||
"version": "8.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.19.0.tgz",
|
||||
@@ -10206,6 +10373,15 @@
|
||||
"@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": {
|
||||
"version": "1.17.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz",
|
||||
@@ -10284,7 +10460,7 @@
|
||||
"version": "18.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.6.tgz",
|
||||
"integrity": "sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
@@ -10349,6 +10525,11 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
|
||||
"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": {
|
||||
"version": "8.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
|
||||
@@ -11976,8 +12157,6 @@
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
|
||||
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"react-is": "^16.7.0"
|
||||
},
|
||||
@@ -11985,9 +12164,7 @@
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -12103,6 +12280,11 @@
|
||||
"integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
|
||||
"dev": true
|
||||
},
|
||||
"immer": {
|
||||
"version": "9.0.16",
|
||||
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.16.tgz",
|
||||
"integrity": "sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ=="
|
||||
},
|
||||
"import-fresh": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||
@@ -13486,6 +13668,19 @@
|
||||
"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": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
|
||||
@@ -13512,12 +13707,6 @@
|
||||
"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": {
|
||||
"version": "2.3.7",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||
@@ -13568,6 +13757,20 @@
|
||||
"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": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
||||
@@ -13673,6 +13876,11 @@
|
||||
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
|
||||
"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": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
|
||||
@@ -14482,6 +14690,12 @@
|
||||
"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": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
|
||||
+3
-1
@@ -8,6 +8,7 @@
|
||||
"@fontsource/roboto-mono": "^4.5.8",
|
||||
"@mui/icons-material": "^5.10.6",
|
||||
"@mui/material": "^5.10.9",
|
||||
"@reduxjs/toolkit": "^1.9.0",
|
||||
"@types/cytoscape": "^3.19.9",
|
||||
"better-react-mathjax": "^2.0.2",
|
||||
"cytoscape": "^3.23.0",
|
||||
@@ -18,7 +19,7 @@
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-markdown": "^8.0.3",
|
||||
"react-use-websocket": "^4.2.0",
|
||||
"react-redux": "^8.0.5",
|
||||
"vscode-ws-jsonrpc": "^2.0.0",
|
||||
"ws": "^8.9.0"
|
||||
},
|
||||
@@ -29,6 +30,7 @@
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@babel/preset-typescript": "^7.18.6",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.8",
|
||||
"@redux-devtools/core": "^3.13.1",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"babel-loader": "^8.2.5",
|
||||
"concurrently": "^7.4.0",
|
||||
|
||||
Reference in New Issue
Block a user