summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/actions/topology/room.js7
-rw-r--r--src/colors/index.js8
-rw-r--r--src/components/map/MapConstants.js3
-rw-r--r--src/components/map/elements/ImageComponent.js39
-rw-r--r--src/components/map/elements/RackFillBar.js67
-rw-r--r--src/components/map/groups/RackGroup.js4
-rw-r--r--src/containers/map/RackEnergyFillContainer.js28
-rw-r--r--src/containers/map/RackSpaceFillContainer.js16
-rw-r--r--src/sagas/topology.js5
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);
}