UNPKG

react-network-diagrams

Version:
266 lines (230 loc) 9.1 kB
/** * Copyright (c) 2018, The Regents of the University of California, * through Lawrence Berkeley National Laboratory (subject to receipt * of any required approvals from the U.S. Dept. of Energy). * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ import React from "react"; import _ from "underscore"; import { Label } from "./Label"; //17.52(w) 25.39(d) 24.49(h) /** * An equipment is an svg rect that needs to know its width, height, and style. * It receives its x and y starting position from the parent rack element, or a * default derived from a specified offset value. * * It takes a label as well in the form of a string or list of strings if multilines are desired */ export class EquipmentBase extends React.Component { constructor(props) { super(props); this.state = { yOffset: 25, xOffset: 25, pxToInch: 10, labelStyle: this.props.labelStyle }; this.handleClick = this.handleClick.bind(this); } handleClick(e) { if (this.props.onSelectionChange) { this.props.onSelectionChange("equipment", this.props.name); } e.stopPropagation(); } render() { let classed = "equipment"; let labelClassed = "equipment-label"; let styleModifier = "normal"; if (!_.isUndefined(this.props.classed)) { classed += " " + this.props.classed; } if (this.props.selected) { classed += " selected"; labelClassed += "selected"; styleModifier = "selected"; } if (this.props.muted) { classed += " muted"; labelClassed += "muted"; styleModifier = "muted"; } let opacity = 1.0; if (this.props.invisible) { opacity = 0.0; } else if (this.props.muted) { opacity = 0.3; } // Height is 244.9 px const equipmentPxHeight = this.props.equipmentHeight * this.props.pxToInch; // Width is 175.2 px const equipmentPxWidth = this.props.equipmentWidth * this.props.pxToInch; const posX = this.props.positionX || 25; const posY = this.props.positionY || 25; const centerX = equipmentPxWidth / 2 + posX; const centerY = equipmentPxHeight / 2 + posY; const labelOffsetX = this.props.labelOffsetX || 0; const labelOffsetY = this.props.labelOffsetY || 0; let cx; let cy; let cr = 0; if (this.props.labelDirection === "vertical") { cr = 90; } switch (this.props.labelPosition) { case "top": cx = centerX; cy = posY + 12 * (this.props.pxToInch / 10); break; case "bottom": cx = centerX; cy = posY + equipmentPxHeight - 15 * (this.props.pxToInch / 10); break; default: cx = centerX; cy = centerY; break; } let equipmentLabel = null; const newLabelStyle = _.clone(this.state.labelStyle[styleModifier]); newLabelStyle.fontSize = this.props.pxToInch; if (this.props.selected) { newLabelStyle.fontSize = this.props.pxToInch * 1.2; } else if (this.props.muted) { newLabelStyle.fontSize = this.props.pxToInch * 0.8; } if ( this.props.label && (!(this.props.facing === "Front" && this.props.rackFacing === "Back") && !(this.props.facing === "Back" && this.props.rackFacing === "Front")) && this.props.overlapping ) { equipmentLabel = ( <Label x={cx} y={cy} r={cr} textAnchor={this.props.textAnchor} classed={labelClassed} style={newLabelStyle} label={`**${this.props.label}`} xOffset={labelOffsetX} yOffset={labelOffsetY} labelPosition={this.props.labelPosition} /> ); } else if ( this.props.label && (!(this.props.facing === "Front" && this.props.rackFacing === "Back") && !(this.props.facing === "Back" && this.props.rackFacing === "Front")) ) { equipmentLabel = ( <Label x={cx} y={cy} r={cr} textAnchor={this.props.textAnchor} classed={labelClassed} style={newLabelStyle} label={this.props.label} xOffset={labelOffsetX} yOffset={labelOffsetY} labelPosition={this.props.labelPosition} /> ); } // let widthLine = null; const factor = this.props.pxToInch / 10; let vPath = ""; vPath += "M" + (posX + 10 * factor) + "," + (posY + 5 * factor); vPath += " L " + (posX + 10 * factor) + " " + (posY + equipmentPxHeight - 5 * factor); let hTopPath = ""; hTopPath += "M" + (posX + 7 * factor) + "," + (posY + 5 * factor); hTopPath += " L " + (posX + 13 * factor) + " " + (posY + 5 * factor); let hBottomPath = ""; hBottomPath += "M" + (posX + 7 * factor) + "," + (posY + equipmentPxHeight - 5 * factor); hBottomPath += " L " + (posX + 13 * factor) + " " + (posY + equipmentPxHeight - 5 * factor); const heightFill = this.props.labelStyle[styleModifier]; let heightPath = ( <g strokeWidth={this.props.width} stroke={heightFill.fill} opacity={opacity}> <path className={labelClassed} d={vPath} fill={heightFill.fill} /> <path className={labelClassed} d={hTopPath} fill={heightFill.fill} /> <path className={labelClassed} d={hBottomPath} fill={heightFill.fill} /> </g> ); const heightInRmu = this.props.equipmentHeight / 1.75; let heightLabel = ( <Label x={posX + 15 * factor} y={centerY} textAnchor="begin" classed={labelClassed} style={newLabelStyle} label={`${heightInRmu}U`} labelPosition={"center"} /> ); let backStyle = { fill: this.props.backFill, fillOpacity: "0.7" }; if (this.props.usePattern) { backStyle = { fill: "url(#Pattern)" }; } const frontStyle = { fill: this.props.fill }; const overlapStyle = this.props.overlapFill ? { fill: this.props.overlapFill } : frontStyle; /** * Default to the front view. Only show the back view if the * equipment is back facing on the front of the rack, * or front facing on the back of the rack */ let eqStyle = frontStyle; if (this.props.overlapping) { eqStyle = overlapStyle; } if (this.props.rackFacing === "Front" && this.props.facing === "Back") { eqStyle = backStyle; heightLabel = <g />; heightPath = <g />; } else if (this.props.rackFacing === "Back" && this.props.facing === "Front") { eqStyle = backStyle; heightLabel = <g />; heightPath = <g />; } // const eqStyle = this.props.facing === "Front" && ? frontStyle : backStyle;); if (!this.props.showHeight) { return ( <g onClick={this.handleClick}> <g strokeWidth={this.props.width} stroke={this.props.color} opacity={opacity}> <rect className={classed} width={equipmentPxWidth} height={equipmentPxHeight} x={posX} y={posY} style={eqStyle} /> </g> {equipmentLabel} </g> ); } else { return ( <g onClick={this.handleClick}> <g strokeWidth={this.props.width} stroke={this.props.color} opacity={opacity}> <rect className={classed} width={equipmentPxWidth} height={equipmentPxHeight} x={posX} y={posY} style={eqStyle} /> </g> {equipmentLabel} {heightPath} {heightLabel} </g> ); } } }