diff options
Diffstat (limited to 'src/components')
21 files changed, 142 insertions, 128 deletions
diff --git a/src/components/modals/Modal.js b/src/components/modals/Modal.js index c4f10b29..0b3301af 100644 --- a/src/components/modals/Modal.js +++ b/src/components/modals/Modal.js @@ -10,8 +10,10 @@ class Modal extends React.Component { }; static idCounter = 0; - // Local, up-to-date copy of modal visibility for time between close and props update (to prevent duplicate close - // triggers) + /** + * Local, up-to-date copy of modal visibility for time between close event and a props update (to prevent duplicate + * close triggers). + */ visible = false; constructor() { @@ -23,6 +25,11 @@ class Modal extends React.Component { this.visible = this.props.show; this.openOrCloseModal(); + // Trigger auto-focus + window["$"]("#" + this.id).on("shown.bs.modal", function () { + window["$"](this).find("input").first().focus(); + }); + window["$"]("#" + this.id).on("hide.bs.modal", () => { if (this.visible) { this.props.onCancel(); diff --git a/src/components/modals/TextInputModal.js b/src/components/modals/TextInputModal.js index 4acf25b3..90a5db12 100644 --- a/src/components/modals/TextInputModal.js +++ b/src/components/modals/TextInputModal.js @@ -27,10 +27,14 @@ class TextInputModal extends React.Component { show={this.props.show} onSubmit={this.onSubmit.bind(this)} onCancel={this.onCancel.bind(this)}> - <form> + <form onSubmit={e => { + e.preventDefault(); + this.onSubmit(); + }}> <div className="form-group"> <label className="form-control-label">{this.props.label}:</label> - <input type="text" className="form-control" ref="textInput" value={this.props.initialValue}/> + <input type="text" className="form-control" ref="textInput" value={this.props.initialValue} + autoFocus/> </div> </form> </Modal> diff --git a/src/components/navigation/Navbar.js b/src/components/navigation/Navbar.js index 96dd93b4..ce020fef 100644 --- a/src/components/navigation/Navbar.js +++ b/src/components/navigation/Navbar.js @@ -17,7 +17,7 @@ class Navbar extends Component { </div> </Link> <div className="navigation navbar-button-group"> - <Link className="projects" title="Projects" to="/projects">Projects</Link> + <Link className="simulations" title="Simulations" to="/simulations">Simulations</Link> </div> <div className="user-controls navbar-button-group"> <Mailto className="support" title="Support" email="opendc.tudelft@gmail.com" diff --git a/src/components/navigation/Navbar.sass b/src/components/navigation/Navbar.sass index 8be622db..e9a83301 100644 --- a/src/components/navigation/Navbar.sass +++ b/src/components/navigation/Navbar.sass @@ -29,6 +29,9 @@ +transition(background, $transition-length) + &:hover + color: #fff + img display: inline-block float: left @@ -73,16 +76,16 @@ .navigation margin-left: 30px - .projects + .simulations float: left padding: 0 20px font-size: 12pt - .projects:hover + .simulations:hover background: #606060 - .projects:active + .simulations:active background: #161616 .user-controls diff --git a/src/components/projects/FilterPanel.js b/src/components/projects/FilterPanel.js deleted file mode 100644 index 050bf0aa..00000000 --- a/src/components/projects/FilterPanel.js +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; -import FilterLink from "../../containers/projects/FilterLink"; -import "./FilterPanel.css"; - -const ProjectFilterPanel = () => ( - <div className="filter-menu"> - <div className="project-filters"> - <FilterLink filter="SHOW_ALL">All Projects</FilterLink> - <FilterLink filter="SHOW_OWN">My Projects</FilterLink> - <FilterLink filter="SHOW_SHARED">Projects shared with me</FilterLink> - </div> - </div> -); - -export default ProjectFilterPanel; diff --git a/src/components/projects/NewProjectButton.js b/src/components/projects/NewProjectButton.js deleted file mode 100644 index 9eaf6df4..00000000 --- a/src/components/projects/NewProjectButton.js +++ /dev/null @@ -1,16 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import './NewProjectButton.css'; - -const NewProjectButton = ({onClick}) => ( - <div className="new-project-btn" onClick={onClick}> - <span className="fa fa-plus"/> - New Project - </div> -); - -NewProjectButton.propTypes = { - onClick: PropTypes.func.isRequired, -}; - -export default NewProjectButton; diff --git a/src/components/projects/NoProjectsAlert.js b/src/components/projects/NoProjectsAlert.js deleted file mode 100644 index 957435c7..00000000 --- a/src/components/projects/NoProjectsAlert.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; -import "./NoProjectsAlert.css"; - -const NoProjectsAlert = () => ( - <div className="no-projects-alert alert alert-info"> - <span className="info-icon fa fa-2x fa-question-circle"/> - <strong>No projects here yet...</strong> Add some with the 'New Project' button! - </div> -); - -export default NoProjectsAlert; diff --git a/src/components/projects/ProjectActionButtons.js b/src/components/projects/ProjectActionButtons.js deleted file mode 100644 index 66eb8bfa..00000000 --- a/src/components/projects/ProjectActionButtons.js +++ /dev/null @@ -1,26 +0,0 @@ -import PropTypes from "prop-types"; -import React from 'react'; - -const ProjectActionButtons = ({projectId, onOpen, onViewUsers, onDelete}) => ( - <div className="project-icons"> - <div className="open" title="Open this project" onClick={() => onOpen(projectId)}> - <span className="fa fa-play"/> - </div> - <div className="users" title="View and edit collaborators on this project" - onClick={() => onViewUsers(projectId)}> - <span className="fa fa-users"/> - </div> - <div className="delete" title="Delete this project" onClick={() => onDelete(projectId)}> - <span className="fa fa-trash"/> - </div> - </div> -); - -ProjectActionButtons.propTypes = { - projectId: PropTypes.number.isRequired, - onOpen: PropTypes.func, - onViewUsers: PropTypes.func, - onDelete: PropTypes.func, -}; - -export default ProjectActionButtons; diff --git a/src/components/projects/ProjectAuth.js b/src/components/projects/ProjectAuth.js deleted file mode 100644 index 10cfd252..00000000 --- a/src/components/projects/ProjectAuth.js +++ /dev/null @@ -1,24 +0,0 @@ -import classNames from 'classnames'; -import React from 'react'; -import ProjectActions from "../../containers/projects/ProjectActions"; -import Shapes from "../../shapes/index"; -import {AUTH_DESCRIPTION_MAP, AUTH_ICON_MAP} from "../../util/authorizations"; -import {parseAndFormatDateTime} from "../../util/date-time"; - -const ProjectAuth = ({projectAuth}) => ( - <div className="project-row"> - <div>{projectAuth.simulation.name}</div> - <div>{parseAndFormatDateTime(projectAuth.simulation.datetimeLastEdited)}</div> - <div> - <span className={classNames("fa", "fa-" + AUTH_ICON_MAP[projectAuth.authorizationLevel])}/> - {AUTH_DESCRIPTION_MAP[projectAuth.authorizationLevel]} - </div> - <ProjectActions projectId={projectAuth.simulation.id}/> - </div> -); - -ProjectAuth.propTypes = { - projectAuth: Shapes.Authorization.isRequired, -}; - -export default ProjectAuth; diff --git a/src/components/projects/FilterButton.js b/src/components/simulations/FilterButton.js index 8d6b7146..2105d281 100644 --- a/src/components/projects/FilterButton.js +++ b/src/components/simulations/FilterButton.js @@ -4,7 +4,7 @@ import React from 'react'; import "./FilterButton.css"; const FilterButton = ({active, children, onClick}) => ( - <div className={classNames("project-filter-button", {"active": active})} + <div className={classNames("simulation-filter-button", {"active": active})} onClick={() => { if (!active) { onClick(); diff --git a/src/components/projects/FilterButton.sass b/src/components/simulations/FilterButton.sass index 0cad68e3..60f6faca 100644 --- a/src/components/projects/FilterButton.sass +++ b/src/components/simulations/FilterButton.sass @@ -1,7 +1,7 @@ @import ../../style-globals/_mixins.sass @import ../../style-globals/_variables.sass -.project-filter-button +.simulation-filter-button display: inline-block width: 33.3% //margin-right: -4px @@ -13,11 +13,11 @@ +clickable +transition(background, $transition-length) -.project-filter-button:last-of-type +.simulation-filter-button:last-of-type border: 0 -.project-filter-button:hover +.simulation-filter-button:hover background: #0c60bf -.project-filter-button:active, .project-filter-button.active +.simulation-filter-button:active, .simulation-filter-button.active background: #073d7d diff --git a/src/components/simulations/FilterPanel.js b/src/components/simulations/FilterPanel.js new file mode 100644 index 00000000..b43139c1 --- /dev/null +++ b/src/components/simulations/FilterPanel.js @@ -0,0 +1,15 @@ +import React from 'react'; +import FilterLink from "../../containers/simulations/FilterLink"; +import "./FilterPanel.css"; + +const FilterPanel = () => ( + <div className="filter-menu"> + <div className="simulation-filters"> + <FilterLink filter="SHOW_ALL">All Simulations</FilterLink> + <FilterLink filter="SHOW_OWN">My Simulations</FilterLink> + <FilterLink filter="SHOW_SHARED">Simulations shared with me</FilterLink> + </div> + </div> +); + +export default FilterPanel; diff --git a/src/components/projects/FilterPanel.sass b/src/components/simulations/FilterPanel.sass index a70c7a90..a59ffdfd 100644 --- a/src/components/projects/FilterPanel.sass +++ b/src/components/simulations/FilterPanel.sass @@ -15,7 +15,7 @@ margin-bottom: 20px - .project-filters + .simulation-filters display: block overflow: hidden margin: 0 -1px diff --git a/src/components/simulations/NewSimulationButton.js b/src/components/simulations/NewSimulationButton.js new file mode 100644 index 00000000..468f7678 --- /dev/null +++ b/src/components/simulations/NewSimulationButton.js @@ -0,0 +1,16 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import './NewSimulationButton.css'; + +const NewSimulationButton = ({onClick}) => ( + <div className="new-simulation-btn" onClick={onClick}> + <span className="fa fa-plus"/> + New Simulation + </div> +); + +NewSimulationButton.propTypes = { + onClick: PropTypes.func.isRequired, +}; + +export default NewSimulationButton; diff --git a/src/components/projects/NewProjectButton.sass b/src/components/simulations/NewSimulationButton.sass index 89435902..9bf82c49 100644 --- a/src/components/projects/NewProjectButton.sass +++ b/src/components/simulations/NewSimulationButton.sass @@ -1,7 +1,7 @@ @import ../../style-globals/_mixins.sass @import ../../style-globals/_variables.sass -.new-project-btn +.new-simulation-btn $button-height: 35px display: inline-block @@ -24,8 +24,8 @@ span margin-right: 10px -.new-project-btn:hover +.new-simulation-btn:hover background: #73ac45 -.new-project-btn:active +.new-simulation-btn:active background: #5c8835 diff --git a/src/components/simulations/NoSimulationsAlert.js b/src/components/simulations/NoSimulationsAlert.js new file mode 100644 index 00000000..d688ae56 --- /dev/null +++ b/src/components/simulations/NoSimulationsAlert.js @@ -0,0 +1,11 @@ +import React from 'react'; +import "./NoSimulationsAlert.css"; + +const NoSimulationsAlert = () => ( + <div className="no-simulations-alert alert alert-info"> + <span className="info-icon fa fa-2x fa-question-circle"/> + <strong>No simulations here yet...</strong> Add some with the 'New Simulation' button! + </div> +); + +export default NoSimulationsAlert; diff --git a/src/components/projects/NoProjectsAlert.sass b/src/components/simulations/NoSimulationsAlert.sass index a526f9ad..10e89e51 100644 --- a/src/components/projects/NoProjectsAlert.sass +++ b/src/components/simulations/NoSimulationsAlert.sass @@ -1,4 +1,4 @@ -.no-projects-alert +.no-simulations-alert position: relative padding-left: 50px diff --git a/src/components/simulations/SimulationActionButtons.js b/src/components/simulations/SimulationActionButtons.js new file mode 100644 index 00000000..d48b4bcf --- /dev/null +++ b/src/components/simulations/SimulationActionButtons.js @@ -0,0 +1,26 @@ +import PropTypes from "prop-types"; +import React from 'react'; + +const SimulationActionButtons = ({simulationId, onOpen, onViewUsers, onDelete}) => ( + <div className="simulation-icons"> + <div className="open" title="Open this simulation" onClick={() => onOpen(simulationId)}> + <span className="fa fa-play"/> + </div> + <div className="users" title="View and edit collaborators on this simulation" + onClick={() => onViewUsers(simulationId)}> + <span className="fa fa-users"/> + </div> + <div className="delete" title="Delete this simulation" onClick={() => onDelete(simulationId)}> + <span className="fa fa-trash"/> + </div> + </div> +); + +SimulationActionButtons.propTypes = { + simulationId: PropTypes.number.isRequired, + onOpen: PropTypes.func, + onViewUsers: PropTypes.func, + onDelete: PropTypes.func, +}; + +export default SimulationActionButtons; diff --git a/src/components/simulations/SimulationAuth.js b/src/components/simulations/SimulationAuth.js new file mode 100644 index 00000000..9b887991 --- /dev/null +++ b/src/components/simulations/SimulationAuth.js @@ -0,0 +1,24 @@ +import classNames from 'classnames'; +import React from 'react'; +import SimulationActions from "../../containers/simulations/SimulationActions"; +import Shapes from "../../shapes/index"; +import {AUTH_DESCRIPTION_MAP, AUTH_ICON_MAP} from "../../util/authorizations"; +import {parseAndFormatDateTime} from "../../util/date-time"; + +const SimulationAuth = ({simulationAuth}) => ( + <div className="simulation-row"> + <div>{simulationAuth.simulation.name}</div> + <div>{parseAndFormatDateTime(simulationAuth.simulation.datetimeLastEdited)}</div> + <div> + <span className={classNames("fa", "fa-" + AUTH_ICON_MAP[simulationAuth.authorizationLevel])}/> + {AUTH_DESCRIPTION_MAP[simulationAuth.authorizationLevel]} + </div> + <SimulationActions simulationId={simulationAuth.simulation.id}/> + </div> +); + +SimulationAuth.propTypes = { + simulationAuth: Shapes.Authorization.isRequired, +}; + +export default SimulationAuth; diff --git a/src/components/projects/ProjectAuthList.js b/src/components/simulations/SimulationAuthList.js index 94e7abad..7653f178 100644 --- a/src/components/projects/ProjectAuthList.js +++ b/src/components/simulations/SimulationAuthList.js @@ -1,33 +1,33 @@ import PropTypes from 'prop-types'; import React from 'react'; import Shapes from "../../shapes/index"; -import NoProjectsAlert from "./NoProjectsAlert"; -import ProjectAuth from "./ProjectAuth"; -import "./ProjectAuthList.css"; +import NoSimulationsAlert from "./NoSimulationsAlert"; +import SimulationAuth from "./SimulationAuth"; +import "./SimulationAuthList.css"; -const ProjectAuthList = ({authorizations}) => { +const SimulationAuthList = ({authorizations}) => { if (authorizations.length === 0) { - return <NoProjectsAlert/>; + return <NoSimulationsAlert/>; } return ( - <div className="project-list"> + <div className="simulation-list"> <div className="list-head"> - <div>Project name</div> + <div>Simulation name</div> <div>Last edited</div> <div>Access rights</div> </div> <div className="list-body"> {authorizations.map(authorization => ( - <ProjectAuth projectAuth={authorization} key={authorization.simulation.id}/> + <SimulationAuth simulationAuth={authorization} key={authorization.simulation.id}/> ))} </div> </div> ); }; -ProjectAuthList.propTypes = { +SimulationAuthList.propTypes = { authorizations: PropTypes.arrayOf(Shapes.Authorization).isRequired, }; -export default ProjectAuthList; +export default SimulationAuthList; diff --git a/src/components/projects/ProjectAuthList.sass b/src/components/simulations/SimulationAuthList.sass index 5cdfacaa..4edfb99e 100644 --- a/src/components/projects/ProjectAuthList.sass +++ b/src/components/simulations/SimulationAuthList.sass @@ -1,16 +1,16 @@ @import ../../style-globals/_mixins.sass @import ../../style-globals/_variables.sass -.project-list +.simulation-list display: block font-size: 12pt border: 0 - .list-head, .list-body .project-row + .list-head, .list-body .simulation-row display: block position: relative - .list-head div, .list-body .project-row div + .list-head div, .list-body .simulation-row div padding: 0 10px display: inline-block @@ -21,18 +21,18 @@ div margin-right: -4px -.project-row +.simulation-row background: #f8f8f8 border: 1px solid #b6b6b6 height: 40px line-height: 40px clear: both -.project-row:not(:first-of-type) +.simulation-row:not(:first-of-type) margin-top: -1px // Sizing of table columns -.project-row, .project-list .list-head +.simulation-row, .simulation-list .list-head div:first-of-type width: 40% @@ -48,10 +48,10 @@ span margin-right: 10px -.project-row .project-icons +.simulation-row .simulation-icons text-align: right -.project-row .project-icons div +.simulation-row .simulation-icons div display: inline position: relative top: 4px |
