diff --git a/src/Board/NewWidget.js b/src/Board/NewWidget.js index 5aac8333a37daba596cb053987c4072bc41bd349..b7f2d6f537b000340c19a9334eceb525a9556695 100644 --- a/src/Board/NewWidget.js +++ b/src/Board/NewWidget.js @@ -1,26 +1,100 @@ import React from 'react'; +import {decorate, observable} from 'mobx' import {observer} from 'mobx-react' -import {forEach} from 'lodash' +import {map} from 'lodash' -import {tab_types} from './Board' +// Mappings from 'string' types (as per tab_types in Board.js) and display names of the available widgets. +const tab_names = { + "video": "Video stream", + "line-chart": "Simple line chart", + "h-gauge": "Gauge", + "memory": "Agent's memory", + "int-trace": "Interaction trace", + "latest-interaction": "Latest interaction", + "mood": "Current mood", + "graph": "Graph" +} +const demo_tab_names = { + "demo-video": "Video stream demo", + "demo-line-chart": "Line chart demo", + "demo-memory": "Agent's memory demo", + "demo-int-trace": "Interaction trace demo", + "demo-latest-interaction": "Latest interaction demo", + "demo-mood": "Current mood demo", + "demo-graph": "Graph demo", + "string": "ROS debug", +} +/** + * This React component appears in a modal, once we click on the '+' button in the menu. It offers the user to choose + * which component he/she wants to add to the dashboard. + */ export const NewWidget = observer( class NewWidget extends React.Component { - render() { - console.debug(tab_types); + selected = Object.keys(tab_names)[0]; + enableDemoWidgets = false; + + /** + * Set the data for a new tab/widget to be added in the dashboard. This will trigger a method in Board.js, thanks to + * Mobx's magic. It also closes this modal. + */ + addTab() { + this.props.store.sharedData.set('newTab', { + component: this.selected, + name: tab_names[this.selected] + }); + this.props.store.exitModal(); + } + + /** + * This method is used to generate radio inputs for the widgets we offer the user to add to the dashboard. It's + * called in a map (Lodash style). + * @param {string} name Display name of the widget + * @param {string} type string for the type of the widget, as used in Board.js' tab_types + */ + inputFromTabName(name, type) { + return ( + <div key={type}> + <label> + <input + type="radio" + name="component-type" + value={type} + checked={type === this.selected} + onChange={(changeEvent) => {this.selected = changeEvent.target.value}} + /> + {name} + </label> + </div> + ); + } - forEach(tab_types, (value, key) => {console.debug(key)}); + render() { + let inputs = map(tab_names, this.inputFromTabName.bind(this)); + // if the user chose to see the demo widgets, add these to the list + if (this.enableDemoWidgets) { + inputs.push(map(demo_tab_names, this.inputFromTabName.bind(this))); + } return ( - <div> - <input - type="radio" - name="react-tips" - value="option1" - checked={true} - onChange={() => {}} - className="form-check-input" - /> - </div>) + <div> + {inputs} + + <label> + <input + type="checkbox" + checked={this.enableDemoWidgets} + onChange={(changeEvent) => {this.enableDemoWidgets = changeEvent.target.checked;}} + /> + Show demo widgets + </label><br/> + + <button onClick={this.addTab.bind(this)}>Add to the dashboard</button> + </div> + ) } }) +decorate(NewWidget, { + selected: observable, + enableDemoWidgets: observable, +}) diff --git a/src/Menu/index.js b/src/Menu/index.js index e0893302f68388db9070e95c2bfd007bfd9258bd..cf3aa45e8c951163fd898214c643bf7a8f3a987f 100644 --- a/src/Menu/index.js +++ b/src/Menu/index.js @@ -13,20 +13,19 @@ function Menu(props) { const new_value = (lock === 'closed') ? 'open' : 'closed'; props.store.sharedData.set('lock', new_value); } + function add_widget() { - props.store.displayModal(<NewWidget/>); + props.store.displayModal(<NewWidget store={props.store}/>); } - - // Display an "add" icon if the lock is open + // Display an "add" icon if the lock is open. This icon is used to add new widgets to the dashboard. let add_button = null; if (lock === 'open') { add_button = ( - <button onClick={add_widget}> - <img className="footer add-button" - src={window.location.origin + "/images/icons/add_circle_outline.svg"} - alt="add a new widget" - /> - </button>); + <img className="footer add-button" + onClick={add_widget} + src={window.location.origin + "/images/icons/add_circle_outline.svg"} + alt="add a new widget" + />); } return( @@ -51,17 +50,15 @@ function Menu(props) { Custom </div> - <NavItem eventKey="demo" onClick={props.drag('line-chart', "line chart")}> + <NavItem eventKey="demo"> <NavIcon> <img className="menu-button" src={window.location.origin + "/images/icons/dashboard-grey.svg"} - alt="line chart" + alt="Demo mode" /> - {/* alt="Demo mode" */} </NavIcon> <NavText> - line chart - {/* Demo */} + Demo </NavText> </NavItem> @@ -73,59 +70,51 @@ function Menu(props) { Algorithm </div> - <NavItem eventKey="memory" onClick={props.drag('h-gauge', "gauge")}> + <NavItem eventKey="memory"> <NavIcon> <img className="menu-button" src={window.location.origin + "/images/icons/memory-grey.svg"} - alt="gauge" + alt="memory dashboard" /> - {/* alt="memory dashboard" */} </NavIcon> <NavText> - gauge - {/* Memory */} + Memory </NavText> </NavItem> - <NavItem eventKey="traces" onClick={props.drag('graph', "graph")}> + <NavItem eventKey="traces"> <NavIcon> <img className="menu-button" src={window.location.origin + "/images/icons/trace-grey.svg"} - alt="graph" + alt="trace dashboard" /> - {/* alt="trace dashboard" */} </NavIcon> <NavText> - graph - {/* Traces */} + Traces </NavText> </NavItem> - <NavItem eventKey="mental-states" onClick={props.drag('video', "video")}> + <NavItem eventKey="mental-states"> <NavIcon> <img className="menu-button" src={window.location.origin + "/images/icons/mood-grey.svg"} - alt="video" + alt="mood dashboard" /> - {/* alt="mood dashboard" */} </NavIcon> <NavText> - video - {/* Mental states */} + Mental states </NavText> </NavItem> - <NavItem eventKey="decision-making" onClick={props.drag('memory', "memory")}> + <NavItem eventKey="decision-making"> <NavIcon> <img className="menu-button" src={window.location.origin + "/images/icons/choice-grey.svg"} - alt="memory" + alt="choice dashboard" /> - {/* alt="choice dashboard" */} </NavIcon> <NavText> - memory - {/* Decision making */} + Decision making </NavText> </NavItem> @@ -133,45 +122,39 @@ function Menu(props) { Robot </div> - <NavItem eventKey="video" onClick={props.drag('int-trace', "interaction trace")}> + <NavItem eventKey="video"> <NavIcon> <img className="menu-button" src={window.location.origin + "/images/icons/video-grey.svg"} - alt="interaction trace" + alt="video dashboard" /> - {/* alt="video dashboard" */} </NavIcon> <NavText> - interaction trace - {/* Video */} + Video </NavText> </NavItem> - <NavItem eventKey="audio" onClick={props.drag('latest-interaction', "latest interaction")}> + <NavItem eventKey="audio"> <NavIcon> <img className="menu-button" src={window.location.origin + "/images/icons/microphone-grey.svg"} - alt="latest interaction" + alt="microphone dashboard" /> - {/* alt="microphone dashboard" */} </NavIcon> <NavText> - latest interaction - {/* Audio */} + Audio </NavText> </NavItem> - <NavItem eventKey="sensory" onClick={props.drag('mood', "mood")}> + <NavItem eventKey="sensory"> <NavIcon> <img className="menu-button" src={window.location.origin + "/images/icons/fingerprint-grey.svg"} - alt="mood" + alt="sensory dashboard" /> - {/* alt="sensory dashboard" */} </NavIcon> <NavText> - mood - {/* Sensory */} + Sensory </NavText> </NavItem> diff --git a/src/index.js b/src/index.js index 5f651f0d47e6991abb580b0943a4581112150f53..8e59e87deed5fb8ef75f1e8a52e48ba083343c35 100644 --- a/src/index.js +++ b/src/index.js @@ -12,12 +12,10 @@ import RosLib from 'roslib'; import {Board} from './Board/Board'; import {Header} from './Header'; import {Menu} from "./Menu"; -import {GadgetModal} from './utils/GadgetModal'; import 'bootstrap/dist/css/bootstrap.min.css' // CSS common to the whole app import './Common.css' -import { throwStatement } from "@babel/types"; class ObservableStore { components = {}