summaryrefslogtreecommitdiff
path: root/frontend/src/components
diff options
context:
space:
mode:
authorGeorgios Andreadis <info@gandreadis.com>2020-07-02 18:39:28 +0200
committerFabian Mastenbroek <mail.fabianm@gmail.com>2020-08-24 19:47:21 +0200
commitf119fc78dda4d1e828dde04f378a63a93e3a0a7e (patch)
treebea1eace5d47f21a7ccb835c6a6079bc92e48710 /frontend/src/components
parent7f27a6370a0af25e1bf6ff8f46360c6c26c21e0b (diff)
Add current progress on frontend port
Diffstat (limited to 'frontend/src/components')
-rw-r--r--frontend/src/components/app/map/LoadingScreen.js2
-rw-r--r--frontend/src/components/app/map/groups/RackGroup.js4
-rw-r--r--frontend/src/components/app/map/groups/RoomGroup.js6
-rw-r--r--frontend/src/components/app/map/groups/TileGroup.js10
-rw-r--r--frontend/src/components/app/map/groups/TopologyGroup.js (renamed from frontend/src/components/app/map/groups/DatacenterGroup.js)16
-rw-r--r--frontend/src/components/app/map/layers/MapLayerComponent.js4
-rw-r--r--frontend/src/components/app/sidebars/simulation/ExperimentMetadataComponent.js4
-rw-r--r--frontend/src/components/app/sidebars/simulation/SimulationSidebarComponent.js4
-rw-r--r--frontend/src/components/app/sidebars/simulation/TaskComponent.js58
-rw-r--r--frontend/src/components/app/sidebars/simulation/TraceComponent.js20
-rw-r--r--frontend/src/components/app/sidebars/topology/machine/UnitAddComponent.js4
-rw-r--r--frontend/src/components/app/sidebars/topology/machine/UnitComponent.js8
-rw-r--r--frontend/src/components/app/sidebars/topology/machine/UnitListComponent.js4
-rw-r--r--frontend/src/components/app/sidebars/topology/rack/MachineComponent.js4
-rw-r--r--frontend/src/components/app/sidebars/topology/room/RoomSidebarComponent.js11
-rw-r--r--frontend/src/components/app/sidebars/topology/room/RoomTypeComponent.js8
-rw-r--r--frontend/src/components/app/timeline/TimelineControlsComponent.js13
-rw-r--r--frontend/src/components/experiments/ExperimentListComponent.js4
-rw-r--r--frontend/src/components/experiments/ExperimentRowComponent.js10
-rw-r--r--frontend/src/components/home/TeamSection.js18
-rw-r--r--frontend/src/components/modals/custom-components/ChangeTopologyModalComponent.js111
-rw-r--r--frontend/src/components/modals/custom-components/NewExperimentModalComponent.js21
-rw-r--r--frontend/src/components/navigation/AppNavbar.js76
23 files changed, 206 insertions, 214 deletions
diff --git a/frontend/src/components/app/map/LoadingScreen.js b/frontend/src/components/app/map/LoadingScreen.js
index ca159982..1fd470fc 100644
--- a/frontend/src/components/app/map/LoadingScreen.js
+++ b/frontend/src/components/app/map/LoadingScreen.js
@@ -4,7 +4,7 @@ import FontAwesome from 'react-fontawesome'
const LoadingScreen = () => (
<div className="display-4">
<FontAwesome name="refresh" className="mr-4" spin/>
- Loading your datacenter...
+ Loading your topology...
</div>
)
diff --git a/frontend/src/components/app/map/groups/RackGroup.js b/frontend/src/components/app/map/groups/RackGroup.js
index 708dcf69..6de939a9 100644
--- a/frontend/src/components/app/map/groups/RackGroup.js
+++ b/frontend/src/components/app/map/groups/RackGroup.js
@@ -22,12 +22,12 @@ const RackGroup = ({ tile, inSimulation, rackLoad }) => {
/>
<Group opacity={inSimulation ? 0.3 : 1}>
<RackSpaceFillContainer
- tileId={tile.id}
+ tileId={tile._id}
positionX={tile.positionX}
positionY={tile.positionY}
/>
<RackEnergyFillContainer
- tileId={tile.id}
+ tileId={tile._id}
positionX={tile.positionX}
positionY={tile.positionY}
/>
diff --git a/frontend/src/components/app/map/groups/RoomGroup.js b/frontend/src/components/app/map/groups/RoomGroup.js
index 230e3c9b..4e3c7410 100644
--- a/frontend/src/components/app/map/groups/RoomGroup.js
+++ b/frontend/src/components/app/map/groups/RoomGroup.js
@@ -11,7 +11,7 @@ const RoomGroup = ({
currentRoomInConstruction,
onClick,
}) => {
- if (currentRoomInConstruction === room.id) {
+ if (currentRoomInConstruction === room._id) {
return (
<Group onClick={onClick}>
{room.tileIds.map(tileId => (
@@ -27,7 +27,7 @@ const RoomGroup = ({
if (
(interactionLevel.mode === 'RACK' ||
interactionLevel.mode === 'MACHINE') &&
- interactionLevel.roomId === room.id
+ interactionLevel.roomId === room._id
) {
return [
room.tileIds
@@ -44,7 +44,7 @@ const RoomGroup = ({
))
}
})()}
- <WallContainer roomId={room.id}/>
+ <WallContainer roomId={room._id}/>
</Group>
)
}
diff --git a/frontend/src/components/app/map/groups/TileGroup.js b/frontend/src/components/app/map/groups/TileGroup.js
index 49e2e52b..54f4ae17 100644
--- a/frontend/src/components/app/map/groups/TileGroup.js
+++ b/frontend/src/components/app/map/groups/TileGroup.js
@@ -9,12 +9,10 @@ import RoomTile from '../elements/RoomTile'
const TileGroup = ({ tile, newTile, inSimulation, roomLoad, onClick }) => {
let tileObject
- switch (tile.objectType) {
- case 'RACK':
- tileObject = <RackContainer tile={tile}/>
- break
- default:
- tileObject = null
+ if (tile.rackId) {
+ tileObject = <RackContainer tile={tile}/>
+ } else {
+ tileObject = null
}
let color = ROOM_DEFAULT_COLOR
diff --git a/frontend/src/components/app/map/groups/DatacenterGroup.js b/frontend/src/components/app/map/groups/TopologyGroup.js
index 3d3b9702..a40a1d41 100644
--- a/frontend/src/components/app/map/groups/DatacenterGroup.js
+++ b/frontend/src/components/app/map/groups/TopologyGroup.js
@@ -4,15 +4,15 @@ import GrayContainer from '../../../../containers/app/map/GrayContainer'
import RoomContainer from '../../../../containers/app/map/RoomContainer'
import Shapes from '../../../../shapes/index'
-const DatacenterGroup = ({ datacenter, interactionLevel }) => {
- if (!datacenter) {
+const TopologyGroup = ({ topology, interactionLevel }) => {
+ if (!topology) {
return <Group/>
}
if (interactionLevel.mode === 'BUILDING') {
return (
<Group>
- {datacenter.roomIds.map(roomId => (
+ {topology.roomIds.map(roomId => (
<RoomContainer key={roomId} roomId={roomId}/>
))}
</Group>
@@ -21,20 +21,20 @@ const DatacenterGroup = ({ datacenter, interactionLevel }) => {
return (
<Group>
- {datacenter.roomIds
+ {topology.roomIds
.filter(roomId => roomId !== interactionLevel.roomId)
.map(roomId => <RoomContainer key={roomId} roomId={roomId}/>)}
{interactionLevel.mode === 'ROOM' ? <GrayContainer/> : null}
- {datacenter.roomIds
+ {topology.roomIds
.filter(roomId => roomId === interactionLevel.roomId)
.map(roomId => <RoomContainer key={roomId} roomId={roomId}/>)}
</Group>
)
}
-DatacenterGroup.propTypes = {
- datacenter: Shapes.Datacenter,
+TopologyGroup.propTypes = {
+ topology: Shapes.Topology,
interactionLevel: Shapes.InteractionLevel,
}
-export default DatacenterGroup
+export default TopologyGroup
diff --git a/frontend/src/components/app/map/layers/MapLayerComponent.js b/frontend/src/components/app/map/layers/MapLayerComponent.js
index 1a31f2b9..940057f9 100644
--- a/frontend/src/components/app/map/layers/MapLayerComponent.js
+++ b/frontend/src/components/app/map/layers/MapLayerComponent.js
@@ -1,6 +1,6 @@
import React from 'react'
import { Group, Layer } from 'react-konva'
-import DatacenterContainer from '../../../../containers/app/map/DatacenterContainer'
+import TopologyContainer from '../../../../containers/app/map/TopologyContainer'
import Backdrop from '../elements/Backdrop'
import GridGroup from '../groups/GridGroup'
@@ -13,7 +13,7 @@ const MapLayerComponent = ({ mapPosition, mapScale }) => (
scaleY={mapScale}
>
<Backdrop/>
- <DatacenterContainer/>
+ <TopologyContainer/>
<GridGroup/>
</Group>
</Layer>
diff --git a/frontend/src/components/app/sidebars/simulation/ExperimentMetadataComponent.js b/frontend/src/components/app/sidebars/simulation/ExperimentMetadataComponent.js
index 54a8b5e9..30990a13 100644
--- a/frontend/src/components/app/sidebars/simulation/ExperimentMetadataComponent.js
+++ b/frontend/src/components/app/sidebars/simulation/ExperimentMetadataComponent.js
@@ -2,14 +2,14 @@ import React from 'react'
const ExperimentMetadataComponent = ({
experimentName,
- pathName,
+ topologyName,
traceName,
schedulerName,
}) => (
<div>
<h2>{experimentName}</h2>
<p>
- Path: <strong>{pathName}</strong>
+ Topology: <strong>{topologyName}</strong>
</p>
<p>
Trace: <strong>{traceName}</strong>
diff --git a/frontend/src/components/app/sidebars/simulation/SimulationSidebarComponent.js b/frontend/src/components/app/sidebars/simulation/SimulationSidebarComponent.js
index 6e89c40e..dba75eb2 100644
--- a/frontend/src/components/app/sidebars/simulation/SimulationSidebarComponent.js
+++ b/frontend/src/components/app/sidebars/simulation/SimulationSidebarComponent.js
@@ -1,7 +1,6 @@
import React from 'react'
import ExperimentMetadataContainer from '../../../../containers/app/sidebars/simulation/ExperimentMetadataContainer'
import LoadMetricContainer from '../../../../containers/app/sidebars/simulation/LoadMetricContainer'
-import TraceContainer from '../../../../containers/app/sidebars/simulation/TraceContainer'
import Sidebar from '../Sidebar'
import './SimulationSidebarComponent.css'
@@ -11,9 +10,6 @@ const SimulationSidebarComponent = () => {
<div className="simulation-sidebar-container flex-column">
<ExperimentMetadataContainer/>
<LoadMetricContainer/>
- <div className="trace-container">
- <TraceContainer/>
- </div>
</div>
</Sidebar>
)
diff --git a/frontend/src/components/app/sidebars/simulation/TaskComponent.js b/frontend/src/components/app/sidebars/simulation/TaskComponent.js
deleted file mode 100644
index 94617086..00000000
--- a/frontend/src/components/app/sidebars/simulation/TaskComponent.js
+++ /dev/null
@@ -1,58 +0,0 @@
-import approx from 'approximate-number'
-import classNames from 'classnames'
-import React from 'react'
-import { convertSecondsToFormattedTime } from '../../../../util/date-time'
-
-const TaskComponent = ({ task, flopsLeft }) => {
- let icon
- let progressBarContent
- let percent
- let infoTitle
-
- if (flopsLeft === task.totalFlopCount) {
- icon = 'hourglass-half'
- progressBarContent = ''
- percent = 0
- infoTitle = 'Not submitted yet'
- } else if (flopsLeft > 0) {
- icon = 'refresh'
- progressBarContent = approx(task.totalFlopCount - flopsLeft) + ' FLOP'
- percent = 100 * (task.totalFlopCount - flopsLeft) / task.totalFlopCount
- infoTitle =
- progressBarContent + ' (' + Math.round(percent * 10) / 10 + '%)'
- } else {
- icon = 'check'
- progressBarContent = 'Completed'
- percent = 100
- infoTitle = 'Completed'
- }
-
- return (
- <li className="list-group-item flex-column align-items-start">
- <div className="d-flex w-100 justify-content-between">
- <h5 className="mb-1">{approx(task.totalFlopCount)} FLOP</h5>
- <small>Starts at {convertSecondsToFormattedTime(task.startTick)}</small>
- </div>
- <div title={infoTitle} style={{ display: 'flex' }}>
- <span
- className={classNames('fa', 'fa-' + icon)}
- style={{ width: '20px' }}
- />
- <div className="progress" style={{ flexGrow: 1 }}>
- <div
- className="progress-bar"
- role="progressbar"
- aria-valuenow={percent}
- aria-valuemin="0"
- aria-valuemax="100"
- style={{ width: percent + '%' }}
- >
- {progressBarContent}
- </div>
- </div>
- </div>
- </li>
- )
-}
-
-export default TaskComponent
diff --git a/frontend/src/components/app/sidebars/simulation/TraceComponent.js b/frontend/src/components/app/sidebars/simulation/TraceComponent.js
deleted file mode 100644
index 1292219b..00000000
--- a/frontend/src/components/app/sidebars/simulation/TraceComponent.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import React from 'react'
-import TaskContainer from '../../../../containers/app/sidebars/simulation/TaskContainer'
-
-const TraceComponent = ({ jobs }) => (
- <div>
- <h3>Trace</h3>
- {jobs.map(job => (
- <div key={job.id}>
- <h4>Job: {job.name}</h4>
- <ul className="list-group">
- {job.taskIds.map(taskId => (
- <TaskContainer taskId={taskId} key={taskId}/>
- ))}
- </ul>
- </div>
- ))}
- </div>
-)
-
-export default TraceComponent
diff --git a/frontend/src/components/app/sidebars/topology/machine/UnitAddComponent.js b/frontend/src/components/app/sidebars/topology/machine/UnitAddComponent.js
index 57e219fd..e8722506 100644
--- a/frontend/src/components/app/sidebars/topology/machine/UnitAddComponent.js
+++ b/frontend/src/components/app/sidebars/topology/machine/UnitAddComponent.js
@@ -16,7 +16,7 @@ class UnitAddComponent extends React.Component {
ref={unitSelect => (this.unitSelect = unitSelect)}
>
{this.props.units.map(unit => (
- <option value={unit.id} key={unit.id}>
+ <option value={unit._id} key={unit._id}>
{unit.manufacturer +
' ' +
unit.family +
@@ -31,7 +31,7 @@ class UnitAddComponent extends React.Component {
type="submit"
className="btn btn-outline-primary"
onClick={() =>
- this.props.onAdd(parseInt(this.unitSelect.value, 10))
+ this.props.onAdd(this.unitSelect.value)
}
>
<span className="fa fa-plus mr-2"/>
diff --git a/frontend/src/components/app/sidebars/topology/machine/UnitComponent.js b/frontend/src/components/app/sidebars/topology/machine/UnitComponent.js
index 93ac1cdd..647c8e5c 100644
--- a/frontend/src/components/app/sidebars/topology/machine/UnitComponent.js
+++ b/frontend/src/components/app/sidebars/topology/machine/UnitComponent.js
@@ -40,13 +40,7 @@ class UnitComponent extends React.Component {
return (
<li className="d-flex list-group-item justify-content-between align-items-center">
<span style={{ maxWidth: '60%' }}>
- {this.props.unit.manufacturer +
- ' ' +
- this.props.unit.family +
- ' ' +
- this.props.unit.model +
- ' ' +
- this.props.unit.generation}
+ {this.props.unit.name}
</span>
<span>
<span
diff --git a/frontend/src/components/app/sidebars/topology/machine/UnitListComponent.js b/frontend/src/components/app/sidebars/topology/machine/UnitListComponent.js
index 31d4db51..da65da23 100644
--- a/frontend/src/components/app/sidebars/topology/machine/UnitListComponent.js
+++ b/frontend/src/components/app/sidebars/topology/machine/UnitListComponent.js
@@ -18,8 +18,8 @@ const UnitListComponent = ({ unitType, unitIds, inSimulation }) => (
<strong>No units of this type in this machine</strong>
) : (
<span>
- <strong>No units...</strong> Add some with the menu above!
- </span>
+ <strong>No units...</strong> Add some with the menu above!
+ </span>
)}
</div>
)}
diff --git a/frontend/src/components/app/sidebars/topology/rack/MachineComponent.js b/frontend/src/components/app/sidebars/topology/rack/MachineComponent.js
index 0a1d1065..b4204136 100644
--- a/frontend/src/components/app/sidebars/topology/rack/MachineComponent.js
+++ b/frontend/src/components/app/sidebars/topology/rack/MachineComponent.js
@@ -61,8 +61,8 @@ const MachineComponent = ({
)}
{hasNoUnits ? (
<span className="badge badge-default badge-warning">
- Machine with no units
- </span>
+ Machine with no units
+ </span>
) : (
undefined
)}
diff --git a/frontend/src/components/app/sidebars/topology/room/RoomSidebarComponent.js b/frontend/src/components/app/sidebars/topology/room/RoomSidebarComponent.js
index d9865744..d8a805cb 100644
--- a/frontend/src/components/app/sidebars/topology/room/RoomSidebarComponent.js
+++ b/frontend/src/components/app/sidebars/topology/room/RoomSidebarComponent.js
@@ -6,18 +6,11 @@ import DeleteRoomContainer from '../../../../../containers/app/sidebars/topology
import EditRoomContainer from '../../../../../containers/app/sidebars/topology/room/EditRoomContainer'
import RackConstructionContainer from '../../../../../containers/app/sidebars/topology/room/RackConstructionContainer'
import RoomNameContainer from '../../../../../containers/app/sidebars/topology/room/RoomNameContainer'
-import RoomTypeContainer from '../../../../../containers/app/sidebars/topology/room/RoomTypeContainer'
-
-const RoomSidebarComponent = ({ roomId, roomType, inSimulation }) => {
- let allowedObjects
- if (!inSimulation && roomType === 'SERVER') {
- allowedObjects = <RackConstructionContainer/>
- }
+const RoomSidebarComponent = ({ roomId, inSimulation }) => {
return (
<div>
<RoomNameContainer/>
- <RoomTypeContainer/>
<BackToBuildingContainer/>
{inSimulation ? (
<div>
@@ -26,7 +19,7 @@ const RoomSidebarComponent = ({ roomId, roomType, inSimulation }) => {
</div>
) : (
<div>
- {allowedObjects}
+ <RackConstructionContainer/>
<EditRoomContainer/>
<DeleteRoomContainer/>
</div>
diff --git a/frontend/src/components/app/sidebars/topology/room/RoomTypeComponent.js b/frontend/src/components/app/sidebars/topology/room/RoomTypeComponent.js
deleted file mode 100644
index b662307c..00000000
--- a/frontend/src/components/app/sidebars/topology/room/RoomTypeComponent.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import React from 'react'
-import { ROOM_TYPE_TO_NAME_MAP } from '../../../../../util/room-types'
-
-const RoomTypeComponent = ({ roomType }) => (
- <p className="lead">{ROOM_TYPE_TO_NAME_MAP[roomType]}</p>
-)
-
-export default RoomTypeComponent
diff --git a/frontend/src/components/app/timeline/TimelineControlsComponent.js b/frontend/src/components/app/timeline/TimelineControlsComponent.js
index 5412b1f5..01911aff 100644
--- a/frontend/src/components/app/timeline/TimelineControlsComponent.js
+++ b/frontend/src/components/app/timeline/TimelineControlsComponent.js
@@ -27,19 +27,6 @@ class TimelineControlsComponent extends React.Component {
),
}}
/>
- {this.props.sectionTicks.map(sectionTick => (
- <div
- key={sectionTick}
- className="section-marker"
- style={{
- left: convertTickToPercentage(
- sectionTick,
- this.props.lastSimulatedTick,
- ),
- }}
- title="Topology changes at this tick"
- />
- ))}
</div>
</div>
)
diff --git a/frontend/src/components/experiments/ExperimentListComponent.js b/frontend/src/components/experiments/ExperimentListComponent.js
index 55a7ff6d..3c53fc94 100644
--- a/frontend/src/components/experiments/ExperimentListComponent.js
+++ b/frontend/src/components/experiments/ExperimentListComponent.js
@@ -31,7 +31,7 @@ const ExperimentListComponent = ({ experimentIds, loading }) => {
<thead>
<tr>
<th>Name</th>
- <th>Path</th>
+ <th>Topology</th>
<th>Trace</th>
<th>Scheduler</th>
<th/>
@@ -52,7 +52,7 @@ const ExperimentListComponent = ({ experimentIds, loading }) => {
}
ExperimentListComponent.propTypes = {
- experimentIds: PropTypes.arrayOf(PropTypes.number).isRequired,
+ experimentIds: PropTypes.arrayOf(PropTypes.string).isRequired,
loading: PropTypes.bool,
}
diff --git a/frontend/src/components/experiments/ExperimentRowComponent.js b/frontend/src/components/experiments/ExperimentRowComponent.js
index 8a2638a7..880d7e31 100644
--- a/frontend/src/components/experiments/ExperimentRowComponent.js
+++ b/frontend/src/components/experiments/ExperimentRowComponent.js
@@ -6,16 +6,12 @@ import Shapes from '../../shapes/index'
const ExperimentRowComponent = ({ experiment, simulationId, onDelete }) => (
<tr>
<td className="pt-3">{experiment.name}</td>
- <td className="pt-3">
- {experiment.path.name
- ? experiment.path.name
- : 'Path ' + experiment.path.id}
- </td>
+ <td className="pt-3">{experiment.topology.name}</td>
<td className="pt-3">{experiment.trace.name}</td>
<td className="pt-3">{experiment.scheduler.name}</td>
<td className="text-right">
<Link
- to={'/simulations/' + simulationId + '/experiments/' + experiment.id}
+ to={'/simulations/' + simulationId + '/experiments/' + experiment._id}
className="btn btn-outline-primary btn-sm mr-2"
title="Open this experiment"
>
@@ -24,7 +20,7 @@ const ExperimentRowComponent = ({ experiment, simulationId, onDelete }) => (
<div
className="btn btn-outline-danger btn-sm"
title="Delete this experiment"
- onClick={() => onDelete(experiment.id)}
+ onClick={() => onDelete(experiment._id)}
>
<span className="fa fa-trash"/>
</div>
diff --git a/frontend/src/components/home/TeamSection.js b/frontend/src/components/home/TeamSection.js
index 2b7bb69d..6823797f 100644
--- a/frontend/src/components/home/TeamSection.js
+++ b/frontend/src/components/home/TeamSection.js
@@ -2,7 +2,7 @@ import React from 'react'
import ContentSection from './ContentSection'
const TeamMember = ({ photoId, name, description }) => (
- <div className="col-xl-3 col-lg-3 col-md-5 col-sm-6 col-12 justify-content-center">
+ <div className="col-xl-4 col-lg-4 col-md-5 col-sm-6 col-12 justify-content-center">
<img
src={'img/portraits/' + photoId + '.png'}
className="col-xl-10 col-lg-10 col-md-10 col-sm-8 col-5 mb-2 mt-2"
@@ -24,12 +24,6 @@ const TeamSection = () => (
description="Project Lead"
/>
<TeamMember
- photoId="loverweel"
- name="Leon Overweel"
- description="Product Lead and Software Engineer responsible for the web server, database, and
- API specification"
- />
- <TeamMember
photoId="gandreadis"
name="Georgios Andreadis"
description="Software Engineer responsible for the frontend web application"
@@ -39,6 +33,16 @@ const TeamSection = () => (
name="Fabian Mastenbroek"
description="Software Engineer responsible for the datacenter simulator"
/>
+ <TeamMember
+ photoId="jburley"
+ name="Jacob Burley"
+ description="Software Engineer responsible for prefabricated components"
+ />
+ <TeamMember
+ photoId="loverweel"
+ name="Leon Overweel"
+ description="Former product lead and Software Engineer"
+ />
</div>
<div className="text-center lead mt-3">
See{' '}
diff --git a/frontend/src/components/modals/custom-components/ChangeTopologyModalComponent.js b/frontend/src/components/modals/custom-components/ChangeTopologyModalComponent.js
new file mode 100644
index 00000000..e36bde48
--- /dev/null
+++ b/frontend/src/components/modals/custom-components/ChangeTopologyModalComponent.js
@@ -0,0 +1,111 @@
+import PropTypes from 'prop-types'
+import React from 'react'
+import Shapes from '../../../shapes'
+import Modal from '../Modal'
+
+class ChangeTopologyModalComponent extends React.Component {
+ static propTypes = {
+ show: PropTypes.bool.isRequired,
+ topologies: PropTypes.arrayOf(Shapes.Topology),
+ onCreateTopology: PropTypes.func.isRequired,
+ onDuplicateTopology: PropTypes.func.isRequired,
+ onDeleteTopology: PropTypes.func.isRequired,
+ onCancel: PropTypes.func.isRequired,
+ }
+
+ reset() {
+ this.textInput.value = ''
+ this.originTopology.selectedIndex = 0
+ }
+
+ onSubmit() {
+ if (this.originTopology.selectedIndex === 0) {
+ this.onCreate()
+ } else {
+ this.onDuplicate()
+ }
+ }
+
+ onCreate() {
+ this.props.onCreateTopology(this.textInput.value)
+ this.reset()
+ }
+
+ onDuplicate() {
+ this.props.onCreateTopology(
+ this.textInput.value,
+ this.originTopology.value,
+ )
+ this.reset()
+ }
+
+ onDelete(id) {
+ this.props.onDeleteTopology(id)
+ this.reset()
+ }
+
+ onCancel() {
+ this.props.onCancel()
+ this.reset()
+ }
+
+ render() {
+ return (
+ <Modal
+ title="Change Topology"
+ show={this.props.show}
+ onSubmit={this.onSubmit.bind(this)}
+ onCancel={this.onCancel.bind(this)}
+ >
+ <div>
+ {this.props.topologies.forEach(topology => (
+ <div key={topology._id}>
+ {topology.name}
+ <div
+ className="btn btn-danger"
+ onClick={() => this.onDelete(topology._id)}
+ >
+ Delete
+ </div>
+ </div>
+ ))}
+ </div>
+
+ <form
+ onSubmit={e => {
+ e.preventDefault()
+ this.onSubmit()
+ }}
+ >
+ <div className="form-group">
+ <label className="form-control-label">Name</label>
+ <input
+ type="text"
+ className="form-control"
+ required
+ ref={textInput => (this.textInput = textInput)}
+ />
+ </div>
+ <div className="form-group">
+ <label className="form-control-label">Topology to duplicate</label>
+ <select
+ className="form-control"
+ ref={originTopology => (this.originTopology = originTopology)}
+ >
+ <option value={-1} key={-1}>
+ None - start from scratch
+ </option>
+ {this.props.topologies.map(topology => (
+ <option value={topology._id} key={topology._id}>
+ {topology.name}
+ </option>
+ ))}
+ </select>
+ </div>
+ </form>
+ </Modal>
+ )
+ }
+}
+
+export default ChangeTopologyModalComponent
diff --git a/frontend/src/components/modals/custom-components/NewExperimentModalComponent.js b/frontend/src/components/modals/custom-components/NewExperimentModalComponent.js
index 143109ff..ce685837 100644
--- a/frontend/src/components/modals/custom-components/NewExperimentModalComponent.js
+++ b/frontend/src/components/modals/custom-components/NewExperimentModalComponent.js
@@ -6,7 +6,7 @@ import Modal from '../Modal'
class NewExperimentModalComponent extends React.Component {
static propTypes = {
show: PropTypes.bool.isRequired,
- paths: PropTypes.arrayOf(Shapes.Path),
+ topologies: PropTypes.arrayOf(Shapes.Topology),
schedulers: PropTypes.arrayOf(Shapes.Scheduler),
traces: PropTypes.arrayOf(Shapes.Trace),
callback: PropTypes.func.isRequired,
@@ -14,7 +14,7 @@ class NewExperimentModalComponent extends React.Component {
reset() {
this.textInput.value = ''
- this.pathSelect.selectedIndex = 0
+ this.topologySelect.selectedIndex = 0
this.traceSelect.selectedIndex = 0
this.schedulerSelect.selectedIndex = 0
}
@@ -22,8 +22,8 @@ class NewExperimentModalComponent extends React.Component {
onSubmit() {
this.props.callback(
this.textInput.value,
- parseInt(this.pathSelect.value, 10),
- parseInt(this.traceSelect.value, 10),
+ this.topologySelect.value,
+ this.traceSelect.value,
this.schedulerSelect.value,
)
this.reset()
@@ -53,18 +53,19 @@ class NewExperimentModalComponent extends React.Component {
<input
type="text"
className="form-control"
+ required
ref={textInput => (this.textInput = textInput)}
/>
</div>
<div className="form-group">
- <label className="form-control-label">Path</label>
+ <label className="form-control-label">Topology</label>
<select
className="form-control"
- ref={pathSelect => (this.pathSelect = pathSelect)}
+ ref={topologySelect => (this.topologySelect = topologySelect)}
>
- {this.props.paths.map(path => (
- <option value={path.id} key={path.id}>
- {path.name ? path.name : 'Path ' + path.id}
+ {this.props.topologies.map(topology => (
+ <option value={topology._id} key={topology._id}>
+ {topology.name}
</option>
))}
</select>
@@ -76,7 +77,7 @@ class NewExperimentModalComponent extends React.Component {
ref={traceSelect => (this.traceSelect = traceSelect)}
>
{this.props.traces.map(trace => (
- <option value={trace.id} key={trace.id}>
+ <option value={trace._id} key={trace._id}>
{trace.name}
</option>
))}
diff --git a/frontend/src/components/navigation/AppNavbar.js b/frontend/src/components/navigation/AppNavbar.js
index 451bb6a3..da43a330 100644
--- a/frontend/src/components/navigation/AppNavbar.js
+++ b/frontend/src/components/navigation/AppNavbar.js
@@ -4,52 +4,50 @@ import { Link } from 'react-router-dom'
import Navbar, { NavItem } from './Navbar'
import './Navbar.css'
-const AppNavbar = ({ simulationId, inSimulation, fullWidth }) => (
+const AppNavbar = ({ simulationId, inSimulation, fullWidth, onViewTopologies }) => (
<Navbar fullWidth={fullWidth}>
- {inSimulation ? (
- <NavItem route={'/simulations/' + simulationId}>
- <Link
- className="nav-link"
- title="Construction"
- to={'/simulations/' + simulationId}
- >
- <FontAwesome name="industry" className="mr-2"/>
- Construction
- </Link>
- </NavItem>
- ) : (
- undefined
- )}
- {inSimulation ? (
- <NavItem route={'/simulations/' + simulationId + '/experiments'}>
- <Link
- className="nav-link"
- title="Experiments"
- to={'/simulations/' + simulationId + '/experiments'}
- >
- <FontAwesome name="play" className="mr-2"/>
- Experiments
- </Link>
- </NavItem>
- ) : (
- undefined
- )}
<NavItem route="/simulations">
<Link className="nav-link" title="My Simulations" to="/simulations">
<FontAwesome name="list" className="mr-2"/>
My Simulations
</Link>
</NavItem>
- <NavItem route="email">
- <a
- className="nav-link"
- title="Support"
- href="mailto:opendc@atlarge-research.com"
- >
- <FontAwesome name="envelope" className="mr-2"/>
- Support
- </a>
- </NavItem>
+ {inSimulation ? (
+ <>
+ <NavItem route={'/simulations/' + simulationId}>
+ <Link
+ className="nav-link"
+ title="Construction"
+ to={'/simulations/' + simulationId}
+ >
+ <FontAwesome name="industry" className="mr-2"/>
+ Construction
+ </Link>
+ </NavItem>
+ <NavItem route="topologies">
+ <span
+ className="nav-link"
+ title="Topologies"
+ onClick={onViewTopologies}
+ >
+ <FontAwesome name="home" className="mr-2"/>
+ Topologies
+ </span>
+ </NavItem>
+ <NavItem route={'/simulations/' + simulationId + '/experiments'}>
+ <Link
+ className="nav-link"
+ title="Experiments"
+ to={'/simulations/' + simulationId + '/experiments'}
+ >
+ <FontAwesome name="play" className="mr-2"/>
+ Experiments
+ </Link>
+ </NavItem>
+ </>
+ ) : (
+ undefined
+ )}
</Navbar>
)