diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/actions/topology/room.js | 7 | ||||
| -rw-r--r-- | src/colors/index.js | 8 | ||||
| -rw-r--r-- | src/components/map/MapConstants.js | 3 | ||||
| -rw-r--r-- | src/components/map/elements/ImageComponent.js | 39 | ||||
| -rw-r--r-- | src/components/map/elements/RackFillBar.js | 67 | ||||
| -rw-r--r-- | src/components/map/groups/RackGroup.js | 4 | ||||
| -rw-r--r-- | src/containers/map/RackEnergyFillContainer.js | 28 | ||||
| -rw-r--r-- | src/containers/map/RackSpaceFillContainer.js | 16 | ||||
| -rw-r--r-- | src/sagas/topology.js | 5 |
9 files changed, 164 insertions, 13 deletions
diff --git a/src/actions/topology/room.js b/src/actions/topology/room.js index 12133330..07cf2b1d 100644 --- a/src/actions/topology/room.js +++ b/src/actions/topology/room.js @@ -50,13 +50,6 @@ export function addRackToTile(positionX, positionY) { }; } -export function addRackToTileSucceeded(tileId, rackId) { - return dispatch => { - dispatch(addPropToStoreObject("tile", tileId, {objectType: "RACK"})); - dispatch(addPropToStoreObject("tile", tileId, {objectId: rackId})); - }; -} - export function deleteRoom() { return { type: DELETE_ROOM diff --git a/src/colors/index.js b/src/colors/index.js index 8af72285..1e84e162 100644 --- a/src/colors/index.js +++ b/src/colors/index.js @@ -14,10 +14,10 @@ export const TILE_PLUS_COLOR = "rgba(0, 0, 0, 1)"; export const OBJECT_BORDER_COLOR = "rgba(0, 0, 0, 1)"; export const RACK_BACKGROUND_COLOR = "rgba(170, 170, 170, 1)"; -export const RACK_SPACE_BAR_BACKGROUND_COLOR = "rgba(222, 235, 247, 1)"; -export const RACK_SPACE_BAR_FILL_COLOR = "rgba(91, 155, 213, 1)"; -export const RACK_ENERGY_BAR_BACKGROUND_COLOR = "rgba(255, 242, 204, 1)"; -export const RACK_ENERGY_BAR_FILL_COLOR = "rgba(255, 192, 0, 1)"; +export const RACK_SPACE_BAR_BACKGROUND_COLOR = "rgba(222, 235, 247, 0.6)"; +export const RACK_SPACE_BAR_FILL_COLOR = "rgba(91, 155, 213, 0.7)"; +export const RACK_ENERGY_BAR_BACKGROUND_COLOR = "rgba(255, 242, 204, 0.6)"; +export const RACK_ENERGY_BAR_FILL_COLOR = "rgba(244, 215, 0, 0.7)"; export const COOLING_ITEM_BACKGROUND_COLOR = "rgba(40, 50, 230, 1)"; export const PSU_BACKGROUND_COLOR = "rgba(230, 50, 60, 1)"; diff --git a/src/components/map/MapConstants.js b/src/components/map/MapConstants.js index d700ee49..f6f47564 100644 --- a/src/components/map/MapConstants.js +++ b/src/components/map/MapConstants.js @@ -11,4 +11,7 @@ export const WALL_WIDTH_IN_PIXELS = TILE_SIZE_IN_PIXELS / 8; export const OBJECT_BORDER_WIDTH_IN_PIXELS = TILE_SIZE_IN_PIXELS / 12; export const TILE_PLUS_WIDTH_IN_PIXELS = TILE_SIZE_IN_PIXELS / 10; +export const RACK_FILL_ICON_WIDTH = OBJECT_SIZE_IN_PIXELS / 3; +export const RACK_FILL_ICON_OPACITY = 0.8; + export const MAP_MOVE_PIXELS_PER_EVENT = 20; diff --git a/src/components/map/elements/ImageComponent.js b/src/components/map/elements/ImageComponent.js new file mode 100644 index 00000000..00766496 --- /dev/null +++ b/src/components/map/elements/ImageComponent.js @@ -0,0 +1,39 @@ +import PropTypes from "prop-types"; +import React from "react"; +import {Image} from "react-konva"; + +class ImageComponent extends React.Component { + static propTypes = { + src: PropTypes.string.isRequired, + x: PropTypes.number.isRequired, + y: PropTypes.number.isRequired, + width: PropTypes.number.isRequired, + height: PropTypes.number.isRequired, + opacity: PropTypes.number.isRequired, + }; + + state = { + image: null + }; + + componentDidMount() { + const image = new window.Image(); + image.src = this.props.src; + image.onload = () => this.setState({image}); + } + + render() { + return ( + <Image + image={this.state.image} + x={this.props.x} + y={this.props.y} + width={this.props.width} + height={this.props.height} + opacity={this.props.opacity} + /> + ) + } +} + +export default ImageComponent; diff --git a/src/components/map/elements/RackFillBar.js b/src/components/map/elements/RackFillBar.js new file mode 100644 index 00000000..7b1351a5 --- /dev/null +++ b/src/components/map/elements/RackFillBar.js @@ -0,0 +1,67 @@ +import PropTypes from "prop-types"; +import React from "react"; +import {Group, Rect} from "react-konva"; +import { + RACK_ENERGY_BAR_BACKGROUND_COLOR, + RACK_ENERGY_BAR_FILL_COLOR, + RACK_SPACE_BAR_BACKGROUND_COLOR, + RACK_SPACE_BAR_FILL_COLOR +} from "../../../colors/index"; +import { + OBJECT_BORDER_WIDTH_IN_PIXELS, + OBJECT_MARGIN_IN_PIXELS, + RACK_FILL_ICON_OPACITY, + RACK_FILL_ICON_WIDTH, + TILE_SIZE_IN_PIXELS +} from "../MapConstants"; +import ImageComponent from "./ImageComponent"; + +const RackFillBar = ({positionX, positionY, type, fillFraction}) => { + const halfOfObjectBorderWidth = OBJECT_BORDER_WIDTH_IN_PIXELS / 2; + const x = positionX * TILE_SIZE_IN_PIXELS + OBJECT_MARGIN_IN_PIXELS + + (type === "space" ? halfOfObjectBorderWidth : + 0.5 * (TILE_SIZE_IN_PIXELS - 2 * OBJECT_MARGIN_IN_PIXELS)); + const startY = positionY * TILE_SIZE_IN_PIXELS + OBJECT_MARGIN_IN_PIXELS + halfOfObjectBorderWidth; + const width = 0.5 * (TILE_SIZE_IN_PIXELS - OBJECT_MARGIN_IN_PIXELS * 2) - halfOfObjectBorderWidth; + const fullHeight = TILE_SIZE_IN_PIXELS - OBJECT_MARGIN_IN_PIXELS * 2 - OBJECT_BORDER_WIDTH_IN_PIXELS; + + const fractionHeight = fillFraction * fullHeight; + const fractionY = (positionY + 1) * TILE_SIZE_IN_PIXELS - OBJECT_MARGIN_IN_PIXELS - halfOfObjectBorderWidth + - fractionHeight; + + return ( + <Group> + <Rect + x={x} + y={startY} + width={width} + height={fullHeight} + fill={type === "space" ? RACK_SPACE_BAR_BACKGROUND_COLOR : RACK_ENERGY_BAR_BACKGROUND_COLOR} + /> + <Rect + x={x} + y={fractionY} + width={width} + height={fractionHeight} + fill={type === "space" ? RACK_SPACE_BAR_FILL_COLOR : RACK_ENERGY_BAR_FILL_COLOR} + /> + <ImageComponent + src={"/img/topology/rack-" + type + "-icon.png"} + x={x + width * 0.5 - RACK_FILL_ICON_WIDTH * 0.5} + y={startY + fullHeight * 0.5 - RACK_FILL_ICON_WIDTH * 0.5} + width={RACK_FILL_ICON_WIDTH} + height={RACK_FILL_ICON_WIDTH} + opacity={RACK_FILL_ICON_OPACITY} + /> + </Group> + ); +}; + +RackFillBar.propTypes = { + positionX: PropTypes.number.isRequired, + positionY: PropTypes.number.isRequired, + type: PropTypes.string.isRequired, + fillFraction: PropTypes.number.isRequired, +}; + +export default RackFillBar; diff --git a/src/components/map/groups/RackGroup.js b/src/components/map/groups/RackGroup.js index 9583b234..5dd470de 100644 --- a/src/components/map/groups/RackGroup.js +++ b/src/components/map/groups/RackGroup.js @@ -1,12 +1,16 @@ import React from "react"; import {Group} from "react-konva"; import {RACK_BACKGROUND_COLOR} from "../../../colors/index"; +import RackEnergyFillContainer from "../../../containers/map/RackEnergyFillContainer"; +import RackSpaceFillContainer from "../../../containers/map/RackSpaceFillContainer"; import Shapes from "../../../shapes/index"; import TileObject from "../elements/TileObject"; const RackGroup = ({tile}) => ( <Group> <TileObject positionX={tile.positionX} positionY={tile.positionY} color={RACK_BACKGROUND_COLOR}/> + <RackSpaceFillContainer tileId={tile.id} positionX={tile.positionX} positionY={tile.positionY}/> + <RackEnergyFillContainer tileId={tile.id} positionX={tile.positionX} positionY={tile.positionY}/> </Group> ); diff --git a/src/containers/map/RackEnergyFillContainer.js b/src/containers/map/RackEnergyFillContainer.js new file mode 100644 index 00000000..0143ce80 --- /dev/null +++ b/src/containers/map/RackEnergyFillContainer.js @@ -0,0 +1,28 @@ +import {connect} from "react-redux"; +import RackFillBar from "../../components/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/src/containers/map/RackSpaceFillContainer.js b/src/containers/map/RackSpaceFillContainer.js new file mode 100644 index 00000000..d6be823f --- /dev/null +++ b/src/containers/map/RackSpaceFillContainer.js @@ -0,0 +1,16 @@ +import {connect} from "react-redux"; +import RackFillBar from "../../components/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/src/sagas/topology.js b/src/sagas/topology.js index b128ff97..566d2162 100644 --- a/src/sagas/topology.js +++ b/src/sagas/topology.js @@ -9,7 +9,7 @@ import { } from "../actions/topology/building"; import {addUnitSucceeded, deleteMachineSucceeded, deleteUnitSucceeded} from "../actions/topology/machine"; import {addMachineSucceeded, deleteRackSucceeded, editRackNameSucceeded} from "../actions/topology/rack"; -import {addRackToTileSucceeded, deleteRoomSucceeded, editRoomNameSucceeded} from "../actions/topology/room"; +import {deleteRoomSucceeded, editRoomNameSucceeded} from "../actions/topology/room"; import {addRoomToDatacenter} from "../api/routes/datacenters"; import {addTileToRoom, deleteRoom, updateRoom} from "../api/routes/rooms"; import { @@ -242,7 +242,8 @@ export function* onAddRackToTile(action) { }); rack.machineIds = new Array(rack.capacity).fill(null); yield put(addToStore("rack", rack)); - yield put(addRackToTileSucceeded(action.tileId, rack.id)); + yield put(addPropToStoreObject("tile", action.tileId, {objectId: rack.id})); + yield put(addPropToStoreObject("tile", action.tileId, {objectType: "RACK"})); } catch (error) { console.log(error); } |
