summaryrefslogtreecommitdiff
path: root/opendc-web/opendc-web-ui/src/components/app/sidebars/project
diff options
context:
space:
mode:
Diffstat (limited to 'opendc-web/opendc-web-ui/src/components/app/sidebars/project')
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/project/PortfolioListComponent.js66
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/project/ProjectSidebarComponent.js15
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/project/ScenarioListComponent.js62
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/project/TopologyListComponent.js60
4 files changed, 203 insertions, 0 deletions
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/project/PortfolioListComponent.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/project/PortfolioListComponent.js
new file mode 100644
index 00000000..b000b9e2
--- /dev/null
+++ b/opendc-web/opendc-web-ui/src/components/app/sidebars/project/PortfolioListComponent.js
@@ -0,0 +1,66 @@
+import PropTypes from 'prop-types'
+import React from 'react'
+import Shapes from '../../../../shapes'
+import { Link } from 'react-router-dom'
+import FontAwesome from 'react-fontawesome'
+import ScenarioListContainer from '../../../../containers/app/sidebars/project/ScenarioListContainer'
+
+class PortfolioListComponent extends React.Component {
+ static propTypes = {
+ portfolios: PropTypes.arrayOf(Shapes.Portfolio),
+ currentProjectId: PropTypes.string.isRequired,
+ currentPortfolioId: PropTypes.string,
+ onNewPortfolio: PropTypes.func.isRequired,
+ onChoosePortfolio: PropTypes.func.isRequired,
+ onDeletePortfolio: PropTypes.func.isRequired,
+ }
+
+ onDelete(id) {
+ this.props.onDeletePortfolio(id)
+ }
+
+ render() {
+ return (
+ <div className="pb-3">
+ <h2>
+ Portfolios
+ <button
+ className="btn btn-outline-primary float-right"
+ onClick={this.props.onNewPortfolio.bind(this)}
+ >
+ <FontAwesome name="plus" />
+ </button>
+ </h2>
+
+ {this.props.portfolios.map((portfolio, idx) => (
+ <div key={portfolio._id}>
+ <div className="row mb-1">
+ <div
+ className={
+ 'col-7 align-self-center ' +
+ (portfolio._id === this.props.currentPortfolioId ? 'font-weight-bold' : '')
+ }
+ >
+ {portfolio.name}
+ </div>
+ <div className="col-5 text-right">
+ <Link
+ className="btn btn-outline-primary mr-1 fa fa-play"
+ to={`/projects/${this.props.currentProjectId}/portfolios/${portfolio._id}`}
+ onClick={() => this.props.onChoosePortfolio(portfolio._id)}
+ />
+ <span
+ className="btn btn-outline-danger fa fa-trash"
+ onClick={() => this.onDelete(portfolio._id)}
+ />
+ </div>
+ </div>
+ <ScenarioListContainer portfolioId={portfolio._id} />
+ </div>
+ ))}
+ </div>
+ )
+ }
+}
+
+export default PortfolioListComponent
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/project/ProjectSidebarComponent.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/project/ProjectSidebarComponent.js
new file mode 100644
index 00000000..4789315e
--- /dev/null
+++ b/opendc-web/opendc-web-ui/src/components/app/sidebars/project/ProjectSidebarComponent.js
@@ -0,0 +1,15 @@
+import React from 'react'
+import Sidebar from '../Sidebar'
+import TopologyListContainer from '../../../../containers/app/sidebars/project/TopologyListContainer'
+import PortfolioListContainer from '../../../../containers/app/sidebars/project/PortfolioListContainer'
+
+const ProjectSidebarComponent = ({ collapsible }) => (
+ <Sidebar isRight={false} collapsible={collapsible}>
+ <div className="h-100 overflow-auto container-fluid">
+ <TopologyListContainer />
+ <PortfolioListContainer />
+ </div>
+ </Sidebar>
+)
+
+export default ProjectSidebarComponent
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/project/ScenarioListComponent.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/project/ScenarioListComponent.js
new file mode 100644
index 00000000..e775a663
--- /dev/null
+++ b/opendc-web/opendc-web-ui/src/components/app/sidebars/project/ScenarioListComponent.js
@@ -0,0 +1,62 @@
+import PropTypes from 'prop-types'
+import React from 'react'
+import Shapes from '../../../../shapes'
+import { Link } from 'react-router-dom'
+import FontAwesome from 'react-fontawesome'
+
+class ScenarioListComponent extends React.Component {
+ static propTypes = {
+ scenarios: PropTypes.arrayOf(Shapes.Scenario),
+ portfolioId: PropTypes.string,
+ currentProjectId: PropTypes.string.isRequired,
+ currentScenarioId: PropTypes.string,
+ onNewScenario: PropTypes.func.isRequired,
+ onChooseScenario: PropTypes.func.isRequired,
+ onDeleteScenario: PropTypes.func.isRequired,
+ }
+
+ onDelete(id) {
+ this.props.onDeleteScenario(id)
+ }
+
+ render() {
+ return (
+ <>
+ {this.props.scenarios.map((scenario, idx) => (
+ <div key={scenario._id} className="row mb-1">
+ <div
+ className={
+ 'col-7 pl-5 align-self-center ' +
+ (scenario._id === this.props.currentScenarioId ? 'font-weight-bold' : '')
+ }
+ >
+ {scenario.name}
+ </div>
+ <div className="col-5 text-right">
+ <Link
+ className="btn btn-outline-primary mr-1 fa fa-play disabled"
+ to={`/projects/${this.props.currentProjectId}/portfolios/${scenario.portfolioId}/scenarios/${scenario._id}`}
+ onClick={() => this.props.onChooseScenario(scenario.portfolioId, scenario._id)}
+ />
+ <span
+ className={'btn btn-outline-danger fa fa-trash ' + (idx === 0 ? 'disabled' : '')}
+ onClick={() => (idx !== 0 ? this.onDelete(scenario._id) : undefined)}
+ />
+ </div>
+ </div>
+ ))}
+ <div className="pl-4 mb-2">
+ <div
+ className="btn btn-outline-primary"
+ onClick={() => this.props.onNewScenario(this.props.portfolioId)}
+ >
+ <FontAwesome name="plus" className="mr-1" />
+ New scenario
+ </div>
+ </div>
+ </>
+ )
+ }
+}
+
+export default ScenarioListComponent
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/project/TopologyListComponent.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/project/TopologyListComponent.js
new file mode 100644
index 00000000..2f42f7e4
--- /dev/null
+++ b/opendc-web/opendc-web-ui/src/components/app/sidebars/project/TopologyListComponent.js
@@ -0,0 +1,60 @@
+import PropTypes from 'prop-types'
+import React from 'react'
+import Shapes from '../../../../shapes'
+import FontAwesome from 'react-fontawesome'
+
+class TopologyListComponent extends React.Component {
+ static propTypes = {
+ topologies: PropTypes.arrayOf(Shapes.Topology),
+ currentTopologyId: PropTypes.string,
+ onChooseTopology: PropTypes.func.isRequired,
+ onNewTopology: PropTypes.func.isRequired,
+ onDeleteTopology: PropTypes.func.isRequired,
+ }
+
+ onChoose(id) {
+ this.props.onChooseTopology(id)
+ }
+
+ onDelete(id) {
+ this.props.onDeleteTopology(id)
+ }
+
+ render() {
+ return (
+ <div className="pb-3">
+ <h2>
+ Topologies
+ <button className="btn btn-outline-primary float-right" onClick={this.props.onNewTopology}>
+ <FontAwesome name="plus" />
+ </button>
+ </h2>
+
+ {this.props.topologies.map((topology, idx) => (
+ <div key={topology._id} className="row mb-1">
+ <div
+ className={
+ 'col-7 align-self-center ' +
+ (topology._id === this.props.currentTopologyId ? 'font-weight-bold' : '')
+ }
+ >
+ {topology.name}
+ </div>
+ <div className="col-5 text-right">
+ <span
+ className="btn btn-outline-primary mr-1 fa fa-play"
+ onClick={() => this.onChoose(topology._id)}
+ />
+ <span
+ className={'btn btn-outline-danger fa fa-trash ' + (idx === 0 ? 'disabled' : '')}
+ onClick={() => (idx !== 0 ? this.onDelete(topology._id) : undefined)}
+ />
+ </div>
+ </div>
+ ))}
+ </div>
+ )
+ }
+}
+
+export default TopologyListComponent