diff options
Diffstat (limited to 'frontend/src/components/app/sidebars/topology')
28 files changed, 698 insertions, 0 deletions
diff --git a/frontend/src/components/app/sidebars/topology/NameComponent.js b/frontend/src/components/app/sidebars/topology/NameComponent.js new file mode 100644 index 00000000..805538b3 --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/NameComponent.js @@ -0,0 +1,13 @@ +import React from "react"; +import FontAwesome from "react-fontawesome"; + +const NameComponent = ({ name, onEdit }) => ( + <h2> + {name} + <button className="btn btn-outline-secondary float-right" onClick={onEdit}> + <FontAwesome name="pencil" /> + </button> + </h2> +); + +export default NameComponent; diff --git a/frontend/src/components/app/sidebars/topology/TopologySidebarComponent.js b/frontend/src/components/app/sidebars/topology/TopologySidebarComponent.js new file mode 100644 index 00000000..81e510a1 --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/TopologySidebarComponent.js @@ -0,0 +1,31 @@ +import React from "react"; +import BuildingSidebarContainer from "../../../../containers/app/sidebars/topology/building/BuildingSidebarContainer"; +import MachineSidebarContainer from "../../../../containers/app/sidebars/topology/machine/MachineSidebarContainer"; +import RackSidebarContainer from "../../../../containers/app/sidebars/topology/rack/RackSidebarContainer"; +import RoomSidebarContainer from "../../../../containers/app/sidebars/topology/room/RoomSidebarContainer"; +import Sidebar from "../Sidebar"; + +const TopologySidebarComponent = ({ interactionLevel }) => { + let sidebarContent; + + switch (interactionLevel.mode) { + case "BUILDING": + sidebarContent = <BuildingSidebarContainer />; + break; + case "ROOM": + sidebarContent = <RoomSidebarContainer />; + break; + case "RACK": + sidebarContent = <RackSidebarContainer />; + break; + case "MACHINE": + sidebarContent = <MachineSidebarContainer />; + break; + default: + sidebarContent = "Missing Content"; + } + + return <Sidebar isRight={true}>{sidebarContent}</Sidebar>; +}; + +export default TopologySidebarComponent; diff --git a/frontend/src/components/app/sidebars/topology/building/BuildingSidebarComponent.js b/frontend/src/components/app/sidebars/topology/building/BuildingSidebarComponent.js new file mode 100644 index 00000000..f16c19f0 --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/building/BuildingSidebarComponent.js @@ -0,0 +1,20 @@ +import React from "react"; +import NewRoomConstructionContainer from "../../../../../containers/app/sidebars/topology/building/NewRoomConstructionContainer"; + +const BuildingSidebarComponent = ({ inSimulation }) => { + return ( + <div> + <h2>Building</h2> + {inSimulation ? ( + <div className="alert alert-info"> + <span className="fa fa-info-circle mr-2" /> + <strong>Click on individual rooms</strong> to see their stats! + </div> + ) : ( + <NewRoomConstructionContainer /> + )} + </div> + ); +}; + +export default BuildingSidebarComponent; diff --git a/frontend/src/components/app/sidebars/topology/building/NewRoomConstructionComponent.js b/frontend/src/components/app/sidebars/topology/building/NewRoomConstructionComponent.js new file mode 100644 index 00000000..7b049642 --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/building/NewRoomConstructionComponent.js @@ -0,0 +1,31 @@ +import React from "react"; + +const NewRoomConstructionComponent = ({ + onStart, + onFinish, + onCancel, + currentRoomInConstruction +}) => { + if (currentRoomInConstruction === -1) { + return ( + <div className="btn btn-outline-primary btn-block" onClick={onStart}> + <span className="fa fa-plus mr-2" /> + Construct a new room + </div> + ); + } + return ( + <div> + <div className="btn btn-primary btn-block" onClick={onFinish}> + <span className="fa fa-check mr-2" /> + Finalize new room + </div> + <div className="btn btn-default btn-block" onClick={onCancel}> + <span className="fa fa-times mr-2" /> + Cancel construction + </div> + </div> + ); +}; + +export default NewRoomConstructionComponent; diff --git a/frontend/src/components/app/sidebars/topology/machine/BackToRackComponent.js b/frontend/src/components/app/sidebars/topology/machine/BackToRackComponent.js new file mode 100644 index 00000000..7f56aca0 --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/machine/BackToRackComponent.js @@ -0,0 +1,10 @@ +import React from "react"; + +const BackToRackComponent = ({ onClick }) => ( + <div className="btn btn-secondary btn-block" onClick={onClick}> + <span className="fa fa-angle-left mr-2" /> + Back to rack + </div> +); + +export default BackToRackComponent; diff --git a/frontend/src/components/app/sidebars/topology/machine/DeleteMachineComponent.js b/frontend/src/components/app/sidebars/topology/machine/DeleteMachineComponent.js new file mode 100644 index 00000000..d8774bf9 --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/machine/DeleteMachineComponent.js @@ -0,0 +1,10 @@ +import React from "react"; + +const DeleteMachineComponent = ({ onClick }) => ( + <div className="btn btn-outline-danger btn-block" onClick={onClick}> + <span className="fa fa-trash mr-2" /> + Delete this machine + </div> +); + +export default DeleteMachineComponent; diff --git a/frontend/src/components/app/sidebars/topology/machine/MachineNameComponent.js b/frontend/src/components/app/sidebars/topology/machine/MachineNameComponent.js new file mode 100644 index 00000000..0ad8b79c --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/machine/MachineNameComponent.js @@ -0,0 +1,7 @@ +import React from "react"; + +const MachineNameComponent = ({ position }) => ( + <h2>Machine at slot {position}</h2> +); + +export default MachineNameComponent; diff --git a/frontend/src/components/app/sidebars/topology/machine/MachineSidebarComponent.js b/frontend/src/components/app/sidebars/topology/machine/MachineSidebarComponent.js new file mode 100644 index 00000000..5ccaf25c --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/machine/MachineSidebarComponent.js @@ -0,0 +1,27 @@ +import React from "react"; +import LoadBarContainer from "../../../../../containers/app/sidebars/elements/LoadBarContainer"; +import LoadChartContainer from "../../../../../containers/app/sidebars/elements/LoadChartContainer"; +import BackToRackContainer from "../../../../../containers/app/sidebars/topology/machine/BackToRackContainer"; +import DeleteMachineContainer from "../../../../../containers/app/sidebars/topology/machine/DeleteMachineContainer"; +import MachineNameContainer from "../../../../../containers/app/sidebars/topology/machine/MachineNameContainer"; +import UnitTabsContainer from "../../../../../containers/app/sidebars/topology/machine/UnitTabsContainer"; + +const MachineSidebarComponent = ({ inSimulation, machineId }) => { + return ( + <div> + <MachineNameContainer /> + <BackToRackContainer /> + {inSimulation ? ( + <div> + <LoadBarContainer objectType="machine" objectId={machineId} /> + <LoadChartContainer objectType="machine" objectId={machineId} /> + </div> + ) : ( + <DeleteMachineContainer /> + )} + <UnitTabsContainer /> + </div> + ); +}; + +export default MachineSidebarComponent; diff --git a/frontend/src/components/app/sidebars/topology/machine/UnitAddComponent.js b/frontend/src/components/app/sidebars/topology/machine/UnitAddComponent.js new file mode 100644 index 00000000..0c903228 --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/machine/UnitAddComponent.js @@ -0,0 +1,46 @@ +import PropTypes from "prop-types"; +import React from "react"; + +class UnitAddComponent extends React.Component { + static propTypes = { + units: PropTypes.array.isRequired, + onAdd: PropTypes.func.isRequired + }; + + render() { + return ( + <div className="form-inline"> + <div className="form-group w-100"> + <select + className="form-control w-75 mr-1" + ref={unitSelect => (this.unitSelect = unitSelect)} + > + {this.props.units.map(unit => ( + <option value={unit.id} key={unit.id}> + {unit.manufacturer + + " " + + unit.family + + " " + + unit.model + + " " + + unit.generation} + </option> + ))} + </select> + <button + type="submit" + className="btn btn-outline-primary" + onClick={() => + this.props.onAdd(parseInt(this.unitSelect.value, 10)) + } + > + <span className="fa fa-plus mr-2" /> + Add + </button> + </div> + </div> + ); + } +} + +export default UnitAddComponent; diff --git a/frontend/src/components/app/sidebars/topology/machine/UnitComponent.js b/frontend/src/components/app/sidebars/topology/machine/UnitComponent.js new file mode 100644 index 00000000..7c27043d --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/machine/UnitComponent.js @@ -0,0 +1,78 @@ +import React from "react"; +import jQuery from "../../../../../util/jquery"; + +class UnitComponent extends React.Component { + componentDidMount() { + jQuery(".unit-info-popover").popover({ + trigger: "focus" + }); + } + + render() { + let unitInfo; + if (this.props.unitType === "cpu" || this.props.unitType === "gpu") { + unitInfo = + "<strong>Clockrate:</strong> <code>" + + this.props.unit.clockRateMhz + + " MHz</code><br/>" + + "<strong>Num. Cores:</strong> <code>" + + this.props.unit.numberOfCores + + "</code><br/>" + + "<strong>Energy Cons.:</strong> <code>" + + this.props.unit.energyConsumptionW + + " W</code>"; + } else if ( + this.props.unitType === "memory" || + this.props.unitType === "storage" + ) { + unitInfo = + "<strong>Speed:</strong> <code>" + + this.props.unit.speedMbPerS + + " Mb/s</code><br/>" + + "<strong>Size:</strong> <code>" + + this.props.unit.sizeMb + + " MB</code><br/>" + + "<strong>Energy Cons.:</strong> <code> " + + this.props.unit.energyConsumptionW + + " W</code>"; + } + + 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} + </span> + <span> + <span + tabIndex="0" + className="unit-info-popover btn btn-outline-info mr-1 fa fa-info-circle" + role="button" + data-toggle="popover" + data-trigger="focus" + title="Unit information" + data-content={unitInfo} + data-html="true" + /> + {this.props.inSimulation ? ( + undefined + ) : ( + <span + className="btn btn-outline-danger" + onClick={this.props.onDelete} + > + <span className="fa fa-trash" /> + </span> + )} + </span> + </li> + ); + } +} + +export default UnitComponent; diff --git a/frontend/src/components/app/sidebars/topology/machine/UnitListComponent.js b/frontend/src/components/app/sidebars/topology/machine/UnitListComponent.js new file mode 100644 index 00000000..38df806b --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/machine/UnitListComponent.js @@ -0,0 +1,29 @@ +import React from "react"; +import UnitContainer from "../../../../../containers/app/sidebars/topology/machine/UnitContainer"; + +const UnitListComponent = ({ unitType, unitIds, inSimulation }) => ( + <ul className="list-group mt-1"> + {unitIds.length !== 0 ? ( + unitIds.map((unitId, index) => ( + <UnitContainer + unitType={unitType} + unitId={unitId} + index={index} + key={index} + /> + )) + ) : ( + <div className="alert alert-info"> + {inSimulation ? ( + <strong>No units of this type in this machine</strong> + ) : ( + <span> + <strong>No units...</strong> Add some with the menu above! + </span> + )} + </div> + )} + </ul> +); + +export default UnitListComponent; diff --git a/frontend/src/components/app/sidebars/topology/machine/UnitTabsComponent.js b/frontend/src/components/app/sidebars/topology/machine/UnitTabsComponent.js new file mode 100644 index 00000000..0683c796 --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/machine/UnitTabsComponent.js @@ -0,0 +1,65 @@ +import React from "react"; +import UnitAddContainer from "../../../../../containers/app/sidebars/topology/machine/UnitAddContainer"; +import UnitListContainer from "../../../../../containers/app/sidebars/topology/machine/UnitListContainer"; + +const UnitTabsComponent = ({ inSimulation }) => ( + <div> + <ul className="nav nav-tabs mt-2 mb-1" role="tablist"> + <li className="nav-item"> + <a + className="nav-link active" + data-toggle="tab" + href="#cpu-units" + role="tab" + > + CPU + </a> + </li> + <li className="nav-item"> + <a className="nav-link" data-toggle="tab" href="#gpu-units" role="tab"> + GPU + </a> + </li> + <li className="nav-item"> + <a + className="nav-link" + data-toggle="tab" + href="#memory-units" + role="tab" + > + Memory + </a> + </li> + <li className="nav-item"> + <a + className="nav-link" + data-toggle="tab" + href="#storage-units" + role="tab" + > + Storage + </a> + </li> + </ul> + <div className="tab-content"> + <div className="tab-pane active" id="cpu-units" role="tabpanel"> + {inSimulation ? undefined : <UnitAddContainer unitType="cpu" />} + <UnitListContainer unitType="cpu" /> + </div> + <div className="tab-pane" id="gpu-units" role="tabpanel"> + {inSimulation ? undefined : <UnitAddContainer unitType="gpu" />} + <UnitListContainer unitType="gpu" /> + </div> + <div className="tab-pane" id="memory-units" role="tabpanel"> + {inSimulation ? undefined : <UnitAddContainer unitType="memory" />} + <UnitListContainer unitType="memory" /> + </div> + <div className="tab-pane" id="storage-units" role="tabpanel"> + {inSimulation ? undefined : <UnitAddContainer unitType="storage" />} + <UnitListContainer unitType="storage" /> + </div> + </div> + </div> +); + +export default UnitTabsComponent; diff --git a/frontend/src/components/app/sidebars/topology/rack/BackToRoomComponent.js b/frontend/src/components/app/sidebars/topology/rack/BackToRoomComponent.js new file mode 100644 index 00000000..6bcf4088 --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/rack/BackToRoomComponent.js @@ -0,0 +1,10 @@ +import React from "react"; + +const BackToRoomComponent = ({ onClick }) => ( + <div className="btn btn-secondary btn-block mb-2" onClick={onClick}> + <span className="fa fa-angle-left mr-2" /> + Back to room + </div> +); + +export default BackToRoomComponent; diff --git a/frontend/src/components/app/sidebars/topology/rack/DeleteRackComponent.js b/frontend/src/components/app/sidebars/topology/rack/DeleteRackComponent.js new file mode 100644 index 00000000..d8aa7634 --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/rack/DeleteRackComponent.js @@ -0,0 +1,10 @@ +import React from "react"; + +const DeleteRackComponent = ({ onClick }) => ( + <div className="btn btn-outline-danger btn-block" onClick={onClick}> + <span className="fa fa-trash mr-2" /> + Delete this rack + </div> +); + +export default DeleteRackComponent; diff --git a/frontend/src/components/app/sidebars/topology/rack/EmptySlotComponent.js b/frontend/src/components/app/sidebars/topology/rack/EmptySlotComponent.js new file mode 100644 index 00000000..d86f9fee --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/rack/EmptySlotComponent.js @@ -0,0 +1,19 @@ +import React from "react"; + +const EmptySlotComponent = ({ position, onAdd, inSimulation }) => ( + <li className="list-group-item d-flex justify-content-between align-items-center"> + <span className="badge badge-default badge-info mr-1 disabled"> + {position} + </span> + {inSimulation ? ( + <span className="badge badge-default badge-success">Empty Slot</span> + ) : ( + <button className="btn btn-outline-primary" onClick={onAdd}> + <span className="fa fa-plus mr-2" /> + Add machine + </button> + )} + </li> +); + +export default EmptySlotComponent; diff --git a/frontend/src/components/app/sidebars/topology/rack/MachineComponent.js b/frontend/src/components/app/sidebars/topology/rack/MachineComponent.js new file mode 100644 index 00000000..2521f4a2 --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/rack/MachineComponent.js @@ -0,0 +1,78 @@ +import React from "react"; +import Shapes from "../../../../../shapes"; +import { convertLoadToSimulationColor } from "../../../../../util/simulation-load"; + +const UnitIcon = ({ id, type }) => ( + <div> + <img + src={"/img/topology/" + id + "-icon.png"} + alt={"Machine contains " + type + " units"} + className="img-fluid ml-1" + style={{ maxHeight: "35px" }} + /> + </div> +); + +const MachineComponent = ({ + position, + machine, + inSimulation, + machineLoad, + onClick +}) => { + let color = "white"; + if (inSimulation && machineLoad >= 0) { + color = convertLoadToSimulationColor(machineLoad); + } + const hasNoUnits = + machine.cpuIds.length + + machine.gpuIds.length + + machine.memoryIds.length + + machine.storageIds.length === + 0; + + return ( + <li + className="d-flex list-group-item list-group-item-action justify-content-between align-items-center" + onClick={onClick} + style={{ backgroundColor: color }} + > + <span className="badge badge-default badge-info mr-1">{position}</span> + <div className="d-inline-flex"> + {machine.cpuIds.length > 0 ? ( + <UnitIcon id="cpu" type="CPU" /> + ) : ( + undefined + )} + {machine.gpuIds.length > 0 ? ( + <UnitIcon id="gpu" type="GPU" /> + ) : ( + undefined + )} + {machine.memoryIds.length > 0 ? ( + <UnitIcon id="memory" type="memory" /> + ) : ( + undefined + )} + {machine.storageIds.length > 0 ? ( + <UnitIcon id="storage" type="storage" /> + ) : ( + undefined + )} + {hasNoUnits ? ( + <span className="badge badge-default badge-warning"> + Machine with no units + </span> + ) : ( + undefined + )} + </div> + </li> + ); +}; + +MachineComponent.propTypes = { + machine: Shapes.Machine +}; + +export default MachineComponent; diff --git a/frontend/src/components/app/sidebars/topology/rack/MachineListComponent.js b/frontend/src/components/app/sidebars/topology/rack/MachineListComponent.js new file mode 100644 index 00000000..d5521557 --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/rack/MachineListComponent.js @@ -0,0 +1,26 @@ +import React from "react"; +import EmptySlotContainer from "../../../../../containers/app/sidebars/topology/rack/EmptySlotContainer"; +import MachineContainer from "../../../../../containers/app/sidebars/topology/rack/MachineContainer"; +import "./MachineListComponent.css"; + +const MachineListComponent = ({ machineIds }) => { + return ( + <ul className="list-group machine-list"> + {machineIds.map((machineId, index) => { + if (machineId === null) { + return <EmptySlotContainer key={index} position={index + 1} />; + } else { + return ( + <MachineContainer + key={index} + position={index + 1} + machineId={machineId} + /> + ); + } + })} + </ul> + ); +}; + +export default MachineListComponent; diff --git a/frontend/src/components/app/sidebars/topology/rack/MachineListComponent.sass b/frontend/src/components/app/sidebars/topology/rack/MachineListComponent.sass new file mode 100644 index 00000000..bbcfe696 --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/rack/MachineListComponent.sass @@ -0,0 +1,2 @@ +.machine-list li + min-height: 64px diff --git a/frontend/src/components/app/sidebars/topology/rack/RackNameComponent.js b/frontend/src/components/app/sidebars/topology/rack/RackNameComponent.js new file mode 100644 index 00000000..5e095823 --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/rack/RackNameComponent.js @@ -0,0 +1,8 @@ +import React from "react"; +import NameComponent from "../NameComponent"; + +const RackNameComponent = ({ rackName, onEdit }) => ( + <NameComponent name={rackName} onEdit={onEdit} /> +); + +export default RackNameComponent; diff --git a/frontend/src/components/app/sidebars/topology/rack/RackSidebarComponent.js b/frontend/src/components/app/sidebars/topology/rack/RackSidebarComponent.js new file mode 100644 index 00000000..f832b9b9 --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/rack/RackSidebarComponent.js @@ -0,0 +1,34 @@ +import React from "react"; +import LoadBarContainer from "../../../../../containers/app/sidebars/elements/LoadBarContainer"; +import LoadChartContainer from "../../../../../containers/app/sidebars/elements/LoadChartContainer"; +import BackToRoomContainer from "../../../../../containers/app/sidebars/topology/rack/BackToRoomContainer"; +import DeleteRackContainer from "../../../../../containers/app/sidebars/topology/rack/DeleteRackContainer"; +import MachineListContainer from "../../../../../containers/app/sidebars/topology/rack/MachineListContainer"; +import RackNameContainer from "../../../../../containers/app/sidebars/topology/rack/RackNameContainer"; +import "./RackSidebarComponent.css"; + +const RackSidebarComponent = ({ inSimulation, rackId }) => { + return ( + <div className="rack-sidebar-container flex-column"> + <div className="rack-sidebar-header-container"> + <RackNameContainer /> + <BackToRoomContainer /> + {inSimulation ? ( + <div> + <LoadBarContainer objectType="rack" objectId={rackId} /> + <LoadChartContainer objectType="rack" objectId={rackId} /> + </div> + ) : ( + <div> + <DeleteRackContainer /> + </div> + )} + </div> + <div className="machine-list-container mt-2"> + <MachineListContainer /> + </div> + </div> + ); +}; + +export default RackSidebarComponent; diff --git a/frontend/src/components/app/sidebars/topology/rack/RackSidebarComponent.sass b/frontend/src/components/app/sidebars/topology/rack/RackSidebarComponent.sass new file mode 100644 index 00000000..822804bc --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/rack/RackSidebarComponent.sass @@ -0,0 +1,11 @@ +.rack-sidebar-container + display: flex + height: 100% + max-height: 100% + +.rack-sidebar-header-container + flex: 0 + +.machine-list-container + flex: 1 + overflow-y: scroll diff --git a/frontend/src/components/app/sidebars/topology/room/BackToBuildingComponent.js b/frontend/src/components/app/sidebars/topology/room/BackToBuildingComponent.js new file mode 100644 index 00000000..0409dbdd --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/room/BackToBuildingComponent.js @@ -0,0 +1,10 @@ +import React from "react"; + +const BackToBuildingComponent = ({ onClick }) => ( + <div className="btn btn-secondary btn-block mb-2" onClick={onClick}> + <span className="fa fa-angle-left mr-2" /> + Back to building + </div> +); + +export default BackToBuildingComponent; diff --git a/frontend/src/components/app/sidebars/topology/room/DeleteRoomComponent.js b/frontend/src/components/app/sidebars/topology/room/DeleteRoomComponent.js new file mode 100644 index 00000000..3e3b3b36 --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/room/DeleteRoomComponent.js @@ -0,0 +1,10 @@ +import React from "react"; + +const DeleteRoomComponent = ({ onClick }) => ( + <div className="btn btn-outline-danger btn-block" onClick={onClick}> + <span className="fa fa-trash mr-2" /> + Delete this room + </div> +); + +export default DeleteRoomComponent; diff --git a/frontend/src/components/app/sidebars/topology/room/EditRoomComponent.js b/frontend/src/components/app/sidebars/topology/room/EditRoomComponent.js new file mode 100644 index 00000000..c3b9f0ad --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/room/EditRoomComponent.js @@ -0,0 +1,27 @@ +import classNames from "classnames"; +import React from "react"; + +const EditRoomComponent = ({ + onEdit, + onFinish, + isEditing, + isInRackConstructionMode +}) => + isEditing ? ( + <div className="btn btn-info btn-block" onClick={onFinish}> + <span className="fa fa-check mr-2" /> + Finish editing room + </div> + ) : ( + <div + className={classNames("btn btn-outline-info btn-block", { + disabled: isInRackConstructionMode + })} + onClick={() => (isInRackConstructionMode ? undefined : onEdit())} + > + <span className="fa fa-pencil mr-2" /> + Edit the tiles of this room + </div> + ); + +export default EditRoomComponent; diff --git a/frontend/src/components/app/sidebars/topology/room/RackConstructionComponent.js b/frontend/src/components/app/sidebars/topology/room/RackConstructionComponent.js new file mode 100644 index 00000000..06b8a2aa --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/room/RackConstructionComponent.js @@ -0,0 +1,32 @@ +import classNames from "classnames"; +import React from "react"; + +const RackConstructionComponent = ({ + onStart, + onStop, + inRackConstructionMode, + isEditingRoom +}) => { + if (inRackConstructionMode) { + return ( + <div className="btn btn-primary btn-block" onClick={onStop}> + <span className="fa fa-times mr-2" /> + Stop rack construction + </div> + ); + } + + return ( + <div + className={classNames("btn btn-outline-primary btn-block", { + disabled: isEditingRoom + })} + onClick={() => (isEditingRoom ? undefined : onStart())} + > + <span className="fa fa-plus mr-2" /> + Start rack construction + </div> + ); +}; + +export default RackConstructionComponent; diff --git a/frontend/src/components/app/sidebars/topology/room/RoomNameComponent.js b/frontend/src/components/app/sidebars/topology/room/RoomNameComponent.js new file mode 100644 index 00000000..11b88edd --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/room/RoomNameComponent.js @@ -0,0 +1,8 @@ +import React from "react"; +import NameComponent from "../NameComponent"; + +const RoomNameComponent = ({ roomName, onEdit }) => ( + <NameComponent name={roomName} onEdit={onEdit} /> +); + +export default RoomNameComponent; diff --git a/frontend/src/components/app/sidebars/topology/room/RoomSidebarComponent.js b/frontend/src/components/app/sidebars/topology/room/RoomSidebarComponent.js new file mode 100644 index 00000000..275f9624 --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/room/RoomSidebarComponent.js @@ -0,0 +1,38 @@ +import React from "react"; +import LoadBarContainer from "../../../../../containers/app/sidebars/elements/LoadBarContainer"; +import LoadChartContainer from "../../../../../containers/app/sidebars/elements/LoadChartContainer"; +import BackToBuildingContainer from "../../../../../containers/app/sidebars/topology/room/BackToBuildingContainer"; +import DeleteRoomContainer from "../../../../../containers/app/sidebars/topology/room/DeleteRoomContainer"; +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 />; + } + + return ( + <div> + <RoomNameContainer /> + <RoomTypeContainer /> + <BackToBuildingContainer /> + {inSimulation ? ( + <div> + <LoadBarContainer objectType="room" objectId={roomId} /> + <LoadChartContainer objectType="room" objectId={roomId} /> + </div> + ) : ( + <div> + {allowedObjects} + <EditRoomContainer /> + <DeleteRoomContainer /> + </div> + )} + </div> + ); +}; + +export default RoomSidebarComponent; diff --git a/frontend/src/components/app/sidebars/topology/room/RoomTypeComponent.js b/frontend/src/components/app/sidebars/topology/room/RoomTypeComponent.js new file mode 100644 index 00000000..46d91c2c --- /dev/null +++ b/frontend/src/components/app/sidebars/topology/room/RoomTypeComponent.js @@ -0,0 +1,8 @@ +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; |
