UNPKG

ice-frontend-react-mobx

Version:
231 lines (209 loc) 7.46 kB
var debug = require('debug')('ice:ZoneCard: '); // eslint-disable-line no-unused-vars import { inject, observer } from 'mobx-react'; import React from 'react'; import { Avatar, Button, Card, CardText, CardTitle, IconButton, Tooltip } from 'react-toolbox'; import ValueWrapper from '../../common/ValueWrapper/ValueWrapper'; import PhaseData from '../../common/PhaseData/PhaseData'; import PhaseBalance from '../../charts/PhaseBalance/PhaseBalance'; import CapacityReport from '../../Reports/Capacity/Capacity'; import {CollapsingPanel} from '../../../components/Accordion'; import ClassNames from 'classnames/bind'; let styles = require('./ZoneCard.css'); var css = ClassNames.bind(styles); const TooltipButton = Tooltip(Button); const thresholdWarning = 0.8; @inject('store') @observer export default class ZoneCard extends React.Component { constructor (props) { super(props); this.store = this.props.store; this.wordStore = this.props.store.wordStore; this.zone = this.props.zone; this.state = { active: false, displayData: 'zoneData' }; } handleToggle = () => { this.setState({active: !this.state.active}); }; handlePrint = () => { window.print(); } thresholdCalc = (input, limit, metrics) => { if (!metrics) { return 'offline'; } else if (limit - input <= 0) { return 'critical'; } else if ((limit * thresholdWarning) - input <= 0) { return 'warning'; } else { return 'normal'; } }; renderZoneIcon () { if (this.zone.metrics.phasePowerIn.length === 3) { let metrics = this.zone.metrics; let [phase1, phase2, phase3] = metrics.phasePowerIn.map((phase) => (phase.instantaneousW)); return <div className={styles.phaseBalanceWrapper}><PhaseBalance phase1={phase1} phase2={phase2} phase3={phase3} /></div>; } else { return <Avatar icon='flash_on' className={styles.rowPowerIcon}/>; } } renderZoneData () { let metrics = this.zone.metrics; let input = metrics.instantaneousInputPowerW / 1000; let allocated = this.zone.allocatedPower / 1000; let maxUtilPercentage = Math.floor(metrics.maxUtilizationProp * 100); let peak = metrics.maxInputPowerW / 1000; let soc = metrics.averageSocProp * 100; return ( <div className={styles.limits}> <div className={styles.iconWrapper}> {this.renderZoneIcon()} </div> <div className={styles.row}> <div className={styles.rowSection}> <ValueWrapper value={input} label={this.wordStore.translate('input')} size='title' suffix='kW' labelFirst={false} /> <ValueWrapper value={peak} label={this.wordStore.translate('peak')} size='title' suffix='kW' labelFirst={false} /> <ValueWrapper value={allocated} label={this.wordStore.translate('allocated')} size='title' suffix='kW' labelFirst={false} /> </div> <div className={styles.rowSection}> <ValueWrapper value={maxUtilPercentage} label={this.wordStore.translate('max utilization')} formatNumber={false} size='title' suffix='%' labelFirst={false} /> <ValueWrapper value={soc} suffix='%' label={this.wordStore.translate('avg SOC')} size='title' labelFirst={false} /> </div> </div> </div> ); } renderRacks () { let rackIndicators = this.zone.racks.map((rack, index) => { var allocated = rack.allocatedPower; var input = rack.metrics.instantaneousInputPowerW; var metrics = rack.metrics; let rackStyles = () => { return css('rackIndicator', this.thresholdCalc(input, allocated, metrics)); }; return ( <TooltipButton label={rack.redundancy} raised tooltip={rack.name} tooltipDelay={500} className={rackStyles()} key={'rack' + index} /> ); }); return rackIndicators; } renderPhaseData () { if (this.zone.metrics.phasePowerIn.length === 3) { return ( <div className={styles.collapseWrapper}> <CollapsingPanel> <div className={styles.phaseData}> { this.zone.metrics.phasePowerIn.map((phase) => { let input = phase.instantaneousW / 1000; let peak = phase.maxW / 1000; let limit = phase.breakerLimitW / 1000; return ( <PhaseData phase={phase.phase} input={input} peak={peak} limit={limit} key={this.zone.id + phase.phase}> <ValueWrapper value={input} suffix='kW' label='input' size='sm' labelFirst={false} /> <ValueWrapper value={peak} suffix='kW' label='peak' size='sm' labelFirst={false} /> <ValueWrapper value={limit} suffix='kW' label='limit' size='sm' labelFirst={false} /> </PhaseData> ); }) } </div> </CollapsingPanel> </div> ); } } getSensorData = (id) => { this.store.history.push('/reports/capacity/' + id); }; render () { let name = this.zone.name || 'N/A'; let rackCount = this.zone.rackIds.length || 'N/A'; let actions = [ { label: 'Cancel', onClick: this.handleToggle }, { label: 'Print', onClick: this.handlePrint } ]; var allocated = this.zone.allocatedPower; var input = this.zone.metrics.instantaneousInputPowerW; var metrics = this.zone.metrics; let rowThreshold = () => { return css('thresholdIndicator', this.thresholdCalc(input, allocated, metrics)); }; let statusIcon = () => { if (this.thresholdCalc(input, allocated, metrics) === 'warning' || this.thresholdCalc(input, allocated, metrics) === 'normal') { return 'check'; } else { return 'priority_high'; } }; return ( <Card raised key={this.zone.id} className={styles.zoneCard}> <div data-qa-tag='zone-card' data-qa-id={this.zone.id}> <div className={styles.titleWrapper}> <Avatar icon={statusIcon()} className={rowThreshold()}/> <CardTitle title={name} subtitle={ rackCount + ' racks'} className={styles.cardTitle}> </CardTitle> </div> <div className={styles.deviceToggle}> <IconButton icon='info' onClick={this.getSensorData.bind(this, this.zone.id)}/> </div> <CardText> <div> <div className={styles.zoneData}>{this.renderZoneData()}</div> {this.renderPhaseData()} </div> </CardText> <CardText> <h4>Racks:</h4> <div className={styles.rackIndicatorBlock}>{this.renderRacks()}</div> </CardText> </div> <CapacityReport zone={this.zone} actions={actions} active={this.state.active} onEscKeyDown={this.handleToggle} onOverlayClick={this.handleToggle}/> </Card> ); } }