diff options
| author | Georgios Andreadis <info@gandreadis.com> | 2020-06-29 15:47:09 +0200 |
|---|---|---|
| committer | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2020-08-24 16:08:41 +0200 |
| commit | 90fae26aa4bd0e0eb3272ff6e6524060e9004fbb (patch) | |
| tree | bf6943882f5fa5f3114c01fc571503c79ee1056d /frontend/src/containers | |
| parent | 7032a007d4431f5a0c4c5e2d3f3bd20462d49950 (diff) | |
Prepare frontend repository for monorepo
This change prepares the frontend Git repository for the monorepo
residing at https://github.com/atlarge-research.com/opendc. To
accomodate for this, we move all files into a frontend subdirectory.
Diffstat (limited to 'frontend/src/containers')
67 files changed, 1679 insertions, 0 deletions
diff --git a/frontend/src/containers/app/map/DatacenterContainer.js b/frontend/src/containers/app/map/DatacenterContainer.js new file mode 100644 index 00000000..125739f3 --- /dev/null +++ b/frontend/src/containers/app/map/DatacenterContainer.js @@ -0,0 +1,17 @@ +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/GrayContainer.js b/frontend/src/containers/app/map/GrayContainer.js new file mode 100644 index 00000000..d215bf6c --- /dev/null +++ b/frontend/src/containers/app/map/GrayContainer.js @@ -0,0 +1,13 @@ +import { connect } from "react-redux"; +import { goDownOneInteractionLevel } from "../../../actions/interaction-level"; +import GrayLayer from "../../../components/app/map/elements/GrayLayer"; + +const mapDispatchToProps = dispatch => { + return { + onClick: () => dispatch(goDownOneInteractionLevel()) + }; +}; + +const GrayContainer = connect(undefined, mapDispatchToProps)(GrayLayer); + +export default GrayContainer; diff --git a/frontend/src/containers/app/map/MapStage.js b/frontend/src/containers/app/map/MapStage.js new file mode 100644 index 00000000..a8467171 --- /dev/null +++ b/frontend/src/containers/app/map/MapStage.js @@ -0,0 +1,31 @@ +import { connect } from "react-redux"; +import { + setMapDimensions, + setMapPositionWithBoundsCheck, + zoomInOnPosition +} from "../../../actions/map"; +import MapStageComponent from "../../../components/app/map/MapStageComponent"; + +const mapStateToProps = state => { + return { + mapPosition: state.map.position, + mapDimensions: state.map.dimensions + }; +}; + +const mapDispatchToProps = dispatch => { + return { + zoomInOnPosition: (zoomIn, x, y) => + dispatch(zoomInOnPosition(zoomIn, x, y)), + setMapPositionWithBoundsCheck: (x, y) => + dispatch(setMapPositionWithBoundsCheck(x, y)), + setMapDimensions: (width, height) => + dispatch(setMapDimensions(width, height)) + }; +}; + +const MapStage = connect(mapStateToProps, mapDispatchToProps)( + MapStageComponent +); + +export default MapStage; diff --git a/frontend/src/containers/app/map/RackContainer.js b/frontend/src/containers/app/map/RackContainer.js new file mode 100644 index 00000000..365bb062 --- /dev/null +++ b/frontend/src/containers/app/map/RackContainer.js @@ -0,0 +1,30 @@ +import { connect } from "react-redux"; +import RackGroup from "../../../components/app/map/groups/RackGroup"; +import { getStateLoad } from "../../../util/simulation-load"; + +const mapStateToProps = (state, ownProps) => { + const inSimulation = state.currentExperimentId !== -1; + + let rackLoad = undefined; + if (inSimulation) { + if ( + state.states.rack[state.currentTick] && + state.states.rack[state.currentTick][ownProps.tile.objectId] + ) { + rackLoad = getStateLoad( + state.loadMetric, + state.states.rack[state.currentTick][ownProps.tile.objectId] + ); + } + } + + return { + interactionLevel: state.interactionLevel, + inSimulation, + rackLoad + }; +}; + +const RackContainer = connect(mapStateToProps)(RackGroup); + +export default RackContainer; diff --git a/frontend/src/containers/app/map/RackEnergyFillContainer.js b/frontend/src/containers/app/map/RackEnergyFillContainer.js new file mode 100644 index 00000000..0b7921d9 --- /dev/null +++ b/frontend/src/containers/app/map/RackEnergyFillContainer.js @@ -0,0 +1,40 @@ +import { connect } from "react-redux"; +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 machineIds = rack.machineIds; + machineIds.forEach(machineId => { + if (machineId !== null) { + const machine = state.objects.machine[machineId]; + machine.cpuIds.forEach( + id => + (energyConsumptionTotal += state.objects.cpu[id].energyConsumptionW) + ); + machine.gpuIds.forEach( + id => + (energyConsumptionTotal += state.objects.gpu[id].energyConsumptionW) + ); + machine.memoryIds.forEach( + id => + (energyConsumptionTotal += + state.objects.memory[id].energyConsumptionW) + ); + machine.storageIds.forEach( + id => + (energyConsumptionTotal += + state.objects.storage[id].energyConsumptionW) + ); + } + }); + + return { + type: "energy", + fillFraction: Math.min(1, energyConsumptionTotal / rack.powerCapacityW) + }; +}; + +const RackSpaceFillContainer = connect(mapStateToProps)(RackFillBar); + +export default RackSpaceFillContainer; diff --git a/frontend/src/containers/app/map/RackSpaceFillContainer.js b/frontend/src/containers/app/map/RackSpaceFillContainer.js new file mode 100644 index 00000000..cc4d1251 --- /dev/null +++ b/frontend/src/containers/app/map/RackSpaceFillContainer.js @@ -0,0 +1,16 @@ +import { connect } from "react-redux"; +import RackFillBar from "../../../components/app/map/elements/RackFillBar"; + +const mapStateToProps = (state, ownProps) => { + const machineIds = + state.objects.rack[state.objects.tile[ownProps.tileId].objectId].machineIds; + return { + type: "space", + fillFraction: + machineIds.filter(id => id !== null).length / machineIds.length + }; +}; + +const RackSpaceFillContainer = connect(mapStateToProps)(RackFillBar); + +export default RackSpaceFillContainer; diff --git a/frontend/src/containers/app/map/RoomContainer.js b/frontend/src/containers/app/map/RoomContainer.js new file mode 100644 index 00000000..b83c7fa0 --- /dev/null +++ b/frontend/src/containers/app/map/RoomContainer.js @@ -0,0 +1,21 @@ +import { connect } from "react-redux"; +import { goFromBuildingToRoom } from "../../../actions/interaction-level"; +import RoomGroup from "../../../components/app/map/groups/RoomGroup"; + +const mapStateToProps = (state, ownProps) => { + return { + interactionLevel: state.interactionLevel, + currentRoomInConstruction: state.construction.currentRoomInConstruction, + room: state.objects.room[ownProps.roomId] + }; +}; + +const mapDispatchToProps = (dispatch, ownProps) => { + return { + onClick: () => dispatch(goFromBuildingToRoom(ownProps.roomId)) + }; +}; + +const RoomContainer = connect(mapStateToProps, mapDispatchToProps)(RoomGroup); + +export default RoomContainer; diff --git a/frontend/src/containers/app/map/TileContainer.js b/frontend/src/containers/app/map/TileContainer.js new file mode 100644 index 00000000..9e179924 --- /dev/null +++ b/frontend/src/containers/app/map/TileContainer.js @@ -0,0 +1,43 @@ +import { connect } from "react-redux"; +import { goFromRoomToRack } from "../../../actions/interaction-level"; +import TileGroup from "../../../components/app/map/groups/TileGroup"; +import { getStateLoad } from "../../../util/simulation-load"; + +const mapStateToProps = (state, ownProps) => { + const tile = state.objects.tile[ownProps.tileId]; + const inSimulation = state.currentExperimentId !== -1; + + let roomLoad = undefined; + if (inSimulation) { + if ( + state.states.room[state.currentTick] && + state.states.room[state.currentTick][tile.roomId] + ) { + roomLoad = getStateLoad( + state.loadMetric, + state.states.room[state.currentTick][tile.roomId] + ); + } + } + + return { + interactionLevel: state.interactionLevel, + tile, + inSimulation, + roomLoad + }; +}; + +const mapDispatchToProps = dispatch => { + return { + onClick: tile => { + if (tile.objectType) { + dispatch(goFromRoomToRack(tile.id)); + } + } + }; +}; + +const TileContainer = connect(mapStateToProps, mapDispatchToProps)(TileGroup); + +export default TileContainer; diff --git a/frontend/src/containers/app/map/WallContainer.js b/frontend/src/containers/app/map/WallContainer.js new file mode 100644 index 00000000..38192b05 --- /dev/null +++ b/frontend/src/containers/app/map/WallContainer.js @@ -0,0 +1,14 @@ +import { connect } from "react-redux"; +import WallGroup from "../../../components/app/map/groups/WallGroup"; + +const mapStateToProps = (state, ownProps) => { + return { + tiles: state.objects.room[ownProps.roomId].tileIds.map( + tileId => state.objects.tile[tileId] + ) + }; +}; + +const WallContainer = connect(mapStateToProps)(WallGroup); + +export default WallContainer; diff --git a/frontend/src/containers/app/map/controls/ScaleIndicatorContainer.js b/frontend/src/containers/app/map/controls/ScaleIndicatorContainer.js new file mode 100644 index 00000000..f075cde5 --- /dev/null +++ b/frontend/src/containers/app/map/controls/ScaleIndicatorContainer.js @@ -0,0 +1,14 @@ +import { connect } from "react-redux"; +import ScaleIndicatorComponent from "../../../../components/app/map/controls/ScaleIndicatorComponent"; + +const mapStateToProps = state => { + return { + scale: state.map.scale + }; +}; + +const ScaleIndicatorContainer = connect(mapStateToProps)( + ScaleIndicatorComponent +); + +export default ScaleIndicatorContainer; diff --git a/frontend/src/containers/app/map/controls/ZoomControlContainer.js b/frontend/src/containers/app/map/controls/ZoomControlContainer.js new file mode 100644 index 00000000..50910bd6 --- /dev/null +++ b/frontend/src/containers/app/map/controls/ZoomControlContainer.js @@ -0,0 +1,21 @@ +import { connect } from "react-redux"; +import { zoomInOnCenter } from "../../../../actions/map"; +import ZoomControlComponent from "../../../../components/app/map/controls/ZoomControlComponent"; + +const mapStateToProps = state => { + return { + mapScale: state.map.scale + }; +}; + +const mapDispatchToProps = dispatch => { + return { + zoomInOnCenter: zoomIn => dispatch(zoomInOnCenter(zoomIn)) + }; +}; + +const ZoomControlContainer = connect(mapStateToProps, mapDispatchToProps)( + ZoomControlComponent +); + +export default ZoomControlContainer; diff --git a/frontend/src/containers/app/map/layers/MapLayer.js b/frontend/src/containers/app/map/layers/MapLayer.js new file mode 100644 index 00000000..cf971350 --- /dev/null +++ b/frontend/src/containers/app/map/layers/MapLayer.js @@ -0,0 +1,13 @@ +import { connect } from "react-redux"; +import MapLayerComponent from "../../../../components/app/map/layers/MapLayerComponent"; + +const mapStateToProps = state => { + return { + mapPosition: state.map.position, + mapScale: state.map.scale + }; +}; + +const MapLayer = connect(mapStateToProps)(MapLayerComponent); + +export default MapLayer; diff --git a/frontend/src/containers/app/map/layers/ObjectHoverLayer.js b/frontend/src/containers/app/map/layers/ObjectHoverLayer.js new file mode 100644 index 00000000..9b28575e --- /dev/null +++ b/frontend/src/containers/app/map/layers/ObjectHoverLayer.js @@ -0,0 +1,37 @@ +import { connect } from "react-redux"; +import { addRackToTile } from "../../../../actions/topology/room"; +import ObjectHoverLayerComponent from "../../../../components/app/map/layers/ObjectHoverLayerComponent"; +import { findTileWithPosition } from "../../../../util/tile-calculations"; + +const mapStateToProps = state => { + return { + mapPosition: state.map.position, + mapScale: state.map.scale, + isEnabled: () => state.construction.inRackConstructionMode, + isValid: (x, y) => { + if (state.interactionLevel.mode !== "ROOM") { + return false; + } + + const currentRoom = state.objects.room[state.interactionLevel.roomId]; + const tiles = currentRoom.tileIds.map( + tileId => state.objects.tile[tileId] + ); + const tile = findTileWithPosition(tiles, x, y); + + return !(tile === null || tile.objectType); + } + }; +}; + +const mapDispatchToProps = dispatch => { + return { + onClick: (x, y) => dispatch(addRackToTile(x, y)) + }; +}; + +const ObjectHoverLayer = connect(mapStateToProps, mapDispatchToProps)( + ObjectHoverLayerComponent +); + +export default ObjectHoverLayer; diff --git a/frontend/src/containers/app/map/layers/RoomHoverLayer.js b/frontend/src/containers/app/map/layers/RoomHoverLayer.js new file mode 100644 index 00000000..020102bf --- /dev/null +++ b/frontend/src/containers/app/map/layers/RoomHoverLayer.js @@ -0,0 +1,55 @@ +import { connect } from "react-redux"; +import { toggleTileAtLocation } from "../../../../actions/topology/building"; +import RoomHoverLayerComponent from "../../../../components/app/map/layers/RoomHoverLayerComponent"; +import { + deriveValidNextTilePositions, + findPositionInPositions, + findPositionInRooms +} from "../../../../util/tile-calculations"; + +const mapStateToProps = state => { + return { + mapPosition: state.map.position, + mapScale: state.map.scale, + isEnabled: () => state.construction.currentRoomInConstruction !== -1, + isValid: (x, y) => { + const newRoom = Object.assign( + {}, + state.objects.room[state.construction.currentRoomInConstruction] + ); + const oldRooms = Object.keys(state.objects.room) + .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 + ); + + [...oldRooms, newRoom].forEach(room => { + room.tiles = room.tileIds.map(tileId => state.objects.tile[tileId]); + }); + if (newRoom.tileIds.length === 0) { + return findPositionInRooms(oldRooms, x, y) === -1; + } + + const validNextPositions = deriveValidNextTilePositions( + oldRooms, + newRoom.tiles + ); + return findPositionInPositions(validNextPositions, x, y) !== -1; + } + }; +}; + +const mapDispatchToProps = dispatch => { + return { + onClick: (x, y) => dispatch(toggleTileAtLocation(x, y)) + }; +}; + +const RoomHoverLayer = connect(mapStateToProps, mapDispatchToProps)( + RoomHoverLayerComponent +); + +export default RoomHoverLayer; diff --git a/frontend/src/containers/app/sidebars/elements/LoadBarContainer.js b/frontend/src/containers/app/sidebars/elements/LoadBarContainer.js new file mode 100644 index 00000000..2e637f9a --- /dev/null +++ b/frontend/src/containers/app/sidebars/elements/LoadBarContainer.js @@ -0,0 +1,32 @@ +import { connect } from "react-redux"; +import LoadBarComponent from "../../../../components/app/sidebars/elements/LoadBarComponent"; +import { getStateLoad } from "../../../../util/simulation-load"; + +const mapStateToProps = (state, ownProps) => { + let percent = 0; + let enabled = false; + + const objectStates = state.states[ownProps.objectType]; + if ( + objectStates[state.currentTick] && + objectStates[state.currentTick][ownProps.objectId] + ) { + percent = Math.floor( + 100 * + getStateLoad( + state.loadMetric, + objectStates[state.currentTick][ownProps.objectId] + ) + ); + enabled = true; + } + + return { + percent, + enabled + }; +}; + +const LoadBarContainer = connect(mapStateToProps)(LoadBarComponent); + +export default LoadBarContainer; diff --git a/frontend/src/containers/app/sidebars/elements/LoadChartContainer.js b/frontend/src/containers/app/sidebars/elements/LoadChartContainer.js new file mode 100644 index 00000000..57bfec38 --- /dev/null +++ b/frontend/src/containers/app/sidebars/elements/LoadChartContainer.js @@ -0,0 +1,31 @@ +import { connect } from "react-redux"; +import LoadChartComponent from "../../../../components/app/sidebars/elements/LoadChartComponent"; +import { getStateLoad } from "../../../../util/simulation-load"; + +const mapStateToProps = (state, ownProps) => { + const data = []; + + if (state.lastSimulatedTick !== -1) { + const objectStates = state.states[ownProps.objectType]; + Object.keys(objectStates).forEach(tick => { + if (objectStates[tick][ownProps.objectId]) { + data.push({ + x: tick, + y: getStateLoad( + state.loadMetric, + objectStates[tick][ownProps.objectId] + ) + }); + } + }); + } + + return { + data, + currentTick: state.currentTick + }; +}; + +const LoadChartContainer = connect(mapStateToProps)(LoadChartComponent); + +export default LoadChartContainer; diff --git a/frontend/src/containers/app/sidebars/simulation/ExperimentMetadataContainer.js b/frontend/src/containers/app/sidebars/simulation/ExperimentMetadataContainer.js new file mode 100644 index 00000000..25a0d9e9 --- /dev/null +++ b/frontend/src/containers/app/sidebars/simulation/ExperimentMetadataContainer.js @@ -0,0 +1,38 @@ +import { connect } from "react-redux"; +import ExperimentMetadataComponent from "../../../../components/app/sidebars/simulation/ExperimentMetadataComponent"; + +const mapStateToProps = state => { + if (!state.objects.experiment[state.currentExperimentId]) { + return { + experimentName: "Loading experiment", + pathName: "", + traceName: "", + schedulerName: "" + }; + } + + const path = + state.objects.path[ + state.objects.experiment[state.currentExperimentId].pathId + ]; + const pathName = path.name ? path.name : "Path " + path.id; + + return { + experimentName: state.objects.experiment[state.currentExperimentId].name, + pathName, + traceName: + state.objects.trace[ + state.objects.experiment[state.currentExperimentId].traceId + ].name, + schedulerName: + state.objects.scheduler[ + state.objects.experiment[state.currentExperimentId].schedulerName + ].name + }; +}; + +const ExperimentMetadataContainer = connect(mapStateToProps)( + ExperimentMetadataComponent +); + +export default ExperimentMetadataContainer; diff --git a/frontend/src/containers/app/sidebars/simulation/LoadMetricContainer.js b/frontend/src/containers/app/sidebars/simulation/LoadMetricContainer.js new file mode 100644 index 00000000..0c66b582 --- /dev/null +++ b/frontend/src/containers/app/sidebars/simulation/LoadMetricContainer.js @@ -0,0 +1,12 @@ +import { connect } from "react-redux"; +import LoadMetricComponent from "../../../../components/app/sidebars/simulation/LoadMetricComponent"; + +const mapStateToProps = state => { + return { + loadMetric: state.loadMetric + }; +}; + +const LoadMetricContainer = connect(mapStateToProps)(LoadMetricComponent); + +export default LoadMetricContainer; diff --git a/frontend/src/containers/app/sidebars/simulation/TaskContainer.js b/frontend/src/containers/app/sidebars/simulation/TaskContainer.js new file mode 100644 index 00000000..093d4266 --- /dev/null +++ b/frontend/src/containers/app/sidebars/simulation/TaskContainer.js @@ -0,0 +1,26 @@ +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 new file mode 100644 index 00000000..682b6cc9 --- /dev/null +++ b/frontend/src/containers/app/sidebars/simulation/TraceContainer.js @@ -0,0 +1,25 @@ +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/TopologySidebar.js b/frontend/src/containers/app/sidebars/topology/TopologySidebar.js new file mode 100644 index 00000000..31c902fc --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/TopologySidebar.js @@ -0,0 +1,12 @@ +import { connect } from "react-redux"; +import TopologySidebarComponent from "../../../../components/app/sidebars/topology/TopologySidebarComponent"; + +const mapStateToProps = state => { + return { + interactionLevel: state.interactionLevel + }; +}; + +const TopologySidebar = connect(mapStateToProps)(TopologySidebarComponent); + +export default TopologySidebar; diff --git a/frontend/src/containers/app/sidebars/topology/building/BuildingSidebarContainer.js b/frontend/src/containers/app/sidebars/topology/building/BuildingSidebarContainer.js new file mode 100644 index 00000000..da24b8f0 --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/building/BuildingSidebarContainer.js @@ -0,0 +1,14 @@ +import { connect } from "react-redux"; +import BuildingSidebarComponent from "../../../../../components/app/sidebars/topology/building/BuildingSidebarComponent"; + +const mapStateToProps = state => { + return { + inSimulation: state.currentExperimentId !== -1 + }; +}; + +const BuildingSidebarContainer = connect(mapStateToProps)( + BuildingSidebarComponent +); + +export default BuildingSidebarContainer; diff --git a/frontend/src/containers/app/sidebars/topology/building/NewRoomConstructionContainer.js b/frontend/src/containers/app/sidebars/topology/building/NewRoomConstructionContainer.js new file mode 100644 index 00000000..bb64cbb4 --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/building/NewRoomConstructionContainer.js @@ -0,0 +1,27 @@ +import { connect } from "react-redux"; +import { + cancelNewRoomConstruction, + finishNewRoomConstruction, + startNewRoomConstruction +} from "../../../../../actions/topology/building"; +import StartNewRoomConstructionComponent from "../../../../../components/app/sidebars/topology/building/NewRoomConstructionComponent"; + +const mapStateToProps = state => { + return { + currentRoomInConstruction: state.construction.currentRoomInConstruction + }; +}; + +const mapDispatchToProps = dispatch => { + return { + onStart: () => dispatch(startNewRoomConstruction()), + onFinish: () => dispatch(finishNewRoomConstruction()), + onCancel: () => dispatch(cancelNewRoomConstruction()) + }; +}; + +const NewRoomConstructionButton = connect(mapStateToProps, mapDispatchToProps)( + StartNewRoomConstructionComponent +); + +export default NewRoomConstructionButton; diff --git a/frontend/src/containers/app/sidebars/topology/machine/BackToRackContainer.js b/frontend/src/containers/app/sidebars/topology/machine/BackToRackContainer.js new file mode 100644 index 00000000..885c533d --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/machine/BackToRackContainer.js @@ -0,0 +1,15 @@ +import { connect } from "react-redux"; +import { goDownOneInteractionLevel } from "../../../../../actions/interaction-level"; +import BackToRackComponent from "../../../../../components/app/sidebars/topology/machine/BackToRackComponent"; + +const mapDispatchToProps = dispatch => { + return { + onClick: () => dispatch(goDownOneInteractionLevel()) + }; +}; + +const BackToRackContainer = connect(undefined, mapDispatchToProps)( + BackToRackComponent +); + +export default BackToRackContainer; diff --git a/frontend/src/containers/app/sidebars/topology/machine/DeleteMachineContainer.js b/frontend/src/containers/app/sidebars/topology/machine/DeleteMachineContainer.js new file mode 100644 index 00000000..f42c8ba7 --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/machine/DeleteMachineContainer.js @@ -0,0 +1,15 @@ +import { connect } from "react-redux"; +import { openDeleteMachineModal } from "../../../../../actions/modals/topology"; +import DeleteMachineComponent from "../../../../../components/app/sidebars/topology/machine/DeleteMachineComponent"; + +const mapDispatchToProps = dispatch => { + return { + onClick: () => dispatch(openDeleteMachineModal()) + }; +}; + +const DeleteMachineContainer = connect(undefined, mapDispatchToProps)( + DeleteMachineComponent +); + +export default DeleteMachineContainer; diff --git a/frontend/src/containers/app/sidebars/topology/machine/MachineNameContainer.js b/frontend/src/containers/app/sidebars/topology/machine/MachineNameContainer.js new file mode 100644 index 00000000..05d2bf80 --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/machine/MachineNameContainer.js @@ -0,0 +1,12 @@ +import { connect } from "react-redux"; +import MachineNameComponent from "../../../../../components/app/sidebars/topology/machine/MachineNameComponent"; + +const mapStateToProps = state => { + return { + position: state.interactionLevel.position + }; +}; + +const MachineNameContainer = connect(mapStateToProps)(MachineNameComponent); + +export default MachineNameContainer; diff --git a/frontend/src/containers/app/sidebars/topology/machine/MachineSidebarContainer.js b/frontend/src/containers/app/sidebars/topology/machine/MachineSidebarContainer.js new file mode 100644 index 00000000..7729385e --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/machine/MachineSidebarContainer.js @@ -0,0 +1,18 @@ +import { connect } from "react-redux"; +import MachineSidebarComponent from "../../../../../components/app/sidebars/topology/machine/MachineSidebarComponent"; + +const mapStateToProps = state => { + return { + inSimulation: state.currentExperimentId !== -1, + machineId: + state.objects.rack[ + state.objects.tile[state.interactionLevel.tileId].objectId + ].machineIds[state.interactionLevel.position - 1] + }; +}; + +const MachineSidebarContainer = connect(mapStateToProps)( + MachineSidebarComponent +); + +export default MachineSidebarContainer; diff --git a/frontend/src/containers/app/sidebars/topology/machine/UnitAddContainer.js b/frontend/src/containers/app/sidebars/topology/machine/UnitAddContainer.js new file mode 100644 index 00000000..0e5a6073 --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/machine/UnitAddContainer.js @@ -0,0 +1,21 @@ +import { connect } from "react-redux"; +import { addUnit } from "../../../../../actions/topology/machine"; +import UnitAddComponent from "../../../../../components/app/sidebars/topology/machine/UnitAddComponent"; + +const mapStateToProps = (state, ownProps) => { + return { + units: Object.values(state.objects[ownProps.unitType]) + }; +}; + +const mapDispatchToProps = (dispatch, ownProps) => { + return { + onAdd: id => dispatch(addUnit(ownProps.unitType, id)) + }; +}; + +const UnitAddContainer = connect(mapStateToProps, mapDispatchToProps)( + UnitAddComponent +); + +export default UnitAddContainer; diff --git a/frontend/src/containers/app/sidebars/topology/machine/UnitContainer.js b/frontend/src/containers/app/sidebars/topology/machine/UnitContainer.js new file mode 100644 index 00000000..a919e8d3 --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/machine/UnitContainer.js @@ -0,0 +1,22 @@ +import { connect } from "react-redux"; +import { deleteUnit } from "../../../../../actions/topology/machine"; +import UnitComponent from "../../../../../components/app/sidebars/topology/machine/UnitComponent"; + +const mapStateToProps = (state, ownProps) => { + return { + unit: state.objects[ownProps.unitType][ownProps.unitId], + inSimulation: state.currentExperimentId !== -1 + }; +}; + +const mapDispatchToProps = (dispatch, ownProps) => { + return { + onDelete: () => dispatch(deleteUnit(ownProps.unitType, ownProps.index)) + }; +}; + +const UnitContainer = connect(mapStateToProps, mapDispatchToProps)( + UnitComponent +); + +export default UnitContainer; diff --git a/frontend/src/containers/app/sidebars/topology/machine/UnitListContainer.js b/frontend/src/containers/app/sidebars/topology/machine/UnitListContainer.js new file mode 100644 index 00000000..6554b8f8 --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/machine/UnitListContainer.js @@ -0,0 +1,18 @@ +import { connect } from "react-redux"; +import UnitListComponent from "../../../../../components/app/sidebars/topology/machine/UnitListComponent"; + +const mapStateToProps = (state, ownProps) => { + return { + unitIds: + state.objects.machine[ + state.objects.rack[ + state.objects.tile[state.interactionLevel.tileId].objectId + ].machineIds[state.interactionLevel.position - 1] + ][ownProps.unitType + "Ids"], + inSimulation: state.currentExperimentId !== -1 + }; +}; + +const UnitListContainer = connect(mapStateToProps)(UnitListComponent); + +export default UnitListContainer; diff --git a/frontend/src/containers/app/sidebars/topology/machine/UnitTabsContainer.js b/frontend/src/containers/app/sidebars/topology/machine/UnitTabsContainer.js new file mode 100644 index 00000000..85d83877 --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/machine/UnitTabsContainer.js @@ -0,0 +1,12 @@ +import { connect } from "react-redux"; +import UnitTabsComponent from "../../../../../components/app/sidebars/topology/machine/UnitTabsComponent"; + +const mapStateToProps = state => { + return { + inSimulation: state.currentExperimentId !== -1 + }; +}; + +const UnitTabsContainer = connect(mapStateToProps)(UnitTabsComponent); + +export default UnitTabsContainer; diff --git a/frontend/src/containers/app/sidebars/topology/rack/BackToRoomContainer.js b/frontend/src/containers/app/sidebars/topology/rack/BackToRoomContainer.js new file mode 100644 index 00000000..1b1bb2b0 --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/rack/BackToRoomContainer.js @@ -0,0 +1,15 @@ +import { connect } from "react-redux"; +import { goDownOneInteractionLevel } from "../../../../../actions/interaction-level"; +import BackToRoomComponent from "../../../../../components/app/sidebars/topology/rack/BackToRoomComponent"; + +const mapDispatchToProps = dispatch => { + return { + onClick: () => dispatch(goDownOneInteractionLevel()) + }; +}; + +const BackToRoomContainer = connect(undefined, mapDispatchToProps)( + BackToRoomComponent +); + +export default BackToRoomContainer; diff --git a/frontend/src/containers/app/sidebars/topology/rack/DeleteRackContainer.js b/frontend/src/containers/app/sidebars/topology/rack/DeleteRackContainer.js new file mode 100644 index 00000000..a54ceb23 --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/rack/DeleteRackContainer.js @@ -0,0 +1,15 @@ +import { connect } from "react-redux"; +import { openDeleteRackModal } from "../../../../../actions/modals/topology"; +import DeleteRackComponent from "../../../../../components/app/sidebars/topology/rack/DeleteRackComponent"; + +const mapDispatchToProps = dispatch => { + return { + onClick: () => dispatch(openDeleteRackModal()) + }; +}; + +const DeleteRackContainer = connect(undefined, mapDispatchToProps)( + DeleteRackComponent +); + +export default DeleteRackContainer; diff --git a/frontend/src/containers/app/sidebars/topology/rack/EmptySlotContainer.js b/frontend/src/containers/app/sidebars/topology/rack/EmptySlotContainer.js new file mode 100644 index 00000000..527805a2 --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/rack/EmptySlotContainer.js @@ -0,0 +1,21 @@ +import { connect } from "react-redux"; +import { addMachine } from "../../../../../actions/topology/rack"; +import EmptySlotComponent from "../../../../../components/app/sidebars/topology/rack/EmptySlotComponent"; + +const mapStateToProps = state => { + return { + inSimulation: state.currentExperimentId !== -1 + }; +}; + +const mapDispatchToProps = (dispatch, ownProps) => { + return { + onAdd: () => dispatch(addMachine(ownProps.position)) + }; +}; + +const EmptySlotContainer = connect(mapStateToProps, mapDispatchToProps)( + EmptySlotComponent +); + +export default EmptySlotContainer; diff --git a/frontend/src/containers/app/sidebars/topology/rack/MachineContainer.js b/frontend/src/containers/app/sidebars/topology/rack/MachineContainer.js new file mode 100644 index 00000000..8cd177e7 --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/rack/MachineContainer.js @@ -0,0 +1,40 @@ +import { connect } from "react-redux"; +import { goFromRackToMachine } from "../../../../../actions/interaction-level"; +import MachineComponent from "../../../../../components/app/sidebars/topology/rack/MachineComponent"; +import { getStateLoad } from "../../../../../util/simulation-load"; + +const mapStateToProps = (state, ownProps) => { + const machine = state.objects.machine[ownProps.machineId]; + const inSimulation = state.currentExperimentId !== -1; + + let machineLoad = undefined; + if (inSimulation) { + if ( + state.states.machine[state.currentTick] && + state.states.machine[state.currentTick][machine.id] + ) { + machineLoad = getStateLoad( + state.loadMetric, + state.states.machine[state.currentTick][machine.id] + ); + } + } + + return { + machine, + inSimulation, + machineLoad + }; +}; + +const mapDispatchToProps = (dispatch, ownProps) => { + return { + onClick: () => dispatch(goFromRackToMachine(ownProps.position)) + }; +}; + +const MachineContainer = connect(mapStateToProps, mapDispatchToProps)( + MachineComponent +); + +export default MachineContainer; diff --git a/frontend/src/containers/app/sidebars/topology/rack/MachineListContainer.js b/frontend/src/containers/app/sidebars/topology/rack/MachineListContainer.js new file mode 100644 index 00000000..b19a50ae --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/rack/MachineListContainer.js @@ -0,0 +1,15 @@ +import { connect } from "react-redux"; +import MachineListComponent from "../../../../../components/app/sidebars/topology/rack/MachineListComponent"; + +const mapStateToProps = state => { + return { + machineIds: + state.objects.rack[ + state.objects.tile[state.interactionLevel.tileId].objectId + ].machineIds + }; +}; + +const MachineListContainer = connect(mapStateToProps)(MachineListComponent); + +export default MachineListContainer; diff --git a/frontend/src/containers/app/sidebars/topology/rack/RackNameContainer.js b/frontend/src/containers/app/sidebars/topology/rack/RackNameContainer.js new file mode 100644 index 00000000..8f364ca0 --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/rack/RackNameContainer.js @@ -0,0 +1,24 @@ +import { connect } from "react-redux"; +import { openEditRackNameModal } from "../../../../../actions/modals/topology"; +import RackNameComponent from "../../../../../components/app/sidebars/topology/rack/RackNameComponent"; + +const mapStateToProps = state => { + return { + rackName: + state.objects.rack[ + state.objects.tile[state.interactionLevel.tileId].objectId + ].name + }; +}; + +const mapDispatchToProps = dispatch => { + return { + onEdit: () => dispatch(openEditRackNameModal()) + }; +}; + +const RackNameContainer = connect(mapStateToProps, mapDispatchToProps)( + RackNameComponent +); + +export default RackNameContainer; diff --git a/frontend/src/containers/app/sidebars/topology/rack/RackSidebarContainer.js b/frontend/src/containers/app/sidebars/topology/rack/RackSidebarContainer.js new file mode 100644 index 00000000..0a2bfdcc --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/rack/RackSidebarContainer.js @@ -0,0 +1,13 @@ +import { connect } from "react-redux"; +import RackSidebarComponent from "../../../../../components/app/sidebars/topology/rack/RackSidebarComponent"; + +const mapStateToProps = state => { + return { + rackId: state.objects.tile[state.interactionLevel.tileId].objectId, + inSimulation: state.currentExperimentId !== -1 + }; +}; + +const RackSidebarContainer = connect(mapStateToProps)(RackSidebarComponent); + +export default RackSidebarContainer; diff --git a/frontend/src/containers/app/sidebars/topology/room/BackToBuildingContainer.js b/frontend/src/containers/app/sidebars/topology/room/BackToBuildingContainer.js new file mode 100644 index 00000000..02288b7b --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/room/BackToBuildingContainer.js @@ -0,0 +1,15 @@ +import { connect } from "react-redux"; +import { goDownOneInteractionLevel } from "../../../../../actions/interaction-level"; +import BackToBuildingComponent from "../../../../../components/app/sidebars/topology/room/BackToBuildingComponent"; + +const mapDispatchToProps = dispatch => { + return { + onClick: () => dispatch(goDownOneInteractionLevel()) + }; +}; + +const BackToBuildingContainer = connect(undefined, mapDispatchToProps)( + BackToBuildingComponent +); + +export default BackToBuildingContainer; diff --git a/frontend/src/containers/app/sidebars/topology/room/DeleteRoomContainer.js b/frontend/src/containers/app/sidebars/topology/room/DeleteRoomContainer.js new file mode 100644 index 00000000..5223061d --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/room/DeleteRoomContainer.js @@ -0,0 +1,15 @@ +import { connect } from "react-redux"; +import { openDeleteRoomModal } from "../../../../../actions/modals/topology"; +import DeleteRoomComponent from "../../../../../components/app/sidebars/topology/room/DeleteRoomComponent"; + +const mapDispatchToProps = dispatch => { + return { + onClick: () => dispatch(openDeleteRoomModal()) + }; +}; + +const DeleteRoomContainer = connect(undefined, mapDispatchToProps)( + DeleteRoomComponent +); + +export default DeleteRoomContainer; diff --git a/frontend/src/containers/app/sidebars/topology/room/EditRoomContainer.js b/frontend/src/containers/app/sidebars/topology/room/EditRoomContainer.js new file mode 100644 index 00000000..81052f54 --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/room/EditRoomContainer.js @@ -0,0 +1,26 @@ +import { connect } from "react-redux"; +import { + finishRoomEdit, + startRoomEdit +} from "../../../../../actions/topology/building"; +import EditRoomComponent from "../../../../../components/app/sidebars/topology/room/EditRoomComponent"; + +const mapStateToProps = state => { + return { + isEditing: state.construction.currentRoomInConstruction !== -1, + isInRackConstructionMode: state.construction.inRackConstructionMode + }; +}; + +const mapDispatchToProps = dispatch => { + return { + onEdit: () => dispatch(startRoomEdit()), + onFinish: () => dispatch(finishRoomEdit()) + }; +}; + +const EditRoomContainer = connect(mapStateToProps, mapDispatchToProps)( + EditRoomComponent +); + +export default EditRoomContainer; diff --git a/frontend/src/containers/app/sidebars/topology/room/RackConstructionContainer.js b/frontend/src/containers/app/sidebars/topology/room/RackConstructionContainer.js new file mode 100644 index 00000000..c784d3ae --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/room/RackConstructionContainer.js @@ -0,0 +1,26 @@ +import { connect } from "react-redux"; +import { + startRackConstruction, + stopRackConstruction +} from "../../../../../actions/topology/room"; +import RackConstructionComponent from "../../../../../components/app/sidebars/topology/room/RackConstructionComponent"; + +const mapStateToProps = state => { + return { + inRackConstructionMode: state.construction.inRackConstructionMode, + isEditingRoom: state.construction.currentRoomInConstruction !== -1 + }; +}; + +const mapDispatchToProps = dispatch => { + return { + onStart: () => dispatch(startRackConstruction()), + onStop: () => dispatch(stopRackConstruction()) + }; +}; + +const RackConstructionContainer = connect(mapStateToProps, mapDispatchToProps)( + RackConstructionComponent +); + +export default RackConstructionContainer; diff --git a/frontend/src/containers/app/sidebars/topology/room/RoomNameContainer.js b/frontend/src/containers/app/sidebars/topology/room/RoomNameContainer.js new file mode 100644 index 00000000..36125521 --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/room/RoomNameContainer.js @@ -0,0 +1,21 @@ +import { connect } from "react-redux"; +import { openEditRoomNameModal } from "../../../../../actions/modals/topology"; +import RoomNameComponent from "../../../../../components/app/sidebars/topology/room/RoomNameComponent"; + +const mapStateToProps = state => { + return { + roomName: state.objects.room[state.interactionLevel.roomId].name + }; +}; + +const mapDispatchToProps = dispatch => { + return { + onEdit: () => dispatch(openEditRoomNameModal()) + }; +}; + +const RoomNameContainer = connect(mapStateToProps, mapDispatchToProps)( + RoomNameComponent +); + +export default RoomNameContainer; diff --git a/frontend/src/containers/app/sidebars/topology/room/RoomSidebarContainer.js b/frontend/src/containers/app/sidebars/topology/room/RoomSidebarContainer.js new file mode 100644 index 00000000..38d5fb80 --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/room/RoomSidebarContainer.js @@ -0,0 +1,14 @@ +import { connect } from "react-redux"; +import RoomSidebarComponent from "../../../../../components/app/sidebars/topology/room/RoomSidebarComponent"; + +const mapStateToProps = state => { + return { + roomId: state.interactionLevel.roomId, + roomType: state.objects.room[state.interactionLevel.roomId].roomType, + inSimulation: state.currentExperimentId !== -1 + }; +}; + +const RoomSidebarContainer = connect(mapStateToProps)(RoomSidebarComponent); + +export default RoomSidebarContainer; diff --git a/frontend/src/containers/app/sidebars/topology/room/RoomTypeContainer.js b/frontend/src/containers/app/sidebars/topology/room/RoomTypeContainer.js new file mode 100644 index 00000000..414852f1 --- /dev/null +++ b/frontend/src/containers/app/sidebars/topology/room/RoomTypeContainer.js @@ -0,0 +1,12 @@ +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 new file mode 100644 index 00000000..4e3c3d81 --- /dev/null +++ b/frontend/src/containers/app/timeline/PlayButtonContainer.js @@ -0,0 +1,27 @@ +import { connect } from "react-redux"; +import { + pauseSimulation, + playSimulation +} from "../../../actions/simulation/playback"; +import PlayButtonComponent from "../../../components/app/timeline/PlayButtonComponent"; + +const mapStateToProps = state => { + return { + isPlaying: state.isPlaying, + currentTick: state.currentTick, + lastSimulatedTick: state.lastSimulatedTick + }; +}; + +const mapDispatchToProps = dispatch => { + return { + onPlay: () => dispatch(playSimulation()), + onPause: () => dispatch(pauseSimulation()) + }; +}; + +const PlayButtonContainer = connect(mapStateToProps, mapDispatchToProps)( + PlayButtonComponent +); + +export default PlayButtonContainer; diff --git a/frontend/src/containers/app/timeline/TimelineContainer.js b/frontend/src/containers/app/timeline/TimelineContainer.js new file mode 100644 index 00000000..74d37d58 --- /dev/null +++ b/frontend/src/containers/app/timeline/TimelineContainer.js @@ -0,0 +1,41 @@ +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 + }; +}; + +const mapDispatchToProps = dispatch => { + return { + incrementTick: () => dispatch(incrementTick()), + pauseSimulation: () => dispatch(pauseSimulation()), + setCurrentDatacenter: id => dispatch(setCurrentDatacenter(id)) + }; +}; + +const TimelineContainer = connect(mapStateToProps, mapDispatchToProps)( + TimelineComponent +); + +export default TimelineContainer; diff --git a/frontend/src/containers/app/timeline/TimelineControlsContainer.js b/frontend/src/containers/app/timeline/TimelineControlsContainer.js new file mode 100644 index 00000000..ac851b2e --- /dev/null +++ b/frontend/src/containers/app/timeline/TimelineControlsContainer.js @@ -0,0 +1,36 @@ +import { connect } from "react-redux"; +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 + }; +}; + +const mapDispatchToProps = dispatch => { + return { + goToTick: tick => dispatch(goToTick(tick)) + }; +}; + +const TimelineControlsContainer = connect(mapStateToProps, mapDispatchToProps)( + TimelineControlsComponent +); + +export default TimelineControlsContainer; diff --git a/frontend/src/containers/app/timeline/TimelineLabelsContainer.js b/frontend/src/containers/app/timeline/TimelineLabelsContainer.js new file mode 100644 index 00000000..9d7f268d --- /dev/null +++ b/frontend/src/containers/app/timeline/TimelineLabelsContainer.js @@ -0,0 +1,15 @@ +import { connect } from "react-redux"; +import TimelineLabelsComponent from "../../../components/app/timeline/TimelineLabelsComponent"; + +const mapStateToProps = state => { + return { + currentTick: state.currentTick, + lastSimulatedTick: state.lastSimulatedTick + }; +}; + +const TimelineLabelsContainer = connect(mapStateToProps)( + TimelineLabelsComponent +); + +export default TimelineLabelsContainer; diff --git a/frontend/src/containers/auth/Login.js b/frontend/src/containers/auth/Login.js new file mode 100644 index 00000000..15af8e62 --- /dev/null +++ b/frontend/src/containers/auth/Login.js @@ -0,0 +1,65 @@ +import PropTypes from "prop-types"; +import React from "react"; +import GoogleLogin from "react-google-login"; +import { connect } from "react-redux"; +import { logIn } from "../../actions/auth"; + +class LoginContainer extends React.Component { + static propTypes = { + visible: PropTypes.bool.isRequired, + onLogin: PropTypes.func.isRequired + }; + + onAuthResponse(response) { + this.props.onLogin({ + email: response.getBasicProfile().getEmail(), + givenName: response.getBasicProfile().getGivenName(), + familyName: response.getBasicProfile().getFamilyName(), + googleId: response.googleId, + authToken: response.getAuthResponse().id_token, + expiresAt: response.getAuthResponse().expires_at + }); + } + + onAuthFailure(error) { + console.error(error); + } + + render() { + if (!this.props.visible) { + return <span />; + } + + return ( + <GoogleLogin + clientId={process.env.REACT_APP_OAUTH_CLIENT_ID} + onSuccess={this.onAuthResponse.bind(this)} + onFailure={this.onAuthFailure.bind(this)} + render={renderProps => ( + <span onClick={renderProps.onClick} className="login btn btn-primary"> + <span className="fa fa-google" /> Login with Google + </span> + )} + /> + ); + } +} + +const mapStateToProps = (state, ownProps) => { + return { + visible: ownProps.visible + }; +}; + +const mapDispatchToProps = dispatch => { + return { + onLogin: payload => dispatch(logIn(payload)) + }; +}; + +const Login = connect( + mapStateToProps, + mapDispatchToProps +)(LoginContainer); + +export default Login; diff --git a/frontend/src/containers/auth/Logout.js b/frontend/src/containers/auth/Logout.js new file mode 100644 index 00000000..918932f6 --- /dev/null +++ b/frontend/src/containers/auth/Logout.js @@ -0,0 +1,13 @@ +import { connect } from "react-redux"; +import { logOut } from "../../actions/auth"; +import LogoutButton from "../../components/navigation/LogoutButton"; + +const mapDispatchToProps = dispatch => { + return { + onLogout: () => dispatch(logOut()) + }; +}; + +const Logout = connect(undefined, mapDispatchToProps)(LogoutButton); + +export default Logout; diff --git a/frontend/src/containers/auth/ProfileName.js b/frontend/src/containers/auth/ProfileName.js new file mode 100644 index 00000000..21941bd2 --- /dev/null +++ b/frontend/src/containers/auth/ProfileName.js @@ -0,0 +1,14 @@ +import React from "react"; +import { connect } from "react-redux"; + +const mapStateToProps = state => { + return { + text: state.auth.givenName + " " + state.auth.familyName + }; +}; + +const SpanElement = ({ text }) => <span>{text}</span>; + +const ProfileName = connect(mapStateToProps)(SpanElement); + +export default ProfileName; diff --git a/frontend/src/containers/experiments/ExperimentListContainer.js b/frontend/src/containers/experiments/ExperimentListContainer.js new file mode 100644 index 00000000..53bb1dad --- /dev/null +++ b/frontend/src/containers/experiments/ExperimentListContainer.js @@ -0,0 +1,28 @@ +import { connect } from "react-redux"; +import ExperimentListComponent from "../../components/experiments/ExperimentListComponent"; + +const mapStateToProps = state => { + if ( + state.currentSimulationId === -1 || + !("experimentIds" in state.objects.simulation[state.currentSimulationId]) + ) { + return { + loading: true, + experimentIds: [] + }; + } + + const experimentIds = + state.objects.simulation[state.currentSimulationId].experimentIds; + if (experimentIds) { + return { + experimentIds + }; + } +}; + +const ExperimentListContainer = connect(mapStateToProps)( + ExperimentListComponent +); + +export default ExperimentListContainer; diff --git a/frontend/src/containers/experiments/ExperimentRowContainer.js b/frontend/src/containers/experiments/ExperimentRowContainer.js new file mode 100644 index 00000000..96ebc3db --- /dev/null +++ b/frontend/src/containers/experiments/ExperimentRowContainer.js @@ -0,0 +1,30 @@ +import { connect } from "react-redux"; +import { deleteExperiment } from "../../actions/experiments"; +import ExperimentRowComponent from "../../components/experiments/ExperimentRowComponent"; + +const mapStateToProps = (state, ownProps) => { + const experiment = Object.assign( + {}, + state.objects.experiment[ownProps.experimentId] + ); + experiment.trace = state.objects.trace[experiment.traceId]; + experiment.scheduler = state.objects.scheduler[experiment.schedulerName]; + experiment.path = state.objects.path[experiment.pathId]; + + return { + experiment, + simulationId: state.currentSimulationId + }; +}; + +const mapDispatchToProps = dispatch => { + return { + onDelete: id => dispatch(deleteExperiment(id)) + }; +}; + +const ExperimentRowContainer = connect(mapStateToProps, mapDispatchToProps)( + ExperimentRowComponent +); + +export default ExperimentRowContainer; diff --git a/frontend/src/containers/experiments/NewExperimentButtonContainer.js b/frontend/src/containers/experiments/NewExperimentButtonContainer.js new file mode 100644 index 00000000..60eb92a6 --- /dev/null +++ b/frontend/src/containers/experiments/NewExperimentButtonContainer.js @@ -0,0 +1,15 @@ +import { connect } from "react-redux"; +import { openNewExperimentModal } from "../../actions/modals/experiments"; +import NewExperimentButtonComponent from "../../components/experiments/NewExperimentButtonComponent"; + +const mapDispatchToProps = dispatch => { + return { + onClick: () => dispatch(openNewExperimentModal()) + }; +}; + +const NewExperimentButtonContainer = connect(undefined, mapDispatchToProps)( + NewExperimentButtonComponent +); + +export default NewExperimentButtonContainer; diff --git a/frontend/src/containers/modals/DeleteMachineModal.js b/frontend/src/containers/modals/DeleteMachineModal.js new file mode 100644 index 00000000..eba37833 --- /dev/null +++ b/frontend/src/containers/modals/DeleteMachineModal.js @@ -0,0 +1,37 @@ +import React from "react"; +import { connect } from "react-redux"; +import { closeDeleteMachineModal } from "../../actions/modals/topology"; +import { deleteMachine } from "../../actions/topology/machine"; +import ConfirmationModal from "../../components/modals/ConfirmationModal"; + +const DeleteMachineModalComponent = ({ visible, callback }) => ( + <ConfirmationModal + title="Delete this machine" + message="Are you sure you want to delete this machine?" + show={visible} + callback={callback} + /> +); + +const mapStateToProps = state => { + return { + visible: state.modals.deleteMachineModalVisible + }; +}; + +const mapDispatchToProps = dispatch => { + return { + callback: isConfirmed => { + if (isConfirmed) { + dispatch(deleteMachine()); + } + dispatch(closeDeleteMachineModal()); + } + }; +}; + +const DeleteMachineModal = connect(mapStateToProps, mapDispatchToProps)( + DeleteMachineModalComponent +); + +export default DeleteMachineModal; diff --git a/frontend/src/containers/modals/DeleteProfileModal.js b/frontend/src/containers/modals/DeleteProfileModal.js new file mode 100644 index 00000000..674e9408 --- /dev/null +++ b/frontend/src/containers/modals/DeleteProfileModal.js @@ -0,0 +1,37 @@ +import React from "react"; +import { connect } from "react-redux"; +import { closeDeleteProfileModal } from "../../actions/modals/profile"; +import { deleteCurrentUser } from "../../actions/users"; +import ConfirmationModal from "../../components/modals/ConfirmationModal"; + +const DeleteProfileModalComponent = ({ visible, callback }) => ( + <ConfirmationModal + title="Delete my account" + message="Are you sure you want to delete your OpenDC account?" + show={visible} + callback={callback} + /> +); + +const mapStateToProps = state => { + return { + visible: state.modals.deleteProfileModalVisible + }; +}; + +const mapDispatchToProps = dispatch => { + return { + callback: isConfirmed => { + if (isConfirmed) { + dispatch(deleteCurrentUser()); + } + dispatch(closeDeleteProfileModal()); + } + }; +}; + +const DeleteProfileModal = connect(mapStateToProps, mapDispatchToProps)( + DeleteProfileModalComponent +); + +export default DeleteProfileModal; diff --git a/frontend/src/containers/modals/DeleteRackModal.js b/frontend/src/containers/modals/DeleteRackModal.js new file mode 100644 index 00000000..41bacb37 --- /dev/null +++ b/frontend/src/containers/modals/DeleteRackModal.js @@ -0,0 +1,37 @@ +import React from "react"; +import { connect } from "react-redux"; +import { closeDeleteRackModal } from "../../actions/modals/topology"; +import { deleteRack } from "../../actions/topology/rack"; +import ConfirmationModal from "../../components/modals/ConfirmationModal"; + +const DeleteRackModalComponent = ({ visible, callback }) => ( + <ConfirmationModal + title="Delete this rack" + message="Are you sure you want to delete this rack?" + show={visible} + callback={callback} + /> +); + +const mapStateToProps = state => { + return { + visible: state.modals.deleteRackModalVisible + }; +}; + +const mapDispatchToProps = dispatch => { + return { + callback: isConfirmed => { + if (isConfirmed) { + dispatch(deleteRack()); + } + dispatch(closeDeleteRackModal()); + } + }; +}; + +const DeleteRackModal = connect(mapStateToProps, mapDispatchToProps)( + DeleteRackModalComponent +); + +export default DeleteRackModal; diff --git a/frontend/src/containers/modals/DeleteRoomModal.js b/frontend/src/containers/modals/DeleteRoomModal.js new file mode 100644 index 00000000..339ff22c --- /dev/null +++ b/frontend/src/containers/modals/DeleteRoomModal.js @@ -0,0 +1,37 @@ +import React from "react"; +import { connect } from "react-redux"; +import { closeDeleteRoomModal } from "../../actions/modals/topology"; +import { deleteRoom } from "../../actions/topology/room"; +import ConfirmationModal from "../../components/modals/ConfirmationModal"; + +const DeleteRoomModalComponent = ({ visible, callback }) => ( + <ConfirmationModal + title="Delete this room" + message="Are you sure you want to delete this room?" + show={visible} + callback={callback} + /> +); + +const mapStateToProps = state => { + return { + visible: state.modals.deleteRoomModalVisible + }; +}; + +const mapDispatchToProps = dispatch => { + return { + callback: isConfirmed => { + if (isConfirmed) { + dispatch(deleteRoom()); + } + dispatch(closeDeleteRoomModal()); + } + }; +}; + +const DeleteRoomModal = connect(mapStateToProps, mapDispatchToProps)( + DeleteRoomModalComponent +); + +export default DeleteRoomModal; diff --git a/frontend/src/containers/modals/EditRackNameModal.js b/frontend/src/containers/modals/EditRackNameModal.js new file mode 100644 index 00000000..748e847b --- /dev/null +++ b/frontend/src/containers/modals/EditRackNameModal.js @@ -0,0 +1,44 @@ +import React from "react"; +import { connect } from "react-redux"; +import { closeEditRackNameModal } from "../../actions/modals/topology"; +import { editRackName } from "../../actions/topology/rack"; +import TextInputModal from "../../components/modals/TextInputModal"; + +const EditRackNameModalComponent = ({ visible, previousName, callback }) => ( + <TextInputModal + title="Edit rack name" + label="Rack name" + show={visible} + initialValue={previousName} + callback={callback} + /> +); + +const mapStateToProps = state => { + return { + visible: state.modals.editRackNameModalVisible, + previousName: + state.interactionLevel.mode === "RACK" + ? state.objects.rack[ + state.objects.tile[state.interactionLevel.tileId].objectId + ].name + : "" + }; +}; + +const mapDispatchToProps = dispatch => { + return { + callback: name => { + if (name) { + dispatch(editRackName(name)); + } + dispatch(closeEditRackNameModal()); + } + }; +}; + +const EditRackNameModal = connect(mapStateToProps, mapDispatchToProps)( + EditRackNameModalComponent +); + +export default EditRackNameModal; diff --git a/frontend/src/containers/modals/EditRoomNameModal.js b/frontend/src/containers/modals/EditRoomNameModal.js new file mode 100644 index 00000000..be6c547c --- /dev/null +++ b/frontend/src/containers/modals/EditRoomNameModal.js @@ -0,0 +1,42 @@ +import React from "react"; +import { connect } from "react-redux"; +import { closeEditRoomNameModal } from "../../actions/modals/topology"; +import { editRoomName } from "../../actions/topology/room"; +import TextInputModal from "../../components/modals/TextInputModal"; + +const EditRoomNameModalComponent = ({ visible, previousName, callback }) => ( + <TextInputModal + title="Edit room name" + label="Room name" + show={visible} + initialValue={previousName} + callback={callback} + /> +); + +const mapStateToProps = state => { + return { + visible: state.modals.editRoomNameModalVisible, + previousName: + state.interactionLevel.mode === "ROOM" + ? state.objects.room[state.interactionLevel.roomId].name + : "" + }; +}; + +const mapDispatchToProps = dispatch => { + return { + callback: name => { + if (name) { + dispatch(editRoomName(name)); + } + dispatch(closeEditRoomNameModal()); + } + }; +}; + +const EditRoomNameModal = connect(mapStateToProps, mapDispatchToProps)( + EditRoomNameModalComponent +); + +export default EditRoomNameModal; diff --git a/frontend/src/containers/modals/NewExperimentModal.js b/frontend/src/containers/modals/NewExperimentModal.js new file mode 100644 index 00000000..c703c39a --- /dev/null +++ b/frontend/src/containers/modals/NewExperimentModal.js @@ -0,0 +1,39 @@ +import { connect } from "react-redux"; +import { addExperiment } from "../../actions/experiments"; +import { closeNewExperimentModal } from "../../actions/modals/experiments"; +import NewExperimentModalComponent from "../../components/modals/custom-components/NewExperimentModalComponent"; + +const mapStateToProps = state => { + return { + show: state.modals.newExperimentModalVisible, + paths: Object.values(state.objects.path).filter( + path => path.simulationId === state.currentSimulationId + ), + traces: Object.values(state.objects.trace), + schedulers: Object.values(state.objects.scheduler) + }; +}; + +const mapDispatchToProps = dispatch => { + return { + callback: (name, pathId, traceId, schedulerName) => { + if (name) { + dispatch( + addExperiment({ + name, + pathId, + traceId, + schedulerName + }) + ); + } + dispatch(closeNewExperimentModal()); + } + }; +}; + +const NewExperimentModal = connect(mapStateToProps, mapDispatchToProps)( + NewExperimentModalComponent +); + +export default NewExperimentModal; diff --git a/frontend/src/containers/modals/NewSimulationModal.js b/frontend/src/containers/modals/NewSimulationModal.js new file mode 100644 index 00000000..80789cd2 --- /dev/null +++ b/frontend/src/containers/modals/NewSimulationModal.js @@ -0,0 +1,37 @@ +import React from "react"; +import { connect } from "react-redux"; +import { closeNewSimulationModal } from "../../actions/modals/simulations"; +import { addSimulation } from "../../actions/simulations"; +import TextInputModal from "../../components/modals/TextInputModal"; + +const NewSimulationModalComponent = ({ visible, callback }) => ( + <TextInputModal + title="New Simulation" + label="Simulation title" + show={visible} + callback={callback} + /> +); + +const mapStateToProps = state => { + return { + visible: state.modals.newSimulationModalVisible + }; +}; + +const mapDispatchToProps = dispatch => { + return { + callback: text => { + if (text) { + dispatch(addSimulation(text)); + } + dispatch(closeNewSimulationModal()); + } + }; +}; + +const NewSimulationModal = connect(mapStateToProps, mapDispatchToProps)( + NewSimulationModalComponent +); + +export default NewSimulationModal; diff --git a/frontend/src/containers/simulations/FilterLink.js b/frontend/src/containers/simulations/FilterLink.js new file mode 100644 index 00000000..2c5f4ed5 --- /dev/null +++ b/frontend/src/containers/simulations/FilterLink.js @@ -0,0 +1,19 @@ +import { connect } from "react-redux"; +import { setAuthVisibilityFilter } from "../../actions/simulations"; +import FilterButton from "../../components/simulations/FilterButton"; + +const mapStateToProps = (state, ownProps) => { + return { + active: state.simulationList.authVisibilityFilter === ownProps.filter + }; +}; + +const mapDispatchToProps = (dispatch, ownProps) => { + return { + onClick: () => dispatch(setAuthVisibilityFilter(ownProps.filter)) + }; +}; + +const FilterLink = connect(mapStateToProps, mapDispatchToProps)(FilterButton); + +export default FilterLink; diff --git a/frontend/src/containers/simulations/NewSimulationButtonContainer.js b/frontend/src/containers/simulations/NewSimulationButtonContainer.js new file mode 100644 index 00000000..3ea04d24 --- /dev/null +++ b/frontend/src/containers/simulations/NewSimulationButtonContainer.js @@ -0,0 +1,15 @@ +import { connect } from "react-redux"; +import { openNewSimulationModal } from "../../actions/modals/simulations"; +import NewSimulationButtonComponent from "../../components/simulations/NewSimulationButtonComponent"; + +const mapDispatchToProps = dispatch => { + return { + onClick: () => dispatch(openNewSimulationModal()) + }; +}; + +const NewSimulationButtonContainer = connect(undefined, mapDispatchToProps)( + NewSimulationButtonComponent +); + +export default NewSimulationButtonContainer; diff --git a/frontend/src/containers/simulations/SimulationActions.js b/frontend/src/containers/simulations/SimulationActions.js new file mode 100644 index 00000000..32243eff --- /dev/null +++ b/frontend/src/containers/simulations/SimulationActions.js @@ -0,0 +1,22 @@ +import { connect } from "react-redux"; +import { deleteSimulation } from "../../actions/simulations"; +import SimulationActionButtons from "../../components/simulations/SimulationActionButtons"; + +const mapStateToProps = (state, ownProps) => { + return { + simulationId: ownProps.simulationId + }; +}; + +const mapDispatchToProps = dispatch => { + return { + onViewUsers: id => {}, // TODO implement user viewing + onDelete: id => dispatch(deleteSimulation(id)) + }; +}; + +const SimulationActions = connect(mapStateToProps, mapDispatchToProps)( + SimulationActionButtons +); + +export default SimulationActions; diff --git a/frontend/src/containers/simulations/VisibleSimulationAuthList.js b/frontend/src/containers/simulations/VisibleSimulationAuthList.js new file mode 100644 index 00000000..ffc74d9e --- /dev/null +++ b/frontend/src/containers/simulations/VisibleSimulationAuthList.js @@ -0,0 +1,42 @@ +import { connect } from "react-redux"; +import SimulationList from "../../components/simulations/SimulationAuthList"; + +const getVisibleSimulationAuths = (simulationAuths, filter) => { + switch (filter) { + case "SHOW_ALL": + return simulationAuths; + case "SHOW_OWN": + return simulationAuths.filter( + simulationAuth => simulationAuth.authorizationLevel === "OWN" + ); + case "SHOW_SHARED": + return simulationAuths.filter( + simulationAuth => simulationAuth.authorizationLevel !== "OWN" + ); + default: + return simulationAuths; + } +}; + +const mapStateToProps = state => { + const denormalizedAuthorizations = state.simulationList.authorizationsOfCurrentUser.map( + authorizationIds => { + const authorization = state.objects.authorization[authorizationIds]; + authorization.user = state.objects.user[authorization.userId]; + authorization.simulation = + state.objects.simulation[authorization.simulationId]; + return authorization; + } + ); + + return { + authorizations: getVisibleSimulationAuths( + denormalizedAuthorizations, + state.simulationList.authVisibilityFilter + ) + }; +}; + +const VisibleSimulationAuthList = connect(mapStateToProps)(SimulationList); + +export default VisibleSimulationAuthList; |
