diff --git a/docs/dev/z-indexes.md b/docs/dev/z-indexes.md new file mode 100644 index 0000000..ad90220 --- /dev/null +++ b/docs/dev/z-indexes.md @@ -0,0 +1,4 @@ +# Z-indexes + +- 5 = sidebar +- 10 = create-simulation modal diff --git a/package.json b/package.json index 583eae2..639bdbc 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "dev": "webpack-dev-server --open --mode development", "build": "cross-env NODE_ENV=production webpack", "deploy": "ts-node deploy", - "show": "gource -f --start-date \"2019-07-01 12:00\" --key --hide dirnames,filenames,bloom" + "show": "gource -f --start-date \"2019-07-01 12:00\" --key --hide dirnames,filenames,bloom -s 3" }, "devDependencies": { "@babel/core": "^7.5.5", diff --git a/src/index.html b/src/index.html index daaf4ee..275ed07 100644 --- a/src/index.html +++ b/src/index.html @@ -15,6 +15,11 @@ name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no" /> + + (null) diff --git a/src/modules/core/components/App.scss b/src/modules/core/components/App.scss index e8f96f4..82dcb78 100644 --- a/src/modules/core/components/App.scss +++ b/src/modules/core/components/App.scss @@ -1,3 +1,5 @@ +@import '../styles/global-styles/global-styles.scss'; + html, body { height: 100%; diff --git a/src/modules/core/components/App.tsx b/src/modules/core/components/App.tsx index 1abafd6..91c3fe8 100644 --- a/src/modules/core/components/App.tsx +++ b/src/modules/core/components/App.tsx @@ -10,7 +10,8 @@ import Canvas from './Canvas' import CssBaseline from '@material-ui/core/CssBaseline' import Theme from '@material-ui/styles/ThemeProvider' import Sidebar from './Sidebar' -import QuestionModal from './QuestionModal' +import CreateSimulation from '../../create-simulation/components/CreateSimulation' +import Input from '../../input/components/Input' const App = () => { return ( @@ -19,7 +20,8 @@ const App = () => { - + + = createRef() @@ -15,6 +16,8 @@ class Canvas extends Component { public constructor(props: {}) { super(props) + rendererSubject.next(this.renderer) + addGate(this.renderer.simulation, 'not') loop.setDraw(() => { diff --git a/src/modules/core/components/OpenSimulation.tsx b/src/modules/core/components/OpenSimulation.tsx new file mode 100644 index 0000000..905bef7 --- /dev/null +++ b/src/modules/core/components/OpenSimulation.tsx @@ -0,0 +1,73 @@ +import React, { useState } from 'react' +import ListItem from '@material-ui/core/ListItem' +import ListItemIcon from '@material-ui/core/ListItemIcon' +import ListItemText from '@material-ui/core/ListItemText' +import Menu from '@material-ui/core/Menu' +import MenuItem from '@material-ui/core/MenuItem' +import Icon from '@material-ui/core/Icon' +import { saveStore } from '../../saving/stores/saveStore' +import { BehaviorSubject } from 'rxjs' +import { useObservable } from 'rxjs-hooks' +import { rendererSubject } from '../subjects/rendererSubject' +import { currentStore } from '../../saving/stores/currentStore' + +const allSimulations = () => { + return saveStore.ls() +} +const allSimulationSubject = new BehaviorSubject([]) +const updateSimulationList = () => { + allSimulationSubject.next(allSimulations()) +} + +const OpenSimulation = () => { + const [anchorEl, setAnchorEl] = useState(null) + const simulations = useObservable(() => allSimulationSubject, []) + + const handleClose = () => { + setAnchorEl(null) + } + + return ( + <> + { + updateSimulationList() + setAnchorEl(event.currentTarget) + }} + > + + folder_open + + Open simulation + + + + {simulations.map((simulation, index) => ( + { + if (rendererSubject.value) { + const renderer = rendererSubject.value + + currentStore.set(simulation) + renderer.reloadSave() + } + + handleClose() + }} + > + {simulation} + + ))} + + + ) +} + +export default OpenSimulation diff --git a/src/modules/core/components/QuestionModal.tsx b/src/modules/core/components/QuestionModal.tsx deleted file mode 100644 index af53651..0000000 --- a/src/modules/core/components/QuestionModal.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import './QuestionModal.scss' -import { useObservable } from 'rxjs-hooks' -import { QuestionSubject } from '../QuestionModalSubjects' -import React from 'react' - -const QuestionModal = () => { - const question = useObservable(() => QuestionSubject) - - if (!question) return <> - - return
{question.text}
-} - -export default QuestionModal diff --git a/src/modules/core/components/Sidebar.tsx b/src/modules/core/components/Sidebar.tsx index 240a941..9f8232c 100644 --- a/src/modules/core/components/Sidebar.tsx +++ b/src/modules/core/components/Sidebar.tsx @@ -1,29 +1,31 @@ -import { makeStyles, Theme, createStyles } from '@material-ui/core/styles' -import React from 'react' +import React, { useState } from 'react' import Drawer from '@material-ui/core/Drawer' -import Button from '@material-ui/core/Button' +import List from '@material-ui/core/List' +import ListItem from '@material-ui/core/ListItem' +import ListItemIcon from '@material-ui/core/ListItemIcon' +import ListItemText from '@material-ui/core/ListItemText' +import Icon from '@material-ui/core/Icon' +import { handleCreating } from '../../create-simulation/helpers/handleCreating' +import { makeStyles, Theme, createStyles } from '@material-ui/core/styles' +import OpenSimulation from './OpenSimulation' const drawerWidth = 240 const useStyles = makeStyles((theme: Theme) => createStyles({ root: { - display: 'flex' + display: 'flex', + zIndex: 5 }, drawer: { width: drawerWidth, - flexShrink: 0 + flexShrink: 0, + zIndex: 5 }, drawerPaper: { padding: '4px', width: drawerWidth, - background: `#111111` - }, - drawerHeader: { - display: 'flex', - alignItems: 'center', - padding: '0 8px', - ...theme.mixins.toolbar, - justifyContent: 'flex-start' + background: `#111111`, + zIndex: 5 } }) ) @@ -42,9 +44,19 @@ const Sidebar = () => { paper: classes.drawerPaper }} > - + + + + note_add + + Create simulation + + + ) diff --git a/src/modules/core/styles/colors.scss b/src/modules/core/styles/colors.scss new file mode 100644 index 0000000..cf790d9 --- /dev/null +++ b/src/modules/core/styles/colors.scss @@ -0,0 +1,2 @@ +$modal-bg-color: rgba(0, 0, 0, 0.7); +$primary: #673ab7; diff --git a/src/modules/core/styles/global-styles/global-styles.scss b/src/modules/core/styles/global-styles/global-styles.scss new file mode 100644 index 0000000..578c293 --- /dev/null +++ b/src/modules/core/styles/global-styles/global-styles.scss @@ -0,0 +1,2 @@ +@import './mui-overrides.scss'; +@import './toasts.scss'; diff --git a/src/modules/core/styles/global-styles/mui-overrides.scss b/src/modules/core/styles/global-styles/mui-overrides.scss new file mode 100644 index 0000000..92cfe73 --- /dev/null +++ b/src/modules/core/styles/global-styles/mui-overrides.scss @@ -0,0 +1,6 @@ +@import '../colors.scss'; + +.MuiListItem-root.contained { + // i spent hours trying to find a better solution + background-color: $primary !important; +} diff --git a/src/modules/core/styles/global-styles/toasts.scss b/src/modules/core/styles/global-styles/toasts.scss new file mode 100644 index 0000000..d8aa9e9 --- /dev/null +++ b/src/modules/core/styles/global-styles/toasts.scss @@ -0,0 +1,6 @@ +div.Toastify__toast { + background: black; +} +div.Toastify__taast-body { + color: white; +} diff --git a/src/modules/core/styles/indexes.scss b/src/modules/core/styles/indexes.scss new file mode 100644 index 0000000..401ac70 --- /dev/null +++ b/src/modules/core/styles/indexes.scss @@ -0,0 +1 @@ +$modal-index: 10; diff --git a/src/modules/core/styles/mixins/flex.scss b/src/modules/core/styles/mixins/flex.scss new file mode 100644 index 0000000..dff97fd --- /dev/null +++ b/src/modules/core/styles/mixins/flex.scss @@ -0,0 +1,6 @@ +@mixin flex { + display: flex; + justify-content: center; + flex-direction: column; + align-items: center; +} diff --git a/src/modules/core/components/QuestionModal.scss b/src/modules/core/styles/mixins/full-screen.scss similarity index 80% rename from src/modules/core/components/QuestionModal.scss rename to src/modules/core/styles/mixins/full-screen.scss index bea18a2..5c67538 100644 --- a/src/modules/core/components/QuestionModal.scss +++ b/src/modules/core/styles/mixins/full-screen.scss @@ -1,7 +1,7 @@ -.questionModal { +@mixin full-screen { position: absolute; + height: 100%; + width: 100%; top: 0; left: 0; - width: 100%; - height: 100%; } diff --git a/src/modules/core/styles/mixins/visibility.scss b/src/modules/core/styles/mixins/visibility.scss new file mode 100644 index 0000000..3bad4e2 --- /dev/null +++ b/src/modules/core/styles/mixins/visibility.scss @@ -0,0 +1,10 @@ +@mixin hidden { + visibility: hidden; + opacity: 0; + transition: all 0.6s ease-in-out 0s; +} + +@mixin visible { + visibility: visible; + opacity: 1; +} diff --git a/src/modules/core/subjects/rendererSubject.ts b/src/modules/core/subjects/rendererSubject.ts new file mode 100644 index 0000000..9f10225 --- /dev/null +++ b/src/modules/core/subjects/rendererSubject.ts @@ -0,0 +1,6 @@ +import { BehaviorSubject } from 'rxjs' +import { SimulationRenderer } from '../../simulationRenderer/classes/SimulationRenderer' + +export const rendererSubject = new BehaviorSubject( + null +) diff --git a/src/modules/create-simulation/components/CreateOption.scss b/src/modules/create-simulation/components/CreateOption.scss new file mode 100644 index 0000000..b962742 --- /dev/null +++ b/src/modules/create-simulation/components/CreateOption.scss @@ -0,0 +1,30 @@ +#create-options { + width: 100%; + display: flex; + justify-content: space-evenly; +} + +.create-option { + @include flex(); + + background-color: #444444; + height: 17em; + width: 17em; + border-radius: 1em; +} + +.create-option > .create-option-icon > * { + font-size: 7em; +} + +.create-option > .create-option-name { + font-size: 2em; +} + +#ic { + font-size: 1.7em; +} + +.create-option:hover { + border: 0.3em solid white; +} diff --git a/src/modules/create-simulation/components/CreateSimulation.scss b/src/modules/create-simulation/components/CreateSimulation.scss new file mode 100644 index 0000000..f76b979 --- /dev/null +++ b/src/modules/create-simulation/components/CreateSimulation.scss @@ -0,0 +1,17 @@ +@import '../../core/styles/mixins/flex.scss'; +@import '../../core/styles/mixins/visibility.scss'; +@import '../../modals/styles/mixins/modal-container.scss'; +@import '../../modals/styles/mixins/modal-title.scss'; +@import './CreateOption.scss'; + +#create-content { + @include modal-container(); +} + +.shown#create-content { + @include visible(); +} + +#create-title { + @include modal-title(); +} diff --git a/src/modules/create-simulation/components/CreateSimulation.tsx b/src/modules/create-simulation/components/CreateSimulation.tsx new file mode 100644 index 0000000..74b4e3f --- /dev/null +++ b/src/modules/create-simulation/components/CreateSimulation.tsx @@ -0,0 +1,69 @@ +import React from 'react' +import './CreateSimulation.scss' +import { useObservable } from 'rxjs-hooks' +import { CreateSimulationStore } from '../stores/CreateSimulationStore' +import { simulationMode } from '../../saving/types/SimulationSave' +import Icon from '@material-ui/core/Icon' + +export interface CreateSimulationOption { + mode: simulationMode + icon: string + name: string +} + +export const createSimulationOptions: CreateSimulationOption[] = [ + { + name: 'project', + mode: 'project', + icon: 'gamepad' + }, + { + name: 'integrated circuit', + icon: 'memory', + mode: 'ic' + } +] + +const CreateSimulation = () => { + const open = useObservable(() => CreateSimulationStore.data.open, false) + + const closeModal = () => { + CreateSimulationStore.actions.next('quit') + } + + return ( +
+
+ What kind of simulation do you want to create? +
+ +
+ {createSimulationOptions.map((option, index) => ( +
{ + e.stopPropagation() + + CreateSimulationStore.data.output.next(option.mode) + CreateSimulationStore.actions.next('submit') + }} + > +
+ {option.icon} +
+
+ {option.name} +
+
+ ))} +
+
+ ) +} + +export default CreateSimulation diff --git a/src/modules/create-simulation/helpers/handleCreating.ts b/src/modules/create-simulation/helpers/handleCreating.ts new file mode 100644 index 0000000..0c9cb92 --- /dev/null +++ b/src/modules/create-simulation/helpers/handleCreating.ts @@ -0,0 +1,12 @@ +import { CreateSimulationStore } from '../stores/CreateSimulationStore' +import { initSimulation } from '../../saving/helpers/initSimulation' + +export const handleCreating = async () => { + const options = await CreateSimulationStore.create() + + if (!options) return null + + const simulation = initSimulation(options.name, options.mode) + + return simulation +} diff --git a/src/modules/create-simulation/stores/CreateSimulationStore.ts b/src/modules/create-simulation/stores/CreateSimulationStore.ts new file mode 100644 index 0000000..c4546fe --- /dev/null +++ b/src/modules/create-simulation/stores/CreateSimulationStore.ts @@ -0,0 +1,46 @@ +import { BehaviorSubject, Subject } from 'rxjs' +import { take } from 'rxjs/operators' +import { simulationMode } from '../../saving/types/SimulationSave' +import { InputStore } from '../../input/stores/InputStore' + +export type CreateSimulationStoreAction = 'quit' | 'submit' + +export const CreateSimulationStore = { + create: async () => { + CreateSimulationStore.open() + + const action = await CreateSimulationStore.actions + .pipe(take(1)) + .toPromise() + + CreateSimulationStore.close() + + if (action === 'quit') { + return null + } + + const name = await InputStore.get( + 'What do you want your simulation to be called?' + ) + + if (!name) { + return null + } + + return { + mode: CreateSimulationStore.data.output.value, + name + } + }, + open() { + CreateSimulationStore.data.open.next(true) + }, + close() { + CreateSimulationStore.data.open.next(false) + }, + data: { + open: new BehaviorSubject(false), + output: new BehaviorSubject('project') + }, + actions: new Subject() +} diff --git a/src/modules/input/components/Input.scss b/src/modules/input/components/Input.scss new file mode 100644 index 0000000..433f746 --- /dev/null +++ b/src/modules/input/components/Input.scss @@ -0,0 +1,35 @@ +@import '../../core/styles/mixins/flex.scss'; +@import '../../core/styles/mixins/visibility.scss'; +@import '../../modals/styles/mixins/modal-container.scss'; +@import '../../modals/styles/mixins/modal-title.scss'; + +#input-container { + @include modal-container(); + + justify-content: center; +} + +.visible#input-container { + @include visible(); +} + +#input-container > #input-title { + @include modal-title(); + + margin-bottom: 1rem; +} + +#input-container > #actual-input { + background-color: transparent; + color: inherit; + + text-align: center; + font-size: 2.5em; + font-family: inherit; + + height: 4rem; + width: 80%; + + border: none; + border-bottom: 5px solid white; +} diff --git a/src/modules/input/components/Input.tsx b/src/modules/input/components/Input.tsx new file mode 100644 index 0000000..5cb3873 --- /dev/null +++ b/src/modules/input/components/Input.tsx @@ -0,0 +1,48 @@ +import React from 'react' +import keycode from 'keycode' +import './Input.scss' + +import { useObservable } from 'rxjs-hooks' +import { InputStore } from '../stores/InputStore' + +const Input = () => { + const open = useObservable(() => InputStore.data.open, false) + const question = useObservable(() => InputStore.data.question, '') + const output = useObservable(() => InputStore.data.output, '') + + const handleQuit = () => { + InputStore.actions.next('quit') + } + + return ( +
+
{question}
+ { + e.stopPropagation() + }} + type="text" + id="actual-input" + onChange={e => { + const element = e.target as HTMLInputElement + + InputStore.data.output.next(element.value) + }} + onKeyDown={e => { + if (keycode('enter') === e.keyCode) { + e.preventDefault() + return InputStore.actions.next('submit') + } + }} + /> +
+ ) +} + +export default Input diff --git a/src/modules/input/stores/InputStore.ts b/src/modules/input/stores/InputStore.ts new file mode 100644 index 0000000..c47f3ac --- /dev/null +++ b/src/modules/input/stores/InputStore.ts @@ -0,0 +1,34 @@ +import { Subject, BehaviorSubject } from 'rxjs' +import { take } from 'rxjs/operators' + +export type InputAction = 'quit' | 'submit' + +export const InputStore = { + async get(text: string) { + InputStore.open(text) + + const action = await InputStore.actions.pipe(take(1)).toPromise() + + InputStore.close() + + if (action === 'quit') { + return null + } + + return InputStore.data.output.value + }, + open(text: string) { + InputStore.data.open.next(true) + InputStore.data.output.next('') + InputStore.data.question.next(text) + }, + close() { + InputStore.data.open.next(false) + }, + data: { + question: new BehaviorSubject(''), + output: new BehaviorSubject(''), + open: new BehaviorSubject(false) + }, + actions: new Subject() +} diff --git a/src/modules/modals/styles/mixins/modal-container.scss b/src/modules/modals/styles/mixins/modal-container.scss new file mode 100644 index 0000000..bc54c99 --- /dev/null +++ b/src/modules/modals/styles/mixins/modal-container.scss @@ -0,0 +1,17 @@ +@import '../../core/styles/indexes.scss'; +@import '../../core/styles/colors.scss'; +@import '../../core/styles/mixins/flex.scss'; +@import '../../core/styles/mixins/full-screen.scss'; +@import '../../core/styles/mixins/visibility.scss'; + +@mixin modal-container { + @include flex(); + @include full-screen(); + @include hidden(); + + justify-content: space-evenly; + z-index: $modal-index; + color: white; + background-color: $modal-bg-color; + font-family: 'Righteous'; +} diff --git a/src/modules/modals/styles/mixins/modal-title.scss b/src/modules/modals/styles/mixins/modal-title.scss new file mode 100644 index 0000000..c6adc30 --- /dev/null +++ b/src/modules/modals/styles/mixins/modal-title.scss @@ -0,0 +1,5 @@ +@mixin modal-title { + font-size: 2.75em; + width: 80%; + text-align: center; +} diff --git a/src/modules/saving/constants.ts b/src/modules/saving/constants.ts index 3b83afa..78ce138 100644 --- a/src/modules/saving/constants.ts +++ b/src/modules/saving/constants.ts @@ -1,4 +1,5 @@ import { GateTemplate } from '../simulation/types/GateTemplate' +import { RendererState } from './types/SimulationSave' export const defaultSimulationName = 'default' export const baseTemplates: DeepPartial[] = [ @@ -25,3 +26,19 @@ export const baseTemplates: DeepPartial[] = [ } } ] + +export const baseSave: RendererState = { + camera: { + transform: { + position: [0, 0], + scale: [1, 1], + rotation: 0 + } + }, + simulation: { + gates: [], + mode: 'project', + wires: [], + name: 'default' + } +} diff --git a/src/modules/saving/helpers/cloneState.ts b/src/modules/saving/helpers/cloneState.ts new file mode 100644 index 0000000..d4692bb --- /dev/null +++ b/src/modules/saving/helpers/cloneState.ts @@ -0,0 +1 @@ +export const cloneState = (state: T): T => JSON.parse(JSON.stringify(state)) diff --git a/src/modules/saving/helpers/getState.ts b/src/modules/saving/helpers/getState.ts index 75a5cb0..4c516c1 100644 --- a/src/modules/saving/helpers/getState.ts +++ b/src/modules/saving/helpers/getState.ts @@ -48,7 +48,8 @@ export const getSimulationState = (simulation: Simulation): SimulationState => { return { gates: Array.from(simulation.gates).map(getGateState), wires: simulation.wires.map(getWireState), - mode: simulation.mode + mode: simulation.mode, + name: simulation.name } } diff --git a/src/modules/saving/helpers/initSimulation.ts b/src/modules/saving/helpers/initSimulation.ts new file mode 100644 index 0000000..cd3c783 --- /dev/null +++ b/src/modules/saving/helpers/initSimulation.ts @@ -0,0 +1,24 @@ +import { simulationMode } from '../types/SimulationSave' +import { baseSave } from '../constants' +import { cloneState } from './cloneState' +import { saveStore } from '../stores/saveStore' +import { toast } from 'react-toastify' +import { createToastArguments } from '../../toasts/helpers/createToastArguments' + +export const initSimulation = (name: string, mode: simulationMode) => { + const state = cloneState(baseSave) + + state.simulation.name = name + state.simulation.mode = mode + + saveStore.set(name, state) + + toast.success( + ...createToastArguments( + `Successfully created simulation ${name}`, + 'check' + ) + ) + + return state +} diff --git a/src/modules/saving/helpers/save.ts b/src/modules/saving/helpers/save.ts index e5657d0..90f5e78 100644 --- a/src/modules/saving/helpers/save.ts +++ b/src/modules/saving/helpers/save.ts @@ -14,7 +14,7 @@ export const save = (renderer: SimulationRenderer) => { saveStore.set(current, state) - toast.info(...createToastArguments(`Succesfully saved ${current}`)) + toast(...createToastArguments(`Succesfully saved ${current}`, 'save')) } else { throw new SimulationError( 'Cannot save without knowing the name of the active simulation' diff --git a/src/modules/saving/types/SimulationSave.ts b/src/modules/saving/types/SimulationSave.ts index 3cb0f9d..fe30e60 100644 --- a/src/modules/saving/types/SimulationSave.ts +++ b/src/modules/saving/types/SimulationSave.ts @@ -35,6 +35,7 @@ export interface SimulationState { wires: WireState[] mode: simulationMode + name: string } export interface RendererState { diff --git a/src/modules/simulation/classes/Simulation.ts b/src/modules/simulation/classes/Simulation.ts index 9c1a961..6e6f038 100644 --- a/src/modules/simulation/classes/Simulation.ts +++ b/src/modules/simulation/classes/Simulation.ts @@ -8,7 +8,10 @@ export class Simulation { public gates = new GateStorage() public wires: Wire[] = [] - public constructor(public mode: simulationMode = 'project') {} + public constructor( + public mode: simulationMode = 'project', + public name: string + ) {} public push(...gates: Gate[]) { for (const gate of gates) { diff --git a/src/modules/simulation/stores/idStore.ts b/src/modules/simulation/stores/idStore.ts index 354db10..e7aff2e 100644 --- a/src/modules/simulation/stores/idStore.ts +++ b/src/modules/simulation/stores/idStore.ts @@ -5,6 +5,12 @@ const store = new LocalStore('id') export const idStore = { generate() { const current = store.get() + + if (current === undefined) { + store.set(1) + return 1 + } + store.set(current + 1) return current + 1 diff --git a/src/modules/simulationRenderer/classes/SimulationRenderer.ts b/src/modules/simulationRenderer/classes/SimulationRenderer.ts index b8910fd..49defd5 100644 --- a/src/modules/simulationRenderer/classes/SimulationRenderer.ts +++ b/src/modules/simulationRenderer/classes/SimulationRenderer.ts @@ -1,6 +1,6 @@ import { Camera } from './Camera' import { Simulation } from '../../simulation/classes/Simulation' -import { Subject, fromEvent } from 'rxjs' +import { Subject } from 'rxjs' import { MouseEventInfo } from '../../core/components/FluidCanvas' import { pointInSquare } from '../../../common/math/helpers/pointInSquare' import { vector2 } from '../../../common/math/types/vector2' @@ -12,14 +12,12 @@ import { defaultSimulationRendererOptions } from '../constants' import { getPinPosition } from '../helpers/pinPosition' import { pointInCircle } from '../../../common/math/helpers/pointInCircle' import { SelectedPins } from '../types/SelectedPins' -import { getRendererState } from '../../saving/helpers/getState' import { Wire } from '../../simulation/classes/Wire' import { KeyBindingMap } from '../../keybindings/types/KeyBindingMap' import { save } from '../../saving/helpers/save' import { initKeyBindings } from '../../keybindings/helpers/initialiseKeyBindings' import { currentStore } from '../../saving/stores/currentStore' import { saveStore } from '../../saving/stores/saveStore' -import { SimulationError } from '../../errors/classes/SimulationError' import { fromSimulationState, fromCameraState @@ -28,7 +26,7 @@ import merge from 'deepmerge' import { wireConnectedToGate } from '../helpers/wireConnectedToGate' import { updateMouse, handleScroll } from '../helpers/scaleCanvas' import { RefObject } from 'react' -// import { WheelEvent } from 'react' +import { Singleton } from '@eix-js/utils' export class SimulationRenderer { public mouseDownOutput = new Subject() @@ -57,7 +55,7 @@ export class SimulationRenderer { public constructor( public ref: RefObject, options: Partial = {}, - public simulation = new Simulation() + public simulation = new Simulation('project', 'default') ) { this.options = merge(defaultSimulationRendererOptions, options) diff --git a/src/modules/storage/classes/LocalStore.ts b/src/modules/storage/classes/LocalStore.ts index d87cd55..64537ae 100644 --- a/src/modules/storage/classes/LocalStore.ts +++ b/src/modules/storage/classes/LocalStore.ts @@ -36,21 +36,18 @@ export class LocalStore { return this.getAll()[key] } - public set(key: string | T = 'index', value?: T) { + public set(key: string | T, value?: T) { + let finalKey = key as string + let finalValue = value as T + if (typeof key !== 'string' || value === undefined) { - localStorage.setItem( - this.name, - JSON.stringify({ - index: key - }) - ) - } else { - localStorage.setItem( - this.name, - JSON.stringify({ - [key]: value - }) - ) + finalKey = 'index' + finalValue = key as T } + + const currentData = this.getAll() + + currentData[finalKey] = finalValue + localStorage.setItem(this.name, JSON.stringify(currentData)) } } diff --git a/src/modules/toasts/components/ToastContent.scss b/src/modules/toasts/components/ToastContent.scss new file mode 100644 index 0000000..2acd320 --- /dev/null +++ b/src/modules/toasts/components/ToastContent.scss @@ -0,0 +1,14 @@ +@import '../../core/styles/mixins/flex.scss'; + +.toast-content-container { + @include flex(); + + justify-content: space-evenly; + flex-direction: row; + font-size: 1em; + color: white; +} + +.toast-content-container > #toast-content-icon { + font-size: 2em; +} diff --git a/src/modules/toasts/components/ToastContent.tsx b/src/modules/toasts/components/ToastContent.tsx new file mode 100644 index 0000000..a602ac4 --- /dev/null +++ b/src/modules/toasts/components/ToastContent.tsx @@ -0,0 +1,19 @@ +import React from 'react' +import './ToastContent.scss' +import Icon from '@material-ui/core/Icon' + +export interface ToastContentProps { + message: string + icon: string +} + +const ToastContent = (props: ToastContentProps) => { + return ( +
+ {props.icon} +
{props.message}
+
+ ) +} + +export default ToastContent diff --git a/src/modules/toasts/helpers/createToastArguments.ts b/src/modules/toasts/helpers/createToastArguments.ts deleted file mode 100644 index 0b6592c..0000000 --- a/src/modules/toasts/helpers/createToastArguments.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { ToastOptions } from 'react-toastify' - -export const createToastArguments = ( - message: string -): [string, ToastOptions] => [ - message, - { - position: 'top-left', - autoClose: 5000, - hideProgressBar: false, - closeOnClick: true, - pauseOnHover: true, - draggable: true - } -] diff --git a/src/modules/toasts/helpers/createToastArguments.tsx b/src/modules/toasts/helpers/createToastArguments.tsx new file mode 100644 index 0000000..aeea2b5 --- /dev/null +++ b/src/modules/toasts/helpers/createToastArguments.tsx @@ -0,0 +1,18 @@ +import { ToastOptions } from 'react-toastify' +import React from 'react' +import ToastContent from '../components/ToastContent' + +export const createToastArguments = ( + message: string, + icon?: string +): [string | JSX.Element, ToastOptions] => [ + icon ? : message, + { + position: 'bottom-right', + autoClose: 5000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true + } +]