summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--opendc-web/opendc-web-ui/src/actions/modals/portfolios.js14
-rw-r--r--opendc-web/opendc-web-ui/src/actions/modals/prefabs.js14
-rw-r--r--opendc-web/opendc-web-ui/src/actions/modals/scenarios.js14
-rw-r--r--opendc-web/opendc-web-ui/src/actions/modals/topology.js84
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/project/PortfolioListComponent.js38
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/project/ProjectSidebarComponent.js5
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/project/ScenarioListComponent.js40
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/project/TopologyListComponent.js38
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/machine/DeleteMachineComponent.js10
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/machine/MachineNameComponent.js5
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/DeleteRackComponent.js10
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackNameComponent.js6
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/room/EditRoomComponent.js22
-rw-r--r--opendc-web/opendc-web-ui/src/components/app/sidebars/topology/room/RoomNameComponent.js6
-rw-r--r--opendc-web/opendc-web-ui/src/containers/app/App.js20
-rw-r--r--opendc-web/opendc-web-ui/src/containers/app/map/TopologyContainer.js4
-rw-r--r--opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js56
-rw-r--r--opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js79
-rw-r--r--opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js63
-rw-r--r--opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/machine/DeleteMachineContainer.js31
-rw-r--r--opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/machine/MachineNameContainer.js5
-rw-r--r--opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/rack/DeleteRackContainer.js31
-rw-r--r--opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/rack/RackNameContainer.js29
-rw-r--r--opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/room/DeleteRoomContainer.js32
-rw-r--r--opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/room/EditRoomContainer.js28
-rw-r--r--opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/room/RoomNameContainer.js30
-rw-r--r--opendc-web/opendc-web-ui/src/containers/modals/DeleteMachineModal.js26
-rw-r--r--opendc-web/opendc-web-ui/src/containers/modals/DeleteRackModal.js27
-rw-r--r--opendc-web/opendc-web-ui/src/containers/modals/DeleteRoomModal.js28
-rw-r--r--opendc-web/opendc-web-ui/src/containers/modals/EditRackNameModal.js37
-rw-r--r--opendc-web/opendc-web-ui/src/containers/modals/EditRoomNameModal.js31
-rw-r--r--opendc-web/opendc-web-ui/src/containers/modals/NewPortfolioModal.js24
-rw-r--r--opendc-web/opendc-web-ui/src/containers/modals/NewScenarioModal.js53
-rw-r--r--opendc-web/opendc-web-ui/src/containers/modals/NewTopologyModal.js48
-rw-r--r--opendc-web/opendc-web-ui/src/containers/navigation/AppNavbarContainer.js4
-rw-r--r--opendc-web/opendc-web-ui/src/reducers/index.js2
-rw-r--r--opendc-web/opendc-web-ui/src/reducers/modals.js41
-rw-r--r--opendc-web/opendc-web-ui/src/store/hooks/experiments.js37
-rw-r--r--opendc-web/opendc-web-ui/src/store/hooks/project.js48
-rw-r--r--opendc-web/opendc-web-ui/src/store/hooks/topology.js21
40 files changed, 450 insertions, 691 deletions
diff --git a/opendc-web/opendc-web-ui/src/actions/modals/portfolios.js b/opendc-web/opendc-web-ui/src/actions/modals/portfolios.js
deleted file mode 100644
index f6dce2e3..00000000
--- a/opendc-web/opendc-web-ui/src/actions/modals/portfolios.js
+++ /dev/null
@@ -1,14 +0,0 @@
-export const OPEN_NEW_PORTFOLIO_MODAL = 'OPEN_NEW_PORTFOLIO_MODAL'
-export const CLOSE_NEW_PORTFOLIO_MODAL = 'CLOSE_PORTFOLIO_MODAL'
-
-export function openNewPortfolioModal() {
- return {
- type: OPEN_NEW_PORTFOLIO_MODAL,
- }
-}
-
-export function closeNewPortfolioModal() {
- return {
- type: CLOSE_NEW_PORTFOLIO_MODAL,
- }
-}
diff --git a/opendc-web/opendc-web-ui/src/actions/modals/prefabs.js b/opendc-web/opendc-web-ui/src/actions/modals/prefabs.js
deleted file mode 100644
index 826565d2..00000000
--- a/opendc-web/opendc-web-ui/src/actions/modals/prefabs.js
+++ /dev/null
@@ -1,14 +0,0 @@
-export const OPEN_NEW_PREFAB_MODAL = 'OPEN_NEW_PREFAB_MODAL'
-export const CLOSE_NEW_PREFAB_MODAL = 'CLOSE_PREFAB_MODAL'
-
-export function openNewPrefabModal() {
- return {
- type: OPEN_NEW_PREFAB_MODAL,
- }
-}
-
-export function closeNewPrefabModal() {
- return {
- type: CLOSE_NEW_PREFAB_MODAL,
- }
-}
diff --git a/opendc-web/opendc-web-ui/src/actions/modals/scenarios.js b/opendc-web/opendc-web-ui/src/actions/modals/scenarios.js
deleted file mode 100644
index b71cb27b..00000000
--- a/opendc-web/opendc-web-ui/src/actions/modals/scenarios.js
+++ /dev/null
@@ -1,14 +0,0 @@
-export const OPEN_NEW_SCENARIO_MODAL = 'OPEN_NEW_SCENARIO_MODAL'
-export const CLOSE_NEW_SCENARIO_MODAL = 'CLOSE_SCENARIO_MODAL'
-
-export function openNewScenarioModal() {
- return {
- type: OPEN_NEW_SCENARIO_MODAL,
- }
-}
-
-export function closeNewScenarioModal() {
- return {
- type: CLOSE_NEW_SCENARIO_MODAL,
- }
-}
diff --git a/opendc-web/opendc-web-ui/src/actions/modals/topology.js b/opendc-web/opendc-web-ui/src/actions/modals/topology.js
deleted file mode 100644
index b5fecac1..00000000
--- a/opendc-web/opendc-web-ui/src/actions/modals/topology.js
+++ /dev/null
@@ -1,84 +0,0 @@
-export const OPEN_NEW_TOPOLOGY_MODAL = 'OPEN_NEW_TOPOLOGY_MODAL'
-export const CLOSE_NEW_TOPOLOGY_MODAL = 'CLOSE_NEW_TOPOLOGY_MODAL'
-export const OPEN_EDIT_ROOM_NAME_MODAL = 'OPEN_EDIT_ROOM_NAME_MODAL'
-export const CLOSE_EDIT_ROOM_NAME_MODAL = 'CLOSE_EDIT_ROOM_NAME_MODAL'
-export const OPEN_DELETE_ROOM_MODAL = 'OPEN_DELETE_ROOM_MODAL'
-export const CLOSE_DELETE_ROOM_MODAL = 'CLOSE_DELETE_ROOM_MODAL'
-export const OPEN_EDIT_RACK_NAME_MODAL = 'OPEN_EDIT_RACK_NAME_MODAL'
-export const CLOSE_EDIT_RACK_NAME_MODAL = 'CLOSE_EDIT_RACK_NAME_MODAL'
-export const OPEN_DELETE_RACK_MODAL = 'OPEN_DELETE_RACK_MODAL'
-export const CLOSE_DELETE_RACK_MODAL = 'CLOSE_DELETE_RACK_MODAL'
-export const OPEN_DELETE_MACHINE_MODAL = 'OPEN_DELETE_MACHINE_MODAL'
-export const CLOSE_DELETE_MACHINE_MODAL = 'CLOSE_DELETE_MACHINE_MODAL'
-
-export function openNewTopologyModal() {
- return {
- type: OPEN_NEW_TOPOLOGY_MODAL,
- }
-}
-
-export function closeNewTopologyModal() {
- return {
- type: CLOSE_NEW_TOPOLOGY_MODAL,
- }
-}
-
-export function openEditRoomNameModal() {
- return {
- type: OPEN_EDIT_ROOM_NAME_MODAL,
- }
-}
-
-export function closeEditRoomNameModal() {
- return {
- type: CLOSE_EDIT_ROOM_NAME_MODAL,
- }
-}
-
-export function openDeleteRoomModal() {
- return {
- type: OPEN_DELETE_ROOM_MODAL,
- }
-}
-
-export function closeDeleteRoomModal() {
- return {
- type: CLOSE_DELETE_ROOM_MODAL,
- }
-}
-
-export function openEditRackNameModal() {
- return {
- type: OPEN_EDIT_RACK_NAME_MODAL,
- }
-}
-
-export function closeEditRackNameModal() {
- return {
- type: CLOSE_EDIT_RACK_NAME_MODAL,
- }
-}
-
-export function openDeleteRackModal() {
- return {
- type: OPEN_DELETE_RACK_MODAL,
- }
-}
-
-export function closeDeleteRackModal() {
- return {
- type: CLOSE_DELETE_RACK_MODAL,
- }
-}
-
-export function openDeleteMachineModal() {
- return {
- type: OPEN_DELETE_MACHINE_MODAL,
- }
-}
-
-export function closeDeleteMachineModal() {
- return {
- type: CLOSE_DELETE_MACHINE_MODAL,
- }
-}
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
index d002b473..ae965939 100644
--- 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
@@ -4,6 +4,8 @@ import { Portfolio } from '../../../../shapes'
import Link from 'next/link'
import FontAwesome from 'react-fontawesome'
import ScenarioListContainer from '../../../../containers/app/sidebars/project/ScenarioListContainer'
+import { Button, Col, Row } from 'reactstrap'
+import classNames from 'classnames'
function PortfolioListComponent({
portfolios,
@@ -17,35 +19,39 @@ function PortfolioListComponent({
<div className="pb-3">
<h2>
Portfolios
- <button className="btn btn-outline-primary float-right" onClick={(e) => onNewPortfolio(e)}>
+ <Button color="primary" outline className="float-right" onClick={(e) => onNewPortfolio(e)}>
<FontAwesome name="plus" />
- </button>
+ </Button>
</h2>
{portfolios.map((portfolio, idx) => (
<div key={portfolio._id}>
- <div className="row mb-1">
- <div
- className={
- 'col-7 align-self-center ' +
- (portfolio._id === currentPortfolioId ? 'font-weight-bold' : '')
- }
+ <Row className="row mb-1">
+ <Col
+ xs="7"
+ className={classNames('align-self-center', {
+ 'font-weight-bold': portfolio._id === currentPortfolioId,
+ })}
>
{portfolio.name}
- </div>
- <div className="col-5 text-right">
+ </Col>
+ <Col xs="5" className="text-right">
<Link href={`/projects/${currentProjectId}/portfolios/${portfolio._id}`}>
- <a
- className="btn btn-outline-primary mr-1 fa fa-play"
+ <Button
+ color="primary"
+ outline
+ className="mr-1 fa fa-play"
onClick={() => onChoosePortfolio(portfolio._id)}
/>
</Link>
- <span
- className="btn btn-outline-danger fa fa-trash"
+ <Button
+ color="danger"
+ outline
+ className="fa fa-trash"
onClick={() => onDeletePortfolio(portfolio._id)}
/>
- </div>
- </div>
+ </Col>
+ </Row>
<ScenarioListContainer portfolioId={portfolio._id} />
</div>
))}
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
index 4789315e..7dd13663 100644
--- 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
@@ -2,13 +2,14 @@ import React from 'react'
import Sidebar from '../Sidebar'
import TopologyListContainer from '../../../../containers/app/sidebars/project/TopologyListContainer'
import PortfolioListContainer from '../../../../containers/app/sidebars/project/PortfolioListContainer'
+import { Container } from 'reactstrap'
const ProjectSidebarComponent = ({ collapsible }) => (
<Sidebar isRight={false} collapsible={collapsible}>
- <div className="h-100 overflow-auto container-fluid">
+ <Container fluid className="h-100 overflow-auto">
<TopologyListContainer />
<PortfolioListContainer />
- </div>
+ </Container>
</Sidebar>
)
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
index 26543d12..168b8e02 100644
--- 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
@@ -3,6 +3,8 @@ import React from 'react'
import { Scenario } from '../../../../shapes'
import Link from 'next/link'
import FontAwesome from 'react-fontawesome'
+import { Button, Col, Row } from 'reactstrap'
+import classNames from 'classnames'
function ScenarioListComponent({
scenarios,
@@ -16,36 +18,42 @@ function ScenarioListComponent({
return (
<>
{scenarios.map((scenario, idx) => (
- <div key={scenario._id} className="row mb-1">
- <div
- className={
- 'col-7 pl-5 align-self-center ' +
- (scenario._id === currentScenarioId ? 'font-weight-bold' : '')
- }
+ <Row key={scenario._id} className="mb-1">
+ <Col
+ xs="7"
+ className={classNames('pl-5 align-self-center', {
+ 'font-weight-bold': scenario._id === currentScenarioId,
+ })}
>
{scenario.name}
- </div>
- <div className="col-5 text-right">
+ </Col>
+ <Col xs="5" className="text-right">
<Link
href={`/projects/${currentProjectId}/portfolios/${scenario.portfolioId}/scenarios/${scenario._id}`}
>
- <a
- className="btn btn-outline-primary mr-1 fa fa-play disabled"
+ <Button
+ color="primary"
+ outline
+ disabled
+ className="mr-1 fa fa-play"
onClick={() => onChooseScenario(scenario.portfolioId, scenario._id)}
/>
</Link>
- <span
- className={'btn btn-outline-danger fa fa-trash ' + (idx === 0 ? 'disabled' : '')}
+ <Button
+ color="danger"
+ outline
+ className="fa fa-trash"
+ disabled={idx === 0}
onClick={() => (idx !== 0 ? onDeleteScenario(scenario._id) : undefined)}
/>
- </div>
- </div>
+ </Col>
+ </Row>
))}
<div className="pl-4 mb-2">
- <div className="btn btn-outline-primary" onClick={() => onNewScenario(this.props.portfolioId)}>
+ <Button color="primary" outline onClick={() => onNewScenario(portfolioId)}>
<FontAwesome name="plus" className="mr-1" />
New scenario
- </div>
+ </Button>
</div>
</>
)
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
index a7d78c4a..d5627abc 100644
--- 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
@@ -2,37 +2,45 @@ import PropTypes from 'prop-types'
import React from 'react'
import { Topology } from '../../../../shapes'
import FontAwesome from 'react-fontawesome'
+import { Button, Col, Row } from 'reactstrap'
+import classNames from 'classnames'
function TopologyListComponent({ topologies, currentTopologyId, onChooseTopology, onNewTopology, onDeleteTopology }) {
return (
<div className="pb-3">
<h2>
Topologies
- <button className="btn btn-outline-primary float-right" onClick={onNewTopology}>
+ <Button color="primary" outline className="float-right" onClick={onNewTopology}>
<FontAwesome name="plus" />
- </button>
+ </Button>
</h2>
{topologies.map((topology, idx) => (
- <div key={topology._id} className="row mb-1">
- <div
- className={
- 'col-7 align-self-center ' + (topology._id === currentTopologyId ? 'font-weight-bold' : '')
- }
+ <Row key={topology._id} className="mb-1">
+ <Col
+ xs="7"
+ className={classNames('align-self-center', {
+ 'font-weight-bold': topology._id === currentTopologyId,
+ })}
>
{topology.name}
- </div>
- <div className="col-5 text-right">
- <span
- className="btn btn-outline-primary mr-1 fa fa-play"
+ </Col>
+ <Col xs="5" className="text-right">
+ <Button
+ color="primary"
+ outline
+ className="mr-1 fa fa-play"
onClick={() => onChooseTopology(topology._id)}
/>
- <span
- className={'btn btn-outline-danger fa fa-trash ' + (idx === 0 ? 'disabled' : '')}
+ <Button
+ color="danger"
+ outline
+ className="fa fa-trash"
+ disable={idx === 0}
onClick={() => (idx !== 0 ? onDeleteTopology(topology._id) : undefined)}
/>
- </div>
- </div>
+ </Col>
+ </Row>
))}
</div>
)
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/machine/DeleteMachineComponent.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/machine/DeleteMachineComponent.js
deleted file mode 100644
index 37820316..00000000
--- a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/machine/DeleteMachineComponent.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import React from 'react'
-
-const DeleteMachineComponent = ({ onClick }) => (
- <div className="btn btn-outline-danger btn-block" onClick={onClick}>
- <span className="fa fa-trash mr-2" />
- Delete this machine
- </div>
-)
-
-export default DeleteMachineComponent
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/machine/MachineNameComponent.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/machine/MachineNameComponent.js
deleted file mode 100644
index 992383c4..00000000
--- a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/machine/MachineNameComponent.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import React from 'react'
-
-const MachineNameComponent = ({ position }) => <h2>Machine at slot {position}</h2>
-
-export default MachineNameComponent
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/DeleteRackComponent.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/DeleteRackComponent.js
deleted file mode 100644
index 23b0daac..00000000
--- a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/DeleteRackComponent.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import React from 'react'
-
-const DeleteRackComponent = ({ onClick }) => (
- <div className="btn btn-outline-danger btn-block" onClick={onClick}>
- <span className="fa fa-trash mr-2" />
- Delete this rack
- </div>
-)
-
-export default DeleteRackComponent
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackNameComponent.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackNameComponent.js
deleted file mode 100644
index b701909a..00000000
--- a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/rack/RackNameComponent.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import React from 'react'
-import NameComponent from '../NameComponent'
-
-const RackNameComponent = ({ rackName, onEdit }) => <NameComponent name={rackName} onEdit={onEdit} />
-
-export default RackNameComponent
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/room/EditRoomComponent.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/room/EditRoomComponent.js
deleted file mode 100644
index 857a646f..00000000
--- a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/room/EditRoomComponent.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import classNames from 'classnames'
-import React from 'react'
-
-const EditRoomComponent = ({ onEdit, onFinish, isEditing, isInRackConstructionMode }) =>
- isEditing ? (
- <div className="btn btn-info btn-block" onClick={onFinish}>
- <span className="fa fa-check mr-2" />
- Finish editing room
- </div>
- ) : (
- <div
- className={classNames('btn btn-outline-info btn-block', {
- disabled: isInRackConstructionMode,
- })}
- onClick={() => (isInRackConstructionMode ? undefined : onEdit())}
- >
- <span className="fa fa-pencil mr-2" />
- Edit the tiles of this room
- </div>
- )
-
-export default EditRoomComponent
diff --git a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/room/RoomNameComponent.js b/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/room/RoomNameComponent.js
deleted file mode 100644
index d637828e..00000000
--- a/opendc-web/opendc-web-ui/src/components/app/sidebars/topology/room/RoomNameComponent.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import React from 'react'
-import NameComponent from '../NameComponent'
-
-const RoomNameComponent = ({ roomName, onEdit }) => <NameComponent name={roomName} onEdit={onEdit} />
-
-export default RoomNameComponent
diff --git a/opendc-web/opendc-web-ui/src/containers/app/App.js b/opendc-web/opendc-web-ui/src/containers/app/App.js
index bb9c5d56..432435cf 100644
--- a/opendc-web/opendc-web-ui/src/containers/app/App.js
+++ b/opendc-web/opendc-web-ui/src/containers/app/App.js
@@ -32,26 +32,18 @@ import LoadingScreen from '../../components/app/map/LoadingScreen'
import ScaleIndicatorContainer from '../../containers/app/map/controls/ScaleIndicatorContainer'
import MapStage from '../../containers/app/map/MapStage'
import TopologySidebarContainer from '../../containers/app/sidebars/topology/TopologySidebarContainer'
-import DeleteMachineModal from '../../containers/modals/DeleteMachineModal'
-import DeleteRackModal from '../../containers/modals/DeleteRackModal'
-import DeleteRoomModal from '../../containers/modals/DeleteRoomModal'
-import EditRackNameModal from '../../containers/modals/EditRackNameModal'
-import EditRoomNameModal from '../../containers/modals/EditRoomNameModal'
-import NewTopologyModal from '../../containers/modals/NewTopologyModal'
import AppNavbarContainer from '../../containers/navigation/AppNavbarContainer'
import ProjectSidebarContainer from '../../containers/app/sidebars/project/ProjectSidebarContainer'
import { openScenarioSucceeded } from '../../actions/scenarios'
-import NewPortfolioModal from '../../containers/modals/NewPortfolioModal'
-import NewScenarioModal from '../../containers/modals/NewScenarioModal'
import PortfolioResultsContainer from '../../containers/app/results/PortfolioResultsContainer'
import KeymapConfiguration from '../../shortcuts/keymap'
import { useRequireAuth } from '../../auth/hook'
-import { useProject } from '../../store/hooks/project'
+import { useActiveProject } from '../../store/hooks/project'
const App = ({ projectId, portfolioId, scenarioId }) => {
useRequireAuth()
- const projectName = useProject()?.name
+ const projectName = useActiveProject()?.name
const topologyIsLoading = useSelector((state) => state.currentTopologyId === '-1')
const dispatch = useDispatch()
@@ -106,14 +98,6 @@ const App = ({ projectId, portfolioId, scenarioId }) => {
</Head>
<AppNavbarContainer fullWidth={true} />
{scenarioId ? scenarioElements : portfolioId ? portfolioElements : constructionElements}
- <NewTopologyModal />
- <NewPortfolioModal />
- <NewScenarioModal />
- <EditRoomNameModal />
- <DeleteRoomModal />
- <EditRackNameModal />
- <DeleteRackModal />
- <DeleteMachineModal />
</HotKeys>
)
}
diff --git a/opendc-web/opendc-web-ui/src/containers/app/map/TopologyContainer.js b/opendc-web/opendc-web-ui/src/containers/app/map/TopologyContainer.js
index 30379490..25fbe3c0 100644
--- a/opendc-web/opendc-web-ui/src/containers/app/map/TopologyContainer.js
+++ b/opendc-web/opendc-web-ui/src/containers/app/map/TopologyContainer.js
@@ -1,10 +1,10 @@
import React from 'react'
import { useSelector } from 'react-redux'
import TopologyGroup from '../../../components/app/map/groups/TopologyGroup'
-import { useTopology } from '../../../store/hooks/topology'
+import { useActiveTopology } from '../../../store/hooks/topology'
const TopologyContainer = () => {
- const topology = useTopology()
+ const topology = useActiveTopology()
const interactionLevel = useSelector((state) => state.interactionLevel)
return <TopologyGroup topology={topology} interactionLevel={interactionLevel} />
diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js
index ce295f03..dca7d7db 100644
--- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js
+++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/PortfolioListContainer.js
@@ -1,34 +1,23 @@
-import React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
+import React, { useState } from 'react'
+import { useDispatch } from 'react-redux'
import { useRouter } from 'next/router'
import PortfolioListComponent from '../../../../components/app/sidebars/project/PortfolioListComponent'
-import { deletePortfolio, setCurrentPortfolio } from '../../../../actions/portfolios'
-import { openNewPortfolioModal } from '../../../../actions/modals/portfolios'
+import { addPortfolio, deletePortfolio, setCurrentPortfolio } from '../../../../actions/portfolios'
import { getState } from '../../../../util/state-utils'
import { setCurrentTopology } from '../../../../actions/topology/building'
+import NewPortfolioModalComponent from '../../../../components/modals/custom-components/NewPortfolioModalComponent'
+import { useActivePortfolio, useActiveProject, usePortfolios } from '../../../../store/hooks/project'
-const PortfolioListContainer = (props) => {
- const state = useSelector((state) => {
- let portfolios = state.objects.project[state.currentProjectId]
- ? state.objects.project[state.currentProjectId].portfolioIds.map((t) => state.objects.portfolio[t])
- : []
- if (portfolios.filter((t) => !t).length > 0) {
- portfolios = []
- }
-
- return {
- currentProjectId: state.currentProjectId,
- currentPortfolioId: state.currentPortfolioId,
- portfolios,
- }
- })
+const PortfolioListContainer = () => {
+ const currentProjectId = useActiveProject()?._id
+ const currentPortfolioId = useActivePortfolio()?._id
+ const portfolios = usePortfolios(currentProjectId)
const dispatch = useDispatch()
+ const [isVisible, setVisible] = useState(false)
const router = useRouter()
const actions = {
- onNewPortfolio: () => {
- dispatch(openNewPortfolioModal())
- },
+ onNewPortfolio: () => setVisible(true),
onChoosePortfolio: (portfolioId) => {
dispatch(setCurrentPortfolio(portfolioId))
},
@@ -41,7 +30,28 @@ const PortfolioListContainer = (props) => {
}
},
}
- return <PortfolioListComponent {...props} {...state} {...actions} />
+ const callback = (name, targets) => {
+ if (name) {
+ dispatch(
+ addPortfolio({
+ name,
+ targets,
+ })
+ )
+ }
+ setVisible(false)
+ }
+ return (
+ <>
+ <PortfolioListComponent
+ currentProjectId={currentProjectId}
+ currentPortfolioId={currentPortfolioId}
+ portfolios={portfolios}
+ {...actions}
+ />
+ <NewPortfolioModalComponent callback={callback} show={isVisible} />
+ </>
+ )
}
export default PortfolioListContainer
diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js
index 18d0735e..5d747820 100644
--- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js
+++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/ScenarioListContainer.js
@@ -1,28 +1,27 @@
-import React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
+import React, { useState } from 'react'
+import { useDispatch } from 'react-redux'
import ScenarioListComponent from '../../../../components/app/sidebars/project/ScenarioListComponent'
-import { openNewScenarioModal } from '../../../../actions/modals/scenarios'
-import { deleteScenario, setCurrentScenario } from '../../../../actions/scenarios'
+import { addScenario, deleteScenario, setCurrentScenario } from '../../../../actions/scenarios'
import { setCurrentPortfolio } from '../../../../actions/portfolios'
+import NewScenarioModalComponent from '../../../../components/modals/custom-components/NewScenarioModalComponent'
+import { useProjectTopologies } from '../../../../store/hooks/topology'
+import { useActiveScenario, useActiveProject, useScenarios } from '../../../../store/hooks/project'
+import { useSchedulers, useTraces } from '../../../../store/hooks/experiments'
-const ScenarioListContainer = ({ portfolioId, children }) => {
- const currentProjectId = useSelector((state) => state.currentProjectId)
- const currentScenarioId = useSelector((state) => state.currentScenarioId)
- const scenarios = useSelector((state) => {
- let scenarios = state.objects.portfolio[portfolioId]
- ? state.objects.portfolio[portfolioId].scenarioIds.map((t) => state.objects.scenario[t])
- : []
- if (scenarios.filter((t) => !t).length > 0) {
- scenarios = []
- }
-
- return scenarios
- })
+const ScenarioListContainer = ({ portfolioId }) => {
+ const currentProjectId = useActiveProject()?._id
+ const currentScenarioId = useActiveScenario()?._id
+ const scenarios = useScenarios(portfolioId)
+ const topologies = useProjectTopologies()
+ const traces = useTraces()
+ const schedulers = useSchedulers()
const dispatch = useDispatch()
+ const [isVisible, setVisible] = useState(false)
+
const onNewScenario = (currentPortfolioId) => {
dispatch(setCurrentPortfolio(currentPortfolioId))
- dispatch(openNewScenarioModal())
+ setVisible(true)
}
const onChooseScenario = (portfolioId, scenarioId) => {
dispatch(setCurrentScenario(portfolioId, scenarioId))
@@ -32,17 +31,43 @@ const ScenarioListContainer = ({ portfolioId, children }) => {
dispatch(deleteScenario(id))
}
}
+ const callback = (name, portfolioId, trace, topology, operational) => {
+ if (name) {
+ dispatch(
+ addScenario({
+ portfolioId,
+ name,
+ trace,
+ topology,
+ operational,
+ })
+ )
+ }
+
+ setVisible(false)
+ }
return (
- <ScenarioListComponent
- portfolioId={portfolioId}
- currentProjectId={currentProjectId}
- currentScenarioId={currentScenarioId}
- scenarios={scenarios}
- onNewScenario={onNewScenario}
- onChooseScenario={onChooseScenario}
- onDeleteScenario={onDeleteScenario}
- />
+ <>
+ <ScenarioListComponent
+ portfolioId={portfolioId}
+ currentProjectId={currentProjectId}
+ currentScenarioId={currentScenarioId}
+ scenarios={scenarios}
+ onNewScenario={onNewScenario}
+ onChooseScenario={onChooseScenario}
+ onDeleteScenario={onDeleteScenario}
+ />
+ <NewScenarioModalComponent
+ show={isVisible}
+ currentPortfolioId={currentProjectId}
+ currentPortfolioScenarioIds={scenarios.map((s) => s._id)}
+ traces={traces}
+ schedulers={schedulers}
+ topologies={topologies}
+ callback={callback}
+ />
+ </>
)
}
diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js
index e9c05f17..3779705a 100644
--- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js
+++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/project/TopologyListContainer.js
@@ -1,36 +1,25 @@
-import React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
+import React, { useState } from 'react'
+import { useDispatch } from 'react-redux'
import TopologyListComponent from '../../../../components/app/sidebars/project/TopologyListComponent'
import { setCurrentTopology } from '../../../../actions/topology/building'
-import { openNewTopologyModal } from '../../../../actions/modals/topology'
import { useRouter } from 'next/router'
import { getState } from '../../../../util/state-utils'
-import { deleteTopology } from '../../../../actions/topologies'
+import { addTopology, deleteTopology } from '../../../../actions/topologies'
+import NewTopologyModalComponent from '../../../../components/modals/custom-components/NewTopologyModalComponent'
+import { useActiveTopology, useProjectTopologies } from '../../../../store/hooks/topology'
const TopologyListContainer = () => {
const dispatch = useDispatch()
const router = useRouter()
-
- const topologies = useSelector((state) => {
- let topologies = state.objects.project[state.currentProjectId]
- ? state.objects.project[state.currentProjectId].topologyIds.map((t) => state.objects.topology[t])
- : []
- if (topologies.filter((t) => !t).length > 0) {
- topologies = []
- }
-
- return topologies
- })
- const currentTopologyId = useSelector((state) => state.currentTopologyId)
+ const topologies = useProjectTopologies()
+ const currentTopologyId = useActiveTopology()?._id
+ const [isVisible, setVisible] = useState(false)
const onChooseTopology = async (id) => {
dispatch(setCurrentTopology(id))
const state = await getState(dispatch)
router.push(`/projects/${state.currentProjectId}`)
}
- const onNewTopology = () => {
- dispatch(openNewTopologyModal())
- }
const onDeleteTopology = async (id) => {
if (id) {
const state = await getState(dispatch)
@@ -39,15 +28,37 @@ const TopologyListContainer = () => {
router.push(`/projects/${state.currentProjectId}`)
}
}
+ const onCreateTopology = (name) => {
+ if (name) {
+ dispatch(addTopology(name, undefined))
+ }
+ setVisible(false)
+ }
+ const onDuplicateTopology = (name, id) => {
+ if (name) {
+ dispatch(addTopology(name, id))
+ }
+ setVisible(false)
+ }
+ const onCancel = () => setVisible(false)
return (
- <TopologyListComponent
- topologies={topologies}
- currentTopologyId={currentTopologyId}
- onChooseTopology={onChooseTopology}
- onNewTopology={onNewTopology}
- onDeleteTopology={onDeleteTopology}
- />
+ <>
+ <TopologyListComponent
+ topologies={topologies}
+ currentTopologyId={currentTopologyId}
+ onChooseTopology={onChooseTopology}
+ onNewTopology={() => setVisible(true)}
+ onDeleteTopology={onDeleteTopology}
+ />
+ <NewTopologyModalComponent
+ show={isVisible}
+ topologies={topologies}
+ onCreateTopology={onCreateTopology}
+ onDuplicateTopology={onDuplicateTopology}
+ onCancel={onCancel}
+ />
+ </>
)
}
diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/machine/DeleteMachineContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/machine/DeleteMachineContainer.js
index 1510a436..2f171ce8 100644
--- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/machine/DeleteMachineContainer.js
+++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/machine/DeleteMachineContainer.js
@@ -1,11 +1,32 @@
-import React from 'react'
+import React, { useState } from 'react'
import { useDispatch } from 'react-redux'
-import { openDeleteMachineModal } from '../../../../../actions/modals/topology'
-import DeleteMachineComponent from '../../../../../components/app/sidebars/topology/machine/DeleteMachineComponent'
+import ConfirmationModal from '../../../../../components/modals/ConfirmationModal'
+import { deleteMachine } from '../../../../../actions/topology/machine'
+import { Button } from 'reactstrap'
-const DeleteMachineContainer = (props) => {
+const DeleteMachineContainer = () => {
const dispatch = useDispatch()
- return <DeleteMachineComponent {...props} onClick={() => dispatch(openDeleteMachineModal())} />
+ const [isVisible, setVisible] = useState(false)
+ const callback = (isConfirmed) => {
+ if (isConfirmed) {
+ dispatch(deleteMachine())
+ }
+ setVisible(false)
+ }
+ return (
+ <>
+ <Button color="danger" outline block onClick={() => setVisible(true)}>
+ <span className="fa fa-trash mr-2" />
+ Delete this machine
+ </Button>
+ <ConfirmationModal
+ title="Delete this machine"
+ message="Are you sure you want to delete this machine?"
+ show={isVisible}
+ callback={callback}
+ />
+ </>
+ )
}
export default DeleteMachineContainer
diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/machine/MachineNameContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/machine/MachineNameContainer.js
index 6f4285b2..9cbb32c5 100644
--- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/machine/MachineNameContainer.js
+++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/machine/MachineNameContainer.js
@@ -1,10 +1,9 @@
import React from 'react'
import { useSelector } from 'react-redux'
-import MachineNameComponent from '../../../../../components/app/sidebars/topology/machine/MachineNameComponent'
-const MachineNameContainer = (props) => {
+const MachineNameContainer = () => {
const position = useSelector((state) => state.interactionLevel.position)
- return <MachineNameComponent {...props} position={position} />
+ return <h2>Machine at slot {position}</h2>
}
export default MachineNameContainer
diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/rack/DeleteRackContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/rack/DeleteRackContainer.js
index de46e491..4c7fd8bf 100644
--- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/rack/DeleteRackContainer.js
+++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/rack/DeleteRackContainer.js
@@ -1,11 +1,32 @@
-import React from 'react'
+import React, { useState } from 'react'
import { useDispatch } from 'react-redux'
-import { openDeleteRackModal } from '../../../../../actions/modals/topology'
-import DeleteRackComponent from '../../../../../components/app/sidebars/topology/rack/DeleteRackComponent'
+import ConfirmationModal from '../../../../../components/modals/ConfirmationModal'
+import { deleteRack } from '../../../../../actions/topology/rack'
+import { Button } from 'reactstrap'
-const DeleteRackContainer = (props) => {
+const DeleteRackContainer = () => {
const dispatch = useDispatch()
- return <DeleteRackComponent {...props} onClick={() => dispatch(openDeleteRackModal())} />
+ const [isVisible, setVisible] = useState(false)
+ const callback = (isConfirmed) => {
+ if (isConfirmed) {
+ dispatch(deleteRack())
+ }
+ setVisible(false)
+ }
+ return (
+ <>
+ <Button color="danger" outline block onClick={() => setVisible(true)}>
+ <span className="fa fa-trash mr-2" />
+ Delete this rack
+ </Button>
+ <ConfirmationModal
+ title="Delete this rack"
+ message="Are you sure you want to delete this rack?"
+ show={isVisible}
+ callback={callback}
+ />
+ </>
+ )
}
export default DeleteRackContainer
diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/rack/RackNameContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/rack/RackNameContainer.js
index 7dfdb473..dd9b05fc 100644
--- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/rack/RackNameContainer.js
+++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/rack/RackNameContainer.js
@@ -1,14 +1,33 @@
-import React from 'react'
+import React, { useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
-import { openEditRackNameModal } from '../../../../../actions/modals/topology'
-import RackNameComponent from '../../../../../components/app/sidebars/topology/rack/RackNameComponent'
+import NameComponent from '../../../../../components/app/sidebars/topology/NameComponent'
+import TextInputModal from '../../../../../components/modals/TextInputModal'
+import { editRackName } from '../../../../../actions/topology/rack'
-const RackNameContainer = (props) => {
+const RackNameContainer = () => {
+ const [isVisible, setVisible] = useState(false)
const rackName = useSelector(
(state) => state.objects.rack[state.objects.tile[state.interactionLevel.tileId].rackId].name
)
const dispatch = useDispatch()
- return <RackNameComponent {...props} rackName={rackName} onEdit={() => dispatch(openEditRackNameModal())} />
+ const callback = (name) => {
+ if (name) {
+ dispatch(editRackName(name))
+ }
+ setVisible(false)
+ }
+ return (
+ <>
+ <NameComponent name={rackName} onEdit={() => setVisible(true)} />
+ <TextInputModal
+ title="Edit rack name"
+ label="Rack name"
+ show={isVisible}
+ initialValue={rackName}
+ callback={callback}
+ />
+ </>
+ )
}
export default RackNameContainer
diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/room/DeleteRoomContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/room/DeleteRoomContainer.js
index 6a80e9b0..2062462f 100644
--- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/room/DeleteRoomContainer.js
+++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/room/DeleteRoomContainer.js
@@ -1,12 +1,32 @@
-import React from 'react'
+import React, { useState } from 'react'
import { useDispatch } from 'react-redux'
-import { openDeleteRoomModal } from '../../../../../actions/modals/topology'
-import DeleteRoomComponent from '../../../../../components/app/sidebars/topology/room/DeleteRoomComponent'
+import { Button } from 'reactstrap'
+import ConfirmationModal from '../../../../../components/modals/ConfirmationModal'
+import { deleteRoom } from '../../../../../actions/topology/room'
-const DeleteRoomContainer = (props) => {
+const DeleteRoomContainer = () => {
const dispatch = useDispatch()
- const onClick = () => dispatch(openDeleteRoomModal())
- return <DeleteRoomComponent {...props} onClick={onClick} />
+ const [isVisible, setVisible] = useState(false)
+ const callback = (isConfirmed) => {
+ if (isConfirmed) {
+ dispatch(deleteRoom())
+ }
+ setVisible(false)
+ }
+ return (
+ <>
+ <Button color="danger" outline block onClick={() => setVisible(true)}>
+ <span className="fa fa-trash mr-2" />
+ Delete this room
+ </Button>
+ <ConfirmationModal
+ title="Delete this room"
+ message="Are you sure you want to delete this room?"
+ show={isVisible}
+ callback={callback}
+ />
+ </>
+ )
}
export default DeleteRoomContainer
diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/room/EditRoomContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/room/EditRoomContainer.js
index 37027fc5..f03b0efb 100644
--- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/room/EditRoomContainer.js
+++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/room/EditRoomContainer.js
@@ -1,9 +1,9 @@
import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { finishRoomEdit, startRoomEdit } from '../../../../../actions/topology/building'
-import EditRoomComponent from '../../../../../components/app/sidebars/topology/room/EditRoomComponent'
+import { Button } from 'reactstrap'
-const EditRoomContainer = (props) => {
+const EditRoomContainer = () => {
const isEditing = useSelector((state) => state.construction.currentRoomInConstruction !== '-1')
const isInRackConstructionMode = useSelector((state) => state.construction.inRackConstructionMode)
@@ -11,14 +11,22 @@ const EditRoomContainer = (props) => {
const onEdit = () => dispatch(startRoomEdit())
const onFinish = () => dispatch(finishRoomEdit())
- return (
- <EditRoomComponent
- {...props}
- onEdit={onEdit}
- onFinish={onFinish}
- isEditing={isEditing}
- isInRackConstructionMode={isInRackConstructionMode}
- />
+ return isEditing ? (
+ <Button color="info" outline block onClick={onFinish}>
+ <span className="fa fa-check mr-2" />
+ Finish editing room
+ </Button>
+ ) : (
+ <Button
+ color="info"
+ outline
+ block
+ disabled={isInRackConstructionMode}
+ onClick={() => (isInRackConstructionMode ? undefined : onEdit())}
+ >
+ <span className="fa fa-pencil mr-2" />
+ Edit the tiles of this room
+ </Button>
)
}
diff --git a/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/room/RoomNameContainer.js b/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/room/RoomNameContainer.js
index 1f53aeb6..946bb864 100644
--- a/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/room/RoomNameContainer.js
+++ b/opendc-web/opendc-web-ui/src/containers/app/sidebars/topology/room/RoomNameContainer.js
@@ -1,13 +1,31 @@
-import React from 'react'
+import React, { useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
-import { openEditRoomNameModal } from '../../../../../actions/modals/topology'
-import RoomNameComponent from '../../../../../components/app/sidebars/topology/room/RoomNameComponent'
+import NameComponent from '../../../../../components/app/sidebars/topology/NameComponent'
+import TextInputModal from '../../../../../components/modals/TextInputModal'
+import { editRoomName } from '../../../../../actions/topology/room'
-const RoomNameContainer = (props) => {
+const RoomNameContainer = () => {
+ const [isVisible, setVisible] = useState(false)
const roomName = useSelector((state) => state.objects.room[state.interactionLevel.roomId].name)
const dispatch = useDispatch()
- const onEdit = () => dispatch(openEditRoomNameModal())
- return <RoomNameComponent {...props} onEdit={onEdit} roomName={roomName} />
+ const callback = (name) => {
+ if (name) {
+ dispatch(editRoomName(name))
+ }
+ setVisible(false)
+ }
+ return (
+ <>
+ <NameComponent name={roomName} onEdit={() => setVisible(true)} />
+ <TextInputModal
+ title="Edit room name"
+ label="Room name"
+ show={isVisible}
+ initialValue={roomName}
+ callback={callback}
+ />
+ </>
+ )
}
export default RoomNameContainer
diff --git a/opendc-web/opendc-web-ui/src/containers/modals/DeleteMachineModal.js b/opendc-web/opendc-web-ui/src/containers/modals/DeleteMachineModal.js
deleted file mode 100644
index 33b2612f..00000000
--- a/opendc-web/opendc-web-ui/src/containers/modals/DeleteMachineModal.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import { closeDeleteMachineModal } from '../../actions/modals/topology'
-import { deleteMachine } from '../../actions/topology/machine'
-import ConfirmationModal from '../../components/modals/ConfirmationModal'
-
-const DeleteMachineModal = () => {
- const dispatch = useDispatch()
- const callback = (isConfirmed) => {
- if (isConfirmed) {
- dispatch(deleteMachine())
- }
- dispatch(closeDeleteMachineModal())
- }
- const visible = useSelector((state) => state.modals.deleteMachineModalVisible)
- return (
- <ConfirmationModal
- title="Delete this machine"
- message="Are you sure you want to delete this machine?"
- show={visible}
- callback={callback}
- />
- )
-}
-
-export default DeleteMachineModal
diff --git a/opendc-web/opendc-web-ui/src/containers/modals/DeleteRackModal.js b/opendc-web/opendc-web-ui/src/containers/modals/DeleteRackModal.js
deleted file mode 100644
index ca76fd04..00000000
--- a/opendc-web/opendc-web-ui/src/containers/modals/DeleteRackModal.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import { closeDeleteRackModal } from '../../actions/modals/topology'
-import { deleteRack } from '../../actions/topology/rack'
-import ConfirmationModal from '../../components/modals/ConfirmationModal'
-
-const DeleteRackModal = (props) => {
- const visible = useSelector((state) => state.modals.deleteRackModalVisible)
- const dispatch = useDispatch()
- const callback = (isConfirmed) => {
- if (isConfirmed) {
- dispatch(deleteRack())
- }
- dispatch(closeDeleteRackModal())
- }
- return (
- <ConfirmationModal
- title="Delete this rack"
- message="Are you sure you want to delete this rack?"
- show={visible}
- callback={callback}
- {...props}
- />
- )
-}
-
-export default DeleteRackModal
diff --git a/opendc-web/opendc-web-ui/src/containers/modals/DeleteRoomModal.js b/opendc-web/opendc-web-ui/src/containers/modals/DeleteRoomModal.js
deleted file mode 100644
index 9a7be6a6..00000000
--- a/opendc-web/opendc-web-ui/src/containers/modals/DeleteRoomModal.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import { closeDeleteRoomModal } from '../../actions/modals/topology'
-import { deleteRoom } from '../../actions/topology/room'
-import ConfirmationModal from '../../components/modals/ConfirmationModal'
-
-const DeleteRoomModal = (props) => {
- const visible = useSelector((state) => state.modals.deleteRoomModalVisible)
-
- const dispatch = useDispatch()
- const callback = (isConfirmed) => {
- if (isConfirmed) {
- dispatch(deleteRoom())
- }
- dispatch(closeDeleteRoomModal())
- }
- return (
- <ConfirmationModal
- title="Delete this room"
- message="Are you sure you want to delete this room?"
- show={visible}
- callback={callback}
- {...props}
- />
- )
-}
-
-export default DeleteRoomModal
diff --git a/opendc-web/opendc-web-ui/src/containers/modals/EditRackNameModal.js b/opendc-web/opendc-web-ui/src/containers/modals/EditRackNameModal.js
deleted file mode 100644
index edb57217..00000000
--- a/opendc-web/opendc-web-ui/src/containers/modals/EditRackNameModal.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import { closeEditRackNameModal } from '../../actions/modals/topology'
-import { editRackName } from '../../actions/topology/rack'
-import TextInputModal from '../../components/modals/TextInputModal'
-
-const EditRackNameModal = (props) => {
- const { visible, previousName } = useSelector((state) => {
- return {
- visible: state.modals.editRackNameModalVisible,
- previousName:
- state.interactionLevel.mode === 'RACK'
- ? state.objects.rack[state.objects.tile[state.interactionLevel.tileId].rackId].name
- : '',
- }
- })
-
- const dispatch = useDispatch()
- const callback = (name) => {
- if (name) {
- dispatch(editRackName(name))
- }
- dispatch(closeEditRackNameModal())
- }
- return (
- <TextInputModal
- title="Edit rack name"
- label="Rack name"
- show={visible}
- initialValue={previousName}
- callback={callback}
- {...props}
- />
- )
-}
-
-export default EditRackNameModal
diff --git a/opendc-web/opendc-web-ui/src/containers/modals/EditRoomNameModal.js b/opendc-web/opendc-web-ui/src/containers/modals/EditRoomNameModal.js
deleted file mode 100644
index a804c0b0..00000000
--- a/opendc-web/opendc-web-ui/src/containers/modals/EditRoomNameModal.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import { closeEditRoomNameModal } from '../../actions/modals/topology'
-import { editRoomName } from '../../actions/topology/room'
-import TextInputModal from '../../components/modals/TextInputModal'
-
-const EditRoomNameModal = (props) => {
- const visible = useSelector((state) => state.modals.editRoomNameModalVisible)
- const previousName = useSelector((state) =>
- state.interactionLevel.mode === 'ROOM' ? state.objects.room[state.interactionLevel.roomId].name : ''
- )
-
- const dispatch = useDispatch()
- const callback = (name) => {
- if (name) {
- dispatch(editRoomName(name))
- }
- dispatch(closeEditRoomNameModal())
- }
- return (
- <TextInputModal
- title="Edit room name"
- label="Room name"
- show={visible}
- initialValue={previousName}
- callback={callback}
- {...props}
- />
- )
-}
-export default EditRoomNameModal
diff --git a/opendc-web/opendc-web-ui/src/containers/modals/NewPortfolioModal.js b/opendc-web/opendc-web-ui/src/containers/modals/NewPortfolioModal.js
deleted file mode 100644
index b364ed4c..00000000
--- a/opendc-web/opendc-web-ui/src/containers/modals/NewPortfolioModal.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import { closeNewPortfolioModal } from '../../actions/modals/portfolios'
-import NewPortfolioModalComponent from '../../components/modals/custom-components/NewPortfolioModalComponent'
-import { addPortfolio } from '../../actions/portfolios'
-
-const NewPortfolioModal = (props) => {
- const show = useSelector((state) => state.modals.newPortfolioModalVisible)
- const dispatch = useDispatch()
- const callback = (name, targets) => {
- if (name) {
- dispatch(
- addPortfolio({
- name,
- targets,
- })
- )
- }
- dispatch(closeNewPortfolioModal())
- }
- return <NewPortfolioModalComponent {...props} callback={callback} show={show} />
-}
-
-export default NewPortfolioModal
diff --git a/opendc-web/opendc-web-ui/src/containers/modals/NewScenarioModal.js b/opendc-web/opendc-web-ui/src/containers/modals/NewScenarioModal.js
deleted file mode 100644
index 18ad65f9..00000000
--- a/opendc-web/opendc-web-ui/src/containers/modals/NewScenarioModal.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import NewScenarioModalComponent from '../../components/modals/custom-components/NewScenarioModalComponent'
-import { addScenario } from '../../actions/scenarios'
-import { closeNewScenarioModal } from '../../actions/modals/scenarios'
-
-const NewScenarioModal = (props) => {
- const topologies = useSelector(({ currentProjectId, objects }) => {
- if (currentProjectId === '-1' || !objects.project[currentProjectId]) {
- return []
- }
-
- const topologies = objects.project[currentProjectId].topologyIds.map((t) => objects.topology[t])
-
- if (topologies.filter((t) => !t).length > 0) {
- return []
- }
-
- return topologies
- })
- const state = useSelector((state) => {
- return {
- show: state.modals.newScenarioModalVisible,
- currentPortfolioId: state.currentPortfolioId,
- currentPortfolioScenarioIds:
- state.currentPortfolioId !== '-1' && state.objects.portfolio[state.currentPortfolioId]
- ? state.objects.portfolio[state.currentPortfolioId].scenarioIds
- : [],
- traces: Object.values(state.objects.trace),
- schedulers: Object.values(state.objects.scheduler),
- }
- })
-
- const dispatch = useDispatch()
- const callback = (name, portfolioId, trace, topology, operational) => {
- if (name) {
- dispatch(
- addScenario({
- portfolioId,
- name,
- trace,
- topology,
- operational,
- })
- )
- }
- dispatch(closeNewScenarioModal())
- }
-
- return <NewScenarioModalComponent {...props} {...state} topologies={topologies} callback={callback} />
-}
-
-export default NewScenarioModal
diff --git a/opendc-web/opendc-web-ui/src/containers/modals/NewTopologyModal.js b/opendc-web/opendc-web-ui/src/containers/modals/NewTopologyModal.js
deleted file mode 100644
index 2f81706e..00000000
--- a/opendc-web/opendc-web-ui/src/containers/modals/NewTopologyModal.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import NewTopologyModalComponent from '../../components/modals/custom-components/NewTopologyModalComponent'
-import { closeNewTopologyModal } from '../../actions/modals/topology'
-import { addTopology } from '../../actions/topologies'
-
-const NewTopologyModal = () => {
- const show = useSelector((state) => state.modals.changeTopologyModalVisible)
- const topologies = useSelector((state) => {
- let topologies = state.objects.project[state.currentProjectId]
- ? state.objects.project[state.currentProjectId].topologyIds.map((t) => state.objects.topology[t])
- : []
- if (topologies.filter((t) => !t).length > 0) {
- topologies = []
- }
-
- return topologies
- })
-
- const dispatch = useDispatch()
- const onCreateTopology = (name) => {
- if (name) {
- dispatch(addTopology(name, undefined))
- }
- dispatch(closeNewTopologyModal())
- }
- const onDuplicateTopology = (name, id) => {
- if (name) {
- dispatch(addTopology(name, id))
- }
- dispatch(closeNewTopologyModal())
- }
- const onCancel = () => {
- dispatch(closeNewTopologyModal())
- }
-
- return (
- <NewTopologyModalComponent
- show={show}
- topologies={topologies}
- onCreateTopology={onCreateTopology}
- onDuplicateTopology={onDuplicateTopology}
- onCancel={onCancel}
- />
- )
-}
-
-export default NewTopologyModal
diff --git a/opendc-web/opendc-web-ui/src/containers/navigation/AppNavbarContainer.js b/opendc-web/opendc-web-ui/src/containers/navigation/AppNavbarContainer.js
index d0d28ccb..47988827 100644
--- a/opendc-web/opendc-web-ui/src/containers/navigation/AppNavbarContainer.js
+++ b/opendc-web/opendc-web-ui/src/containers/navigation/AppNavbarContainer.js
@@ -1,9 +1,9 @@
import React from 'react'
import AppNavbarComponent from '../../components/navigation/AppNavbarComponent'
-import { useProject } from '../../store/hooks/project'
+import { useActiveProject } from '../../store/hooks/project'
const AppNavbarContainer = (props) => {
- const project = useProject()
+ const project = useActiveProject()
return <AppNavbarComponent {...props} project={project} />
}
diff --git a/opendc-web/opendc-web-ui/src/reducers/index.js b/opendc-web/opendc-web-ui/src/reducers/index.js
index 787d5a74..9dff379b 100644
--- a/opendc-web/opendc-web-ui/src/reducers/index.js
+++ b/opendc-web/opendc-web-ui/src/reducers/index.js
@@ -4,13 +4,11 @@ import { construction } from './construction-mode'
import { currentPortfolioId, currentProjectId, currentScenarioId, currentTopologyId } from './current-ids'
import { interactionLevel } from './interaction-level'
import { map } from './map'
-import { modals } from './modals'
import { objects } from './objects'
import { projectList } from './project-list'
const rootReducer = combineReducers({
objects,
- modals,
projectList,
construction,
map,
diff --git a/opendc-web/opendc-web-ui/src/reducers/modals.js b/opendc-web/opendc-web-ui/src/reducers/modals.js
deleted file mode 100644
index a58d8708..00000000
--- a/opendc-web/opendc-web-ui/src/reducers/modals.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import { combineReducers } from 'redux'
-import {
- CLOSE_NEW_TOPOLOGY_MODAL,
- CLOSE_DELETE_MACHINE_MODAL,
- CLOSE_DELETE_RACK_MODAL,
- CLOSE_DELETE_ROOM_MODAL,
- CLOSE_EDIT_RACK_NAME_MODAL,
- CLOSE_EDIT_ROOM_NAME_MODAL,
- OPEN_NEW_TOPOLOGY_MODAL,
- OPEN_DELETE_MACHINE_MODAL,
- OPEN_DELETE_RACK_MODAL,
- OPEN_DELETE_ROOM_MODAL,
- OPEN_EDIT_RACK_NAME_MODAL,
- OPEN_EDIT_ROOM_NAME_MODAL,
-} from '../actions/modals/topology'
-import { CLOSE_NEW_PORTFOLIO_MODAL, OPEN_NEW_PORTFOLIO_MODAL } from '../actions/modals/portfolios'
-import { CLOSE_NEW_SCENARIO_MODAL, OPEN_NEW_SCENARIO_MODAL } from '../actions/modals/scenarios'
-
-function modal(openAction, closeAction) {
- return function (state = false, action) {
- switch (action.type) {
- case openAction:
- return true
- case closeAction:
- return false
- default:
- return state
- }
- }
-}
-
-export const modals = combineReducers({
- changeTopologyModalVisible: modal(OPEN_NEW_TOPOLOGY_MODAL, CLOSE_NEW_TOPOLOGY_MODAL),
- editRoomNameModalVisible: modal(OPEN_EDIT_ROOM_NAME_MODAL, CLOSE_EDIT_ROOM_NAME_MODAL),
- deleteRoomModalVisible: modal(OPEN_DELETE_ROOM_MODAL, CLOSE_DELETE_ROOM_MODAL),
- editRackNameModalVisible: modal(OPEN_EDIT_RACK_NAME_MODAL, CLOSE_EDIT_RACK_NAME_MODAL),
- deleteRackModalVisible: modal(OPEN_DELETE_RACK_MODAL, CLOSE_DELETE_RACK_MODAL),
- deleteMachineModalVisible: modal(OPEN_DELETE_MACHINE_MODAL, CLOSE_DELETE_MACHINE_MODAL),
- newPortfolioModalVisible: modal(OPEN_NEW_PORTFOLIO_MODAL, CLOSE_NEW_PORTFOLIO_MODAL),
- newScenarioModalVisible: modal(OPEN_NEW_SCENARIO_MODAL, CLOSE_NEW_SCENARIO_MODAL),
-})
diff --git a/opendc-web/opendc-web-ui/src/store/hooks/experiments.js b/opendc-web/opendc-web-ui/src/store/hooks/experiments.js
new file mode 100644
index 00000000..aef512e5
--- /dev/null
+++ b/opendc-web/opendc-web-ui/src/store/hooks/experiments.js
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import { useSelector } from 'react-redux'
+
+/**
+ * Return the available traces to experiment with.
+ */
+export function useTraces() {
+ return useSelector((state) => Object.values(state.objects.trace))
+}
+
+/**
+ * Return the available schedulers to experiment with.
+ */
+export function useSchedulers() {
+ return useSelector((state) => Object.values(state.objects.scheduler))
+}
diff --git a/opendc-web/opendc-web-ui/src/store/hooks/project.js b/opendc-web/opendc-web-ui/src/store/hooks/project.js
index 0f2f1b66..0db49fdd 100644
--- a/opendc-web/opendc-web-ui/src/store/hooks/project.js
+++ b/opendc-web/opendc-web-ui/src/store/hooks/project.js
@@ -25,8 +25,54 @@ import { useSelector } from 'react-redux'
/**
* Return the current active project.
*/
-export function useProject() {
+export function useActiveProject() {
return useSelector((state) =>
state.currentProjectId !== '-1' ? state.objects.project[state.currentProjectId] : undefined
)
}
+
+/**
+ * Return the active portfolio.
+ */
+export function useActivePortfolio() {
+ return useSelector((state) => state.objects.portfolio[state.currentPortfolioId])
+}
+
+/**
+ * Return the active scenario.
+ */
+export function useActiveScenario() {
+ return useSelector((state) => state.objects.scenario[state.currentScenarioId])
+}
+
+/**
+ * Return the portfolios for the specified project id.
+ */
+export function usePortfolios(projectId) {
+ return useSelector((state) => {
+ let portfolios = state.objects.project[projectId]
+ ? state.objects.project[projectId].portfolioIds.map((t) => state.objects.portfolio[t])
+ : []
+ if (portfolios.filter((t) => !t).length > 0) {
+ portfolios = []
+ }
+
+ return portfolios
+ })
+}
+
+/**
+ * Return the scenarios for the specified portfolio id.
+ */
+export function useScenarios(portfolioId) {
+ return useSelector((state) => {
+ let scenarios = state.objects.portfolio[portfolioId]
+ ? state.objects.portfolio[portfolioId].scenarioIds.map((t) => state.objects.scenario[t])
+ : []
+ if (scenarios.filter((t) => !t).length > 0) {
+ scenarios = []
+ }
+
+ return scenarios
+ })
+}
diff --git a/opendc-web/opendc-web-ui/src/store/hooks/topology.js b/opendc-web/opendc-web-ui/src/store/hooks/topology.js
index e5e14804..d3ffb3e1 100644
--- a/opendc-web/opendc-web-ui/src/store/hooks/topology.js
+++ b/opendc-web/opendc-web-ui/src/store/hooks/topology.js
@@ -25,6 +25,25 @@ import { useSelector } from 'react-redux'
/**
* Return the current active topology.
*/
-export function useTopology() {
+export function useActiveTopology() {
return useSelector((state) => state.currentTopologyId !== '-1' && state.objects.topology[state.currentTopologyId])
}
+
+/**
+ * Return the topologies for the active project.
+ */
+export function useProjectTopologies() {
+ return useSelector(({ currentProjectId, objects }) => {
+ if (currentProjectId === '-1' || !objects.project[currentProjectId]) {
+ return []
+ }
+
+ const topologies = objects.project[currentProjectId].topologyIds.map((t) => objects.topology[t])
+
+ if (topologies.filter((t) => !t).length > 0) {
+ return []
+ }
+
+ return topologies
+ })
+}