summaryrefslogtreecommitdiff
path: root/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'frontend')
-rw-r--r--frontend/.prettierrc.yaml1
-rw-r--r--frontend/package.json150
-rw-r--r--frontend/public/humans.txt16
-rw-r--r--frontend/public/img/datacenter-drawing.pngbin219576 -> 207909 bytes
-rw-r--r--frontend/public/img/portraits/aiosup.pngbin111629 -> 71879 bytes
-rw-r--r--frontend/public/img/portraits/fmastenbroek.pngbin135589 -> 121867 bytes
-rw-r--r--frontend/public/img/portraits/gandreadis.pngbin118477 -> 76426 bytes
-rw-r--r--frontend/public/img/portraits/jburley.pngbin0 -> 328112 bytes
-rw-r--r--frontend/public/img/portraits/loverweel.pngbin107768 -> 65866 bytes
-rw-r--r--frontend/src/actions/experiments.js3
-rw-r--r--frontend/src/actions/map.js17
-rw-r--r--frontend/src/actions/modals/topology.js14
-rw-r--r--frontend/src/actions/objects.js13
-rw-r--r--frontend/src/actions/profile.js0
-rw-r--r--frontend/src/actions/simulation/tick.js24
-rw-r--r--frontend/src/actions/topologies.js16
-rw-r--r--frontend/src/actions/topology/building.js14
-rw-r--r--frontend/src/actions/topology/room.js2
-rw-r--r--frontend/src/actions/users.js10
-rw-r--r--frontend/src/api/index.js2
-rw-r--r--frontend/src/api/routes/datacenters.js26
-rw-r--r--frontend/src/api/routes/experiments.js27
-rw-r--r--frontend/src/api/routes/jobs.js5
-rw-r--r--frontend/src/api/routes/paths.js30
-rw-r--r--frontend/src/api/routes/room-types.js9
-rw-r--r--frontend/src/api/routes/rooms.js46
-rw-r--r--frontend/src/api/routes/sections.js5
-rw-r--r--frontend/src/api/routes/simulations.js14
-rw-r--r--frontend/src/api/routes/specifications.js57
-rw-r--r--frontend/src/api/routes/tiles.js146
-rw-r--r--frontend/src/api/routes/topologies.js42
-rw-r--r--frontend/src/api/routes/traces.js6
-rw-r--r--frontend/src/api/routes/users.js25
-rw-r--r--frontend/src/api/socket.js4
-rw-r--r--frontend/src/auth/index.js4
-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
-rw-r--r--frontend/src/containers/app/map/DatacenterContainer.js17
-rw-r--r--frontend/src/containers/app/map/MapStage.js6
-rw-r--r--frontend/src/containers/app/map/RackContainer.js4
-rw-r--r--frontend/src/containers/app/map/RackEnergyFillContainer.js2
-rw-r--r--frontend/src/containers/app/map/RackSpaceFillContainer.js2
-rw-r--r--frontend/src/containers/app/map/TileContainer.js4
-rw-r--r--frontend/src/containers/app/map/TopologyContainer.js17
-rw-r--r--frontend/src/containers/app/map/layers/ObjectHoverLayer.js2
-rw-r--r--frontend/src/containers/app/map/layers/RoomHoverLayer.js6
-rw-r--r--frontend/src/containers/app/sidebars/simulation/ExperimentMetadataContainer.js12
-rw-r--r--frontend/src/containers/app/sidebars/simulation/TaskContainer.js26
-rw-r--r--frontend/src/containers/app/sidebars/simulation/TraceContainer.js25
-rw-r--r--frontend/src/containers/app/sidebars/topology/building/BuildingSidebarContainer.js3
-rw-r--r--frontend/src/containers/app/sidebars/topology/machine/MachineSidebarContainer.js2
-rw-r--r--frontend/src/containers/app/sidebars/topology/machine/UnitContainer.js2
-rw-r--r--frontend/src/containers/app/sidebars/topology/machine/UnitListContainer.js4
-rw-r--r--frontend/src/containers/app/sidebars/topology/rack/MachineContainer.js4
-rw-r--r--frontend/src/containers/app/sidebars/topology/rack/MachineListContainer.js2
-rw-r--r--frontend/src/containers/app/sidebars/topology/rack/RackNameContainer.js2
-rw-r--r--frontend/src/containers/app/sidebars/topology/rack/RackSidebarContainer.js2
-rw-r--r--frontend/src/containers/app/sidebars/topology/room/EditRoomContainer.js5
-rw-r--r--frontend/src/containers/app/sidebars/topology/room/RackConstructionContainer.js5
-rw-r--r--frontend/src/containers/app/sidebars/topology/room/RoomSidebarContainer.js3
-rw-r--r--frontend/src/containers/app/sidebars/topology/room/RoomTypeContainer.js12
-rw-r--r--frontend/src/containers/app/timeline/PlayButtonContainer.js5
-rw-r--r--frontend/src/containers/app/timeline/TimelineContainer.js17
-rw-r--r--frontend/src/containers/app/timeline/TimelineControlsContainer.js14
-rw-r--r--frontend/src/containers/experiments/ExperimentRowContainer.js2
-rw-r--r--frontend/src/containers/modals/ChangeTopologyModal.js56
-rw-r--r--frontend/src/containers/modals/EditRackNameModal.js2
-rw-r--r--frontend/src/containers/modals/NewExperimentModal.js10
-rw-r--r--frontend/src/index.js3
-rw-r--r--frontend/src/pages/App.js66
-rw-r--r--frontend/src/pages/Experiments.js30
-rw-r--r--frontend/src/pages/Home.js22
-rw-r--r--frontend/src/pages/NotFound.js2
-rw-r--r--frontend/src/pages/Profile.js19
-rw-r--r--frontend/src/pages/Simulations.js19
-rw-r--r--frontend/src/reducers/current-ids.js10
-rw-r--r--frontend/src/reducers/index.js4
-rw-r--r--frontend/src/reducers/interaction-level.js4
-rw-r--r--frontend/src/reducers/modals.js45
-rw-r--r--frontend/src/reducers/objects.js46
-rw-r--r--frontend/src/reducers/simulation-list.js2
-rw-r--r--frontend/src/reducers/states.js3
-rw-r--r--frontend/src/registerServiceWorker.js108
-rw-r--r--frontend/src/routes/index.js49
-rw-r--r--frontend/src/sagas/experiments.js98
-rw-r--r--frontend/src/sagas/index.js15
-rw-r--r--frontend/src/sagas/objects.js251
-rw-r--r--frontend/src/sagas/simulations.js8
-rw-r--r--frontend/src/sagas/topology.js370
-rw-r--r--frontend/src/sagas/users.js10
-rw-r--r--frontend/src/shapes/index.js124
-rw-r--r--frontend/src/store/configure-store.js5
-rw-r--r--frontend/src/store/middlewares/viewport-adjustment.js16
-rw-r--r--frontend/src/util/date-time.js17
-rw-r--r--frontend/src/util/date-time.test.js2
-rw-r--r--frontend/src/util/room-types.js7
-rw-r--r--frontend/src/util/tile-calculations.js18
-rw-r--r--frontend/src/util/timeline.js14
-rw-r--r--frontend/src/util/unit-specifications.js46
-rw-r--r--frontend/yarn.lock18
121 files changed, 1054 insertions, 1820 deletions
diff --git a/frontend/.prettierrc.yaml b/frontend/.prettierrc.yaml
index 6e8842f0..9a2b9a95 100644
--- a/frontend/.prettierrc.yaml
+++ b/frontend/.prettierrc.yaml
@@ -2,3 +2,4 @@ trailingComma: "es5"
tabWidth: 4
semi: false
singleQuote: true
+printWidth: 120
diff --git a/frontend/package.json b/frontend/package.json
index cb4f25b4..2180f092 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,77 +1,79 @@
{
- "name": "opendc-frontend",
- "version": "0.1.0",
- "description": "The user-facing component of the OpenDC stack, allowing users to build and interact with their own (virtual) datacenters.",
- "keywords": [
- "opendc",
- "simulation",
- "datacenter",
- "frontend"
- ],
- "homepage": "http://opendc.org",
- "bugs": {
- "url": "https://github.com/atlarge-research/opendc-frontend/issues",
- "email": "opendc@atlarge-research.com"
- },
- "author": "Georgios Andreadis <g.andreadis@atlarge-research.com> (https://gandreadis.com/)",
- "license": "MIT",
- "private": true,
- "proxy": "http://localhost:8081",
- "dependencies": {
- "approximate-number": "~2.0.0",
- "classnames": "~2.2.5",
- "husky": "~4.2.5",
- "konva": "~6.0.0",
- "lint-staged": "~10.2.2",
- "node-sass-chokidar": "~1.4.0",
- "npm-run-all": "~4.1.2",
- "prettier": "~2.0.5",
- "prop-types": "~15.7.2",
- "react": "~16.13.1",
- "react-document-title": "~2.0.3",
- "react-dom": "~16.13.1",
- "react-fontawesome": "~1.7.1",
- "react-google-login": "~5.1.14",
- "react-konva": "~16.13.0-2",
- "react-redux": "~7.2.0",
- "react-router-dom": "~5.1.2",
- "react-scripts": "~3.4.1",
- "react-shortcuts": "~2.1.0",
- "redux": "~4.0.5",
- "redux-localstorage": "~0.4.1",
- "redux-logger": "~3.0.6",
- "redux-saga": "~1.1.3",
- "redux-thunk": "~2.3.0",
- "socket.io-client": "~2.3.0",
- "svgsaver": "~0.9.0",
- "victory": "~34.2.1"
- },
- "lint-staged": {
- "src/**/*.{js,jsx,json}": [
- "prettier --write",
- "git add"
- ]
- },
- "scripts": {
- "precommit": "lint-staged",
- "build-css": "node-sass-chokidar src/ -o src/",
- "watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
- "start-js": "react-scripts start",
- "start": "npm-run-all -p watch-css start-js",
- "build": "npm run build-css && react-scripts build",
- "test": "react-scripts test --env=jsdom",
- "eject": "react-scripts eject"
- },
- "browserslist": {
- "production": [
- ">0.2%",
- "not dead",
- "not op_mini all"
+ "name": "opendc-frontend",
+ "version": "0.1.0",
+ "description": "The user-facing component of the OpenDC stack, allowing users to build and interact with their own (virtual) datacenters.",
+ "keywords": [
+ "opendc",
+ "simulation",
+ "datacenter",
+ "frontend"
],
- "development": [
- "last 1 chrome version",
- "last 1 firefox version",
- "last 1 safari version"
- ]
- }
+ "homepage": "http://opendc.org",
+ "bugs": {
+ "url": "https://github.com/atlarge-research/opendc-frontend/issues",
+ "email": "opendc@atlarge-research.com"
+ },
+ "author": "Georgios Andreadis <g.andreadis@atlarge-research.com> (https://gandreadis.com/)",
+ "license": "MIT",
+ "private": true,
+ "proxy": "http://localhost:8081",
+ "dependencies": {
+ "approximate-number": "~2.0.0",
+ "classnames": "~2.2.5",
+ "husky": "~4.2.5",
+ "konva": "~6.0.0",
+ "lint-staged": "~10.2.2",
+ "node-sass-chokidar": "~1.4.0",
+ "npm-run-all": "~4.1.2",
+ "prettier": "~2.0.5",
+ "prop-types": "~15.7.2",
+ "react": "~16.13.1",
+ "react-document-title": "~2.0.3",
+ "react-dom": "~16.13.1",
+ "react-fontawesome": "~1.7.1",
+ "react-google-login": "~5.1.14",
+ "react-konva": "~16.13.0-2",
+ "react-redux": "~7.2.0",
+ "react-router-dom": "~5.1.2",
+ "react-scripts": "~3.4.1",
+ "react-shortcuts": "~2.1.0",
+ "redux": "~4.0.5",
+ "redux-localstorage": "~0.4.1",
+ "redux-logger": "~3.0.6",
+ "redux-saga": "~1.1.3",
+ "redux-thunk": "~2.3.0",
+ "socket.io-client": "~2.3.0",
+ "svgsaver": "~0.9.0",
+ "uuidv4": "^6.1.1",
+ "victory": "~34.2.1"
+ },
+ "lint-staged": {
+ "src/**/*.{js,jsx,json}": [
+ "prettier --write",
+ "git add"
+ ]
+ },
+ "scripts": {
+ "format": "prettier --write src/**/*.js",
+ "precommit": "lint-staged",
+ "build-css": "node-sass-chokidar src/ -o src/",
+ "watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
+ "start-js": "react-scripts start",
+ "start": "npm-run-all -p watch-css start-js",
+ "build": "npm run build-css && react-scripts build",
+ "test": "react-scripts test --env=jsdom",
+ "eject": "react-scripts eject"
+ },
+ "browserslist": {
+ "production": [
+ ">0.2%",
+ "not dead",
+ "not op_mini all"
+ ],
+ "development": [
+ "last 1 chrome version",
+ "last 1 firefox version",
+ "last 1 safari version"
+ ]
+ }
}
diff --git a/frontend/public/humans.txt b/frontend/public/humans.txt
index d037fcfd..dadcd530 100644
--- a/frontend/public/humans.txt
+++ b/frontend/public/humans.txt
@@ -4,12 +4,7 @@ Site: http://www.ds.ewi.tudelft.nl/~iosup/
Twitter: aiosup.
Location: Delft, Netherlands.
-Backend Engineer: Leon Overweel.
-Site: http://leonoverweel.com/
-Twitter: layon_overwhale.
-Location: Delft, Netherlands.
-
-Frontend Engineer: Georgios Andreadis.
+Full-Stack Engineer: Georgios Andreadis.
Site: https://github.com/gandreadis
Location: Delft, Netherlands.
@@ -17,6 +12,15 @@ Simulation Engineer: Fabian Mastenbroek.
Site: https://github.com/fabianishere
Location: Delft, Netherlands.
+Simulation Engineer: Jacob Burley.
+Site: https://github.com/jc0b
+Location: Amsterdam, Netherlands.
+
+Backend Engineer: Leon Overweel.
+Site: http://leonoverweel.com/
+Twitter: layon_overwhale.
+Location: Delft, Netherlands.
+
Simulation Engineer: Matthijs Bijman.
Site: https://github.com/MDBijman
Location: Delft, Netherlands.
diff --git a/frontend/public/img/datacenter-drawing.png b/frontend/public/img/datacenter-drawing.png
index 401168e3..ec2b7398 100644
--- a/frontend/public/img/datacenter-drawing.png
+++ b/frontend/public/img/datacenter-drawing.png
Binary files differ
diff --git a/frontend/public/img/portraits/aiosup.png b/frontend/public/img/portraits/aiosup.png
index 30de349c..d2019b4d 100644
--- a/frontend/public/img/portraits/aiosup.png
+++ b/frontend/public/img/portraits/aiosup.png
Binary files differ
diff --git a/frontend/public/img/portraits/fmastenbroek.png b/frontend/public/img/portraits/fmastenbroek.png
index fd0d9de1..f17ef697 100644
--- a/frontend/public/img/portraits/fmastenbroek.png
+++ b/frontend/public/img/portraits/fmastenbroek.png
Binary files differ
diff --git a/frontend/public/img/portraits/gandreadis.png b/frontend/public/img/portraits/gandreadis.png
index 403870fa..96a3abda 100644
--- a/frontend/public/img/portraits/gandreadis.png
+++ b/frontend/public/img/portraits/gandreadis.png
Binary files differ
diff --git a/frontend/public/img/portraits/jburley.png b/frontend/public/img/portraits/jburley.png
new file mode 100644
index 00000000..d2691659
--- /dev/null
+++ b/frontend/public/img/portraits/jburley.png
Binary files differ
diff --git a/frontend/public/img/portraits/loverweel.png b/frontend/public/img/portraits/loverweel.png
index d12a9e86..85865977 100644
--- a/frontend/public/img/portraits/loverweel.png
+++ b/frontend/public/img/portraits/loverweel.png
Binary files differ
diff --git a/frontend/src/actions/experiments.js b/frontend/src/actions/experiments.js
index d0eda331..5d384abf 100644
--- a/frontend/src/actions/experiments.js
+++ b/frontend/src/actions/experiments.js
@@ -1,5 +1,4 @@
-export const FETCH_EXPERIMENTS_OF_SIMULATION =
- 'FETCH_EXPERIMENTS_OF_SIMULATION'
+export const FETCH_EXPERIMENTS_OF_SIMULATION = 'FETCH_EXPERIMENTS_OF_SIMULATION'
export const ADD_EXPERIMENT = 'ADD_EXPERIMENT'
export const DELETE_EXPERIMENT = 'DELETE_EXPERIMENT'
export const OPEN_EXPERIMENT_SUCCEEDED = 'OPEN_EXPERIMENT_SUCCEEDED'
diff --git a/frontend/src/actions/map.js b/frontend/src/actions/map.js
index 4ab767f7..0d49d849 100644
--- a/frontend/src/actions/map.js
+++ b/frontend/src/actions/map.js
@@ -36,13 +36,7 @@ export function zoomInOnCenter(zoomIn) {
return (dispatch, getState) => {
const state = getState()
- dispatch(
- zoomInOnPosition(
- zoomIn,
- state.map.dimensions.width / 2,
- state.map.dimensions.height / 2,
- ),
- )
+ dispatch(zoomInOnPosition(zoomIn, state.map.dimensions.width / 2, state.map.dimensions.height / 2))
}
}
@@ -54,13 +48,8 @@ export function zoomInOnPosition(zoomIn, x, y) {
x: x / state.map.scale - state.map.position.x / state.map.scale,
y: y / state.map.scale - state.map.position.y / state.map.scale,
}
- const newScale = zoomIn
- ? state.map.scale * MAP_SCALE_PER_EVENT
- : state.map.scale / MAP_SCALE_PER_EVENT
- const boundedScale = Math.min(
- Math.max(MAP_MIN_SCALE, newScale),
- MAP_MAX_SCALE,
- )
+ const newScale = zoomIn ? state.map.scale * MAP_SCALE_PER_EVENT : state.map.scale / MAP_SCALE_PER_EVENT
+ const boundedScale = Math.min(Math.max(MAP_MIN_SCALE, newScale), MAP_MAX_SCALE)
const newX = -(centerPoint.x - x / boundedScale) * boundedScale
const newY = -(centerPoint.y - y / boundedScale) * boundedScale
diff --git a/frontend/src/actions/modals/topology.js b/frontend/src/actions/modals/topology.js
index bc59e579..7b74e820 100644
--- a/frontend/src/actions/modals/topology.js
+++ b/frontend/src/actions/modals/topology.js
@@ -1,3 +1,5 @@
+export const OPEN_CHANGE_TOPOLOGY_MODAL = 'OPEN_CHANGE_TOPOLOGY_MODAL'
+export const CLOSE_CHANGE_TOPOLOGY_MODAL = 'CLOSE_CHANGE_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'
@@ -9,6 +11,18 @@ 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 openChangeTopologyModal() {
+ return {
+ type: OPEN_CHANGE_TOPOLOGY_MODAL,
+ }
+}
+
+export function closeChangeTopologyModal() {
+ return {
+ type: CLOSE_CHANGE_TOPOLOGY_MODAL,
+ }
+}
+
export function openEditRoomNameModal() {
return {
type: OPEN_EDIT_ROOM_NAME_MODAL,
diff --git a/frontend/src/actions/objects.js b/frontend/src/actions/objects.js
index 2b445c9d..7b648b18 100644
--- a/frontend/src/actions/objects.js
+++ b/frontend/src/actions/objects.js
@@ -1,9 +1,7 @@
export const ADD_TO_STORE = 'ADD_TO_STORE'
export const ADD_PROP_TO_STORE_OBJECT = 'ADD_PROP_TO_STORE_OBJECT'
-export const ADD_ID_TO_STORE_OBJECT_LIST_PROP =
- 'ADD_ID_TO_STORE_OBJECT_LIST_PROP'
-export const REMOVE_ID_FROM_STORE_OBJECT_LIST_PROP =
- 'REMOVE_ID_FROM_STORE_OBJECT_LIST_PROP'
+export const ADD_ID_TO_STORE_OBJECT_LIST_PROP = 'ADD_ID_TO_STORE_OBJECT_LIST_PROP'
+export const REMOVE_ID_FROM_STORE_OBJECT_LIST_PROP = 'REMOVE_ID_FROM_STORE_OBJECT_LIST_PROP'
export function addToStore(objectType, object) {
return {
@@ -32,12 +30,7 @@ export function addIdToStoreObjectListProp(objectType, objectId, propName, id) {
}
}
-export function removeIdFromStoreObjectListProp(
- objectType,
- objectId,
- propName,
- id,
-) {
+export function removeIdFromStoreObjectListProp(objectType, objectId, propName, id) {
return {
type: REMOVE_ID_FROM_STORE_OBJECT_LIST_PROP,
objectType,
diff --git a/frontend/src/actions/profile.js b/frontend/src/actions/profile.js
deleted file mode 100644
index e69de29b..00000000
--- a/frontend/src/actions/profile.js
+++ /dev/null
diff --git a/frontend/src/actions/simulation/tick.js b/frontend/src/actions/simulation/tick.js
index 72387d24..ca2027a4 100644
--- a/frontend/src/actions/simulation/tick.js
+++ b/frontend/src/actions/simulation/tick.js
@@ -1,6 +1,3 @@
-import { getDatacenterIdOfTick } from '../../util/timeline'
-import { setCurrentDatacenter } from '../topology/building'
-
export const GO_TO_TICK = 'GO_TO_TICK'
export const SET_LAST_SIMULATED_TICK = 'SET_LAST_SIMULATED_TICK'
@@ -13,27 +10,6 @@ export function incrementTick() {
export function goToTick(tick) {
return (dispatch, getState) => {
- const state = getState()
-
- let sections = []
- if (state.currentExperimentId !== -1) {
- const sectionIds =
- state.objects.path[
- state.objects.experiment[state.currentExperimentId].pathId
- ].sectionIds
-
- if (sectionIds) {
- sections = sectionIds.map(
- sectionId => state.objects.section[sectionId],
- )
- }
- }
-
- const newDatacenterId = getDatacenterIdOfTick(tick, sections)
- if (state.currentDatacenterId !== newDatacenterId) {
- dispatch(setCurrentDatacenter(newDatacenterId))
- }
-
dispatch({
type: GO_TO_TICK,
tick,
diff --git a/frontend/src/actions/topologies.js b/frontend/src/actions/topologies.js
new file mode 100644
index 00000000..c80ef6b2
--- /dev/null
+++ b/frontend/src/actions/topologies.js
@@ -0,0 +1,16 @@
+export const ADD_TOPOLOGY = 'ADD_TOPOLOGY'
+export const DELETE_TOPOLOGY = 'DELETE_TOPOLOGY'
+
+export function addTopology(topology) {
+ return {
+ type: ADD_TOPOLOGY,
+ topology,
+ }
+}
+
+export function deleteTopology(id) {
+ return {
+ type: DELETE_TOPOLOGY,
+ id,
+ }
+}
diff --git a/frontend/src/actions/topology/building.js b/frontend/src/actions/topology/building.js
index 2d4d399c..da2dc311 100644
--- a/frontend/src/actions/topology/building.js
+++ b/frontend/src/actions/topology/building.js
@@ -1,5 +1,5 @@
-export const SET_CURRENT_DATACENTER = 'SET_CURRENT_DATACENTER'
-export const RESET_CURRENT_DATACENTER = 'RESET_CURRENT_DATACENTER'
+export const SET_CURRENT_TOPOLOGY = 'SET_CURRENT_TOPOLOGY'
+export const RESET_CURRENT_TOPOLOGY = 'RESET_CURRENT_TOPOLOGY'
export const START_NEW_ROOM_CONSTRUCTION = 'START_NEW_ROOM_CONSTRUCTION'
export const START_NEW_ROOM_CONSTRUCTION_SUCCEEDED =
'START_NEW_ROOM_CONSTRUCTION_SUCCEEDED'
@@ -12,16 +12,16 @@ export const FINISH_ROOM_EDIT = 'FINISH_ROOM_EDIT'
export const ADD_TILE = 'ADD_TILE'
export const DELETE_TILE = 'DELETE_TILE'
-export function setCurrentDatacenter(datacenterId) {
+export function setCurrentTopology(topologyId) {
return {
- type: SET_CURRENT_DATACENTER,
- datacenterId,
+ type: SET_CURRENT_TOPOLOGY,
+ topologyId,
}
}
-export function resetCurrentDatacenter() {
+export function resetCurrentTopology() {
return {
- type: RESET_CURRENT_DATACENTER,
+ type: RESET_CURRENT_TOPOLOGY,
}
}
diff --git a/frontend/src/actions/topology/room.js b/frontend/src/actions/topology/room.js
index 3476f0b6..939b475a 100644
--- a/frontend/src/actions/topology/room.js
+++ b/frontend/src/actions/topology/room.js
@@ -35,7 +35,7 @@ export function addRackToTile(positionX, positionY) {
if (tile !== null) {
dispatch({
type: ADD_RACK_TO_TILE,
- tileId: tile.id,
+ tileId: tile._id,
})
}
}
diff --git a/frontend/src/actions/users.js b/frontend/src/actions/users.js
index cae7e211..4868ac34 100644
--- a/frontend/src/actions/users.js
+++ b/frontend/src/actions/users.js
@@ -1,7 +1,5 @@
-export const FETCH_AUTHORIZATIONS_OF_CURRENT_USER =
- 'FETCH_AUTHORIZATIONS_OF_CURRENT_USER'
-export const FETCH_AUTHORIZATIONS_OF_CURRENT_USER_SUCCEEDED =
- 'FETCH_AUTHORIZATIONS_OF_CURRENT_USER_SUCCEEDED'
+export const FETCH_AUTHORIZATIONS_OF_CURRENT_USER = 'FETCH_AUTHORIZATIONS_OF_CURRENT_USER'
+export const FETCH_AUTHORIZATIONS_OF_CURRENT_USER_SUCCEEDED = 'FETCH_AUTHORIZATIONS_OF_CURRENT_USER_SUCCEEDED'
export const DELETE_CURRENT_USER = 'DELETE_CURRENT_USER'
export const DELETE_CURRENT_USER_SUCCEEDED = 'DELETE_CURRENT_USER_SUCCEEDED'
@@ -15,9 +13,7 @@ export function fetchAuthorizationsOfCurrentUser() {
}
}
-export function fetchAuthorizationsOfCurrentUserSucceeded(
- authorizationsOfCurrentUser,
-) {
+export function fetchAuthorizationsOfCurrentUserSucceeded(authorizationsOfCurrentUser) {
return {
type: FETCH_AUTHORIZATIONS_OF_CURRENT_USER_SUCCEEDED,
authorizationsOfCurrentUser,
diff --git a/frontend/src/api/index.js b/frontend/src/api/index.js
index 6f6c924c..cefcb2c5 100644
--- a/frontend/src/api/index.js
+++ b/frontend/src/api/index.js
@@ -2,7 +2,7 @@ import { sendSocketRequest } from './socket'
export function sendRequest(request) {
return new Promise((resolve, reject) => {
- sendSocketRequest(request, response => {
+ sendSocketRequest(request, (response) => {
if (response.status.code === 200) {
resolve(response.content)
} else {
diff --git a/frontend/src/api/routes/datacenters.js b/frontend/src/api/routes/datacenters.js
deleted file mode 100644
index d041b6ae..00000000
--- a/frontend/src/api/routes/datacenters.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import { sendRequest } from '../index'
-import { getById } from './util'
-
-export function getDatacenter(datacenterId) {
- return getById('/datacenters/{datacenterId}', { datacenterId })
-}
-
-export function getRoomsOfDatacenter(datacenterId) {
- return getById('/datacenters/{datacenterId}/rooms', { datacenterId })
-}
-
-export function addRoomToDatacenter(room) {
- return sendRequest({
- path: '/datacenters/{datacenterId}/rooms',
- method: 'POST',
- parameters: {
- body: {
- room,
- },
- path: {
- datacenterId: room.datacenterId,
- },
- query: {},
- },
- })
-}
diff --git a/frontend/src/api/routes/experiments.js b/frontend/src/api/routes/experiments.js
index 75dab7af..ab85613c 100644
--- a/frontend/src/api/routes/experiments.js
+++ b/frontend/src/api/routes/experiments.js
@@ -1,4 +1,21 @@
import { deleteById, getById } from './util'
+import { sendRequest } from '../index'
+
+export function addExperiment(simulationId, experiment) {
+ return sendRequest({
+ path: '/simulations/{simulationId}/experiments',
+ method: 'POST',
+ parameters: {
+ body: {
+ experiment,
+ },
+ path: {
+ simulationId,
+ },
+ query: {},
+ },
+ })
+}
export function getExperiment(experimentId) {
return getById('/experiments/{experimentId}', { experimentId })
@@ -8,12 +25,6 @@ export function deleteExperiment(experimentId) {
return deleteById('/experiments/{experimentId}', { experimentId })
}
-export function getLastSimulatedTick(experimentId) {
- return getById('/experiments/{experimentId}/last-simulated-tick', {
- experimentId,
- })
-}
-
export function getAllMachineStates(experimentId) {
return getById('/experiments/{experimentId}/machine-states', {
experimentId,
@@ -27,7 +38,3 @@ export function getAllRackStates(experimentId) {
export function getAllRoomStates(experimentId) {
return getById('/experiments/{experimentId}/room-states', { experimentId })
}
-
-export function getAllTaskStates(experimentId) {
- return getById('/experiments/{experimentId}/task-states', { experimentId })
-}
diff --git a/frontend/src/api/routes/jobs.js b/frontend/src/api/routes/jobs.js
deleted file mode 100644
index 205c1777..00000000
--- a/frontend/src/api/routes/jobs.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import { getById } from './util'
-
-export function getTasksOfJob(jobId) {
- return getById('/jobs/{jobId}/tasks', { jobId })
-}
diff --git a/frontend/src/api/routes/paths.js b/frontend/src/api/routes/paths.js
deleted file mode 100644
index 74811ab2..00000000
--- a/frontend/src/api/routes/paths.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import { sendRequest } from '../index'
-import { getById } from './util'
-
-export function getPath(pathId) {
- return getById('/paths/{pathId}', { pathId })
-}
-
-export function getBranchesOfPath(pathId) {
- return getById('/paths/{pathId}/branches', { pathId })
-}
-
-export function branchFromPath(pathId, section) {
- return sendRequest({
- path: '/paths/{pathId}/branches',
- method: 'POST',
- parameters: {
- body: {
- section,
- },
- path: {
- pathId,
- },
- query: {},
- },
- })
-}
-
-export function getSectionsOfPath(pathId) {
- return getById('/paths/{pathId}/sections', { pathId })
-}
diff --git a/frontend/src/api/routes/room-types.js b/frontend/src/api/routes/room-types.js
deleted file mode 100644
index 6c964e93..00000000
--- a/frontend/src/api/routes/room-types.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import { getAll, getById } from './util'
-
-export function getAvailableRoomTypes() {
- return getAll('/room-types')
-}
-
-export function getAllowedObjectsOfRoomType(name) {
- return getById('/room-types/{name}/allowed-objects', { name })
-}
diff --git a/frontend/src/api/routes/rooms.js b/frontend/src/api/routes/rooms.js
deleted file mode 100644
index f87d1298..00000000
--- a/frontend/src/api/routes/rooms.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import { sendRequest } from '../index'
-import { deleteById, getById } from './util'
-
-export function getRoom(roomId) {
- return getById('/rooms/{roomId}', { roomId })
-}
-
-export function updateRoom(room) {
- return sendRequest({
- path: '/rooms/{roomId}',
- method: 'PUT',
- parameters: {
- body: {
- room,
- },
- path: {
- roomId: room.id,
- },
- query: {},
- },
- })
-}
-
-export function deleteRoom(roomId) {
- return deleteById('/rooms/{roomId}', { roomId })
-}
-
-export function getTilesOfRoom(roomId) {
- return getById('/rooms/{roomId}/tiles', { roomId })
-}
-
-export function addTileToRoom(tile) {
- return sendRequest({
- path: '/rooms/{roomId}/tiles',
- method: 'POST',
- parameters: {
- body: {
- tile,
- },
- path: {
- roomId: tile.roomId,
- },
- query: {},
- },
- })
-}
diff --git a/frontend/src/api/routes/sections.js b/frontend/src/api/routes/sections.js
deleted file mode 100644
index 1ee8a22a..00000000
--- a/frontend/src/api/routes/sections.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import { getById } from './util'
-
-export function getSection(sectionId) {
- return getById('/sections/{sectionId}', { sectionId })
-}
diff --git a/frontend/src/api/routes/simulations.js b/frontend/src/api/routes/simulations.js
index aec89dcc..e22fbc07 100644
--- a/frontend/src/api/routes/simulations.js
+++ b/frontend/src/api/routes/simulations.js
@@ -39,20 +39,6 @@ export function deleteSimulation(simulationId) {
return deleteById('/simulations/{simulationId}', { simulationId })
}
-export function getAuthorizationsBySimulation(simulationId) {
- return getById('/simulations/{simulationId}/authorizations', {
- simulationId,
- })
-}
-
-export function getPathsOfSimulation(simulationId) {
- return getById('/simulations/{simulationId}/paths', { simulationId })
-}
-
-export function getExperimentsOfSimulation(simulationId) {
- return getById('/simulations/{simulationId}/experiments', { simulationId })
-}
-
export function addExperiment(simulationId, experiment) {
return sendRequest({
path: '/simulations/{simulationId}/experiments',
diff --git a/frontend/src/api/routes/specifications.js b/frontend/src/api/routes/specifications.js
deleted file mode 100644
index 167fdce5..00000000
--- a/frontend/src/api/routes/specifications.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import { getAll, getById } from './util'
-
-export function getAllCoolingItems() {
- return getAll('/specifications/cooling-items')
-}
-
-export function getCoolingItem(id) {
- return getById('/specifications/cooling-items/{id}', { id })
-}
-
-export function getAllCPUs() {
- return getAll('/specifications/cpus')
-}
-
-export function getCPU(id) {
- return getById('/specifications/cpus/{id}', { id })
-}
-
-export function getAllFailureModels() {
- return getAll('/specifications/failure-models')
-}
-
-export function getFailureModel(id) {
- return getById('/specifications/failure-models/{id}', { id })
-}
-
-export function getAllGPUs() {
- return getAll('/specifications/gpus')
-}
-
-export function getGPU(id) {
- return getById('/specifications/gpus/{id}', { id })
-}
-
-export function getAllMemories() {
- return getAll('/specifications/memories')
-}
-
-export function getMemory(id) {
- return getById('/specifications/memories/{id}', { id })
-}
-
-export function getAllPSUs() {
- return getAll('/specifications/psus')
-}
-
-export function getPSU(id) {
- return getById('/specifications/psus/{id}', { id })
-}
-
-export function getAllStorages() {
- return getAll('/specifications/storages')
-}
-
-export function getStorage(id) {
- return getById('/specifications/storages/{id}', { id })
-}
diff --git a/frontend/src/api/routes/tiles.js b/frontend/src/api/routes/tiles.js
deleted file mode 100644
index 170fe462..00000000
--- a/frontend/src/api/routes/tiles.js
+++ /dev/null
@@ -1,146 +0,0 @@
-import { sendRequest } from '../index'
-import { deleteById, getById } from './util'
-
-export function getTile(tileId) {
- return getById('/tiles/{tileId}', { tileId })
-}
-
-export function deleteTile(tileId) {
- return deleteById('/tiles/{tileId}', { tileId })
-}
-
-export function getRackByTile(tileId) {
- return getTileObject(tileId, '/rack')
-}
-
-export function addRackToTile(tileId, rack) {
- return addTileObject(tileId, { rack }, '/rack')
-}
-
-export function updateRackOnTile(tileId, rack) {
- return updateTileObject(tileId, { rack }, '/rack')
-}
-
-export function deleteRackFromTile(tileId) {
- return deleteTileObject(tileId, '/rack')
-}
-
-export function getMachinesOfRackByTile(tileId) {
- return getById('/tiles/{tileId}/rack/machines', { tileId })
-}
-
-export function addMachineToRackOnTile(tileId, machine) {
- return sendRequest({
- path: '/tiles/{tileId}/rack/machines',
- method: 'POST',
- parameters: {
- body: {
- machine,
- },
- path: {
- tileId,
- },
- query: {},
- },
- })
-}
-
-export function updateMachineInRackOnTile(tileId, position, machine) {
- return sendRequest({
- path: '/tiles/{tileId}/rack/machines/{position}',
- method: 'PUT',
- parameters: {
- body: {
- machine,
- },
- path: {
- tileId,
- position,
- },
- query: {},
- },
- })
-}
-
-export function deleteMachineInRackOnTile(tileId, position) {
- return sendRequest({
- path: '/tiles/{tileId}/rack/machines/{position}',
- method: 'DELETE',
- parameters: {
- body: {},
- path: {
- tileId,
- position,
- },
- query: {},
- },
- })
-}
-
-export function getCoolingItemByTile(tileId) {
- return getTileObject(tileId, '/cooling-item')
-}
-
-export function addCoolingItemToTile(tileId, coolingItemId) {
- return addTileObject(tileId, { coolingItemId }, '/cooling-item')
-}
-
-export function updateCoolingItemOnTile(tileId, coolingItemId) {
- return updateTileObject(tileId, { coolingItemId }, '/cooling-item')
-}
-
-export function deleteCoolingItemFromTile(tileId) {
- return deleteTileObject(tileId, '/cooling-item')
-}
-
-export function getPSUByTile(tileId) {
- return getTileObject(tileId, '/psu')
-}
-
-export function addPSUToTile(tileId, psuId) {
- return addTileObject(tileId, { psuId }, '/psu')
-}
-
-export function updatePSUOnTile(tileId, psuId) {
- return updateTileObject(tileId, { psuId }, '/psu')
-}
-
-export function deletePSUFromTile(tileId) {
- return deleteTileObject(tileId, '/psu')
-}
-
-function getTileObject(tileId, endpoint) {
- return getById('/tiles/{tileId}' + endpoint, { tileId })
-}
-
-function addTileObject(tileId, objectBody, endpoint) {
- return sendRequest({
- path: '/tiles/{tileId}' + endpoint,
- method: 'POST',
- parameters: {
- body: objectBody,
- path: {
- tileId,
- },
- query: {},
- },
- })
-}
-
-function updateTileObject(tileId, objectBody, endpoint) {
- return sendRequest({
- path: '/tiles/{tileId}' + endpoint,
- method: 'PUT',
- parameters: {
- body: objectBody,
- path: {
- tileId,
- },
- query: {},
- },
- })
-}
-
-function deleteTileObject(tileId, endpoint) {
- return deleteById('/tiles/{tileId}' + endpoint, { tileId })
-}
diff --git a/frontend/src/api/routes/topologies.js b/frontend/src/api/routes/topologies.js
new file mode 100644
index 00000000..307ea7ab
--- /dev/null
+++ b/frontend/src/api/routes/topologies.js
@@ -0,0 +1,42 @@
+import { deleteById, getById } from './util'
+import { sendRequest } from '../index'
+
+export function addTopology(topology) {
+ return sendRequest({
+ path: '/simulations/{simulationId}/topologies',
+ method: 'POST',
+ parameters: {
+ body: {
+ topology,
+ },
+ path: {
+ simulationId: topology.simulationId,
+ },
+ query: {},
+ },
+ })
+}
+
+export function getTopology(topologyId) {
+ return getById('/topologies/{topologyId}', { topologyId })
+}
+
+export function updateTopology(topology) {
+ return sendRequest({
+ path: '/topologies/{topologyId}',
+ method: 'PUT',
+ parameters: {
+ body: {
+ topology,
+ },
+ path: {
+ topologyId: topology._id,
+ },
+ query: {},
+ },
+ })
+}
+
+export function deleteTopology(topologyId) {
+ return deleteById('/topologies/{topologyId}', { topologyId })
+}
diff --git a/frontend/src/api/routes/traces.js b/frontend/src/api/routes/traces.js
index 140408b1..67895a87 100644
--- a/frontend/src/api/routes/traces.js
+++ b/frontend/src/api/routes/traces.js
@@ -1,9 +1,5 @@
-import { getAll, getById } from './util'
+import { getAll } from './util'
export function getAllTraces() {
return getAll('/traces')
}
-
-export function getJobsOfTrace(traceId) {
- return getById('/traces/{traceId}/jobs', { traceId })
-}
diff --git a/frontend/src/api/routes/users.js b/frontend/src/api/routes/users.js
index 4cb194ce..3028f3f7 100644
--- a/frontend/src/api/routes/users.js
+++ b/frontend/src/api/routes/users.js
@@ -1,5 +1,5 @@
import { sendRequest } from '../index'
-import { deleteById, getById } from './util'
+import { deleteById } from './util'
export function getUserByEmail(email) {
return sendRequest({
@@ -43,29 +43,6 @@ export function getUser(userId) {
})
}
-export function updateUser(userId, user) {
- return sendRequest({
- path: '/users/{userId}',
- method: 'PUT',
- parameters: {
- body: {
- user: {
- givenName: user.givenName,
- familyName: user.familyName,
- },
- },
- path: {
- userId,
- },
- query: {},
- },
- })
-}
-
export function deleteUser(userId) {
return deleteById('/users/{userId}', { userId })
}
-
-export function getAuthorizationsByUser(userId) {
- return getById('/users/{userId}/authorizations', { userId })
-}
diff --git a/frontend/src/api/socket.js b/frontend/src/api/socket.js
index ce5f7587..93ce8fa8 100644
--- a/frontend/src/api/socket.js
+++ b/frontend/src/api/socket.js
@@ -10,9 +10,7 @@ export function setupSocketConnection(onConnect) {
if (process.env.NODE_ENV !== 'production') {
port = 8081
}
- socket = io.connect(
- window.location.protocol + '//' + window.location.hostname + ':' + port,
- )
+ socket = io.connect(window.location.protocol + '//' + window.location.hostname + ':' + port)
socket.on('connect', onConnect)
socket.on('response', onSocketResponse)
}
diff --git a/frontend/src/auth/index.js b/frontend/src/auth/index.js
index 7922f567..f93c7141 100644
--- a/frontend/src/auth/index.js
+++ b/frontend/src/auth/index.js
@@ -29,7 +29,7 @@ export const getAuthToken = () => {
return authObj.authToken
}
-export const saveAuthLocalStorage = payload => {
+export const saveAuthLocalStorage = (payload) => {
localStorage.setItem('auth', JSON.stringify(payload))
}
@@ -37,7 +37,7 @@ export const clearAuthLocalStorage = () => {
localStorage.setItem('auth', '')
}
-export const authRedirectMiddleware = store => next => action => {
+export const authRedirectMiddleware = (store) => (next) => (action) => {
switch (action.type) {
case LOG_IN_SUCCEEDED:
saveAuthLocalStorage(action.payload)
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>
)
diff --git a/frontend/src/containers/app/map/DatacenterContainer.js b/frontend/src/containers/app/map/DatacenterContainer.js
deleted file mode 100644
index 9ed1d38c..00000000
--- a/frontend/src/containers/app/map/DatacenterContainer.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import { connect } from 'react-redux'
-import DatacenterGroup from '../../../components/app/map/groups/DatacenterGroup'
-
-const mapStateToProps = state => {
- if (state.currentDatacenterId === -1) {
- return {}
- }
-
- return {
- datacenter: state.objects.datacenter[state.currentDatacenterId],
- interactionLevel: state.interactionLevel,
- }
-}
-
-const DatacenterContainer = connect(mapStateToProps)(DatacenterGroup)
-
-export default DatacenterContainer
diff --git a/frontend/src/containers/app/map/MapStage.js b/frontend/src/containers/app/map/MapStage.js
index e8abb86f..f749e85a 100644
--- a/frontend/src/containers/app/map/MapStage.js
+++ b/frontend/src/containers/app/map/MapStage.js
@@ -1,9 +1,5 @@
import { connect } from 'react-redux'
-import {
- setMapDimensions,
- setMapPositionWithBoundsCheck,
- zoomInOnPosition,
-} from '../../../actions/map'
+import { setMapDimensions, setMapPositionWithBoundsCheck, zoomInOnPosition } from '../../../actions/map'
import MapStageComponent from '../../../components/app/map/MapStageComponent'
const mapStateToProps = state => {
diff --git a/frontend/src/containers/app/map/RackContainer.js b/frontend/src/containers/app/map/RackContainer.js
index 614421b4..362ba2e2 100644
--- a/frontend/src/containers/app/map/RackContainer.js
+++ b/frontend/src/containers/app/map/RackContainer.js
@@ -9,11 +9,11 @@ const mapStateToProps = (state, ownProps) => {
if (inSimulation) {
if (
state.states.rack[state.currentTick] &&
- state.states.rack[state.currentTick][ownProps.tile.objectId]
+ state.states.rack[state.currentTick][ownProps.tile.rackId]
) {
rackLoad = getStateLoad(
state.loadMetric,
- state.states.rack[state.currentTick][ownProps.tile.objectId],
+ state.states.rack[state.currentTick][ownProps.tile.rackId],
)
}
}
diff --git a/frontend/src/containers/app/map/RackEnergyFillContainer.js b/frontend/src/containers/app/map/RackEnergyFillContainer.js
index e25cd37d..d5989839 100644
--- a/frontend/src/containers/app/map/RackEnergyFillContainer.js
+++ b/frontend/src/containers/app/map/RackEnergyFillContainer.js
@@ -3,7 +3,7 @@ import RackFillBar from '../../../components/app/map/elements/RackFillBar'
const mapStateToProps = (state, ownProps) => {
let energyConsumptionTotal = 0
- const rack = state.objects.rack[state.objects.tile[ownProps.tileId].objectId]
+ const rack = state.objects.rack[state.objects.tile[ownProps.tileId].rackId]
const machineIds = rack.machineIds
machineIds.forEach(machineId => {
if (machineId !== null) {
diff --git a/frontend/src/containers/app/map/RackSpaceFillContainer.js b/frontend/src/containers/app/map/RackSpaceFillContainer.js
index c43695a9..8110b1fb 100644
--- a/frontend/src/containers/app/map/RackSpaceFillContainer.js
+++ b/frontend/src/containers/app/map/RackSpaceFillContainer.js
@@ -3,7 +3,7 @@ import RackFillBar from '../../../components/app/map/elements/RackFillBar'
const mapStateToProps = (state, ownProps) => {
const machineIds =
- state.objects.rack[state.objects.tile[ownProps.tileId].objectId].machineIds
+ state.objects.rack[state.objects.tile[ownProps.tileId].rackId].machineIds
return {
type: 'space',
fillFraction:
diff --git a/frontend/src/containers/app/map/TileContainer.js b/frontend/src/containers/app/map/TileContainer.js
index 6122be96..7d9f7754 100644
--- a/frontend/src/containers/app/map/TileContainer.js
+++ b/frontend/src/containers/app/map/TileContainer.js
@@ -31,8 +31,8 @@ const mapStateToProps = (state, ownProps) => {
const mapDispatchToProps = dispatch => {
return {
onClick: tile => {
- if (tile.objectType) {
- dispatch(goFromRoomToRack(tile.id))
+ if (tile.rackId) {
+ dispatch(goFromRoomToRack(tile._id))
}
},
}
diff --git a/frontend/src/containers/app/map/TopologyContainer.js b/frontend/src/containers/app/map/TopologyContainer.js
new file mode 100644
index 00000000..37cc5a06
--- /dev/null
+++ b/frontend/src/containers/app/map/TopologyContainer.js
@@ -0,0 +1,17 @@
+import { connect } from 'react-redux'
+import TopologyGroup from '../../../components/app/map/groups/TopologyGroup'
+
+const mapStateToProps = state => {
+ if (state.currentTopologyId === -1) {
+ return {}
+ }
+
+ return {
+ topology: state.objects.topology[state.currentTopologyId],
+ interactionLevel: state.interactionLevel,
+ }
+}
+
+const TopologyContainer = connect(mapStateToProps)(TopologyGroup)
+
+export default TopologyContainer
diff --git a/frontend/src/containers/app/map/layers/ObjectHoverLayer.js b/frontend/src/containers/app/map/layers/ObjectHoverLayer.js
index dc489e82..4619c0b8 100644
--- a/frontend/src/containers/app/map/layers/ObjectHoverLayer.js
+++ b/frontend/src/containers/app/map/layers/ObjectHoverLayer.js
@@ -19,7 +19,7 @@ const mapStateToProps = state => {
)
const tile = findTileWithPosition(tiles, x, y)
- return !(tile === null || tile.objectType)
+ return !(tile === null || tile.rackId)
},
}
}
diff --git a/frontend/src/containers/app/map/layers/RoomHoverLayer.js b/frontend/src/containers/app/map/layers/RoomHoverLayer.js
index b5a891ce..c05627ea 100644
--- a/frontend/src/containers/app/map/layers/RoomHoverLayer.js
+++ b/frontend/src/containers/app/map/layers/RoomHoverLayer.js
@@ -21,9 +21,9 @@ const mapStateToProps = state => {
.map(id => Object.assign({}, state.objects.room[id]))
.filter(
room =>
- state.objects.datacenter[state.currentDatacenterId].roomIds.indexOf(
- room.id,
- ) !== -1 && room.id !== state.construction.currentRoomInConstruction,
+ state.objects.topology[state.currentTopologyId].roomIds.indexOf(
+ room._id,
+ ) !== -1 && room._id !== state.construction.currentRoomInConstruction,
);
[...oldRooms, newRoom].forEach(room => {
diff --git a/frontend/src/containers/app/sidebars/simulation/ExperimentMetadataContainer.js b/frontend/src/containers/app/sidebars/simulation/ExperimentMetadataContainer.js
index 06d0b88a..0dc20ea7 100644
--- a/frontend/src/containers/app/sidebars/simulation/ExperimentMetadataContainer.js
+++ b/frontend/src/containers/app/sidebars/simulation/ExperimentMetadataContainer.js
@@ -5,21 +5,21 @@ const mapStateToProps = state => {
if (!state.objects.experiment[state.currentExperimentId]) {
return {
experimentName: 'Loading experiment',
- pathName: '',
+ topologyName: '',
traceName: '',
schedulerName: '',
}
}
- const path =
- state.objects.path[
- state.objects.experiment[state.currentExperimentId].pathId
+ const topology =
+ state.objects.topology[
+ state.objects.experiment[state.currentExperimentId].topologyId
]
- const pathName = path.name ? path.name : 'Path ' + path.id
+ const topologyName = topology.name
return {
experimentName: state.objects.experiment[state.currentExperimentId].name,
- pathName,
+ topologyName,
traceName:
state.objects.trace[
state.objects.experiment[state.currentExperimentId].traceId
diff --git a/frontend/src/containers/app/sidebars/simulation/TaskContainer.js b/frontend/src/containers/app/sidebars/simulation/TaskContainer.js
deleted file mode 100644
index c4c86284..00000000
--- a/frontend/src/containers/app/sidebars/simulation/TaskContainer.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import { connect } from 'react-redux'
-import TaskComponent from '../../../../components/app/sidebars/simulation/TaskComponent'
-
-const mapStateToProps = (state, ownProps) => {
- let flopsLeft = state.objects.task[ownProps.taskId].totalFlopCount
-
- if (
- state.states.task[state.currentTick] &&
- state.states.task[state.currentTick][ownProps.taskId]
- ) {
- flopsLeft = state.states.task[state.currentTick][ownProps.taskId].flopsLeft
- } else if (
- state.objects.task[ownProps.taskId].startTick < state.currentTick
- ) {
- flopsLeft = 0
- }
-
- return {
- task: state.objects.task[ownProps.taskId],
- flopsLeft,
- }
-}
-
-const TaskContainer = connect(mapStateToProps)(TaskComponent)
-
-export default TaskContainer
diff --git a/frontend/src/containers/app/sidebars/simulation/TraceContainer.js b/frontend/src/containers/app/sidebars/simulation/TraceContainer.js
deleted file mode 100644
index 907c8874..00000000
--- a/frontend/src/containers/app/sidebars/simulation/TraceContainer.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import { connect } from 'react-redux'
-import TraceComponent from '../../../../components/app/sidebars/simulation/TraceComponent'
-
-const mapStateToProps = state => {
- if (
- !state.objects.experiment[state.currentExperimentId] ||
- !state.objects.trace[
- state.objects.experiment[state.currentExperimentId].traceId
- ].jobIds
- ) {
- return {
- jobs: [],
- }
- }
-
- return {
- jobs: state.objects.trace[
- state.objects.experiment[state.currentExperimentId].traceId
- ].jobIds.map(id => state.objects.job[id]),
- }
-}
-
-const TraceContainer = connect(mapStateToProps)(TraceComponent)
-
-export default TraceContainer
diff --git a/frontend/src/containers/app/sidebars/topology/building/BuildingSidebarContainer.js b/frontend/src/containers/app/sidebars/topology/building/BuildingSidebarContainer.js
index 711b2b82..1869705a 100644
--- a/frontend/src/containers/app/sidebars/topology/building/BuildingSidebarContainer.js
+++ b/frontend/src/containers/app/sidebars/topology/building/BuildingSidebarContainer.js
@@ -1,6 +1,5 @@
import { connect } from 'react-redux'
-import BuildingSidebarComponent
- from '../../../../../components/app/sidebars/topology/building/BuildingSidebarComponent'
+import BuildingSidebarComponent from '../../../../../components/app/sidebars/topology/building/BuildingSidebarComponent'
const mapStateToProps = state => {
return {
diff --git a/frontend/src/containers/app/sidebars/topology/machine/MachineSidebarContainer.js b/frontend/src/containers/app/sidebars/topology/machine/MachineSidebarContainer.js
index f5baee44..a39bd2d6 100644
--- a/frontend/src/containers/app/sidebars/topology/machine/MachineSidebarContainer.js
+++ b/frontend/src/containers/app/sidebars/topology/machine/MachineSidebarContainer.js
@@ -6,7 +6,7 @@ const mapStateToProps = state => {
inSimulation: state.currentExperimentId !== -1,
machineId:
state.objects.rack[
- state.objects.tile[state.interactionLevel.tileId].objectId
+ state.objects.tile[state.interactionLevel.tileId].rackId
].machineIds[state.interactionLevel.position - 1],
}
}
diff --git a/frontend/src/containers/app/sidebars/topology/machine/UnitContainer.js b/frontend/src/containers/app/sidebars/topology/machine/UnitContainer.js
index 1a01cad0..d8e549a7 100644
--- a/frontend/src/containers/app/sidebars/topology/machine/UnitContainer.js
+++ b/frontend/src/containers/app/sidebars/topology/machine/UnitContainer.js
@@ -4,8 +4,8 @@ import UnitComponent from '../../../../../components/app/sidebars/topology/machi
const mapStateToProps = (state, ownProps) => {
return {
- unit: state.objects[ownProps.unitType][ownProps.unitId],
inSimulation: state.currentExperimentId !== -1,
+ unit: state.objects[ownProps.unitType][ownProps.unitId],
}
}
diff --git a/frontend/src/containers/app/sidebars/topology/machine/UnitListContainer.js b/frontend/src/containers/app/sidebars/topology/machine/UnitListContainer.js
index fce657d4..2f11a22f 100644
--- a/frontend/src/containers/app/sidebars/topology/machine/UnitListContainer.js
+++ b/frontend/src/containers/app/sidebars/topology/machine/UnitListContainer.js
@@ -3,13 +3,13 @@ import UnitListComponent from '../../../../../components/app/sidebars/topology/m
const mapStateToProps = (state, ownProps) => {
return {
+ inSimulation: state.currentExperimentId !== -1,
unitIds:
state.objects.machine[
state.objects.rack[
- state.objects.tile[state.interactionLevel.tileId].objectId
+ state.objects.tile[state.interactionLevel.tileId].rackId
].machineIds[state.interactionLevel.position - 1]
][ownProps.unitType + 'Ids'],
- inSimulation: state.currentExperimentId !== -1,
}
}
diff --git a/frontend/src/containers/app/sidebars/topology/rack/MachineContainer.js b/frontend/src/containers/app/sidebars/topology/rack/MachineContainer.js
index f205257e..89818f1d 100644
--- a/frontend/src/containers/app/sidebars/topology/rack/MachineContainer.js
+++ b/frontend/src/containers/app/sidebars/topology/rack/MachineContainer.js
@@ -11,11 +11,11 @@ const mapStateToProps = (state, ownProps) => {
if (inSimulation) {
if (
state.states.machine[state.currentTick] &&
- state.states.machine[state.currentTick][machine.id]
+ state.states.machine[state.currentTick][machine._id]
) {
machineLoad = getStateLoad(
state.loadMetric,
- state.states.machine[state.currentTick][machine.id],
+ state.states.machine[state.currentTick][machine._id],
)
}
}
diff --git a/frontend/src/containers/app/sidebars/topology/rack/MachineListContainer.js b/frontend/src/containers/app/sidebars/topology/rack/MachineListContainer.js
index 3a797ed5..3898d119 100644
--- a/frontend/src/containers/app/sidebars/topology/rack/MachineListContainer.js
+++ b/frontend/src/containers/app/sidebars/topology/rack/MachineListContainer.js
@@ -5,7 +5,7 @@ const mapStateToProps = state => {
return {
machineIds:
state.objects.rack[
- state.objects.tile[state.interactionLevel.tileId].objectId
+ state.objects.tile[state.interactionLevel.tileId].rackId
].machineIds,
}
}
diff --git a/frontend/src/containers/app/sidebars/topology/rack/RackNameContainer.js b/frontend/src/containers/app/sidebars/topology/rack/RackNameContainer.js
index 11173b82..1eb885fc 100644
--- a/frontend/src/containers/app/sidebars/topology/rack/RackNameContainer.js
+++ b/frontend/src/containers/app/sidebars/topology/rack/RackNameContainer.js
@@ -6,7 +6,7 @@ const mapStateToProps = state => {
return {
rackName:
state.objects.rack[
- state.objects.tile[state.interactionLevel.tileId].objectId
+ state.objects.tile[state.interactionLevel.tileId].rackId
].name,
}
}
diff --git a/frontend/src/containers/app/sidebars/topology/rack/RackSidebarContainer.js b/frontend/src/containers/app/sidebars/topology/rack/RackSidebarContainer.js
index 89382ef0..21745b1d 100644
--- a/frontend/src/containers/app/sidebars/topology/rack/RackSidebarContainer.js
+++ b/frontend/src/containers/app/sidebars/topology/rack/RackSidebarContainer.js
@@ -3,7 +3,7 @@ import RackSidebarComponent from '../../../../../components/app/sidebars/topolog
const mapStateToProps = state => {
return {
- rackId: state.objects.tile[state.interactionLevel.tileId].objectId,
+ rackId: state.objects.tile[state.interactionLevel.tileId].rackId,
inSimulation: state.currentExperimentId !== -1,
}
}
diff --git a/frontend/src/containers/app/sidebars/topology/room/EditRoomContainer.js b/frontend/src/containers/app/sidebars/topology/room/EditRoomContainer.js
index 29014022..87470bfe 100644
--- a/frontend/src/containers/app/sidebars/topology/room/EditRoomContainer.js
+++ b/frontend/src/containers/app/sidebars/topology/room/EditRoomContainer.js
@@ -1,8 +1,5 @@
import { connect } from 'react-redux'
-import {
- finishRoomEdit,
- startRoomEdit,
-} from '../../../../../actions/topology/building'
+import { finishRoomEdit, startRoomEdit } from '../../../../../actions/topology/building'
import EditRoomComponent from '../../../../../components/app/sidebars/topology/room/EditRoomComponent'
const mapStateToProps = state => {
diff --git a/frontend/src/containers/app/sidebars/topology/room/RackConstructionContainer.js b/frontend/src/containers/app/sidebars/topology/room/RackConstructionContainer.js
index fe42647c..30f7a688 100644
--- a/frontend/src/containers/app/sidebars/topology/room/RackConstructionContainer.js
+++ b/frontend/src/containers/app/sidebars/topology/room/RackConstructionContainer.js
@@ -1,8 +1,5 @@
import { connect } from 'react-redux'
-import {
- startRackConstruction,
- stopRackConstruction,
-} from '../../../../../actions/topology/room'
+import { startRackConstruction, stopRackConstruction } from '../../../../../actions/topology/room'
import RackConstructionComponent from '../../../../../components/app/sidebars/topology/room/RackConstructionComponent'
const mapStateToProps = state => {
diff --git a/frontend/src/containers/app/sidebars/topology/room/RoomSidebarContainer.js b/frontend/src/containers/app/sidebars/topology/room/RoomSidebarContainer.js
index f940b282..443495de 100644
--- a/frontend/src/containers/app/sidebars/topology/room/RoomSidebarContainer.js
+++ b/frontend/src/containers/app/sidebars/topology/room/RoomSidebarContainer.js
@@ -3,9 +3,8 @@ import RoomSidebarComponent from '../../../../../components/app/sidebars/topolog
const mapStateToProps = state => {
return {
- roomId: state.interactionLevel.roomId,
- roomType: state.objects.room[state.interactionLevel.roomId].roomType,
inSimulation: state.currentExperimentId !== -1,
+ roomId: state.interactionLevel.roomId,
}
}
diff --git a/frontend/src/containers/app/sidebars/topology/room/RoomTypeContainer.js b/frontend/src/containers/app/sidebars/topology/room/RoomTypeContainer.js
deleted file mode 100644
index de4c8c85..00000000
--- a/frontend/src/containers/app/sidebars/topology/room/RoomTypeContainer.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import { connect } from 'react-redux'
-import RoomTypeComponent from '../../../../../components/app/sidebars/topology/room/RoomTypeComponent'
-
-const mapStateToProps = state => {
- return {
- roomType: state.objects.room[state.interactionLevel.roomId].roomType,
- }
-}
-
-const RoomNameContainer = connect(mapStateToProps)(RoomTypeComponent)
-
-export default RoomNameContainer
diff --git a/frontend/src/containers/app/timeline/PlayButtonContainer.js b/frontend/src/containers/app/timeline/PlayButtonContainer.js
index e332f08b..9662d753 100644
--- a/frontend/src/containers/app/timeline/PlayButtonContainer.js
+++ b/frontend/src/containers/app/timeline/PlayButtonContainer.js
@@ -1,8 +1,5 @@
import { connect } from 'react-redux'
-import {
- pauseSimulation,
- playSimulation,
-} from '../../../actions/simulation/playback'
+import { pauseSimulation, playSimulation } from '../../../actions/simulation/playback'
import PlayButtonComponent from '../../../components/app/timeline/PlayButtonComponent'
const mapStateToProps = state => {
diff --git a/frontend/src/containers/app/timeline/TimelineContainer.js b/frontend/src/containers/app/timeline/TimelineContainer.js
index 4fcaaaaf..9b196a1b 100644
--- a/frontend/src/containers/app/timeline/TimelineContainer.js
+++ b/frontend/src/containers/app/timeline/TimelineContainer.js
@@ -1,28 +1,14 @@
import { connect } from 'react-redux'
import { pauseSimulation } from '../../../actions/simulation/playback'
import { incrementTick } from '../../../actions/simulation/tick'
-import { setCurrentDatacenter } from '../../../actions/topology/building'
import TimelineComponent from '../../../components/app/timeline/TimelineComponent'
const mapStateToProps = state => {
- let sections = []
- if (state.currentExperimentId !== -1) {
- const sectionIds =
- state.objects.path[
- state.objects.experiment[state.currentExperimentId].pathId
- ].sectionIds
-
- if (sectionIds) {
- sections = sectionIds.map(sectionId => state.objects.section[sectionId])
- }
- }
-
return {
isPlaying: state.isPlaying,
currentTick: state.currentTick,
lastSimulatedTick: state.lastSimulatedTick,
- currentDatacenterId: state.currentDatacenterId,
- sections,
+ currentTopologyId: state.currentTopologyId,
}
}
@@ -30,7 +16,6 @@ const mapDispatchToProps = dispatch => {
return {
incrementTick: () => dispatch(incrementTick()),
pauseSimulation: () => dispatch(pauseSimulation()),
- setCurrentDatacenter: id => dispatch(setCurrentDatacenter(id)),
}
}
diff --git a/frontend/src/containers/app/timeline/TimelineControlsContainer.js b/frontend/src/containers/app/timeline/TimelineControlsContainer.js
index 92e03e6a..91aba98d 100644
--- a/frontend/src/containers/app/timeline/TimelineControlsContainer.js
+++ b/frontend/src/containers/app/timeline/TimelineControlsContainer.js
@@ -3,23 +3,9 @@ import { goToTick } from '../../../actions/simulation/tick'
import TimelineControlsComponent from '../../../components/app/timeline/TimelineControlsComponent'
const mapStateToProps = state => {
- let sectionTicks = []
- if (state.currentExperimentId !== -1) {
- const sectionIds =
- state.objects.path[
- state.objects.experiment[state.currentExperimentId].pathId
- ].sectionIds
- if (sectionIds) {
- sectionTicks = sectionIds
- .filter(sectionId => state.objects.section[sectionId].startTick !== 0)
- .map(sectionId => state.objects.section[sectionId].startTick)
- }
- }
-
return {
currentTick: state.currentTick,
lastSimulatedTick: state.lastSimulatedTick,
- sectionTicks,
}
}
diff --git a/frontend/src/containers/experiments/ExperimentRowContainer.js b/frontend/src/containers/experiments/ExperimentRowContainer.js
index bec32617..523c0747 100644
--- a/frontend/src/containers/experiments/ExperimentRowContainer.js
+++ b/frontend/src/containers/experiments/ExperimentRowContainer.js
@@ -9,7 +9,7 @@ const mapStateToProps = (state, ownProps) => {
)
experiment.trace = state.objects.trace[experiment.traceId]
experiment.scheduler = state.objects.scheduler[experiment.schedulerName]
- experiment.path = state.objects.path[experiment.pathId]
+ experiment.topology = state.objects.topology[experiment.topologyId]
return {
experiment,
diff --git a/frontend/src/containers/modals/ChangeTopologyModal.js b/frontend/src/containers/modals/ChangeTopologyModal.js
new file mode 100644
index 00000000..bd364194
--- /dev/null
+++ b/frontend/src/containers/modals/ChangeTopologyModal.js
@@ -0,0 +1,56 @@
+import { connect } from 'react-redux'
+import ChangeTopologyModalComponent from '../../components/modals/custom-components/ChangeTopologyModalComponent'
+import { closeChangeTopologyModal } from '../../actions/modals/topology'
+import { addTopology, deleteTopology } from '../../actions/topologies'
+
+const mapStateToProps = state => {
+ let topologies = state.objects.simulation[state.currentSimulationId] ? state.objects.simulation[state.currentSimulationId].topologyIds.map(t => (
+ state.objects.topology[t]
+ )) : []
+ if (topologies.filter(t => !t).length > 0) {
+ topologies = []
+ }
+
+ return {
+ show: state.modals.newExperimentModalVisible,
+ topologies,
+ }
+}
+
+const mapDispatchToProps = dispatch => {
+ return {
+ onCreateTopology: (name) => {
+ if (name) {
+ dispatch(
+ addTopology({name})
+ )
+ }
+ dispatch(closeChangeTopologyModal())
+ },
+ onDuplicateTopology: (name) => {
+ if (name) {
+ // TODO different handling here
+ dispatch(
+ addTopology({name})
+ )
+ }
+ dispatch(closeChangeTopologyModal())
+ },
+ onDeleteTopology: (id) => {
+ if (id) {
+ dispatch(
+ deleteTopology(id)
+ )
+ }
+ },
+ onCancel: () => {
+ dispatch(closeChangeTopologyModal())
+ },
+ }
+}
+
+const ChangeTopologyModal = connect(mapStateToProps, mapDispatchToProps)(
+ ChangeTopologyModalComponent,
+)
+
+export default ChangeTopologyModal
diff --git a/frontend/src/containers/modals/EditRackNameModal.js b/frontend/src/containers/modals/EditRackNameModal.js
index e5c87e35..495c107b 100644
--- a/frontend/src/containers/modals/EditRackNameModal.js
+++ b/frontend/src/containers/modals/EditRackNameModal.js
@@ -20,7 +20,7 @@ const mapStateToProps = state => {
previousName:
state.interactionLevel.mode === 'RACK'
? state.objects.rack[
- state.objects.tile[state.interactionLevel.tileId].objectId
+ state.objects.tile[state.interactionLevel.tileId].rackId
].name
: '',
}
diff --git a/frontend/src/containers/modals/NewExperimentModal.js b/frontend/src/containers/modals/NewExperimentModal.js
index db60f088..2ac5a4b8 100644
--- a/frontend/src/containers/modals/NewExperimentModal.js
+++ b/frontend/src/containers/modals/NewExperimentModal.js
@@ -6,9 +6,9 @@ import NewExperimentModalComponent from '../../components/modals/custom-componen
const mapStateToProps = state => {
return {
show: state.modals.newExperimentModalVisible,
- paths: Object.values(state.objects.path).filter(
- path => path.simulationId === state.currentSimulationId,
- ),
+ topologies: state.objects.simulation[state.currentSimulationId].topologyIds.map(t => (
+ state.objects.topology[t]
+ )),
traces: Object.values(state.objects.trace),
schedulers: Object.values(state.objects.scheduler),
}
@@ -16,12 +16,12 @@ const mapStateToProps = state => {
const mapDispatchToProps = dispatch => {
return {
- callback: (name, pathId, traceId, schedulerName) => {
+ callback: (name, topologyId, traceId, schedulerName) => {
if (name) {
dispatch(
addExperiment({
name,
- pathId,
+ topologyId,
traceId,
schedulerName,
}),
diff --git a/frontend/src/index.js b/frontend/src/index.js
index 940a8dd7..a81a4bc2 100644
--- a/frontend/src/index.js
+++ b/frontend/src/index.js
@@ -3,7 +3,6 @@ import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import { setupSocketConnection } from './api/socket'
import './index.css'
-import registerServiceWorker from './registerServiceWorker'
import Routes from './routes'
import configureStore from './store/configure-store'
@@ -16,6 +15,4 @@ setupSocketConnection(() => {
</Provider>,
document.getElementById('root'),
)
-
- registerServiceWorker()
})
diff --git a/frontend/src/pages/App.js b/frontend/src/pages/App.js
index c2b9bd51..3034f7ff 100644
--- a/frontend/src/pages/App.js
+++ b/frontend/src/pages/App.js
@@ -5,7 +5,7 @@ import { connect } from 'react-redux'
import { ShortcutManager } from 'react-shortcuts'
import { openExperimentSucceeded } from '../actions/experiments'
import { openSimulationSucceeded } from '../actions/simulations'
-import { resetCurrentDatacenter } from '../actions/topology/building'
+import { resetCurrentTopology } from '../actions/topology/building'
import ToolPanelComponent from '../components/app/map/controls/ToolPanelComponent'
import LoadingScreen from '../components/app/map/LoadingScreen'
import SimulationSidebarComponent from '../components/app/sidebars/simulation/SimulationSidebarComponent'
@@ -20,6 +20,8 @@ import DeleteRoomModal from '../containers/modals/DeleteRoomModal'
import EditRackNameModal from '../containers/modals/EditRackNameModal'
import EditRoomNameModal from '../containers/modals/EditRoomNameModal'
import KeymapConfiguration from '../shortcuts/keymap'
+import ChangeTopologyModal from '../containers/modals/ChangeTopologyModal'
+import { openChangeTopologyModal } from '../actions/modals/topology'
const shortcutManager = new ShortcutManager(KeymapConfiguration)
@@ -29,18 +31,16 @@ class AppComponent extends React.Component {
inSimulation: PropTypes.bool,
experimentId: PropTypes.number,
simulationName: PropTypes.string,
+ onViewTopologies: PropTypes.func,
}
static childContextTypes = {
shortcuts: PropTypes.object.isRequired,
}
componentDidMount() {
- this.props.resetCurrentDatacenter()
+ // TODO this.props.resetCurrentTopology()
if (this.props.inSimulation) {
- this.props.openExperimentSucceeded(
- this.props.simulationId,
- this.props.experimentId,
- )
+ this.props.openExperimentSucceeded(this.props.simulationId, this.props.experimentId)
return
}
this.props.openSimulationSucceeded(this.props.simulationId)
@@ -55,66 +55,58 @@ class AppComponent extends React.Component {
render() {
return (
<DocumentTitle
- title={
- this.props.simulationName
- ? this.props.simulationName + ' - OpenDC'
- : 'Simulation - OpenDC'
- }
+ title={this.props.simulationName ? this.props.simulationName + ' - OpenDC' : 'Simulation - OpenDC'}
>
<div className="page-container full-height">
<AppNavbar
simulationId={this.props.simulationId}
inSimulation={true}
fullWidth={true}
+ onViewTopologies={this.props.onViewTopologies}
/>
- {this.props.datacenterIsLoading ? (
+ {this.props.topologyIsLoading ? (
<div className="full-height d-flex align-items-center justify-content-center">
- <LoadingScreen/>
+ <LoadingScreen />
</div>
) : (
<div className="full-height">
- <MapStage/>
- <ScaleIndicatorContainer/>
- <ToolPanelComponent/>
- <TopologySidebar/>
- {this.props.inSimulation ? <TimelineContainer/> : undefined}
- {this.props.inSimulation ? (
- <SimulationSidebarComponent/>
- ) : (
- undefined
- )}
+ <MapStage />
+ <ScaleIndicatorContainer />
+ <ToolPanelComponent />
+ <TopologySidebar />
+ {this.props.inSimulation ? <TimelineContainer /> : undefined}
+ {this.props.inSimulation ? <SimulationSidebarComponent /> : undefined}
</div>
)}
- <EditRoomNameModal/>
- <DeleteRoomModal/>
- <EditRackNameModal/>
- <DeleteRackModal/>
- <DeleteMachineModal/>
+ <ChangeTopologyModal />
+ <EditRoomNameModal />
+ <DeleteRoomModal />
+ <EditRackNameModal />
+ <DeleteRackModal />
+ <DeleteMachineModal />
</div>
</DocumentTitle>
)
}
}
-const mapStateToProps = state => {
+const mapStateToProps = (state) => {
let simulationName = undefined
- if (
- state.currentSimulationId !== -1 &&
- state.objects.simulation[state.currentSimulationId]
- ) {
+ if (state.currentSimulationId !== -1 && state.objects.simulation[state.currentSimulationId]) {
simulationName = state.objects.simulation[state.currentSimulationId].name
}
return {
- datacenterIsLoading: state.currentDatacenterId === -1,
+ topologyIsLoading: state.currentTopologyId === -1,
simulationName,
}
}
-const mapDispatchToProps = dispatch => {
+const mapDispatchToProps = (dispatch) => {
return {
- resetCurrentDatacenter: () => dispatch(resetCurrentDatacenter()),
- openSimulationSucceeded: id => dispatch(openSimulationSucceeded(id)),
+ resetCurrentTopology: () => dispatch(resetCurrentTopology()),
+ openSimulationSucceeded: (id) => dispatch(openSimulationSucceeded(id)),
+ onViewTopologies: () => dispatch(openChangeTopologyModal()),
openExperimentSucceeded: (simulationId, experimentId) =>
dispatch(openExperimentSucceeded(simulationId, experimentId)),
}
diff --git a/frontend/src/pages/Experiments.js b/frontend/src/pages/Experiments.js
index 67e3fd77..97e63f44 100644
--- a/frontend/src/pages/Experiments.js
+++ b/frontend/src/pages/Experiments.js
@@ -30,28 +30,21 @@ class ExperimentsComponent extends React.Component {
}
>
<div className="full-height">
- <AppNavbar
- simulationId={this.props.simulationId}
- inSimulation={true}
- fullWidth={true}
- />
+ <AppNavbar simulationId={this.props.simulationId} inSimulation={true} fullWidth={true} />
<div className="container text-page-container full-height">
- <ExperimentListContainer/>
- <NewExperimentButtonContainer/>
+ <ExperimentListContainer />
+ <NewExperimentButtonContainer />
</div>
- <NewExperimentModal/>
+ <NewExperimentModal />
</div>
</DocumentTitle>
)
}
}
-const mapStateToProps = state => {
+const mapStateToProps = (state) => {
let simulationName = undefined
- if (
- state.currentSimulationId !== -1 &&
- state.objects.simulation[state.currentSimulationId]
- ) {
+ if (state.currentSimulationId !== -1 && state.objects.simulation[state.currentSimulationId]) {
simulationName = state.objects.simulation[state.currentSimulationId].name
}
@@ -60,16 +53,13 @@ const mapStateToProps = state => {
}
}
-const mapDispatchToProps = dispatch => {
+const mapDispatchToProps = (dispatch) => {
return {
- storeSimulationId: id => dispatch(openSimulationSucceeded(id)),
- fetchExperimentsOfSimulation: id =>
- dispatch(fetchExperimentsOfSimulation(id)),
+ storeSimulationId: (id) => dispatch(openSimulationSucceeded(id)),
+ fetchExperimentsOfSimulation: (id) => dispatch(fetchExperimentsOfSimulation(id)),
}
}
-const Experiments = connect(mapStateToProps, mapDispatchToProps)(
- ExperimentsComponent,
-)
+const Experiments = connect(mapStateToProps, mapDispatchToProps)(ExperimentsComponent)
export default Experiments
diff --git a/frontend/src/pages/Home.js b/frontend/src/pages/Home.js
index e69c2049..1bdfc5c7 100644
--- a/frontend/src/pages/Home.js
+++ b/frontend/src/pages/Home.js
@@ -21,7 +21,7 @@ class Home extends React.Component {
const scrollOffset = 60
jQuery('#navbar')
.find('li a')
- .click(function(e) {
+ .click(function (e) {
if (jQuery(e.target).parents('.auth-links').length > 0) {
return
}
@@ -42,17 +42,17 @@ class Home extends React.Component {
render() {
return (
<div>
- <HomeNavbar/>
+ <HomeNavbar />
<div className="body-wrapper page-container">
- <JumbotronHeader/>
- <IntroSection/>
- <StakeholderSection/>
- <ModelingSection/>
- <SimulationSection/>
- <TechnologiesSection/>
- <TeamSection/>
- <ContactSection/>
- <DocumentTitle title="OpenDC"/>
+ <JumbotronHeader />
+ <IntroSection />
+ <StakeholderSection />
+ <ModelingSection />
+ <SimulationSection />
+ <TechnologiesSection />
+ <TeamSection />
+ <ContactSection />
+ <DocumentTitle title="OpenDC" />
</div>
</div>
)
diff --git a/frontend/src/pages/NotFound.js b/frontend/src/pages/NotFound.js
index 959cceec..f72c7d01 100644
--- a/frontend/src/pages/NotFound.js
+++ b/frontend/src/pages/NotFound.js
@@ -6,7 +6,7 @@ import './NotFound.css'
const NotFound = () => (
<DocumentTitle title="Page Not Found - OpenDC">
<div className="not-found-backdrop">
- <TerminalWindow/>
+ <TerminalWindow />
</div>
</DocumentTitle>
)
diff --git a/frontend/src/pages/Profile.js b/frontend/src/pages/Profile.js
index e6d2aa7b..45b48247 100644
--- a/frontend/src/pages/Profile.js
+++ b/frontend/src/pages/Profile.js
@@ -8,28 +8,23 @@ import DeleteProfileModal from '../containers/modals/DeleteProfileModal'
const ProfileContainer = ({ onDelete }) => (
<DocumentTitle title="My Profile - OpenDC">
<div className="full-height">
- <AppNavbar inSimulation={false} fullWidth={false}/>
+ <AppNavbar inSimulation={false} fullWidth={false} />
<div className="container text-page-container full-height">
- <button
- className="btn btn-danger mb-2 ml-auto mr-auto"
- style={{ maxWidth: 300 }}
- onClick={onDelete}
- >
+ <button className="btn btn-danger mb-2 ml-auto mr-auto" style={{ maxWidth: 300 }} onClick={onDelete}>
Delete my account on OpenDC
</button>
<p className="text-muted text-center">
- This does not delete your Google account, but simply disconnects it
- from the OpenDC platform and deletes any simulation info that is
- associated with you (simulations you own and any authorizations you
- may have on other projects).
+ This does not delete your Google account, but simply disconnects it from the OpenDC platform and
+ deletes any simulation info that is associated with you (simulations you own and any authorizations
+ you may have on other projects).
</p>
</div>
- <DeleteProfileModal/>
+ <DeleteProfileModal />
</div>
</DocumentTitle>
)
-const mapDispatchToProps = dispatch => {
+const mapDispatchToProps = (dispatch) => {
return {
onDelete: () => dispatch(openDeleteProfileModal()),
}
diff --git a/frontend/src/pages/Simulations.js b/frontend/src/pages/Simulations.js
index 116eb1b2..ce2386fd 100644
--- a/frontend/src/pages/Simulations.js
+++ b/frontend/src/pages/Simulations.js
@@ -18,29 +18,26 @@ class SimulationsContainer extends React.Component {
return (
<DocumentTitle title="My Simulations - OpenDC">
<div className="full-height">
- <AppNavbar inSimulation={false} fullWidth={false}/>
+ <AppNavbar inSimulation={false} fullWidth={false} />
<div className="container text-page-container full-height">
- <SimulationFilterPanel/>
- <VisibleSimulationList/>
- <NewSimulationButtonContainer/>
+ <SimulationFilterPanel />
+ <VisibleSimulationList />
+ <NewSimulationButtonContainer />
</div>
- <NewSimulationModal/>
+ <NewSimulationModal />
</div>
</DocumentTitle>
)
}
}
-const mapDispatchToProps = dispatch => {
+const mapDispatchToProps = (dispatch) => {
return {
- fetchAuthorizationsOfCurrentUser: () =>
- dispatch(fetchAuthorizationsOfCurrentUser()),
+ fetchAuthorizationsOfCurrentUser: () => dispatch(fetchAuthorizationsOfCurrentUser()),
openNewSimulationModal: () => dispatch(openNewSimulationModal()),
}
}
-const Simulations = connect(undefined, mapDispatchToProps)(
- SimulationsContainer,
-)
+const Simulations = connect(undefined, mapDispatchToProps)(SimulationsContainer)
export default Simulations
diff --git a/frontend/src/reducers/current-ids.js b/frontend/src/reducers/current-ids.js
index 6a605d9f..76ae67c7 100644
--- a/frontend/src/reducers/current-ids.js
+++ b/frontend/src/reducers/current-ids.js
@@ -1,12 +1,12 @@
import { OPEN_EXPERIMENT_SUCCEEDED } from '../actions/experiments'
import { OPEN_SIMULATION_SUCCEEDED } from '../actions/simulations'
-import { RESET_CURRENT_DATACENTER, SET_CURRENT_DATACENTER } from '../actions/topology/building'
+import { RESET_CURRENT_TOPOLOGY, SET_CURRENT_TOPOLOGY } from '../actions/topology/building'
-export function currentDatacenterId(state = -1, action) {
+export function currentTopologyId(state = -1, action) {
switch (action.type) {
- case SET_CURRENT_DATACENTER:
- return action.datacenterId
- case RESET_CURRENT_DATACENTER:
+ case SET_CURRENT_TOPOLOGY:
+ return action.topologyId
+ case RESET_CURRENT_TOPOLOGY:
return -1
default:
return state
diff --git a/frontend/src/reducers/index.js b/frontend/src/reducers/index.js
index a5b14f4a..1c3ee145 100644
--- a/frontend/src/reducers/index.js
+++ b/frontend/src/reducers/index.js
@@ -1,7 +1,7 @@
import { combineReducers } from 'redux'
import { auth } from './auth'
import { construction } from './construction-mode'
-import { currentDatacenterId, currentSimulationId } from './current-ids'
+import { currentTopologyId, currentSimulationId } from './current-ids'
import { interactionLevel } from './interaction-level'
import { map } from './map'
import { modals } from './modals'
@@ -18,7 +18,7 @@ const rootReducer = combineReducers({
construction,
map,
currentSimulationId,
- currentDatacenterId,
+ currentTopologyId,
currentExperimentId,
currentTick,
lastSimulatedTick,
diff --git a/frontend/src/reducers/interaction-level.js b/frontend/src/reducers/interaction-level.js
index 12d5d70e..88c3b30e 100644
--- a/frontend/src/reducers/interaction-level.js
+++ b/frontend/src/reducers/interaction-level.js
@@ -6,13 +6,13 @@ import {
GO_FROM_ROOM_TO_RACK,
} from '../actions/interaction-level'
import { OPEN_SIMULATION_SUCCEEDED } from '../actions/simulations'
-import { SET_CURRENT_DATACENTER } from '../actions/topology/building'
+import { SET_CURRENT_TOPOLOGY } from '../actions/topology/building'
export function interactionLevel(state = { mode: 'BUILDING' }, action) {
switch (action.type) {
case OPEN_EXPERIMENT_SUCCEEDED:
case OPEN_SIMULATION_SUCCEEDED:
- case SET_CURRENT_DATACENTER:
+ case SET_CURRENT_TOPOLOGY:
return {
mode: 'BUILDING',
}
diff --git a/frontend/src/reducers/modals.js b/frontend/src/reducers/modals.js
index 04e9ab49..81a0660e 100644
--- a/frontend/src/reducers/modals.js
+++ b/frontend/src/reducers/modals.js
@@ -4,11 +4,13 @@ import { CLOSE_NEW_EXPERIMENT_MODAL, OPEN_NEW_EXPERIMENT_MODAL } from '../action
import { CLOSE_DELETE_PROFILE_MODAL, OPEN_DELETE_PROFILE_MODAL } from '../actions/modals/profile'
import { CLOSE_NEW_SIMULATION_MODAL, OPEN_NEW_SIMULATION_MODAL } from '../actions/modals/simulations'
import {
+ CLOSE_CHANGE_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_CHANGE_TOPOLOGY_MODAL,
OPEN_DELETE_MACHINE_MODAL,
OPEN_DELETE_RACK_MODAL,
OPEN_DELETE_ROOM_MODAL,
@@ -17,7 +19,7 @@ import {
} from '../actions/modals/topology'
function modal(openAction, closeAction) {
- return function(state = false, action) {
+ return function (state = false, action) {
switch (action.type) {
case openAction:
return true
@@ -31,36 +33,13 @@ function modal(openAction, closeAction) {
}
export const modals = combineReducers({
- newSimulationModalVisible: modal(
- OPEN_NEW_SIMULATION_MODAL,
- CLOSE_NEW_SIMULATION_MODAL,
- ),
- deleteProfileModalVisible: modal(
- OPEN_DELETE_PROFILE_MODAL,
- CLOSE_DELETE_PROFILE_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,
- ),
- newExperimentModalVisible: modal(
- OPEN_NEW_EXPERIMENT_MODAL,
- CLOSE_NEW_EXPERIMENT_MODAL,
- ),
+ newSimulationModalVisible: modal(OPEN_NEW_SIMULATION_MODAL, CLOSE_NEW_SIMULATION_MODAL),
+ deleteProfileModalVisible: modal(OPEN_DELETE_PROFILE_MODAL, CLOSE_DELETE_PROFILE_MODAL),
+ changeTopologyModalVisible: modal(OPEN_CHANGE_TOPOLOGY_MODAL, CLOSE_CHANGE_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),
+ newExperimentModalVisible: modal(OPEN_NEW_EXPERIMENT_MODAL, CLOSE_NEW_EXPERIMENT_MODAL),
})
diff --git a/frontend/src/reducers/objects.js b/frontend/src/reducers/objects.js
index 1dc1e7e8..f52ca369 100644
--- a/frontend/src/reducers/objects.js
+++ b/frontend/src/reducers/objects.js
@@ -5,41 +5,32 @@ import {
ADD_TO_STORE,
REMOVE_ID_FROM_STORE_OBJECT_LIST_PROP,
} from '../actions/objects'
+import { CPU_UNITS, GPU_UNITS, MEMORY_UNITS, STORAGE_UNITS } from '../util/unit-specifications'
export const objects = combineReducers({
simulation: object('simulation'),
user: object('user'),
- authorization: objectWithId('authorization', object => [
- object.userId,
- object.simulationId,
- ]),
- failureModel: object('failureModel'),
- cpu: object('cpu'),
- gpu: object('gpu'),
- memory: object('memory'),
- storage: object('storage'),
+ authorization: objectWithId('authorization', (object) => [object.userId, object.simulationId]),
+ cpu: object('cpu', CPU_UNITS),
+ gpu: object('gpu', GPU_UNITS),
+ memory: object('memory', MEMORY_UNITS),
+ storage: object('storage', STORAGE_UNITS),
machine: object('machine'),
rack: object('rack'),
- coolingItem: object('coolingItem'),
- psu: object('psu'),
tile: object('tile'),
room: object('room'),
- datacenter: object('datacenter'),
- section: object('section'),
- path: object('path'),
- task: object('task'),
- job: object('job'),
+ topology: object('topology'),
trace: object('trace'),
scheduler: object('scheduler'),
experiment: object('experiment'),
})
-function object(type) {
- return objectWithId(type, object => object._id)
+function object(type, defaultState = {}) {
+ return objectWithId(type, (object) => object._id, defaultState)
}
-function objectWithId(type, getId) {
- return (state = {}, action) => {
+function objectWithId(type, getId, defaultState = {}) {
+ return (state = defaultState, action) => {
if (action.objectType !== type) {
return state
}
@@ -50,27 +41,18 @@ function objectWithId(type, getId) {
})
} else if (action.type === ADD_PROP_TO_STORE_OBJECT) {
return Object.assign({}, state, {
- [action.objectId]: Object.assign(
- {},
- state[action.objectId],
- action.propObject,
- ),
+ [action.objectId]: Object.assign({}, state[action.objectId], action.propObject),
})
} else if (action.type === ADD_ID_TO_STORE_OBJECT_LIST_PROP) {
return Object.assign({}, state, {
[action.objectId]: Object.assign({}, state[action.objectId], {
- [action.propName]: [
- ...state[action.objectId][action.propName],
- action.id,
- ],
+ [action.propName]: [...state[action.objectId][action.propName], action.id],
}),
})
} else if (action.type === REMOVE_ID_FROM_STORE_OBJECT_LIST_PROP) {
return Object.assign({}, state, {
[action.objectId]: Object.assign({}, state[action.objectId], {
- [action.propName]: state[action.objectId][action.propName].filter(
- id => id !== action.id,
- ),
+ [action.propName]: state[action.objectId][action.propName].filter((id) => id !== action.id),
}),
})
}
diff --git a/frontend/src/reducers/simulation-list.js b/frontend/src/reducers/simulation-list.js
index 78f3c4fe..383f4b35 100644
--- a/frontend/src/reducers/simulation-list.js
+++ b/frontend/src/reducers/simulation-list.js
@@ -13,7 +13,7 @@ export function authorizationsOfCurrentUser(state = [], action) {
case ADD_SIMULATION_SUCCEEDED:
return [...state, action.authorization]
case DELETE_SIMULATION_SUCCEEDED:
- return state.filter(authorization => authorization[1] !== action.id)
+ return state.filter((authorization) => authorization[1] !== action.id)
default:
return state
}
diff --git a/frontend/src/reducers/states.js b/frontend/src/reducers/states.js
index e4c2fd19..c9bb4158 100644
--- a/frontend/src/reducers/states.js
+++ b/frontend/src/reducers/states.js
@@ -2,7 +2,6 @@ import { combineReducers } from 'redux'
import { ADD_BATCH_TO_STATES } from '../actions/states'
export const states = combineReducers({
- task: objectStates('task'),
room: objectStates('room'),
rack: objectStates('rack'),
machine: objectStates('machine'),
@@ -21,7 +20,7 @@ function objectStates(type) {
{},
state[action.objects[i].tick],
batch[action.objects[i].tick],
- { [action.objects[i][action.objectType + 'Id']]: action.objects[i] },
+ { [action.objects[i][action.objectType + 'Id']]: action.objects[i] }
)
}
diff --git a/frontend/src/registerServiceWorker.js b/frontend/src/registerServiceWorker.js
deleted file mode 100644
index 32a116a6..00000000
--- a/frontend/src/registerServiceWorker.js
+++ /dev/null
@@ -1,108 +0,0 @@
-// In production, we register a service worker to serve assets from local cache.
-
-// This lets the app load faster on subsequent visits in production, and gives
-// it offline capabilities. However, it also means that developers (and users)
-// will only see deployed updates on the "N+1" visit to a page, since previously
-// cached resources are updated in the background.
-
-// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
-// This link also includes instructions on opting out of this behavior.
-
-const isLocalhost = Boolean(
- window.location.hostname === 'localhost' ||
- // [::1] is the IPv6 localhost address.
- window.location.hostname === '[::1]' ||
- // 127.0.0.1/8 is considered localhost for IPv4.
- window.location.hostname.match(
- /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/,
- ),
-)
-
-export default function register() {
- if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
- // The URL constructor is available in all browsers that support SW.
- const publicUrl = new URL(process.env.PUBLIC_URL, window.location)
- if (publicUrl.origin !== window.location.origin) {
- // Our service worker won't work if PUBLIC_URL is on a different origin
- // from what our page is served on. This might happen if a CDN is used to
- // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
- return
- }
-
- window.addEventListener('load', () => {
- const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
-
- if (!isLocalhost) {
- // Is not local host. Just register service worker
- registerValidSW(swUrl)
- } else {
- // This is running on localhost. Lets check if a service worker still exists or not.
- checkValidServiceWorker(swUrl)
- }
- })
- }
-}
-
-function registerValidSW(swUrl) {
- navigator.serviceWorker
- .register(swUrl)
- .then(registration => {
- registration.onupdatefound = () => {
- const installingWorker = registration.installing
- installingWorker.onstatechange = () => {
- if (installingWorker.state === 'installed') {
- if (navigator.serviceWorker.controller) {
- // At this point, the old content will have been purged and
- // the fresh content will have been added to the cache.
- // It's the perfect time to display a "New content is
- // available; please refresh." message in your web app.
- console.log('New content is available; please refresh.')
- } else {
- // At this point, everything has been precached.
- // It's the perfect time to display a
- // "Content is cached for offline use." message.
- console.log('Content is cached for offline use.')
- }
- }
- }
- }
- })
- .catch(error => {
- console.error('Error during service worker registration:', error)
- })
-}
-
-function checkValidServiceWorker(swUrl) {
- // Check if the service worker can be found. If it can't reload the page.
- fetch(swUrl)
- .then(response => {
- // Ensure service worker exists, and that we really are getting a JS file.
- if (
- response.status === 404 ||
- response.headers.get('content-type').indexOf('javascript') === -1
- ) {
- // No service worker found. Probably a different app. Reload the page.
- navigator.serviceWorker.ready.then(registration => {
- registration.unregister().then(() => {
- window.location.reload()
- })
- })
- } else {
- // Service worker found. Proceed as normal.
- registerValidSW(swUrl)
- }
- })
- .catch(() => {
- console.log(
- 'No internet connection found. App is running in offline mode.',
- )
- })
-}
-
-export function unregister() {
- if ('serviceWorker' in navigator) {
- navigator.serviceWorker.ready.then(registration => {
- registration.unregister()
- })
- }
-}
diff --git a/frontend/src/routes/index.js b/frontend/src/routes/index.js
index 119cdb54..ea703567 100644
--- a/frontend/src/routes/index.js
+++ b/frontend/src/routes/index.js
@@ -8,55 +8,30 @@ import NotFound from '../pages/NotFound'
import Profile from '../pages/Profile'
import Simulations from '../pages/Simulations'
-const ProtectedComponent = component => () =>
- userIsLoggedIn() ? component : <Redirect to="/"/>
+const ProtectedComponent = (component) => () => (userIsLoggedIn() ? component : <Redirect to="/" />)
const AppComponent = ({ match }) =>
- userIsLoggedIn() ? (
- <App simulationId={parseInt(match.params.simulationId, 10)}/>
- ) : (
- <Redirect to="/"/>
- )
+ userIsLoggedIn() ? <App simulationId={match.params.simulationId} /> : <Redirect to="/" />
const ExperimentsComponent = ({ match }) =>
- userIsLoggedIn() ? (
- <Experiments simulationId={parseInt(match.params.simulationId, 10)}/>
- ) : (
- <Redirect to="/"/>
- )
+ userIsLoggedIn() ? <Experiments simulationId={match.params.simulationId} /> : <Redirect to="/" />
const SimulationComponent = ({ match }) =>
userIsLoggedIn() ? (
- <App
- simulationId={parseInt(match.params.simulationId, 10)}
- inSimulation={true}
- experimentId={parseInt(match.params.experimentId, 10)}
- />
+ <App simulationId={match.params.simulationId} inSimulation={true} experimentId={match.params.experimentId} />
) : (
- <Redirect to="/"/>
+ <Redirect to="/" />
)
const Routes = () => (
<BrowserRouter>
<Switch>
- <Route exact path="/" component={Home}/>
- <Route
- exact
- path="/simulations"
- render={ProtectedComponent(<Simulations/>)}
- />
- <Route exact path="/simulations/:simulationId" component={AppComponent}/>
- <Route
- exact
- path="/simulations/:simulationId/experiments"
- component={ExperimentsComponent}
- />
- <Route
- exact
- path="/simulations/:simulationId/experiments/:experimentId"
- component={SimulationComponent}
- />
- <Route exact path="/profile" render={ProtectedComponent(<Profile/>)}/>
- <Route path="/*" component={NotFound}/>
+ <Route exact path="/" component={Home} />
+ <Route exact path="/simulations" render={ProtectedComponent(<Simulations />)} />
+ <Route exact path="/simulations/:simulationId" component={AppComponent} />
+ <Route exact path="/simulations/:simulationId/experiments" component={ExperimentsComponent} />
+ <Route exact path="/simulations/:simulationId/experiments/:experimentId" component={SimulationComponent} />
+ <Route exact path="/profile" render={ProtectedComponent(<Profile />)} />
+ <Route path="/*" component={NotFound} />
</Switch>
</BrowserRouter>
)
diff --git a/frontend/src/sagas/experiments.js b/frontend/src/sagas/experiments.js
index a361759b..b9106fdc 100644
--- a/frontend/src/sagas/experiments.js
+++ b/frontend/src/sagas/experiments.js
@@ -7,15 +7,11 @@ import {
getAllMachineStates,
getAllRackStates,
getAllRoomStates,
- getAllTaskStates,
getExperiment,
- getLastSimulatedTick,
} from '../api/routes/experiments'
-import { getTasksOfJob } from '../api/routes/jobs'
-import { addExperiment, getExperimentsOfSimulation, getSimulation } from '../api/routes/simulations'
-import { getJobsOfTrace } from '../api/routes/traces'
-import { fetchAndStoreAllSchedulers, fetchAndStoreAllTraces, fetchAndStorePathsOfSimulation } from './objects'
-import { fetchAllDatacentersOfExperiment } from './topology'
+import { addExperiment, getSimulation } from '../api/routes/simulations'
+import { fetchAndStoreAllSchedulers, fetchAndStoreAllTraces } from './objects'
+import { fetchAndStoreAllTopologiesOfSimulation, fetchTopologyOfExperiment } from './topology'
export function* onOpenExperimentSucceeded(action) {
try {
@@ -26,9 +22,8 @@ export function* onOpenExperimentSucceeded(action) {
yield put(addToStore('experiment', experiment))
yield fetchExperimentSpecifications()
- yield fetchWorkloadOfTrace(experiment.traceId)
- yield fetchAllDatacentersOfExperiment(experiment)
+ yield fetchTopologyOfExperiment(experiment)
yield startStateFetchLoop(action.experimentId)
} catch (error) {
console.error(error)
@@ -37,20 +32,15 @@ export function* onOpenExperimentSucceeded(action) {
function* startStateFetchLoop(experimentId) {
try {
- while ((yield select(state => state.currentExperimentId)) !== -1) {
- const lastSimulatedTick = (yield call(getLastSimulatedTick, experimentId))
- .lastSimulatedTick
- if (
- lastSimulatedTick !== (yield select(state => state.lastSimulatedTick))
- ) {
+ while ((yield select((state) => state.currentExperimentId)) !== -1) {
+ const lastSimulatedTick = (yield call(getExperiment, experimentId)).lastSimulatedTick
+ if (lastSimulatedTick !== (yield select((state) => state.lastSimulatedTick))) {
yield put(setLastSimulatedTick(lastSimulatedTick))
- const taskStates = yield call(getAllTaskStates, experimentId)
const machineStates = yield call(getAllMachineStates, experimentId)
const rackStates = yield call(getAllRackStates, experimentId)
const roomStates = yield call(getAllRoomStates, experimentId)
- yield put(addBatchToStates('task', taskStates))
yield put(addBatchToStates('machine', machineStates))
yield put(addBatchToStates('rack', rackStates))
yield put(addBatchToStates('room', roomStates))
@@ -67,23 +57,15 @@ function* startStateFetchLoop(experimentId) {
export function* onFetchExperimentsOfSimulation() {
try {
- const currentSimulationId = yield select(
- state => state.currentSimulationId,
- )
+ const currentSimulationId = yield select((state) => state.currentSimulationId)
+ const currentSimulation = yield select((state) => state.object.simulation[currentSimulationId])
yield fetchExperimentSpecifications()
- const experiments = yield call(
- getExperimentsOfSimulation,
- currentSimulationId,
- )
- for (let i in experiments) {
- yield put(addToStore('experiment', experiments[i]))
+
+ for (let i in currentSimulation.experimentIds) {
+ const experiment = yield call(getExperiment, currentSimulation.experimentIds[i])
+ yield put(addToStore('experiment', experiment))
}
- yield put(
- addPropToStoreObject('simulation', currentSimulationId, {
- experimentIds: experiments.map(experiment => experiment.id),
- }),
- )
} catch (error) {
console.error(error)
}
@@ -91,10 +73,8 @@ export function* onFetchExperimentsOfSimulation() {
function* fetchExperimentSpecifications() {
try {
- const currentSimulationId = yield select(
- state => state.currentSimulationId,
- )
- yield fetchAndStorePathsOfSimulation(currentSimulationId)
+ const currentSimulationId = yield select((state) => state.currentSimulationId)
+ yield fetchAndStoreAllTopologiesOfSimulation(currentSimulationId)
yield fetchAndStoreAllTraces()
yield fetchAndStoreAllSchedulers()
} catch (error) {
@@ -102,33 +82,9 @@ function* fetchExperimentSpecifications() {
}
}
-function* fetchWorkloadOfTrace(traceId) {
- try {
- const jobs = yield call(getJobsOfTrace, traceId)
- for (let i in jobs) {
- const job = jobs[i]
- const tasks = yield call(getTasksOfJob, job.id)
- job.taskIds = tasks.map(task => task.id)
- for (let j in tasks) {
- yield put(addToStore('task', tasks[j]))
- }
- yield put(addToStore('job', job))
- }
- yield put(
- addPropToStoreObject('trace', traceId, {
- jobIds: jobs.map(job => job.id),
- }),
- )
- } catch (error) {
- console.error(error)
- }
-}
-
export function* onAddExperiment(action) {
try {
- const currentSimulationId = yield select(
- state => state.currentSimulationId,
- )
+ const currentSimulationId = yield select((state) => state.currentSimulationId)
const experiment = yield call(
addExperiment,
@@ -136,17 +92,15 @@ export function* onAddExperiment(action) {
Object.assign({}, action.experiment, {
id: -1,
simulationId: currentSimulationId,
- }),
+ })
)
yield put(addToStore('experiment', experiment))
- const experimentIds = yield select(
- state => state.objects.simulation[currentSimulationId].experimentIds,
- )
+ const experimentIds = yield select((state) => state.objects.simulation[currentSimulationId].experimentIds)
yield put(
addPropToStoreObject('simulation', currentSimulationId, {
- experimentIds: experimentIds.concat([experiment.id]),
- }),
+ experimentIds: experimentIds.concat([experiment._id]),
+ })
)
} catch (error) {
console.error(error)
@@ -157,17 +111,13 @@ export function* onDeleteExperiment(action) {
try {
yield call(deleteExperiment, action.id)
- const currentSimulationId = yield select(
- state => state.currentSimulationId,
- )
- const experimentIds = yield select(
- state => state.objects.simulation[currentSimulationId].experimentIds,
- )
+ const currentSimulationId = yield select((state) => state.currentSimulationId)
+ const experimentIds = yield select((state) => state.objects.simulation[currentSimulationId].experimentIds)
yield put(
addPropToStoreObject('simulation', currentSimulationId, {
- experimentIds: experimentIds.filter(id => id !== action.id),
- }),
+ experimentIds: experimentIds.filter((id) => id !== action.id),
+ })
)
} catch (error) {
console.error(error)
diff --git a/frontend/src/sagas/index.js b/frontend/src/sagas/index.js
index d1de906f..0947befc 100644
--- a/frontend/src/sagas/index.js
+++ b/frontend/src/sagas/index.js
@@ -29,26 +29,26 @@ import {
onAddMachine,
onAddRackToTile,
onAddTile,
+ onAddTopology,
onAddUnit,
onCancelNewRoomConstruction,
onDeleteMachine,
onDeleteRack,
onDeleteRoom,
onDeleteTile,
+ onDeleteTopology,
onDeleteUnit,
onEditRackName,
onEditRoomName,
onStartNewRoomConstruction,
} from './topology'
import { onFetchAuthorizationsOfCurrentUser, onFetchLoggedInUser } from './users'
+import { ADD_TOPOLOGY, DELETE_TOPOLOGY } from '../actions/topologies'
export default function* rootSaga() {
yield takeEvery(LOG_IN, onFetchLoggedInUser)
- yield takeEvery(
- FETCH_AUTHORIZATIONS_OF_CURRENT_USER,
- onFetchAuthorizationsOfCurrentUser,
- )
+ yield takeEvery(FETCH_AUTHORIZATIONS_OF_CURRENT_USER, onFetchAuthorizationsOfCurrentUser)
yield takeEvery(ADD_SIMULATION, onSimulationAdd)
yield takeEvery(DELETE_SIMULATION, onSimulationDelete)
@@ -57,6 +57,8 @@ export default function* rootSaga() {
yield takeEvery(OPEN_SIMULATION_SUCCEEDED, onOpenSimulationSucceeded)
yield takeEvery(OPEN_EXPERIMENT_SUCCEEDED, onOpenExperimentSucceeded)
+ yield takeEvery(ADD_TOPOLOGY, onAddTopology)
+ yield takeEvery(DELETE_TOPOLOGY, onDeleteTopology)
yield takeEvery(START_NEW_ROOM_CONSTRUCTION, onStartNewRoomConstruction)
yield takeEvery(CANCEL_NEW_ROOM_CONSTRUCTION, onCancelNewRoomConstruction)
yield takeEvery(ADD_TILE, onAddTile)
@@ -71,10 +73,7 @@ export default function* rootSaga() {
yield takeEvery(ADD_UNIT, onAddUnit)
yield takeEvery(DELETE_UNIT, onDeleteUnit)
- yield takeEvery(
- FETCH_EXPERIMENTS_OF_SIMULATION,
- onFetchExperimentsOfSimulation,
- )
+ yield takeEvery(FETCH_EXPERIMENTS_OF_SIMULATION, onFetchExperimentsOfSimulation)
yield takeEvery(ADD_EXPERIMENT, onAddExperiment)
yield takeEvery(DELETE_EXPERIMENT, onDeleteExperiment)
}
diff --git a/frontend/src/sagas/objects.js b/frontend/src/sagas/objects.js
index faa75be2..174f9c3e 100644
--- a/frontend/src/sagas/objects.js
+++ b/frontend/src/sagas/objects.js
@@ -1,46 +1,25 @@
import { call, put, select } from 'redux-saga/effects'
import { addToStore } from '../actions/objects'
-import { getDatacenter, getRoomsOfDatacenter } from '../api/routes/datacenters'
-import { getPath, getSectionsOfPath } from '../api/routes/paths'
-import { getTilesOfRoom } from '../api/routes/rooms'
import { getAllSchedulers } from '../api/routes/schedulers'
-import { getSection } from '../api/routes/sections'
-import { getPathsOfSimulation, getSimulation } from '../api/routes/simulations'
-import {
- getAllCPUs,
- getAllGPUs,
- getAllMemories,
- getAllStorages,
- getCoolingItem,
- getCPU,
- getFailureModel,
- getGPU,
- getMemory,
- getPSU,
- getStorage,
-} from '../api/routes/specifications'
-import { getMachinesOfRackByTile, getRackByTile } from '../api/routes/tiles'
+import { getSimulation } from '../api/routes/simulations'
import { getAllTraces } from '../api/routes/traces'
import { getUser } from '../api/routes/users'
+import { getTopology, updateTopology } from '../api/routes/topologies'
+import { uuid } from 'uuidv4'
export const OBJECT_SELECTORS = {
- simulation: state => state.objects.simulation,
- user: state => state.objects.user,
- authorization: state => state.objects.authorization,
- failureModel: state => state.objects.failureModel,
- cpu: state => state.objects.cpu,
- gpu: state => state.objects.gpu,
- memory: state => state.objects.memory,
- storage: state => state.objects.storage,
- machine: state => state.objects.machine,
- rack: state => state.objects.rack,
- coolingItem: state => state.objects.coolingItem,
- psu: state => state.objects.psu,
- tile: state => state.objects.tile,
- room: state => state.objects.room,
- datacenter: state => state.objects.datacenter,
- section: state => state.objects.section,
- path: state => state.objects.path,
+ simulation: (state) => state.objects.simulation,
+ user: (state) => state.objects.user,
+ authorization: (state) => state.objects.authorization,
+ cpu: (state) => state.objects.cpu,
+ gpu: (state) => state.objects.gpu,
+ memory: (state) => state.objects.memory,
+ storage: (state) => state.objects.storage,
+ machine: (state) => state.objects.machine,
+ rack: (state) => state.objects.rack,
+ tile: (state) => state.objects.tile,
+ room: (state) => state.objects.room,
+ topology: (state) => state.objects.topology,
}
function* fetchAndStoreObject(objectType, id, apiCall) {
@@ -61,79 +40,151 @@ function* fetchAndStoreObjects(objectType, apiCall) {
return objects
}
-export const fetchAndStoreSimulation = id =>
- fetchAndStoreObject('simulation', id, call(getSimulation, id))
-
-export const fetchAndStoreUser = id =>
- fetchAndStoreObject('user', id, call(getUser, id))
-
-export const fetchAndStoreFailureModel = id =>
- fetchAndStoreObject('failureModel', id, call(getFailureModel, id))
-
-export const fetchAndStoreAllCPUs = () =>
- fetchAndStoreObjects('cpu', call(getAllCPUs))
-
-export const fetchAndStoreCPU = id =>
- fetchAndStoreObject('cpu', id, call(getCPU, id))
-
-export const fetchAndStoreAllGPUs = () =>
- fetchAndStoreObjects('gpu', call(getAllGPUs))
-
-export const fetchAndStoreGPU = id =>
- fetchAndStoreObject('gpu', id, call(getGPU, id))
-
-export const fetchAndStoreAllMemories = () =>
- fetchAndStoreObjects('memory', call(getAllMemories))
-
-export const fetchAndStoreMemory = id =>
- fetchAndStoreObject('memory', id, call(getMemory, id))
-
-export const fetchAndStoreAllStorages = () =>
- fetchAndStoreObjects('storage', call(getAllStorages))
-
-export const fetchAndStoreStorage = id =>
- fetchAndStoreObject('storage', id, call(getStorage, id))
-
-export const fetchAndStoreMachinesOfTile = tileId =>
- fetchAndStoreObjects('machine', call(getMachinesOfRackByTile, tileId))
-
-export const fetchAndStoreRackOnTile = (id, tileId) =>
- fetchAndStoreObject('rack', id, call(getRackByTile, tileId))
-
-export const fetchAndStoreCoolingItem = id =>
- fetchAndStoreObject('coolingItem', id, call(getCoolingItem, id))
-
-export const fetchAndStorePSU = id =>
- fetchAndStoreObject('psu', id, call(getPSU, id))
-
-export const fetchAndStoreTilesOfRoom = roomId =>
- fetchAndStoreObjects('tile', call(getTilesOfRoom, roomId))
-
-export const fetchAndStoreRoomsOfDatacenter = datacenterId =>
- fetchAndStoreObjects('room', call(getRoomsOfDatacenter, datacenterId))
-
-export const fetchAndStoreDatacenter = id =>
- fetchAndStoreObject('datacenter', id, call(getDatacenter, id))
+export const fetchAndStoreSimulation = (id) => fetchAndStoreObject('simulation', id, call(getSimulation, id))
+
+export const fetchAndStoreUser = (id) => fetchAndStoreObject('user', id, call(getUser, id))
+
+export const fetchAndStoreTopology = function* (id) {
+ const topologyStore = yield select(OBJECT_SELECTORS['topology'])
+ const roomStore = yield select(OBJECT_SELECTORS['room'])
+ const tileStore = yield select(OBJECT_SELECTORS['tile'])
+ const rackStore = yield select(OBJECT_SELECTORS['rack'])
+ const machineStore = yield select(OBJECT_SELECTORS['machine'])
+
+ let topology = topologyStore[id]
+ if (!topology) {
+ const fullTopology = yield call(getTopology, id)
+
+ for (let roomIdx in fullTopology.rooms) {
+ const fullRoom = fullTopology.rooms[roomIdx]
+
+ generateIdIfNotPresent(fullRoom)
+
+ if (!roomStore[fullRoom._id]) {
+ for (let tileIdx in fullRoom.tiles) {
+ const fullTile = fullRoom.tiles[tileIdx]
+
+ generateIdIfNotPresent(fullTile)
+
+ if (!tileStore[fullTile._id]) {
+ if (fullTile.rack) {
+ const fullRack = fullTile.rack
+
+ generateIdIfNotPresent(fullTile)
+
+ if (!rackStore[fullRack._id]) {
+ for (let machineIdx in fullRack.machines) {
+ const fullMachine = fullRoom.machines[machineIdx]
+
+ generateIdIfNotPresent(fullMachine)
+
+ if (!machineStore[fullMachine._id]) {
+ let machine = (({ _id, position, cpuIds, gpuIds, memoryIds, storageIds }) => ({
+ _id,
+ rackId: fullRack._id,
+ position,
+ cpuIds,
+ gpuIds,
+ memoryIds,
+ storageIds,
+ }))(fullMachine)
+ yield put(addToStore('machine', machine))
+ }
+ }
+
+ const filledSlots = new Array(fullRack.capacity).fill(null)
+ fullRack.machines.forEach(
+ (machine) => (filledSlots[machine.position - 1] = machine._id)
+ )
+ let rack = (({ _id, capacity, powerCapacityW }) => ({
+ _id,
+ capacity,
+ powerCapacityW,
+ machineIds: filledSlots,
+ }))(fullRack)
+ yield put(addToStore('rack', rack))
+ }
+ }
+
+ let tile = (({ _id, positionX, positionY, rack }) => ({
+ _id,
+ roomId: fullRoom._id,
+ positionX,
+ positionY,
+ rackId: rack ? rack._id : undefined,
+ }))(fullTile)
+ yield put(addToStore('tile', tile))
+ }
+ }
+
+ let room = (({ _id, name, tiles }) => ({ _id, name, tileIds: tiles.map((t) => t._id) }))(fullRoom)
+ yield put(addToStore('room', room))
+ }
+ }
+
+ topology = (({ _id, name, rooms }) => ({ _id, name, roomIds: rooms.map((r) => r._id) }))(fullTopology)
+ yield put(addToStore('topology', topology))
+
+ console.log('Full topology after insertion', fullTopology)
+ // TODO consider pushing the IDs
+ }
-export const fetchAndStoreSection = id =>
- fetchAndStoreObject('section', id, call(getSection, id))
+ return topology
+}
-export const fetchAndStoreSectionsOfPath = pathId =>
- fetchAndStoreObjects('section', call(getSectionsOfPath, pathId))
+const generateIdIfNotPresent = (obj) => {
+ if (!obj._id) {
+ obj._id = uuid()
+ }
+}
-export const fetchAndStorePath = id =>
- fetchAndStoreObject('path', id, call(getPath, id))
+export const updateTopologyOnServer = function* (id) {
+ const topologyStore = yield select(OBJECT_SELECTORS['topology'])
+ const roomStore = yield select(OBJECT_SELECTORS['room'])
+ const tileStore = yield select(OBJECT_SELECTORS['tile'])
+ const rackStore = yield select(OBJECT_SELECTORS['rack'])
+ const machineStore = yield select(OBJECT_SELECTORS['machine'])
+
+ const topology = {
+ _id: id,
+ name: topologyStore[id].name,
+ rooms: topologyStore[id].roomIds.map((roomId) => ({
+ _id: roomId,
+ name: roomStore[roomId].name,
+ tiles: roomStore[roomId].tileIds.map((tileId) => ({
+ _id: tileId,
+ positionX: tileStore[tileId].positionX,
+ positionY: tileStore[tileId].positionY,
+ rack: !tileStore[tileId].rackId
+ ? undefined
+ : {
+ _id: rackStore[tileStore[tileId].rackId]._id,
+ capacity: rackStore[tileStore[tileId].rackId].capacity,
+ powerCapacityW: rackStore[tileStore[tileId].rackId].powerCapacityW,
+ machines: rackStore[tileStore[tileId].rackId].machineIds
+ .filter((m) => m !== null)
+ .map((machineId) => ({
+ _id: machineId,
+ position: machineStore[machineId].position,
+ cpuIds: machineStore[machineId].cpuIds,
+ gpuIds: machineStore[machineId].gpuIds,
+ memoryIds: machineStore[machineId].memoryIds,
+ storageIds: machineStore[machineId].storageIds,
+ })),
+ },
+ })),
+ })),
+ }
-export const fetchAndStorePathsOfSimulation = simulationId =>
- fetchAndStoreObjects('path', call(getPathsOfSimulation, simulationId))
+ yield call(updateTopology, topology)
+}
-export const fetchAndStoreAllTraces = () =>
- fetchAndStoreObjects('trace', call(getAllTraces))
+export const fetchAndStoreAllTraces = () => fetchAndStoreObjects('trace', call(getAllTraces))
export const fetchAndStoreAllSchedulers = function* () {
const objects = yield call(getAllSchedulers)
for (let index in objects) {
- objects[index].id = objects[index].name
+ objects[index]._id = objects[index].name
yield put(addToStore('scheduler', objects[index]))
}
return objects
diff --git a/frontend/src/sagas/simulations.js b/frontend/src/sagas/simulations.js
index b57fac95..be69fedd 100644
--- a/frontend/src/sagas/simulations.js
+++ b/frontend/src/sagas/simulations.js
@@ -2,14 +2,14 @@ import { call, put } from 'redux-saga/effects'
import { addToStore } from '../actions/objects'
import { addSimulationSucceeded, deleteSimulationSucceeded } from '../actions/simulations'
import { addSimulation, deleteSimulation, getSimulation } from '../api/routes/simulations'
-import { fetchLatestDatacenter } from './topology'
+import { fetchAndStoreAllTopologiesOfSimulation } from './topology'
export function* onOpenSimulationSucceeded(action) {
try {
const simulation = yield call(getSimulation, action.id)
yield put(addToStore('simulation', simulation))
- yield fetchLatestDatacenter(action.id)
+ yield fetchAndStoreAllTopologiesOfSimulation(action.id)
} catch (error) {
console.error(error)
}
@@ -27,9 +27,7 @@ export function* onSimulationAdd(action) {
simulation,
}
yield put(addToStore('authorization', authorization))
- yield put(
- addSimulationSucceeded([authorization.userId, authorization.simulationId]),
- )
+ yield put(addSimulationSucceeded([authorization.userId, authorization.simulationId]))
} catch (error) {
console.error(error)
}
diff --git a/frontend/src/sagas/topology.js b/frontend/src/sagas/topology.js
index b38358a4..0be619a9 100644
--- a/frontend/src/sagas/topology.js
+++ b/frontend/src/sagas/topology.js
@@ -8,181 +8,95 @@ import {
} from '../actions/objects'
import {
cancelNewRoomConstructionSucceeded,
- setCurrentDatacenter,
+ setCurrentTopology,
startNewRoomConstructionSucceeded,
} from '../actions/topology/building'
-import { addRoomToDatacenter } from '../api/routes/datacenters'
-import { addTileToRoom, deleteRoom, updateRoom } from '../api/routes/rooms'
-import {
- addMachineToRackOnTile,
- addRackToTile,
- deleteMachineInRackOnTile,
- deleteRackFromTile,
- deleteTile,
- updateMachineInRackOnTile,
- updateRackOnTile,
-} from '../api/routes/tiles'
import {
DEFAULT_RACK_POWER_CAPACITY,
DEFAULT_RACK_SLOT_CAPACITY,
MAX_NUM_UNITS_PER_MACHINE,
} from '../components/app/map/MapConstants'
-import {
- fetchAndStoreAllCPUs,
- fetchAndStoreAllGPUs,
- fetchAndStoreAllMemories,
- fetchAndStoreAllStorages,
- fetchAndStoreCoolingItem,
- fetchAndStoreCPU,
- fetchAndStoreDatacenter,
- fetchAndStoreGPU,
- fetchAndStoreMachinesOfTile,
- fetchAndStoreMemory,
- fetchAndStorePath,
- fetchAndStorePathsOfSimulation,
- fetchAndStorePSU,
- fetchAndStoreRackOnTile,
- fetchAndStoreRoomsOfDatacenter,
- fetchAndStoreSectionsOfPath,
- fetchAndStoreStorage,
- fetchAndStoreTilesOfRoom,
-} from './objects'
+import { fetchAndStoreTopology, updateTopologyOnServer } from './objects'
+import { uuid } from 'uuidv4'
+import { addTopology, deleteTopology } from '../api/routes/topologies'
-export function* fetchLatestDatacenter(simulationId) {
+export function* fetchTopologyOfExperiment(experiment) {
try {
- const paths = yield fetchAndStorePathsOfSimulation(simulationId)
- const latestPath = paths[paths.length - 1]
- const sections = yield fetchAndStoreSectionsOfPath(latestPath.id)
- const latestSection = sections[sections.length - 1]
- yield fetchAllUnitSpecifications()
- yield fetchDatacenter(latestSection.datacenterId)
- yield put(setCurrentDatacenter(latestSection.datacenterId))
+ yield fetchAndStoreTopology(experiment.topologyId)
+ yield put(setCurrentTopology(experiment.topologyId))
} catch (error) {
console.error(error)
}
}
-export function* fetchAllDatacentersOfExperiment(experiment) {
+export function* fetchAndStoreAllTopologiesOfSimulation(simulationId) {
try {
- const path = yield fetchAndStorePath(experiment.pathId)
- const sections = yield fetchAndStoreSectionsOfPath(path.id)
- path.sectionIds = sections.map(section => section.id)
- yield fetchAllUnitSpecifications()
+ const simulation = yield select((state) => state.objects.simulation[simulationId])
- for (let i in sections) {
- yield fetchDatacenter(sections[i].datacenterId)
+ for (let i in simulation.topologyIds) {
+ yield fetchAndStoreTopology(simulation.topologyIds[i])
}
- yield put(setCurrentDatacenter(sections[0].datacenterId))
+
+ yield put(setCurrentTopology(simulation.topologyIds[0]))
} catch (error) {
console.error(error)
}
}
-function* fetchDatacenter(datacenterId) {
+export function* onAddTopology(action) {
try {
- yield fetchAndStoreDatacenter(datacenterId)
- const rooms = yield fetchAndStoreRoomsOfDatacenter(datacenterId)
- yield put(
- addPropToStoreObject('datacenter', datacenterId, {
- roomIds: rooms.map(room => room.id),
- }),
+ const currentSimulationId = yield select((state) => state.currentSimulationId)
+
+ const topology = yield call(
+ addTopology,
+ Object.assign({}, action.topology, {
+ _id: -1,
+ simulationId: currentSimulationId,
+ })
)
+ yield put(addToStore('topology', topology))
- for (let index in rooms) {
- yield fetchRoom(rooms[index].id)
- }
+ const topologyIds = yield select((state) => state.objects.simulation[currentSimulationId].topologyIds)
+ yield put(
+ addPropToStoreObject('simulation', currentSimulationId, {
+ topologyIds: topologyIds.concat([topology._id]),
+ })
+ )
} catch (error) {
console.error(error)
}
}
-function* fetchAllUnitSpecifications() {
+export function* onDeleteTopology(action) {
try {
- yield fetchAndStoreAllCPUs()
- yield fetchAndStoreAllGPUs()
- yield fetchAndStoreAllMemories()
- yield fetchAndStoreAllStorages()
- } catch (error) {
- console.error(error)
- }
-}
-
-function* fetchRoom(roomId) {
- const tiles = yield fetchAndStoreTilesOfRoom(roomId)
- yield put(
- addPropToStoreObject('room', roomId, {
- tileIds: tiles.map(tile => tile.id),
- }),
- )
-
- for (let index in tiles) {
- yield fetchTile(tiles[index])
- }
-}
-
-function* fetchTile(tile) {
- if (!tile.objectType) {
- return
- }
-
- switch (tile.objectType) {
- case 'RACK':
- const rack = yield fetchAndStoreRackOnTile(tile.objectId, tile.id)
- yield put(addPropToStoreObject('tile', tile.id, { rackId: rack.id }))
- yield fetchMachinesOfRack(tile.id, rack)
- break
- case 'COOLING_ITEM':
- const coolingItem = yield fetchAndStoreCoolingItem(tile.objectId)
- yield put(
- addPropToStoreObject('tile', tile.id, { coolingItemId: coolingItem.id }),
- )
- break
- case 'PSU':
- const psu = yield fetchAndStorePSU(tile.objectId)
- yield put(addPropToStoreObject('tile', tile.id, { psuId: psu.id }))
- break
- default:
- console.warn('Unknown rack type encountered while fetching tile objects')
- }
-}
-
-function* fetchMachinesOfRack(tileId, rack) {
- const machines = yield fetchAndStoreMachinesOfTile(tileId)
- const machineIds = new Array(rack.capacity).fill(null)
- machines.forEach(machine => (machineIds[machine.position - 1] = machine.id))
+ yield call(deleteTopology, action.id)
- yield put(addPropToStoreObject('rack', rack.id, { machineIds }))
+ const currentSimulationId = yield select((state) => state.currentSimulationId)
+ const topologyIds = yield select((state) => state.objects.simulation[currentSimulationId].topologyIds)
- for (let index in machines) {
- for (let i in machines[index].cpuIds) {
- yield fetchAndStoreCPU(machines[index].cpuIds[i])
- }
- for (let i in machines[index].gpuIds) {
- yield fetchAndStoreGPU(machines[index].gpuIds[i])
- }
- for (let i in machines[index].memoryIds) {
- yield fetchAndStoreMemory(machines[index].memoryIds[i])
- }
- for (let i in machines[index].storageIds) {
- yield fetchAndStoreStorage(machines[index].storageIds[i])
- }
+ yield put(
+ addPropToStoreObject('simulation', currentSimulationId, {
+ topologyIds: topologyIds.filter((id) => id !== action.id),
+ })
+ )
+ } catch (error) {
+ console.error(error)
}
}
export function* onStartNewRoomConstruction() {
try {
- const datacenterId = yield select(state => state.currentDatacenterId)
- const room = yield call(addRoomToDatacenter, {
- id: -1,
- datacenterId,
- roomType: 'SERVER',
- })
- const roomWithEmptyTileList = Object.assign({}, room, { tileIds: [] })
- yield put(addToStore('room', roomWithEmptyTileList))
- yield put(
- addIdToStoreObjectListProp('datacenter', datacenterId, 'roomIds', room.id),
- )
- yield put(startNewRoomConstructionSucceeded(room.id))
+ const topologyId = yield select((state) => state.currentTopologyId)
+ const room = {
+ _id: uuid(),
+ name: 'Room',
+ topologyId,
+ tileIds: [],
+ }
+ yield put(addToStore('room', room))
+ yield put(addIdToStoreObjectListProp('topology', topologyId, 'roomIds', room._id))
+ yield updateTopologyOnServer(topologyId)
+ yield put(startNewRoomConstructionSucceeded(room._id))
} catch (error) {
console.error(error)
}
@@ -190,19 +104,11 @@ export function* onStartNewRoomConstruction() {
export function* onCancelNewRoomConstruction() {
try {
- const datacenterId = yield select(state => state.currentDatacenterId)
- const roomId = yield select(
- state => state.construction.currentRoomInConstruction,
- )
- yield call(deleteRoom, roomId)
- yield put(
- removeIdFromStoreObjectListProp(
- 'datacenter',
- datacenterId,
- 'roomIds',
- roomId,
- ),
- )
+ const topologyId = yield select((state) => state.currentTopologyId)
+ const roomId = yield select((state) => state.construction.currentRoomInConstruction)
+ yield put(removeIdFromStoreObjectListProp('topology', topologyId, 'roomIds', roomId))
+ // TODO remove room from store, too
+ yield updateTopologyOnServer(topologyId)
yield put(cancelNewRoomConstructionSucceeded())
} catch (error) {
console.error(error)
@@ -211,16 +117,17 @@ export function* onCancelNewRoomConstruction() {
export function* onAddTile(action) {
try {
- const roomId = yield select(
- state => state.construction.currentRoomInConstruction,
- )
- const tile = yield call(addTileToRoom, {
+ const topologyId = yield select((state) => state.currentTopologyId)
+ const roomId = yield select((state) => state.construction.currentRoomInConstruction)
+ const tile = {
+ _id: uuid(),
roomId,
positionX: action.positionX,
positionY: action.positionY,
- })
+ }
yield put(addToStore('tile', tile))
- yield put(addIdToStoreObjectListProp('room', roomId, 'tileIds', tile.id))
+ yield put(addIdToStoreObjectListProp('room', roomId, 'tileIds', tile._id))
+ yield updateTopologyOnServer(topologyId)
} catch (error) {
console.error(error)
}
@@ -228,13 +135,10 @@ export function* onAddTile(action) {
export function* onDeleteTile(action) {
try {
- const roomId = yield select(
- state => state.construction.currentRoomInConstruction,
- )
- yield call(deleteTile, action.tileId)
- yield put(
- removeIdFromStoreObjectListProp('room', roomId, 'tileIds', action.tileId),
- )
+ const topologyId = yield select((state) => state.currentTopologyId)
+ const roomId = yield select((state) => state.construction.currentRoomInConstruction)
+ yield put(removeIdFromStoreObjectListProp('room', roomId, 'tileIds', action.tileId))
+ yield updateTopologyOnServer(topologyId)
} catch (error) {
console.error(error)
}
@@ -242,14 +146,12 @@ export function* onDeleteTile(action) {
export function* onEditRoomName(action) {
try {
- const roomId = yield select(state => state.interactionLevel.roomId)
- const room = Object.assign(
- {},
- yield select(state => state.objects.room[roomId]),
- )
+ const topologyId = yield select((state) => state.currentTopologyId)
+ const roomId = yield select((state) => state.interactionLevel.roomId)
+ const room = Object.assign({}, yield select((state) => state.objects.room[roomId]))
room.name = action.name
- yield call(updateRoom, room)
yield put(addPropToStoreObject('room', roomId, { name: action.name }))
+ yield updateTopologyOnServer(topologyId)
} catch (error) {
console.error(error)
}
@@ -257,18 +159,11 @@ export function* onEditRoomName(action) {
export function* onDeleteRoom() {
try {
- const datacenterId = yield select(state => state.currentDatacenterId)
- const roomId = yield select(state => state.interactionLevel.roomId)
- yield call(deleteRoom, roomId)
+ const topologyId = yield select((state) => state.currentTopologyId)
+ const roomId = yield select((state) => state.interactionLevel.roomId)
yield put(goDownOneInteractionLevel())
- yield put(
- removeIdFromStoreObjectListProp(
- 'datacenter',
- datacenterId,
- 'roomIds',
- roomId,
- ),
- )
+ yield put(removeIdFromStoreObjectListProp('topology', topologyId, 'roomIds', roomId))
+ yield updateTopologyOnServer(topologyId)
} catch (error) {
console.error(error)
}
@@ -276,17 +171,12 @@ export function* onDeleteRoom() {
export function* onEditRackName(action) {
try {
- const tileId = yield select(state => state.interactionLevel.tileId)
- const rackId = yield select(
- state => state.objects.tile[state.interactionLevel.tileId].objectId,
- )
- const rack = Object.assign(
- {},
- yield select(state => state.objects.rack[rackId]),
- )
+ const topologyId = yield select((state) => state.currentTopologyId)
+ const rackId = yield select((state) => state.objects.tile[state.interactionLevel.tileId].rackId)
+ const rack = Object.assign({}, yield select((state) => state.objects.rack[rackId]))
rack.name = action.name
- yield call(updateRackOnTile, tileId, rack)
yield put(addPropToStoreObject('rack', rackId, { name: action.name }))
+ yield updateTopologyOnServer(topologyId)
} catch (error) {
console.error(error)
}
@@ -294,11 +184,11 @@ export function* onEditRackName(action) {
export function* onDeleteRack() {
try {
- const tileId = yield select(state => state.interactionLevel.tileId)
- yield call(deleteRackFromTile, tileId)
+ const topologyId = yield select((state) => state.currentTopologyId)
+ const tileId = yield select((state) => state.interactionLevel.tileId)
yield put(goDownOneInteractionLevel())
- yield put(addPropToStoreObject('tile', tileId, { objectType: undefined }))
- yield put(addPropToStoreObject('tile', tileId, { objectId: undefined }))
+ yield put(addPropToStoreObject('tile', tileId, { rackId: undefined }))
+ yield updateTopologyOnServer(topologyId)
} catch (error) {
console.error(error)
}
@@ -306,20 +196,16 @@ export function* onDeleteRack() {
export function* onAddRackToTile(action) {
try {
- const rack = yield call(addRackToTile, action.tileId, {
- id: -1,
- name: 'Rack',
+ const topologyId = yield select((state) => state.currentTopologyId)
+ const rack = {
+ _id: uuid(),
capacity: DEFAULT_RACK_SLOT_CAPACITY,
powerCapacityW: DEFAULT_RACK_POWER_CAPACITY,
- })
+ }
rack.machineIds = new Array(rack.capacity).fill(null)
yield put(addToStore('rack', rack))
- yield put(
- addPropToStoreObject('tile', action.tileId, { objectId: rack.id }),
- )
- yield put(
- addPropToStoreObject('tile', action.tileId, { objectType: 'RACK' }),
- )
+ yield put(addPropToStoreObject('tile', action.tileId, { rackId: rack._id }))
+ yield updateTopologyOnServer(topologyId)
} catch (error) {
console.error(error)
}
@@ -327,27 +213,24 @@ export function* onAddRackToTile(action) {
export function* onAddMachine(action) {
try {
- const tileId = yield select(state => state.interactionLevel.tileId)
- const rackId = yield select(
- state => state.objects.tile[state.interactionLevel.tileId].objectId,
- )
- const rack = yield select(state => state.objects.rack[rackId])
+ const topologyId = yield select((state) => state.currentTopologyId)
+ const rackId = yield select((state) => state.objects.tile[state.interactionLevel.tileId].rackId)
+ const rack = yield select((state) => state.objects.rack[rackId])
- const machine = yield call(addMachineToRackOnTile, tileId, {
- id: -1,
- rackId,
+ const machine = {
+ _id: -1,
position: action.position,
- tags: [],
cpuIds: [],
gpuIds: [],
memoryIds: [],
storageIds: [],
- })
+ }
yield put(addToStore('machine', machine))
const machineIds = [...rack.machineIds]
- machineIds[machine.position - 1] = machine.id
+ machineIds[machine.position - 1] = machine._id
yield put(addPropToStoreObject('rack', rackId, { machineIds }))
+ yield updateTopologyOnServer(topologyId)
} catch (error) {
console.error(error)
}
@@ -355,16 +238,15 @@ export function* onAddMachine(action) {
export function* onDeleteMachine() {
try {
- const tileId = yield select(state => state.interactionLevel.tileId)
- const position = yield select(state => state.interactionLevel.position)
- const rack = yield select(
- state => state.objects.rack[state.objects.tile[tileId].objectId],
- )
- yield call(deleteMachineInRackOnTile, tileId, position)
+ const topologyId = yield select((state) => state.currentTopologyId)
+ const tileId = yield select((state) => state.interactionLevel.tileId)
+ const position = yield select((state) => state.interactionLevel.position)
+ const rack = yield select((state) => state.objects.rack[state.objects.tile[tileId].rackId])
const machineIds = [...rack.machineIds]
machineIds[position - 1] = null
yield put(goDownOneInteractionLevel())
- yield put(addPropToStoreObject('rack', rack.id, { machineIds }))
+ yield put(addPropToStoreObject('rack', rack._id, { machineIds }))
+ yield updateTopologyOnServer(topologyId)
} catch (error) {
console.error(error)
}
@@ -372,15 +254,12 @@ export function* onDeleteMachine() {
export function* onAddUnit(action) {
try {
- const tileId = yield select(state => state.interactionLevel.tileId)
- const position = yield select(state => state.interactionLevel.position)
+ const topologyId = yield select((state) => state.currentTopologyId)
+ const tileId = yield select((state) => state.interactionLevel.tileId)
+ const position = yield select((state) => state.interactionLevel.position)
const machine = yield select(
- state =>
- state.objects.machine[
- state.objects.rack[state.objects.tile[tileId].objectId].machineIds[
- position - 1
- ]
- ],
+ (state) =>
+ state.objects.machine[state.objects.rack[state.objects.tile[tileId].rackId].machineIds[position - 1]]
)
if (machine[action.unitType + 'Ids'].length >= MAX_NUM_UNITS_PER_MACHINE) {
@@ -388,17 +267,12 @@ export function* onAddUnit(action) {
}
const units = [...machine[action.unitType + 'Ids'], action.id]
- const updatedMachine = Object.assign({}, machine, {
- [action.unitType + 'Ids']: units,
- })
-
- yield call(updateMachineInRackOnTile, tileId, position, updatedMachine)
-
yield put(
- addPropToStoreObject('machine', machine.id, {
+ addPropToStoreObject('machine', machine._id, {
[action.unitType + 'Ids']: units,
- }),
+ })
)
+ yield updateTopologyOnServer(topologyId)
} catch (error) {
console.error(error)
}
@@ -406,28 +280,22 @@ export function* onAddUnit(action) {
export function* onDeleteUnit(action) {
try {
- const tileId = yield select(state => state.interactionLevel.tileId)
- const position = yield select(state => state.interactionLevel.position)
+ const topologyId = yield select((state) => state.currentTopologyId)
+ const tileId = yield select((state) => state.interactionLevel.tileId)
+ const position = yield select((state) => state.interactionLevel.position)
const machine = yield select(
- state =>
- state.objects.machine[
- state.objects.rack[state.objects.tile[tileId].objectId].machineIds[
- position - 1
- ]
- ],
+ (state) =>
+ state.objects.machine[state.objects.rack[state.objects.tile[tileId].rackId].machineIds[position - 1]]
)
const unitIds = machine[action.unitType + 'Ids'].slice()
unitIds.splice(action.index, 1)
- const updatedMachine = Object.assign({}, machine, {
- [action.unitType + 'Ids']: unitIds,
- })
- yield call(updateMachineInRackOnTile, tileId, position, updatedMachine)
yield put(
- addPropToStoreObject('machine', machine.id, {
+ addPropToStoreObject('machine', machine._id, {
[action.unitType + 'Ids']: unitIds,
- }),
+ })
)
+ yield updateTopologyOnServer(topologyId)
} catch (error) {
console.error(error)
}
diff --git a/frontend/src/sagas/users.js b/frontend/src/sagas/users.js
index a10887a0..a95893d2 100644
--- a/frontend/src/sagas/users.js
+++ b/frontend/src/sagas/users.js
@@ -9,10 +9,7 @@ import { fetchAndStoreSimulation, fetchAndStoreUser } from './objects'
export function* onFetchLoggedInUser(action) {
try {
- const tokenResponse = yield call(
- performTokenSignIn,
- action.payload.authToken,
- )
+ const tokenResponse = yield call(performTokenSignIn, action.payload.authToken)
let userId = tokenResponse.userId
@@ -38,10 +35,7 @@ export function* onFetchAuthorizationsOfCurrentUser(action) {
yield fetchAndStoreSimulation(authorization.simulationId)
}
- const authorizationIds = user.authorizations.map(authorization => [
- action.userId,
- authorization.simulationId,
- ])
+ const authorizationIds = user.authorizations.map((authorization) => [action.userId, authorization.simulationId])
yield put(fetchAuthorizationsOfCurrentUserSucceeded(authorizationIds))
} catch (error) {
diff --git a/frontend/src/shapes/index.js b/frontend/src/shapes/index.js
index 4c63fdfe..d43496d9 100644
--- a/frontend/src/shapes/index.js
+++ b/frontend/src/shapes/index.js
@@ -8,6 +8,7 @@ Shapes.User = PropTypes.shape({
email: PropTypes.string.isRequired,
givenName: PropTypes.string.isRequired,
familyName: PropTypes.string.isRequired,
+ authorizations: PropTypes.array.isRequired,
})
Shapes.Simulation = PropTypes.shape({
@@ -15,6 +16,8 @@ Shapes.Simulation = PropTypes.shape({
name: PropTypes.string.isRequired,
datetimeCreated: PropTypes.string.isRequired,
datetimeLastEdited: PropTypes.string.isRequired,
+ topologyIds: PropTypes.array.isRequired,
+ experimentIds: PropTypes.array.isRequired,
})
Shapes.Authorization = PropTypes.shape({
@@ -25,148 +28,81 @@ Shapes.Authorization = PropTypes.shape({
authorizationLevel: PropTypes.string.isRequired,
})
-Shapes.FailureModel = PropTypes.shape({
- id: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- rate: PropTypes.number.isRequired,
-})
-
Shapes.ProcessingUnit = PropTypes.shape({
- id: PropTypes.number.isRequired,
- manufacturer: PropTypes.string.isRequired,
- family: PropTypes.string.isRequired,
- generation: PropTypes.string.isRequired,
- model: PropTypes.string.isRequired,
+ _id: PropTypes.string.isRequired,
+ name: PropTypes.string.isRequired,
clockRateMhz: PropTypes.number.isRequired,
numberOfCores: PropTypes.number.isRequired,
energyConsumptionW: PropTypes.number.isRequired,
- failureModelId: PropTypes.number.isRequired,
- failureModel: Shapes.FailureModel,
})
Shapes.StorageUnit = PropTypes.shape({
- id: PropTypes.number.isRequired,
- manufacturer: PropTypes.string.isRequired,
- family: PropTypes.string.isRequired,
- generation: PropTypes.string.isRequired,
- model: PropTypes.string.isRequired,
+ _id: PropTypes.string.isRequired,
+ name: PropTypes.string.isRequired,
speedMbPerS: PropTypes.number.isRequired,
sizeMb: PropTypes.number.isRequired,
energyConsumptionW: PropTypes.number.isRequired,
- failureModelId: PropTypes.number.isRequired,
- failureModel: Shapes.FailureModel,
})
Shapes.Machine = PropTypes.shape({
- id: PropTypes.number.isRequired,
- rackId: PropTypes.number.isRequired,
+ _id: PropTypes.string.isRequired,
+ rackId: PropTypes.string.isRequired,
position: PropTypes.number.isRequired,
- cpuIds: PropTypes.arrayOf(PropTypes.number.isRequired),
+ cpuIds: PropTypes.arrayOf(PropTypes.string.isRequired),
cpus: PropTypes.arrayOf(Shapes.ProcessingUnit),
- gpuIds: PropTypes.arrayOf(PropTypes.number.isRequired),
+ gpuIds: PropTypes.arrayOf(PropTypes.string.isRequired),
gpus: PropTypes.arrayOf(Shapes.ProcessingUnit),
- memoryIds: PropTypes.arrayOf(PropTypes.number.isRequired),
+ memoryIds: PropTypes.arrayOf(PropTypes.string.isRequired),
memories: PropTypes.arrayOf(Shapes.StorageUnit),
- storageIds: PropTypes.arrayOf(PropTypes.number.isRequired),
+ storageIds: PropTypes.arrayOf(PropTypes.string.isRequired),
storages: PropTypes.arrayOf(Shapes.StorageUnit),
})
Shapes.Rack = PropTypes.shape({
- id: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
+ _id: PropTypes.string.isRequired,
capacity: PropTypes.number.isRequired,
powerCapacityW: PropTypes.number.isRequired,
machines: PropTypes.arrayOf(Shapes.Machine),
})
-Shapes.CoolingItem = PropTypes.shape({
- id: PropTypes.number.isRequired,
- energyConsumptionW: PropTypes.number.isRequired,
- type: PropTypes.string.isRequired,
- failureModelId: PropTypes.number.isRequired,
- failureModel: Shapes.FailureModel,
-})
-
-Shapes.PSU = PropTypes.shape({
- id: PropTypes.number.isRequired,
- energyKwh: PropTypes.number.isRequired,
- type: PropTypes.string.isRequired,
- failureModelId: PropTypes.number.isRequired,
- failureModel: Shapes.FailureModel,
-})
-
Shapes.Tile = PropTypes.shape({
- id: PropTypes.number.isRequired,
- roomId: PropTypes.number.isRequired,
+ _id: PropTypes.string.isRequired,
+ roomId: PropTypes.string.isRequired,
positionX: PropTypes.number.isRequired,
positionY: PropTypes.number.isRequired,
- objectId: PropTypes.number,
- objectType: PropTypes.string,
+ rackId: PropTypes.string,
rack: Shapes.Rack,
- coolingItem: Shapes.CoolingItem,
- psu: Shapes.PSU,
})
Shapes.Room = PropTypes.shape({
- id: PropTypes.number.isRequired,
- datacenterId: PropTypes.number.isRequired,
+ _id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
- roomType: PropTypes.string.isRequired,
tiles: PropTypes.arrayOf(Shapes.Tile),
})
-Shapes.Datacenter = PropTypes.shape({
- id: PropTypes.number.isRequired,
+Shapes.Topology = PropTypes.shape({
+ _id: PropTypes.string.isRequired,
+ name: PropTypes.string.isRequired,
rooms: PropTypes.arrayOf(Shapes.Room),
})
-Shapes.Section = PropTypes.shape({
- id: PropTypes.number.isRequired,
- pathId: PropTypes.number.isRequired,
- startTick: PropTypes.number.isRequired,
- datacenterId: PropTypes.number.isRequired,
- datacenter: Shapes.Datacenter,
-})
-
-Shapes.Path = PropTypes.shape({
- id: PropTypes.number.isRequired,
- simulationId: PropTypes.number.isRequired,
- name: PropTypes.string,
- datetimeCreated: PropTypes.string.isRequired,
- sections: PropTypes.arrayOf(Shapes.Section),
-})
-
Shapes.Scheduler = PropTypes.shape({
name: PropTypes.string.isRequired,
})
-Shapes.Task = PropTypes.shape({
- id: PropTypes.number.isRequired,
- jobId: PropTypes.number.isRequired,
- startTick: PropTypes.number.isRequired,
- totalFlopCount: PropTypes.number.isRequired,
-})
-
-Shapes.Job = PropTypes.shape({
- id: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- traceId: PropTypes.number.isRequired,
- taskIds: PropTypes.arrayOf(PropTypes.number),
-})
-
Shapes.Trace = PropTypes.shape({
- id: PropTypes.number.isRequired,
+ _id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
- jobIds: PropTypes.arrayOf(PropTypes.number),
+ type: PropTypes.string.isRequired,
})
Shapes.Experiment = PropTypes.shape({
- id: PropTypes.number.isRequired,
- simulationId: PropTypes.number.isRequired,
- traceId: PropTypes.number.isRequired,
+ _id: PropTypes.string.isRequired,
+ simulationId: PropTypes.string.isRequired,
+ topologyId: PropTypes.string.isRequired,
+ topology: Shapes.Topology,
+ traceId: PropTypes.string.isRequired,
trace: Shapes.Trace,
- pathId: PropTypes.number.isRequired,
- path: Shapes.Path,
schedulerName: PropTypes.string.isRequired,
scheduler: Shapes.Scheduler,
name: PropTypes.string.isRequired,
@@ -181,8 +117,8 @@ Shapes.WallSegment = PropTypes.shape({
Shapes.InteractionLevel = PropTypes.shape({
mode: PropTypes.string.isRequired,
- roomId: PropTypes.number,
- rackId: PropTypes.bool,
+ roomId: PropTypes.string,
+ rackId: PropTypes.string,
})
export default Shapes
diff --git a/frontend/src/store/configure-store.js b/frontend/src/store/configure-store.js
index f01b61bb..d8f343ed 100644
--- a/frontend/src/store/configure-store.js
+++ b/frontend/src/store/configure-store.js
@@ -27,10 +27,7 @@ const middlewares = [
export let store = undefined
export default function configureStore() {
- const configuredStore = createStore(
- rootReducer,
- compose(persistState('auth'), applyMiddleware(...middlewares)),
- )
+ const configuredStore = createStore(rootReducer, compose(persistState('auth'), applyMiddleware(...middlewares)))
sagaMiddleware.run(rootSaga)
store = configuredStore
diff --git a/frontend/src/store/middlewares/viewport-adjustment.js b/frontend/src/store/middlewares/viewport-adjustment.js
index 0a074f61..ae8f032a 100644
--- a/frontend/src/store/middlewares/viewport-adjustment.js
+++ b/frontend/src/store/middlewares/viewport-adjustment.js
@@ -1,5 +1,5 @@
import { SET_MAP_DIMENSIONS, setMapPosition, setMapScale } from '../../actions/map'
-import { SET_CURRENT_DATACENTER } from '../../actions/topology/building'
+import { SET_CURRENT_TOPOLOGY } from '../../actions/topology/building'
import {
MAP_MAX_SCALE,
MAP_MIN_SCALE,
@@ -12,21 +12,21 @@ import { calculateRoomListBounds } from '../../util/tile-calculations'
export const viewportAdjustmentMiddleware = store => next => action => {
const state = store.getState()
- let datacenterId = -1
+ let topologyId = -1
let mapDimensions = {}
- if (action.type === SET_CURRENT_DATACENTER && action.datacenterId !== -1) {
- datacenterId = action.datacenterId
+ if (action.type === SET_CURRENT_TOPOLOGY && action.topologyId !== -1) {
+ topologyId = action.topologyId
mapDimensions = state.map.dimensions
} else if (
action.type === SET_MAP_DIMENSIONS &&
- state.currentDatacenterId !== -1
+ state.currentTopologyId !== -1
) {
- datacenterId = state.currentDatacenterId
+ topologyId = state.currentTopologyId
mapDimensions = { width: action.width, height: action.height }
}
- if (datacenterId !== -1) {
- const roomIds = state.objects.datacenter[datacenterId].roomIds
+ if (topologyId !== -1) {
+ const roomIds = state.objects.topology[topologyId].roomIds
const rooms = roomIds.map(id => Object.assign({}, state.objects.room[id]))
rooms.forEach(
room =>
diff --git a/frontend/src/util/date-time.js b/frontend/src/util/date-time.js
index d176ebef..66efdf5b 100644
--- a/frontend/src/util/date-time.js
+++ b/frontend/src/util/date-time.js
@@ -39,10 +39,7 @@ export function formatDateTime(dateTime) {
'/' +
addPaddingToTwo(dateTime.getFullYear())
- if (
- dateTime.getFullYear() === currentDate.getFullYear() &&
- dateTime.getMonth() === currentDate.getMonth()
- ) {
+ if (dateTime.getFullYear() === currentDate.getFullYear() && dateTime.getMonth() === currentDate.getMonth()) {
if (dateTime.getDate() === currentDate.getDate()) {
date = 'Today'
} else if (dateTime.getDate() === currentDate.getDate() - 1) {
@@ -50,13 +47,7 @@ export function formatDateTime(dateTime) {
}
}
- return (
- date +
- ', ' +
- addPaddingToTwo(dateTime.getHours()) +
- ':' +
- addPaddingToTwo(dateTime.getMinutes())
- )
+ return date + ', ' + addPaddingToTwo(dateTime.getHours()) + ':' + addPaddingToTwo(dateTime.getMinutes())
}
/**
@@ -83,9 +74,7 @@ export function convertSecondsToFormattedTime(seconds) {
} else if (hour === 0) {
return minute + 'm' + addPaddingToTwo(second) + 's'
} else {
- return (
- hour + 'h' + addPaddingToTwo(minute) + 'm' + addPaddingToTwo(second) + 's'
- )
+ return hour + 'h' + addPaddingToTwo(minute) + 'm' + addPaddingToTwo(second) + 's'
}
}
diff --git a/frontend/src/util/date-time.test.js b/frontend/src/util/date-time.test.js
index 9274d4b7..3d95eba6 100644
--- a/frontend/src/util/date-time.test.js
+++ b/frontend/src/util/date-time.test.js
@@ -15,7 +15,7 @@ describe('date-time parsing', () => {
})
describe('tick formatting', () => {
- it('returns \'0s\' for numbers <= 0', () => {
+ it("returns '0s' for numbers <= 0", () => {
expect(convertSecondsToFormattedTime(-1)).toEqual('0s')
expect(convertSecondsToFormattedTime(0)).toEqual('0s')
})
diff --git a/frontend/src/util/room-types.js b/frontend/src/util/room-types.js
deleted file mode 100644
index ff69d013..00000000
--- a/frontend/src/util/room-types.js
+++ /dev/null
@@ -1,7 +0,0 @@
-export const ROOM_TYPE_TO_NAME_MAP = {
- SERVER: 'Server room',
- HALLWAY: 'Hallway',
- OFFICE: 'Office',
- POWER: 'Power room',
- COOLING: 'Cooling room',
-}
diff --git a/frontend/src/util/tile-calculations.js b/frontend/src/util/tile-calculations.js
index 3ef1cff6..764ae6ac 100644
--- a/frontend/src/util/tile-calculations.js
+++ b/frontend/src/util/tile-calculations.js
@@ -7,7 +7,7 @@ function getWallSegments(tiles) {
const verticalWalls = {}
const horizontalWalls = {}
- tiles.forEach(tile => {
+ tiles.forEach((tile) => {
const x = tile.positionX,
y = tile.positionY
@@ -19,10 +19,7 @@ function getWallSegments(tiles) {
let doInsert = true
for (let tileIndex in tiles) {
- if (
- tiles[tileIndex].positionX === x + dX &&
- tiles[tileIndex].positionY === y + dY
- ) {
+ if (tiles[tileIndex].positionX === x + dX && tiles[tileIndex].positionY === y + dY) {
doInsert = false
break
}
@@ -143,7 +140,7 @@ export function deriveValidNextTilePositions(rooms, selectedTiles) {
newPosition = { x: 0, y: 0 }
let isSurroundingTile
- selectedTiles.forEach(tile => {
+ selectedTiles.forEach((tile) => {
const x = tile.positionX
const y = tile.positionY
result.push({ x, y })
@@ -168,10 +165,7 @@ export function deriveValidNextTilePositions(rooms, selectedTiles) {
}
}
- if (
- isSurroundingTile &&
- findPositionInRooms(rooms, newPosition.x, newPosition.y) === -1
- ) {
+ if (isSurroundingTile && findPositionInRooms(rooms, newPosition.x, newPosition.y) === -1) {
result.push({ x: newPosition.x, y: newPosition.y })
}
}
@@ -231,8 +225,8 @@ export function calculateRoomListBounds(rooms) {
const min = { x: Number.MAX_VALUE, y: Number.MAX_VALUE }
const max = { x: -1, y: -1 }
- rooms.forEach(room => {
- room.tiles.forEach(tile => {
+ rooms.forEach((room) => {
+ room.tiles.forEach((tile) => {
if (tile.positionX < min.x) {
min.x = tile.positionX
}
diff --git a/frontend/src/util/timeline.js b/frontend/src/util/timeline.js
index 21258e23..7c8a3ef0 100644
--- a/frontend/src/util/timeline.js
+++ b/frontend/src/util/timeline.js
@@ -2,18 +2,8 @@ export function convertTickToPercentage(tick, maxTick) {
if (maxTick === 0) {
return '0%'
} else if (tick > maxTick) {
- return maxTick / (maxTick + 1) * 100 + '%'
+ return (maxTick / (maxTick + 1)) * 100 + '%'
}
- return tick / (maxTick + 1) * 100 + '%'
-}
-
-export function getDatacenterIdOfTick(tick, sections) {
- for (let i in sections.reverse()) {
- if (tick >= sections[i].startTick) {
- return sections[i].datacenterId
- }
- }
-
- return -1
+ return (tick / (maxTick + 1)) * 100 + '%'
}
diff --git a/frontend/src/util/unit-specifications.js b/frontend/src/util/unit-specifications.js
new file mode 100644
index 00000000..43c45b7e
--- /dev/null
+++ b/frontend/src/util/unit-specifications.js
@@ -0,0 +1,46 @@
+export const CPU_UNITS = {
+ 'cpu-1': {
+ _id: 'cpu-1',
+ name: 'Intel i7 v6 6700k',
+ clockRateMhz: 4100,
+ numberOfCores: 4,
+ energyConsumptionW: 70,
+ },
+ 'cpu-2': {
+ _id: 'cpu-2',
+ name: 'Intel i5 v6 6700k',
+ clockRateMhz: 3500,
+ numberOfCores: 2,
+ energyConsumptionW: 50,
+ },
+}
+
+export const GPU_UNITS = {
+ 'gpu-1': {
+ _id: 'gpu-1',
+ name: 'NVIDIA GTX 4 1080',
+ clockRateMhz: 1200,
+ numberOfCores: 200,
+ energyConsumptionW: 250,
+ },
+}
+
+export const MEMORY_UNITS = {
+ 'memory-1': {
+ _id: 'memory-1',
+ name: 'Samsung PC DRAM K4A4G045WD',
+ speedMbPerS: 16000,
+ sizeMb: 4000,
+ energyConsumptionW: 10,
+ },
+}
+
+export const STORAGE_UNITS = {
+ 'storage-1': {
+ _id: 'storage-1',
+ name: 'Samsung EVO 2016 SATA III',
+ speedMbPerS: 6000,
+ sizeMb: 250000,
+ energyConsumptionW: 10,
+ },
+}
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
index 2956bd46..00c6e441 100644
--- a/frontend/yarn.lock
+++ b/frontend/yarn.lock
@@ -1581,6 +1581,11 @@
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==
+"@types/uuid@8.0.0":
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.0.0.tgz#165aae4819ad2174a17476dbe66feebd549556c0"
+ integrity sha512-xSQfNcvOiE5f9dyd4Kzxbof1aTrLobL278pGLKOZI6esGfZ7ts9Ka16CzIN6Y8hFHE1C7jIBZokULhK1bOgjRw==
+
"@types/yargs-parser@*":
version "15.0.0"
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d"
@@ -11512,11 +11517,24 @@ utils-merge@1.0.1:
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
+uuid@8.2.0:
+ version "8.2.0"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.2.0.tgz#cb10dd6b118e2dada7d0cd9730ba7417c93d920e"
+ integrity sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q==
+
uuid@^3.0.1, uuid@^3.3.2:
version "3.4.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
+uuidv4@^6.1.1:
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/uuidv4/-/uuidv4-6.1.1.tgz#6565b4f2be7d6f841c14106f420fdb701eae5c81"
+ integrity sha512-ZplGb1SHFMVH3l7PUQl2Uwo+FpJQV6IPOoU+MjjbqrNYQolqbGwv+/sn9F+AGMsMOgGz3r9JN3ztGUi0VzMxmw==
+ dependencies:
+ "@types/uuid" "8.0.0"
+ uuid "8.2.0"
+
v8-compile-cache@^2.0.3:
version "2.1.1"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745"