diff --git a/client/.env b/client/.env index 1f93d77af..a17d2ddf5 100644 --- a/client/.env +++ b/client/.env @@ -1,6 +1,7 @@ EXTEND_ESLINT = true # This prod site root assumes the netlify build context $URL is available, replace for other hosts + REACT_APP_SITE_ROOT_URL_PROD=https://thoth.latitude.io REACT_APP_SITE_ROOT_URL=http://localhost:3001 @@ -10,4 +11,7 @@ REACT_APP_LAPI_ROOT_URL_PROD=https://api.latitude.io REACT_APP_SITE_STAGING=https://62264f21c3a9860ad1e5bdd3--optimistic-turing-def916.netlify.app/ # Oauth Client Id -REACT_APP_OAUTH_CLIENT_ID=a6b51c87-7565-42ab-a4b0-38a07f3b6c56 \ No newline at end of file + +REACT_APP_OAUTH_CLIENT_ID=a6b51c87-7565-42ab-a4b0-38a07f3b6c56 + +REACT_APP_SHAREDB=false diff --git a/client/package.json b/client/package.json index a380c0f03..6d0f25876 100644 --- a/client/package.json +++ b/client/package.json @@ -21,17 +21,16 @@ }, "dependencies": { "@callstack/async-storage": "^2.0.3", - "@latitudegames/thoth-core": "0.0.65", - "@material-ui/core": "^4.12.1", - "@material-ui/icons": "^4.11.2", + "@emotion/react": "^11.8.2", + "@emotion/styled": "^11.8.1", + "@latitudegames/thoth-core": "0.0.66", "@monaco-editor/react": "^4.2.1", + "@mui/icons-material": "^5.5.1", + "@mui/material": "^5.5.3", + "@mui/styles": "^5.5.3", "@rebass/forms": "^4.0.6", "@reduxjs/toolkit": "^1.6.2", - "@types/jest": "^26.0.24", - "@types/node": "^16.4.3", - "@types/react": "^17.0.15", - "@types/react-dom": "^17.0.9", - "@types/react-redux": "^7.1.18", + "add": "^2.0.6", "classnames": "^2.3.1", "deep-equal": "^2.0.5", "eslint-config-react-app": "^6.0.0", @@ -39,10 +38,7 @@ "handlebars": "^4.7.7", "history": "^5.0.1", "json-format": "^1.0.1", - "notistack": "^1.0.9", - "pouchdb": "^7.2.2", - "pouchdb-adapter-idb": "^7.2.2", - "pouchdb-find": "^7.2.2", + "notistack": "^2.0.3", "prism-themes": "^1.7.0", "prismjs": "^1.24.0", "pubsub-js": "^1.9.3", @@ -53,24 +49,24 @@ "react-hook-form": "^7.15.4", "react-hotkeys-hook": "^3.3.2", "react-icons": "^4.2.0", - "react-pouchdb": "^2.1.0", "react-redux": "^7.2.5", "react-router": "^6.0.0-beta.8", "react-router-dom": "6", "react-select": "^4.3.1", "react-simple-code-editor": "^0.11.0", "rebass": "^4.0.7", + "reconnecting-websocket": "^4.4.0", "redux": "^4.1.1", + "redux-persist": "^6.0.0", "regenerator-runtime": "^0.13.9", + "rete-comment-plugin": "^0.7.0-rc.1", "rete-connection-reroute-plugin": "^0.4.0", "rete-context-menu-plugin": "^0.6.0-rc.1", "rete-react-render-plugin": "^0.2.1", - "rxdb": "^9.21.0", - "rxjs": "^7.2.0", + "sharedb": "^2.2.5", "unique-names-generator": "^4.5.0", "uuid": "^8.3.2", - "web-vitals": "^1.0.1", - "wouter": "^2.7.4" + "web-vitals": "^1.0.1" }, "devDependencies": { "@babel/plugin-external-helpers": "^7.14.5", @@ -82,6 +78,11 @@ "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", + "@types/jest": "^26.0.24", + "@types/node": "^16.4.3", + "@types/react": "^17.0.15", + "@types/react-dom": "^17.0.9", + "@types/react-redux": "^7.1.18", "@welldone-software/why-did-you-render": "^6.2.1", "babel-loader": "^8.2.2", "babel-plugin-transform-class-properties": "^6.24.1", diff --git a/client/src/App.tsx b/client/src/App.tsx index 6fe2169ed..c5920d86f 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,20 +1,23 @@ import { Routes, Route, Navigate } from 'react-router-dom' -import { useTabManager } from './contexts/TabManagerProvider' -import RequireAuth from './features/common/RequireAuth/RequireAuth' -import ThothPageWrapper from './features/common/ThothPage/ThothPageWrapper' -import HomeScreen from './features/HomeScreen/HomeScreen' -import Thoth from './features/Thoth/Thoth' +import RequireAuth from './components/RequireAuth/RequireAuth' +import ThothPageWrapper from './components/ThothPage/ThothPageWrapper' +import HomeScreen from './screens/HomeScreen/HomeScreen' +import Thoth from './screens/Thoth/Thoth' import { useAuth } from './contexts/AuthProvider' import 'flexlayout-react/style/dark.css' import './design-globals/design-globals.css' import './App.css' +import { activeTabSelector, selectAllTabs } from './state/tabs' +import { useSelector } from 'react-redux' +import { RootState } from './state/store' //These need to be imported last to override styles. function App() { // Use our routes - const { tabs, activeTab } = useTabManager() + const tabs = useSelector((state: RootState) => selectAllTabs(state.tabs)) + const activeTab = useSelector(activeTabSelector) const { user } = useAuth() const redirect = () => { diff --git a/client/src/features/common/Accordion.tsx b/client/src/components/Accordion.tsx similarity index 79% rename from client/src/features/common/Accordion.tsx rename to client/src/components/Accordion.tsx index 783e94c7d..ebd4cd10c 100644 --- a/client/src/features/common/Accordion.tsx +++ b/client/src/components/Accordion.tsx @@ -1,9 +1,9 @@ -import Accordion from '@material-ui/core/Accordion' -import AccordionDetails from '@material-ui/core/AccordionDetails' -import AccordionSummary from '@material-ui/core/AccordionSummary' -import { makeStyles } from '@material-ui/core/styles' -import Typography from '@material-ui/core/Typography' -import ExpandMoreIcon from '@material-ui/icons/ExpandMore' +import Accordion from '@mui/material/Accordion' +import AccordionDetails from '@mui/material/AccordionDetails' +import AccordionSummary from '@mui/material/AccordionSummary' +import makeStyles from '@mui/styles/makeStyles' +import Typography from '@mui/material/Typography' +import ExpandMoreIcon from '@mui/icons-material/ExpandMore' import css from './accordion.module.css' import Icon from './Icon/Icon' @@ -12,7 +12,7 @@ import './accordion-overrides.css' const useStyles = makeStyles(theme => ({ root: { width: '100%', - backgroundColor: 'var(--dark-3)', + backgroundColor: 'var(--dark-3) !important', boxShadow: 'none', padding: '0', }, @@ -59,7 +59,8 @@ export const SimpleAccordion = ({ setExpanded = x => {}, ...props }) => { className={classes.accordionSummary} classes={{ root: classes.root, - expandIcon: classes.expandIcon, + expandIconWrapper: classes.expandIcon, + // content: classes.root, // accordionSummaryContent: classes.summaryContent }} id="panel1a-header" diff --git a/client/src/features/common/Button/button.module.css b/client/src/components/Button/button.module.css similarity index 100% rename from client/src/features/common/Button/button.module.css rename to client/src/components/Button/button.module.css diff --git a/client/src/features/common/Chip/Chip.jsx b/client/src/components/Chip/Chip.tsx similarity index 54% rename from client/src/features/common/Chip/Chip.jsx rename to client/src/components/Chip/Chip.tsx index 6d713ede9..ffbf10105 100644 --- a/client/src/features/common/Chip/Chip.jsx +++ b/client/src/components/Chip/Chip.tsx @@ -1,10 +1,18 @@ import Icon from '../Icon/Icon' import css from './chip.module.css' -const Chip = ({ label, onClick, noEvents }) => { +const Chip = ({ + label, + onClick, + noEvents, +}: { + label: string + onClick?: () => {} + noEvents?: boolean +}) => { return (
{label} diff --git a/client/src/features/common/Chip/chip.module.css b/client/src/components/Chip/chip.module.css similarity index 100% rename from client/src/features/common/Chip/chip.module.css rename to client/src/components/Chip/chip.module.css diff --git a/client/src/features/common/Chip/chip.module.css.d.ts b/client/src/components/Chip/chip.module.css.d.ts similarity index 100% rename from client/src/features/common/Chip/chip.module.css.d.ts rename to client/src/components/Chip/chip.module.css.d.ts diff --git a/client/src/features/common/Icon/Icon.tsx b/client/src/components/Icon/Icon.tsx similarity index 100% rename from client/src/features/common/Icon/Icon.tsx rename to client/src/components/Icon/Icon.tsx diff --git a/client/src/components/Icon/Lock.svg b/client/src/components/Icon/Lock.svg new file mode 100644 index 000000000..da90f6c38 --- /dev/null +++ b/client/src/components/Icon/Lock.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/client/src/features/common/Icon/account.svg b/client/src/components/Icon/account.svg similarity index 100% rename from client/src/features/common/Icon/account.svg rename to client/src/components/Icon/account.svg diff --git a/client/src/features/common/Icon/add.svg b/client/src/components/Icon/add.svg similarity index 100% rename from client/src/features/common/Icon/add.svg rename to client/src/components/Icon/add.svg diff --git a/client/src/features/common/Icon/ankh.svg b/client/src/components/Icon/ankh.svg similarity index 100% rename from client/src/features/common/Icon/ankh.svg rename to client/src/components/Icon/ankh.svg diff --git a/client/src/features/common/Icon/bird.svg b/client/src/components/Icon/bird.svg similarity index 100% rename from client/src/features/common/Icon/bird.svg rename to client/src/components/Icon/bird.svg diff --git a/client/src/features/common/Icon/close.svg b/client/src/components/Icon/close.svg similarity index 100% rename from client/src/features/common/Icon/close.svg rename to client/src/components/Icon/close.svg diff --git a/client/src/features/common/Icon/cloth.svg b/client/src/components/Icon/cloth.svg similarity index 100% rename from client/src/features/common/Icon/cloth.svg rename to client/src/components/Icon/cloth.svg diff --git a/client/src/features/common/Icon/cup.svg b/client/src/components/Icon/cup.svg similarity index 100% rename from client/src/features/common/Icon/cup.svg rename to client/src/components/Icon/cup.svg diff --git a/client/src/features/common/Icon/dangerTrash.svg b/client/src/components/Icon/dangerTrash.svg similarity index 100% rename from client/src/features/common/Icon/dangerTrash.svg rename to client/src/components/Icon/dangerTrash.svg diff --git a/client/src/features/common/Icon/feathers.svg b/client/src/components/Icon/feathers.svg similarity index 100% rename from client/src/features/common/Icon/feathers.svg rename to client/src/components/Icon/feathers.svg diff --git a/client/src/features/common/Icon/fewshot.svg b/client/src/components/Icon/fewshot.svg similarity index 100% rename from client/src/features/common/Icon/fewshot.svg rename to client/src/components/Icon/fewshot.svg diff --git a/client/src/features/common/Icon/folder.svg b/client/src/components/Icon/folder.svg similarity index 100% rename from client/src/features/common/Icon/folder.svg rename to client/src/components/Icon/folder.svg diff --git a/client/src/features/common/Icon/hand.svg b/client/src/components/Icon/hand.svg similarity index 100% rename from client/src/features/common/Icon/hand.svg rename to client/src/components/Icon/hand.svg diff --git a/client/src/features/common/Icon/icon.module.css b/client/src/components/Icon/icon.module.css similarity index 97% rename from client/src/features/common/Icon/icon.module.css rename to client/src/components/Icon/icon.module.css index 64f115710..c96935730 100644 --- a/client/src/features/common/Icon/icon.module.css +++ b/client/src/components/Icon/icon.module.css @@ -136,3 +136,7 @@ .trash:hover { background-image: url('dangerTrash.svg'); } + +.node-lock { + background-image: url('node-lock.svg'); +} diff --git a/client/src/features/common/Icon/icon.module.css.d.ts b/client/src/components/Icon/icon.module.css.d.ts similarity index 97% rename from client/src/features/common/Icon/icon.module.css.d.ts rename to client/src/components/Icon/icon.module.css.d.ts index 59645227f..d96641326 100644 --- a/client/src/features/common/Icon/icon.module.css.d.ts +++ b/client/src/components/Icon/icon.module.css.d.ts @@ -18,6 +18,7 @@ interface CssExports { 'minus': string; 'moon': string; 'newnode': string; + 'node-lock': string; 'pause': string; 'person': string; 'play': string; diff --git a/client/src/features/common/Icon/info.svg b/client/src/components/Icon/info.svg similarity index 100% rename from client/src/features/common/Icon/info.svg rename to client/src/components/Icon/info.svg diff --git a/client/src/features/common/Icon/merge.svg b/client/src/components/Icon/merge.svg similarity index 100% rename from client/src/features/common/Icon/merge.svg rename to client/src/components/Icon/merge.svg diff --git a/client/src/features/common/Icon/minus.svg b/client/src/components/Icon/minus.svg similarity index 100% rename from client/src/features/common/Icon/minus.svg rename to client/src/components/Icon/minus.svg diff --git a/client/src/features/common/Icon/moon.svg b/client/src/components/Icon/moon.svg similarity index 100% rename from client/src/features/common/Icon/moon.svg rename to client/src/components/Icon/moon.svg diff --git a/client/src/features/common/Icon/newnode.svg b/client/src/components/Icon/newnode.svg similarity index 100% rename from client/src/features/common/Icon/newnode.svg rename to client/src/components/Icon/newnode.svg diff --git a/client/src/components/Icon/node-lock.svg b/client/src/components/Icon/node-lock.svg new file mode 100644 index 000000000..86a39d67a --- /dev/null +++ b/client/src/components/Icon/node-lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/src/features/common/Icon/pause.svg b/client/src/components/Icon/pause.svg similarity index 100% rename from client/src/features/common/Icon/pause.svg rename to client/src/components/Icon/pause.svg diff --git a/client/src/features/common/Icon/person.svg b/client/src/components/Icon/person.svg similarity index 100% rename from client/src/features/common/Icon/person.svg rename to client/src/components/Icon/person.svg diff --git a/client/src/features/common/Icon/play-print.svg b/client/src/components/Icon/play-print.svg similarity index 100% rename from client/src/features/common/Icon/play-print.svg rename to client/src/components/Icon/play-print.svg diff --git a/client/src/features/common/Icon/play.svg b/client/src/components/Icon/play.svg similarity index 100% rename from client/src/features/common/Icon/play.svg rename to client/src/components/Icon/play.svg diff --git a/client/src/features/common/Icon/properties.svg b/client/src/components/Icon/properties.svg similarity index 100% rename from client/src/features/common/Icon/properties.svg rename to client/src/components/Icon/properties.svg diff --git a/client/src/features/common/Icon/refresh.svg b/client/src/components/Icon/refresh.svg similarity index 100% rename from client/src/features/common/Icon/refresh.svg rename to client/src/components/Icon/refresh.svg diff --git a/client/src/features/common/Icon/search.svg b/client/src/components/Icon/search.svg similarity index 100% rename from client/src/features/common/Icon/search.svg rename to client/src/components/Icon/search.svg diff --git a/client/src/features/common/Icon/seive.svg b/client/src/components/Icon/seive.svg similarity index 100% rename from client/src/features/common/Icon/seive.svg rename to client/src/components/Icon/seive.svg diff --git a/client/src/features/common/Icon/snake.svg b/client/src/components/Icon/snake.svg similarity index 100% rename from client/src/features/common/Icon/snake.svg rename to client/src/components/Icon/snake.svg diff --git a/client/src/features/common/Icon/state-read.svg b/client/src/components/Icon/state-read.svg similarity index 100% rename from client/src/features/common/Icon/state-read.svg rename to client/src/components/Icon/state-read.svg diff --git a/client/src/features/common/Icon/state-write.svg b/client/src/components/Icon/state-write.svg similarity index 100% rename from client/src/features/common/Icon/state-write.svg rename to client/src/components/Icon/state-write.svg diff --git a/client/src/features/common/Icon/state.svg b/client/src/components/Icon/state.svg similarity index 100% rename from client/src/features/common/Icon/state.svg rename to client/src/components/Icon/state.svg diff --git a/client/src/features/common/Icon/stop-sign.svg b/client/src/components/Icon/stop-sign.svg similarity index 100% rename from client/src/features/common/Icon/stop-sign.svg rename to client/src/components/Icon/stop-sign.svg diff --git a/client/src/features/common/Icon/stop.svg b/client/src/components/Icon/stop.svg similarity index 100% rename from client/src/features/common/Icon/stop.svg rename to client/src/components/Icon/stop.svg diff --git a/client/src/features/common/Icon/switch.svg b/client/src/components/Icon/switch.svg similarity index 100% rename from client/src/features/common/Icon/switch.svg rename to client/src/components/Icon/switch.svg diff --git a/client/src/features/common/Icon/temperature.svg b/client/src/components/Icon/temperature.svg similarity index 100% rename from client/src/features/common/Icon/temperature.svg rename to client/src/components/Icon/temperature.svg diff --git a/client/src/features/common/Icon/text.svg b/client/src/components/Icon/text.svg similarity index 100% rename from client/src/features/common/Icon/text.svg rename to client/src/components/Icon/text.svg diff --git a/client/src/features/common/Icon/tiles.svg b/client/src/components/Icon/tiles.svg similarity index 100% rename from client/src/features/common/Icon/tiles.svg rename to client/src/components/Icon/tiles.svg diff --git a/client/src/features/common/Icon/time.svg b/client/src/components/Icon/time.svg similarity index 100% rename from client/src/features/common/Icon/time.svg rename to client/src/components/Icon/time.svg diff --git a/client/src/features/common/Icon/trash.svg b/client/src/components/Icon/trash.svg similarity index 100% rename from client/src/features/common/Icon/trash.svg rename to client/src/components/Icon/trash.svg diff --git a/client/src/features/common/Icon/warn.svg b/client/src/components/Icon/warn.svg similarity index 100% rename from client/src/features/common/Icon/warn.svg rename to client/src/components/Icon/warn.svg diff --git a/client/src/features/common/Icon/water-play.svg b/client/src/components/Icon/water-play.svg similarity index 100% rename from client/src/features/common/Icon/water-play.svg rename to client/src/components/Icon/water-play.svg diff --git a/client/src/features/common/Icon/water-run.svg b/client/src/components/Icon/water-run.svg similarity index 100% rename from client/src/features/common/Icon/water-run.svg rename to client/src/components/Icon/water-run.svg diff --git a/client/src/features/common/Icon/water.svg b/client/src/components/Icon/water.svg similarity index 100% rename from client/src/features/common/Icon/water.svg rename to client/src/components/Icon/water.svg diff --git a/client/src/features/common/Input/Input.tsx b/client/src/components/Input/Input.tsx similarity index 100% rename from client/src/features/common/Input/Input.tsx rename to client/src/components/Input/Input.tsx diff --git a/client/src/features/common/Input/input.module.css b/client/src/components/Input/input.module.css similarity index 100% rename from client/src/features/common/Input/input.module.css rename to client/src/components/Input/input.module.css diff --git a/client/src/features/common/LoadingScreen/LoadingScreen.jsx b/client/src/components/LoadingScreen/LoadingScreen.jsx similarity index 100% rename from client/src/features/common/LoadingScreen/LoadingScreen.jsx rename to client/src/components/LoadingScreen/LoadingScreen.jsx diff --git a/client/src/features/common/LoadingScreen/ankh.gif b/client/src/components/LoadingScreen/ankh.gif similarity index 100% rename from client/src/features/common/LoadingScreen/ankh.gif rename to client/src/components/LoadingScreen/ankh.gif diff --git a/client/src/features/common/MenuBar/MenuBar.js b/client/src/components/MenuBar/MenuBar.tsx similarity index 51% rename from client/src/features/common/MenuBar/MenuBar.js rename to client/src/components/MenuBar/MenuBar.tsx index 3183d21b5..f67acd12c 100644 --- a/client/src/features/common/MenuBar/MenuBar.js +++ b/client/src/components/MenuBar/MenuBar.tsx @@ -1,22 +1,25 @@ import React, { useState, useEffect, useRef } from 'react' import { useHotkeys } from 'react-hotkeys-hook' -import { useModal } from '../../../contexts/ModalProvider' -import { usePubSub } from '../../../contexts/PubSubProvider' -import { useTabManager } from '../../../contexts/TabManagerProvider' +import { useModal } from '../../contexts/ModalProvider' +import { usePubSub } from '../../contexts/PubSubProvider' import css from './menuBar.module.css' import thothlogo from './thoth.png' import { useNavigate } from 'react-router-dom' +import { useSelector } from 'react-redux' +import { activeTabSelector, Tab } from '@/state/tabs' const MenuBar = () => { const navigate = useNavigate() const { publish, events } = usePubSub() - const { activeTab } = useTabManager() + const activeTab = useSelector(activeTabSelector) + const { openModal } = useModal() - const activeTabRef = useRef(null) + const activeTabRef = useRef(null) useEffect(() => { + if (!activeTab) return activeTabRef.current = activeTab }, [activeTab]) @@ -27,8 +30,11 @@ const MenuBar = () => { $CREATE_PLAYTEST, $CREATE_INSPECTOR, $CREATE_TEXT_EDITOR, + $CREATE_CONSOLE, $SERIALIZE, $EXPORT, + $UNDO, + $REDO, } = events const useToggle = (initialValue = false) => { @@ -36,11 +42,12 @@ const MenuBar = () => { const toggle = React.useCallback(() => { setValue(v => !v) }, []) - return [value, toggle] + return [value, toggle as () => void] } const [menuVisibility, togglemenuVisibility] = useToggle() const onSave = () => { + if (!activeTabRef.current) return publish($SAVE_SPELL(activeTabRef.current.id)) } @@ -52,6 +59,7 @@ const MenuBar = () => { } const onEdit = () => { + if (!activeTabRef.current) return openModal({ modal: 'editSpellModal', content: 'This is an example modal', @@ -69,88 +77,90 @@ const MenuBar = () => { } const onSerialize = () => { + if (!activeTabRef.current) return publish($SERIALIZE(activeTabRef.current.id)) } const onStateManagerCreate = () => { + if (!activeTabRef.current) return publish($CREATE_STATE_MANAGER(activeTabRef.current.id)) } const onPlaytestCreate = () => { + if (!activeTabRef.current) return publish($CREATE_PLAYTEST(activeTabRef.current.id)) } const onInspectorCreate = () => { + if (!activeTabRef.current) return publish($CREATE_INSPECTOR(activeTabRef.current.id)) } const onTextEditorCreate = () => { + if (!activeTabRef.current) return publish($CREATE_TEXT_EDITOR(activeTabRef.current.id)) } const onExport = () => { + if (!activeTabRef.current) return publish($EXPORT(activeTabRef.current.id)) } - const onModal = () => { - openModal({ modal: 'example', content: 'This is an example modal' }) + const onConsole = () => { + if (!activeTabRef.current) return + publish($CREATE_CONSOLE(activeTabRef.current.id)) } - //Menu bar hotkeys - useHotkeys( - 'cmd+s, crtl+s', - event => { - event.preventDefault() - onSave() - }, - { enableOnTags: 'INPUT' }, - [onSave] - ) + const onUndo = () => { + if (!activeTabRef.current) return + publish($UNDO(activeTabRef.current.id)) + } - useHotkeys( - 'option+n, crtl+n', - event => { - event.preventDefault() - onNew() - }, - { enableOnTags: 'INPUT' }, - [onNew] - ) + const onRedo = () => { + if (!activeTabRef.current) return + publish($REDO(activeTabRef.current.id)) + } //Menu bar entries const menuBarItems = { file: { items: { - new_project: { + new_spell: { onClick: onNew, + hotKey: 'option+n', }, - open_project: { + open_spell: { onClick: onOpen, + hotKey: 'option+o', }, - edit_project: { + edit_spell: { onClick: onEdit, + hotKey: 'option+e', + }, + save_spell: { + onClick: onSave, + hotKey: 'option+s', }, - save: { - items: { - save_project: { - onClick: onSave, - }, - save_project_as: { - onClick: onSaveAs, - }, - export_project: { - onClick: onExport, - }, - }, + save_spell_as: { + onClick: onSaveAs, + hotKey: 'option+shift+s', + }, + export_spell: { + onClick: onExport, + hotKey: 'option+shift+e', }, }, }, edit: { items: { - undo: {}, - redo: {}, - copy: {}, - paste: {}, + undo: { + onClick: onUndo, + hotKey: 'option+z', + }, + redo: { + onClick: onRedo, + hotKey: 'option+shift+z', + }, }, }, dev: { @@ -160,67 +170,67 @@ const MenuBar = () => { }, }, }, - studio: { + windows: { items: { - tools: { - items: { - text_editor: { - onClick: onTextEditorCreate, - }, - inspector: { - onClick: onInspectorCreate, - }, - state_manager: { - onClick: onStateManagerCreate, - }, - playtest: { - onClick: onPlaytestCreate, - }, - enki: { - items: { - fewshots: {}, - serialization: {}, - preamble: {}, - }, - }, - test: { - items: { - 'open modal ...': { - onClick: onModal, - }, - }, - }, - }, + text_editor: { + onClick: onTextEditorCreate, + }, + inspector: { + onClick: onInspectorCreate, + }, + state_manager: { + onClick: onStateManagerCreate, + }, + playtest: { + onClick: onPlaytestCreate, }, - change_layout: { - items: { - multishot_editing: {}, - enki_fewshot_editing: {}, - node_editing: {}, - }, + console: { + onClick: onConsole, }, }, }, } + const parseStringToUnicode = commandString => { + let formattedCommand = commandString + formattedCommand = formattedCommand.replace('option', '\u2325') + formattedCommand = formattedCommand.replace('shift', '\u21E7') + formattedCommand = formattedCommand.replace('cmd', '\u2318') + formattedCommand = formattedCommand.replace(/[`+`]/g, ' ') + return formattedCommand + } + //Menu bar rendering - const ListItem = ({ item, label, topLevel, onClick }) => { + const ListItem = ({ item, label, topLevel, onClick, hotKeyLabel }) => { label = label ? label.replace(/_/g, ' ') : label - let children = null + let children if (item.items && Object.keys(item.items)) { children = ( ) } @@ -231,9 +241,10 @@ const MenuBar = () => { onClick={onClick} > {label} + {hotKeyLabel && {parseStringToUnicode(hotKeyLabel)}} {children &&
} - {!topLevel &&
} - {children} + {/* {!topLevel &&
} */} + {children && children} ) } @@ -241,7 +252,7 @@ const MenuBar = () => { const handleClick = func => { //Initially intended to control the visibility with a state, but this triggers a re-render and hides the menu anyway! :D //Keeping this intact just in case. - togglemenuVisibility(menuVisibility) + ;(togglemenuVisibility as Function)(menuVisibility) // eslint-disable-next-line no-eval eval(func) } @@ -255,6 +266,7 @@ const MenuBar = () => { label={Object.keys(menuBarItems)[index]} topLevel={true} key={index} + hotKeyLabel={menuBarItems[item].hotKeyLabel} onClick={() => { handleClick(menuBarItems[item].onClick) }} diff --git a/client/src/features/common/MenuBar/menuBar.module.css b/client/src/components/MenuBar/menuBar.module.css similarity index 75% rename from client/src/features/common/MenuBar/menuBar.module.css rename to client/src/components/MenuBar/menuBar.module.css index ff2bd2426..55a42ba10 100644 --- a/client/src/features/common/MenuBar/menuBar.module.css +++ b/client/src/components/MenuBar/menuBar.module.css @@ -1,51 +1,53 @@ ul { margin: 0; - list-style: none; - position: relative; + list-style: none; + position: relative; border-radius: 3px; - } - +} + .list-item { border: 1px solid var(--dark-3); border-top: 0; border-bottom: 0; position: relative; - display: inline-block; - background-color: var(--dark-2); + display: inline-block; + background-color: var(--dark-2); padding: var(--extraSmall); padding-left: var(--small); text-transform: capitalize; + display: flex; + justify-content: space-between; } .list-item:hover { - background-color: var(--primary) + background-color: var(--primary); } /* Hide Dropdowns by Default */ ul ul { - display: none; - position: absolute; - top: var(--c4); /* the height of the main nav */ + display: none; + position: absolute; + top: var(--c4); /* the height of the main nav */ transform: translateX(calc(var(--c7) * -1)); } - + /* Display Dropdowns on Hover */ ul li:hover > ul { - display:inherit; + display: inherit; } - + /* Fisrt Tier Dropdown */ ul ul li { - width: var(--c20); - float:none; - display:list-item; - position: relative; + width: var(--c20); + float: none; + display: list-item; + position: relative; } /* Second, Third and more Tiers */ ul ul ul li { - position: relative; - top:calc(var(--c4) * -1); - left: var(--c23); + position: relative; + top: calc(var(--c4) * -1); + left: var(--c23); } li.list-item:first-child { @@ -79,7 +81,7 @@ li.list-item:only-child { .thoth-logo { position: relative; top: 2px; - margin-left: calc( var(--c2) + 2px); + margin-left: calc(var(--c2) + 2px); margin-right: var(--c3); height: var(--c2); } @@ -90,7 +92,7 @@ li.list-item:only-child { padding: var(--extraSmall); padding-left: var(--small); padding-right: var(--small); - font-family: "IBM Plex Mono"; + font-family: 'IBM Plex Mono'; text-transform: uppercase; list-style: none; @@ -100,7 +102,7 @@ li.list-item:only-child { } .menu-bar-item:hover { background-color: var(--dark-2); - filter: drop-shadow(0px 5px 5px rgba(0,0,0,0.3)); + filter: drop-shadow(0px 5px 5px rgba(0, 0, 0, 0.3)); } .folder-arrow { display: none; @@ -113,4 +115,4 @@ li.list-item:only-child { top: 49%; right: var(--small); transform: translateY(-50%); -} \ No newline at end of file +} diff --git a/client/src/features/common/MenuBar/menuBar.module.css.d.ts b/client/src/components/MenuBar/menuBar.module.css.d.ts similarity index 100% rename from client/src/features/common/MenuBar/menuBar.module.css.d.ts rename to client/src/components/MenuBar/menuBar.module.css.d.ts diff --git a/client/src/features/common/MenuBar/thoth.png b/client/src/components/MenuBar/thoth.png similarity index 100% rename from client/src/features/common/MenuBar/thoth.png rename to client/src/components/MenuBar/thoth.png diff --git a/client/src/features/common/Modal/Modal.jsx b/client/src/components/Modal/Modal.jsx similarity index 96% rename from client/src/features/common/Modal/Modal.jsx rename to client/src/components/Modal/Modal.jsx index 4204aaf1d..6fde2ee5c 100644 --- a/client/src/features/common/Modal/Modal.jsx +++ b/client/src/components/Modal/Modal.jsx @@ -1,6 +1,6 @@ /* eslint-disable jsx-a11y/click-events-have-key-events */ -import { useModal } from '../../../contexts/ModalProvider' +import { useModal } from '../../contexts/ModalProvider' import Icon from '../Icon/Icon' import css from './modal.module.css' diff --git a/client/src/features/common/Modal/modal.module.css b/client/src/components/Modal/modal.module.css similarity index 100% rename from client/src/features/common/Modal/modal.module.css rename to client/src/components/Modal/modal.module.css diff --git a/client/src/features/common/Modal/modal.module.css.d.ts b/client/src/components/Modal/modal.module.css.d.ts similarity index 100% rename from client/src/features/common/Modal/modal.module.css.d.ts rename to client/src/components/Modal/modal.module.css.d.ts diff --git a/client/src/features/common/Modals/DeployModal.jsx b/client/src/components/Modals/DeployModal.jsx similarity index 91% rename from client/src/features/common/Modals/DeployModal.jsx rename to client/src/components/Modals/DeployModal.jsx index 6e4eeca13..e4547a1b1 100644 --- a/client/src/features/common/Modals/DeployModal.jsx +++ b/client/src/components/Modals/DeployModal.jsx @@ -1,6 +1,6 @@ -import { SettingsRemoteSharp } from '@material-ui/icons' +import { SettingsRemoteSharp } from '@mui/icons-material' import { useState } from 'react' -import { useModal } from '../../../contexts/ModalProvider' +import { useModal } from '../../contexts/ModalProvider' import Input from '../Input/Input' import Modal from '../Modal/Modal' diff --git a/client/src/features/common/Modals/EditSpellModal.tsx b/client/src/components/Modals/EditSpellModal.tsx similarity index 92% rename from client/src/features/common/Modals/EditSpellModal.tsx rename to client/src/components/Modals/EditSpellModal.tsx index 3b71a0fe5..6fa4ce226 100644 --- a/client/src/features/common/Modals/EditSpellModal.tsx +++ b/client/src/components/Modals/EditSpellModal.tsx @@ -1,7 +1,6 @@ import { useState } from 'react' import { useSnackbar } from 'notistack' -import { usePatchSpellMutation } from '../../../state/api/spells' -import { useTabManager } from '../../../contexts/TabManagerProvider' +import { usePatchSpellMutation } from '../../state/api/spells' import { useForm } from 'react-hook-form' import Modal from '../Modal/Modal' import css from './modalForms.module.css' @@ -11,8 +10,6 @@ const EditSpellModal = ({ closeModal, spellId, name, tab }) => { const [patchSpell, { isLoading }] = usePatchSpellMutation() const { enqueueSnackbar } = useSnackbar() - const { updateTab } = useTabManager() - const { register, handleSubmit, @@ -81,3 +78,6 @@ const EditSpellModal = ({ closeModal, spellId, name, tab }) => { } export default EditSpellModal +function updateTab(id: any, arg1: { name: any; spell: any }) { + throw new Error('Function not implemented.') +} diff --git a/client/src/features/common/Modals/ExampleModal.jsx b/client/src/components/Modals/ExampleModal.jsx similarity index 85% rename from client/src/features/common/Modals/ExampleModal.jsx rename to client/src/components/Modals/ExampleModal.jsx index 9f3441d88..992111bbf 100644 --- a/client/src/features/common/Modals/ExampleModal.jsx +++ b/client/src/components/Modals/ExampleModal.jsx @@ -1,4 +1,4 @@ -import { useModal } from '../../../contexts/ModalProvider' +import { useModal } from '../../contexts/ModalProvider' import Modal from '../Modal/Modal' const ExampleModal = ({ content }) => { diff --git a/client/src/features/common/Modals/InfoModal.jsx b/client/src/components/Modals/InfoModal.jsx similarity index 100% rename from client/src/features/common/Modals/InfoModal.jsx rename to client/src/components/Modals/InfoModal.jsx diff --git a/client/src/features/common/Modals/SaveAsModal.tsx b/client/src/components/Modals/SaveAsModal.tsx similarity index 81% rename from client/src/features/common/Modals/SaveAsModal.tsx rename to client/src/components/Modals/SaveAsModal.tsx index 9eb8e588b..544ef89df 100644 --- a/client/src/features/common/Modals/SaveAsModal.tsx +++ b/client/src/components/Modals/SaveAsModal.tsx @@ -1,21 +1,19 @@ import { useState } from 'react' import { useSnackbar } from 'notistack' -import { - useGetSpellQuery, - useSaveSpellMutation, -} from '../../../state/api/spells' -import { useTabManager } from '../../../contexts/TabManagerProvider' +import { useGetSpellQuery, useSaveSpellMutation } from '../../state/api/spells' import { useForm } from 'react-hook-form' import Modal from '../Modal/Modal' import css from './modalForms.module.css' +import { openTab } from '@/state/tabs' +import { useDispatch } from 'react-redux' const EditSpellModal = ({ tab, closeModal }) => { + const dispatch = useDispatch() const [error, setError] = useState('') const [saveSpell, { isLoading }] = useSaveSpellMutation() - const { data: spell } = useGetSpellQuery(tab.spell, { - skip: !tab.spell, + const { data: spell } = useGetSpellQuery(tab.spellId, { + skip: !tab.spellId, }) - const { openTab } = useTabManager() const { enqueueSnackbar } = useSnackbar() const { @@ -43,11 +41,13 @@ const EditSpellModal = ({ tab, closeModal }) => { // show snackbar // open a new tab to the new spell - await openTab({ - name: data.name, - spellId: data.name, - type: 'spell', - }) + dispatch( + openTab({ + name: data.name, + spellId: data.name, + type: 'spell', + }) + ) closeModal() }) @@ -74,7 +74,7 @@ const EditSpellModal = ({ tab, closeModal }) => {
diff --git a/client/src/features/common/Modals/index.ts b/client/src/components/Modals/index.ts similarity index 100% rename from client/src/features/common/Modals/index.ts rename to client/src/components/Modals/index.ts diff --git a/client/src/features/common/Modals/loginModal.module.css.d.ts b/client/src/components/Modals/loginModal.module.css.d.ts similarity index 100% rename from client/src/features/common/Modals/loginModal.module.css.d.ts rename to client/src/components/Modals/loginModal.module.css.d.ts diff --git a/client/src/features/common/Modals/modalForms.module.css b/client/src/components/Modals/modalForms.module.css similarity index 100% rename from client/src/features/common/Modals/modalForms.module.css rename to client/src/components/Modals/modalForms.module.css diff --git a/client/src/features/common/Modals/modalForms.module.css.d.ts b/client/src/components/Modals/modalForms.module.css.d.ts similarity index 100% rename from client/src/features/common/Modals/modalForms.module.css.d.ts rename to client/src/components/Modals/modalForms.module.css.d.ts diff --git a/client/src/features/common/Node/Node.module.css b/client/src/components/Node/Node.module.css similarity index 89% rename from client/src/features/common/Node/Node.module.css rename to client/src/components/Node/Node.module.css index d2fcbeadc..cfe2d2908 100644 --- a/client/src/features/common/Node/Node.module.css +++ b/client/src/components/Node/Node.module.css @@ -28,6 +28,7 @@ position: absolute; right: 10px; color: var(--red); + border-radius: var(--extraSmall); } .deprecated-overlay { background-color: var(--red); @@ -141,3 +142,20 @@ align-items: center; display: flex; } + +.node-locked { + background-color: var(--dark-3); + position: absolute; + top: 0; + right: 0; + left: 0; + bottom: 0; + opacity: 0.6; + background-repeat: no-repeat; + background-position: center; + background-size: 20%; + border-radius: var(--extraSmall); + width: 99%; + height: 99%; + margin: auto; +} diff --git a/client/src/features/common/Node/Node.module.css.d.ts b/client/src/components/Node/Node.module.css.d.ts similarity index 95% rename from client/src/features/common/Node/Node.module.css.d.ts rename to client/src/components/Node/Node.module.css.d.ts index 46fdd2f27..735037df9 100644 --- a/client/src/features/common/Node/Node.module.css.d.ts +++ b/client/src/components/Node/Node.module.css.d.ts @@ -11,6 +11,7 @@ interface CssExports { 'node': string; 'node-depricated': string; 'node-id': string; + 'node-locked': string; 'node-title': string; 'nodeGenesis': string; 'out': string; diff --git a/client/src/features/common/Node/Node.js b/client/src/components/Node/Node.tsx similarity index 90% rename from client/src/features/common/Node/Node.js rename to client/src/components/Node/Node.tsx index 668924a95..f993ad09d 100644 --- a/client/src/features/common/Node/Node.js +++ b/client/src/components/Node/Node.tsx @@ -1,10 +1,13 @@ -import React from 'react' import { Node, Socket, Control } from 'rete-react-render-plugin' import Icon, { componentCategories } from '../Icon/Icon' import css from './Node.module.css' +import icons from '../Icon/icon.module.css' export class MyNode extends Node { + props: { node: any; bindSocket: any; bindControl: any } + state: { outputs: any; controls: any; inputs: any; selected: any } + render() { const { node, bindSocket, bindControl } = this.props const { outputs, controls, inputs, selected } = this.state @@ -13,6 +16,7 @@ export class MyNode extends Node { const fullName = node.data.name ? `${name} - ${node.data.name}` : name const hasError = node.data.error const hasSuccess = node.data.success + const nodeLocked = node.data.nodeLocked return (
{node.deprecated &&
} + {nodeLocked && ( +
+ )}
{ @@ -24,7 +24,7 @@ const Panel = ({ } ` + className } style={{ - display: flexRow ? 'flex' : flexColumn, + display: flexRow || flexColumn ? 'flex' : '', flexDirection: flexRow ? 'row' : 'column', gap: gap, backgroundImage: bacgkroundImageURL ? bacgkroundImageURL : undefined, diff --git a/client/src/features/common/Panel/panel.module.css b/client/src/components/Panel/panel.module.css similarity index 100% rename from client/src/features/common/Panel/panel.module.css rename to client/src/components/Panel/panel.module.css diff --git a/client/src/features/common/Panel/panel.module.css.d.ts b/client/src/components/Panel/panel.module.css.d.ts similarity index 100% rename from client/src/features/common/Panel/panel.module.css.d.ts rename to client/src/components/Panel/panel.module.css.d.ts diff --git a/client/src/features/common/RequireAuth/RequireAuth.tsx b/client/src/components/RequireAuth/RequireAuth.tsx similarity index 91% rename from client/src/features/common/RequireAuth/RequireAuth.tsx rename to client/src/components/RequireAuth/RequireAuth.tsx index e4e3a26e8..d214f2cbc 100644 --- a/client/src/features/common/RequireAuth/RequireAuth.tsx +++ b/client/src/components/RequireAuth/RequireAuth.tsx @@ -1,5 +1,5 @@ import { Outlet } from 'react-router-dom' -import { useAuth } from '../../../contexts/AuthProvider' +import { useAuth } from '../../contexts/AuthProvider' const defaultGroups = ['internal', 'thoth', 'creator-tester'] diff --git a/client/src/features/common/Select/Select.jsx b/client/src/components/Select/Select.tsx similarity index 69% rename from client/src/features/common/Select/Select.jsx rename to client/src/components/Select/Select.tsx index 657b9a42a..84b6d1bdc 100644 --- a/client/src/features/common/Select/Select.jsx +++ b/client/src/components/Select/Select.tsx @@ -1,6 +1,7 @@ -import React, { useRef } from 'react' +import { useRef } from 'react' import { useHotkeys } from 'react-hotkeys-hook' import Creatable from 'react-select/creatable' +import Select from 'react-select' import Chip from '../Chip/Chip' import Icon, { componentCategories } from '../Icon/Icon' @@ -12,17 +13,18 @@ const BasicSelect = ({ placeholder, style = {}, focusKey = '', + creatable = true, nested = false, // eslint-disable-next-line @typescript-eslint/no-unused-vars isValidNewOption = (inputValue, selectValue, selectOptions, accessors) => true, ...props }) => { - const selectRef = useRef(null) + const selectRef = useRef(null) const DropdownIndicator = () => { return props.searchable ? ( - + ) : (
) @@ -38,23 +40,26 @@ const BasicSelect = ({ ) - const focusSelect = () => { - selectRef.current.focus() - } + // const focusSelect = () => { + // if (!selectRef.current) return + // // selectRef.current.focus() + // } const blurSelect = () => { + if (!selectRef.current) return selectRef.current.blur() } - useHotkeys( - focusKey, - event => { - event.preventDefault() - focusSelect() - }, - { enableOnTags: 'INPUT' }, - [focusSelect] - ) + // useHotkeys( + // focusKey, + // event => { + // console.log('event', event) + // event.preventDefault() + // focusSelect() + // }, + // { enableOnTags: 'INPUT' as any }, + // [focusSelect] + // ) useHotkeys( 'enter, esc', @@ -62,7 +67,7 @@ const BasicSelect = ({ event.preventDefault() blurSelect() }, - { enableOnTags: 'INPUT' }, + { enableOnTags: 'INPUT' as any }, [blurSelect] ) @@ -125,30 +130,39 @@ const BasicSelect = ({ alignItems: 'center', }), singleValue: () => ({ - color: 'rgba(255,255,255,0.5)', + color: 'rgba(255,255,255)', }), } - const _isValidNewOption = (...args) => { - if (!props.creatable) return false - return isValidNewOption(...args) - } - return ( {options ? ( - + <> + {creatable && ( + + )} + {!creatable && ( + -
- ) -} - -export default ModuleSelect diff --git a/client/src/features/Thoth/windows/InspectorWindow/index.jsx b/client/src/features/Thoth/windows/InspectorWindow/index.jsx deleted file mode 100644 index 2014b4622..000000000 --- a/client/src/features/Thoth/windows/InspectorWindow/index.jsx +++ /dev/null @@ -1,105 +0,0 @@ -import { useEffect, useState } from 'react' - -import { useLayout } from '@thoth/contexts/LayoutProvider' -import { useModal } from '@/contexts/ModalProvider' -import Icon, { componentCategories } from '@common/Icon/Icon' -import Window from '@common/Window/Window' -import DataControls from './DataControls' -import WindowMessage from '@thoth/components/WindowMessage' - -const Inspector = props => { - const { inspectorData, saveInspector } = useLayout() - const [width, setWidth] = useState() - const { openModal } = useModal() - - useEffect(() => { - if (props?.node?._rect?.width) { - setWidth(props.node._rect.width) - } - - // this is to dynamically set the appriopriate height so that Monaco editor doesnt break flexbox when resizing - props.node.setEventListener('resize', data => { - setTimeout(() => { - setWidth(data.rect.width) - }, 0) - }) - - return () => { - props.node.removeEventListener('resize') - } - }, [props]) - - const updateControl = control => { - const newData = { - ...inspectorData, - dataControls: { - ...inspectorData.dataControls, - ...control, - }, - } - - saveInspector(newData) - } - - const updateData = update => { - const newData = { - ...inspectorData, - data: { - ...inspectorData.data, - ...update, - }, - } - - saveInspector(newData) - } - - const toolbar = ( - <> -
- - {inspectorData?.name} -
- {/* I would like to make an "icon button" for this instead of "Help." Leaving it as help just for the function for now.*/} - {inspectorData?.info && ( - - )} - - ) - - if (!inspectorData) return - - return ( - - {inspectorData.deprecated && ( -
-

WARNING

-

{inspectorData.deprecationMessage}

-
- )} - -
- ) -} - -export default Inspector diff --git a/client/src/features/Thoth/workspaces/composer/index.tsx b/client/src/features/Thoth/workspaces/composer/index.tsx deleted file mode 100644 index 1b48bc2a7..000000000 --- a/client/src/features/Thoth/workspaces/composer/index.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import { useEffect, useRef } from 'react' - -import { store } from '@/state/store' -import { useEditor } from '@thoth/contexts/EditorProvider' -import { Layout } from '@thoth/contexts/LayoutProvider' -import { useModule } from '@/contexts/ModuleProvider' -import { - useLazyGetSpellQuery, - useSaveSpellMutation, - selectSpellById, -} from '@/state/api/spells' -import { debounce } from '@/utils/debounce' -import EditorWindow from '@thoth/windows/EditorWindow' -import EventHandler from '@thoth/components/EventHandler' -import Inspector from '@thoth/windows/InspectorWindow' -import Playtest from '@thoth/windows/PlaytestWindow' -import StateManager from '@thoth/windows/StateManagerWindow' -import TextEditor from '@thoth/windows/TextEditorWindow' -import DebugConsole from '@thoth/windows/DebugConsole' -import { Spell } from '../../../../state/api/spells' - -const Workspace = ({ tab, tabs, pubSub }) => { - const spellRef = useRef() - const [loadSpell, { data: spellData }] = useLazyGetSpellQuery() - const [saveSpell] = useSaveSpellMutation() - const { saveModule } = useModule() - const { editor } = useEditor() - - // Set up autosave for the workspaces - useEffect(() => { - if (!editor?.on) return - return editor.on( - 'save nodecreated noderemoved connectioncreated connectionremoved nodetranslated', - debounce(() => { - if (tab.type === 'spell') { - saveSpell({ ...spellRef.current, chain: editor.toJSON() }) - } - if (tab.type === 'module') { - saveModule(tab.module, { data: editor.toJSON() }, false) - // when a module is saved, we look for any open spell tabs, and check if they have the module. - /// if they do, we trigger a save to ensure the module change is captured to the server - tabs - .filter(tab => tab.type === 'spell') - .forEach(filteredTab => { - if (filteredTab.spell) { - const spell = selectSpellById( - store.getState(), - filteredTab.spell - ) - if ( - spell?.modules && - spell?.modules.some(module => module.name === tab.module) - ) - saveSpell({ ...spell }) - } - }) - } - }, 500) - ) - }, [editor]) - - useEffect(() => { - if (!spellData) return - spellRef.current = spellData - }, [spellData]) - - useEffect(() => { - if (!tab || !tab.spell) return - loadSpell(tab.spell) - }, [tab]) - - const factory = tab => { - return node => { - const props = { - tab, - node, - } - const component = node.getComponent() - switch (component) { - case 'stateManager': - return - case 'playtest': - return - case 'inspector': - return - case 'textEditor': - return - case 'editorWindow': - return - case 'debugConsole': - return - default: - return

- } - } - } - - return ( - <> - - - - ) -} - -const Wrapped = props => { - return -} - -export default Wrapped diff --git a/client/src/global.d.ts b/client/src/global.d.ts index a2700b521..fbd2fd5ba 100644 --- a/client/src/global.d.ts +++ b/client/src/global.d.ts @@ -1,7 +1,14 @@ // We need to tell TypeScript that when we write "import styles from './styles.scss' we mean to load a module (to look for a './styles.scss.d.ts'). declare module '*.css' declare module '*.module.css' +declare module '*.jpg' declare module '*.png' { const value: any export default value } + +declare global { + interface Window { + getLayout: any + } +} diff --git a/client/src/index.js b/client/src/index.tsx similarity index 73% rename from client/src/index.js rename to client/src/index.tsx index df1d8e078..c5e3d1dd2 100644 --- a/client/src/index.js +++ b/client/src/index.tsx @@ -4,19 +4,22 @@ import React from 'react' import ReactDOM from 'react-dom' import { Provider } from 'react-redux' import { BrowserRouter as Router } from 'react-router-dom' +import { PersistGate } from 'redux-persist/integration/react' import App from './App' import AppProviders from './contexts/AppProviders' import reportWebVitals from './reportWebVitals' -import { store } from './state/store' +import { persistor, store } from './state/store' ReactDOM.render( - - - + + + + + , diff --git a/client/src/features/HomeScreen/HomeScreen.tsx b/client/src/screens/HomeScreen/HomeScreen.tsx similarity index 74% rename from client/src/features/HomeScreen/HomeScreen.tsx rename to client/src/screens/HomeScreen/HomeScreen.tsx index 86e327db8..85ccfba4d 100644 --- a/client/src/features/HomeScreen/HomeScreen.tsx +++ b/client/src/screens/HomeScreen/HomeScreen.tsx @@ -6,20 +6,19 @@ import { useDeleteSpellMutation, useNewSpellMutation, } from '../../state/api/spells' -import { useDB } from '../../contexts/DatabaseProvider' -import { useTabManager } from '../../contexts/TabManagerProvider' import AllProjects from './screens/AllProjects' import CreateNew from './screens/CreateNew' import OpenProject from './screens/OpenProject' import css from './homeScreen.module.css' -import LoadingScreen from '../common/LoadingScreen/LoadingScreen' -import { ModelsType } from '../../types' +import LoadingScreen from '../../components/LoadingScreen/LoadingScreen' +import { closeTab, openTab } from '@/state/tabs' +import { useDispatch } from 'react-redux' //MAIN const StartScreen = () => { - const { models } = useDB() as unknown as ModelsType - const { openTab, closeTabBySpellId } = useTabManager() + const dispatch = useDispatch() + const navigate = useNavigate() const [deleteSpell] = useDeleteSpellMutation() @@ -34,25 +33,20 @@ const StartScreen = () => { } // TODO check for proper values here and throw errors - // Load modules from the spell - if (spellData?.modules && spellData.modules.length > 0) - await Promise.all( - spellData.modules.map(module => { - return models.modules.updateOrCreate(module) - }) - ) - // Create new spell await newSpell({ chain: spellData.chain, name: spellData.name, + gameState: spellData.gameState, }) - await openTab({ - name: spellData.name, - spellId: spellData.name, - type: 'spell', - }) + dispatch( + openTab({ + name: spellData.name, + spellId: spellData.name, + type: 'spell', + }) + ) navigate('/thoth') } @@ -66,15 +60,15 @@ const StartScreen = () => { const onDelete = async spellId => { try { await deleteSpell(spellId) - await closeTabBySpellId(spellId) + dispatch(closeTab(spellId)) } catch (err) { console.log('Error deleting spell', err) } } const openSpell = async spell => { - await openTab({ name: spell.name, spellId: spell.name, type: 'spell' }) - navigate('/thoth') + // dispatch(openTab({ name: spell.name, spellId: spell.name, type: 'spell' })) + navigate(`/thoth/${spell.name}`) } const [selectedSpell, setSelectedSpell] = useState(null) diff --git a/client/src/features/HomeScreen/components/FileInput.jsx b/client/src/screens/HomeScreen/components/FileInput.jsx similarity index 92% rename from client/src/features/HomeScreen/components/FileInput.jsx rename to client/src/screens/HomeScreen/components/FileInput.jsx index dd2b73e43..edf7cc4a1 100644 --- a/client/src/features/HomeScreen/components/FileInput.jsx +++ b/client/src/screens/HomeScreen/components/FileInput.jsx @@ -1,6 +1,6 @@ import React from 'react' -import Icon from '../../common/Icon/Icon' +import Icon from '../../../components/Icon/Icon' const FileInput = ({ loadFile }) => { const hiddenFileInput = React.useRef(null) diff --git a/client/src/features/HomeScreen/components/ProjectRow.jsx b/client/src/screens/HomeScreen/components/ProjectRow.tsx similarity index 58% rename from client/src/features/HomeScreen/components/ProjectRow.jsx rename to client/src/screens/HomeScreen/components/ProjectRow.tsx index bbecd3865..61ed81627 100644 --- a/client/src/features/HomeScreen/components/ProjectRow.jsx +++ b/client/src/screens/HomeScreen/components/ProjectRow.tsx @@ -1,25 +1,39 @@ -import Icon from '../../common/Icon/Icon' +import { Spell } from '@latitudegames/thoth-core/types' +import { CSSProperties } from 'react' +import Icon from '../../../components/Icon/Icon' import css from '../homeScreen.module.css' +type ProjectProps = { + label: string + selectedSpell?: Spell + icon?: string + onClick: Function + spell?: Spell + style?: CSSProperties + onDelete?: Function +} + const ProjectRow = ({ label, selectedSpell, - onClick, - icon, + onClick = () => {}, + icon = '', spell, - style, - onDelete = false, -}) => { + style = {}, + onDelete, +}: ProjectProps) => { return (
{ + onClick(e) + }} style={style} > - {icon && ( + {icon.length > 0 && ( )} {label} @@ -27,7 +41,7 @@ const ProjectRow = ({ { - onDelete(spell.name) + spell?.name && onDelete(spell.name) }} style={{ marginRight: 'var(--extraSmall)', diff --git a/client/src/features/HomeScreen/components/TemplatePanel.jsx b/client/src/screens/HomeScreen/components/TemplatePanel.jsx similarity index 93% rename from client/src/features/HomeScreen/components/TemplatePanel.jsx rename to client/src/screens/HomeScreen/components/TemplatePanel.jsx index 294c3d73d..eee6238a9 100644 --- a/client/src/features/HomeScreen/components/TemplatePanel.jsx +++ b/client/src/screens/HomeScreen/components/TemplatePanel.jsx @@ -1,4 +1,4 @@ -import Panel from '../../common/Panel/Panel' +import Panel from '../../../components/Panel/Panel' import css from '../homeScreen.module.css' const TemplatePanel = ({ template, setSelectedTemplate, selectedTemplate }) => { diff --git a/client/src/features/HomeScreen/empty.png b/client/src/screens/HomeScreen/empty.png similarity index 100% rename from client/src/features/HomeScreen/empty.png rename to client/src/screens/HomeScreen/empty.png diff --git a/client/src/features/HomeScreen/enki.png b/client/src/screens/HomeScreen/enki.png similarity index 100% rename from client/src/features/HomeScreen/enki.png rename to client/src/screens/HomeScreen/enki.png diff --git a/client/src/features/HomeScreen/homeScreen.module.css b/client/src/screens/HomeScreen/homeScreen.module.css similarity index 100% rename from client/src/features/HomeScreen/homeScreen.module.css rename to client/src/screens/HomeScreen/homeScreen.module.css diff --git a/client/src/features/HomeScreen/homeScreen.module.css.d.ts b/client/src/screens/HomeScreen/homeScreen.module.css.d.ts similarity index 100% rename from client/src/features/HomeScreen/homeScreen.module.css.d.ts rename to client/src/screens/HomeScreen/homeScreen.module.css.d.ts diff --git a/client/src/features/HomeScreen/lang.png b/client/src/screens/HomeScreen/lang.png similarity index 100% rename from client/src/features/HomeScreen/lang.png rename to client/src/screens/HomeScreen/lang.png diff --git a/client/src/features/HomeScreen/screens/AllProjects.jsx b/client/src/screens/HomeScreen/screens/AllProjects.jsx similarity index 94% rename from client/src/features/HomeScreen/screens/AllProjects.jsx rename to client/src/screens/HomeScreen/screens/AllProjects.jsx index e3b924966..d31524c22 100644 --- a/client/src/features/HomeScreen/screens/AllProjects.jsx +++ b/client/src/screens/HomeScreen/screens/AllProjects.jsx @@ -1,7 +1,7 @@ import { Scrollbars } from 'react-custom-scrollbars-2' -import Icon from '../../common/Icon/Icon' -import Panel from '../../common/Panel/Panel' +import Icon from '../../../components/Icon/Icon' +import Panel from '../../../components/Panel/Panel' import css from '../homeScreen.module.css' import FileInput from '../components/FileInput' import ProjectRow from '../components/ProjectRow' diff --git a/client/src/features/HomeScreen/screens/CreateNew.jsx b/client/src/screens/HomeScreen/screens/CreateNew.tsx similarity index 62% rename from client/src/features/HomeScreen/screens/CreateNew.jsx rename to client/src/screens/HomeScreen/screens/CreateNew.tsx index 6f7791f9f..d09683506 100644 --- a/client/src/features/HomeScreen/screens/CreateNew.jsx +++ b/client/src/screens/HomeScreen/screens/CreateNew.tsx @@ -1,5 +1,5 @@ import { useSnackbar } from 'notistack' -import { useState, useEffect } from 'react' +import { useState } from 'react' import { useForm } from 'react-hook-form' import { uniqueNamesGenerator, @@ -9,15 +9,14 @@ import { import { useNavigate } from 'react-router-dom' import { useNewSpellMutation } from '@/state/api/spells' -import { useTabManager } from '@/contexts/TabManagerProvider' -import Panel from '@common/Panel/Panel' -import Input from '@common/Input/Input' +import Panel from '../../../components/Panel/Panel' import emptyImg from '../empty.png' import enkiImg from '../enki.png' import langImg from '../lang.png' import css from '../homeScreen.module.css' import TemplatePanel from '../components/TemplatePanel' -import defaultChain from './chains/default' +import defaultChain from '../../../data/chains/default' +import { ChainData } from '@latitudegames/thoth-core/types' const customConfig = { dictionaries: [adjectives, colors], @@ -25,19 +24,26 @@ const customConfig = { length: 2, } -const templates = [ +export type Template = { + label: string + bg: string + chain: ChainData +} + +export const thothTemplates = [ { label: 'Starter', bg: emptyImg, chain: defaultChain }, { label: 'Language example', bg: langImg, chain: defaultChain }, { label: 'Enki example', bg: enkiImg, chain: defaultChain }, ] const CreateNew = () => { - const [selectedTemplate, setSelectedTemplate] = useState(null) - const [error, setError] = useState(null) + const [selectedTemplate, setSelectedTemplate] = useState