import _ from 'lodash';
import OctopusArms from './util/OctopusArms.jsx';
import PropTypes from 'prop-types';
import React from 'react';
import { Col, Progress, Row } from 'antd';
import { displayName, metricToFormatter } from './util/Utils.js';
import { getSuccessRateClassification, srArcClassLabels } from './util/MetricUtils.jsx' ;
import './../../css/octopus.css';
const maxNumNeighbors = 6; // max number of neighbor nodes to show in the octopus graph
const Metric = ({title, value, className}) => {
return (
{title}
{value}
);
};
Metric.defaultProps = { className: "" };
Metric.propTypes = {
className: PropTypes.string,
title: PropTypes.string.isRequired,
value: PropTypes.string.isRequired
};
export default class Octopus extends React.Component {
static defaultProps = {
neighbors: {},
resource: {},
unmeshedSources: []
}
static propTypes = {
neighbors: PropTypes.shape({}),
resource: PropTypes.shape({}),
unmeshedSources: PropTypes.arrayOf(PropTypes.shape({})),
}
getNeighborDisplayData = neighbors => {
// only display maxNumNeighbors neighboring nodes in the octopus graph,
// otherwise it will be really tall
let upstreams = _.sortBy(neighbors.upstream, "resource.successRate");
let downstreams = _.sortBy(neighbors.downstream, "resource.successRate");
let display = {
upstreams: {
displayed: upstreams,
collapsed: []
},
downstreams: {
displayed: downstreams,
collapsed: []
}
};
if (_.size(upstreams) > maxNumNeighbors) {
display.upstreams.displayed = _.take(upstreams, maxNumNeighbors);
display.upstreams.collapsed = _.slice(upstreams, maxNumNeighbors, _.size(upstreams));
}
if (_.size(downstreams) > maxNumNeighbors) {
display.downstreams.displayed = _.take(downstreams, maxNumNeighbors);
display.downstreams.collapsed = _.slice(downstreams, maxNumNeighbors, _.size(downstreams));
}
return display;
}
linkedResourceTitle = (resource, display) => {
return _.isNil(resource.namespace) ? display :
;
}
renderResourceSummary(resource, type) {
let display = displayName(resource);
return (
{ this.linkedResourceTitle(resource, display) }
metricToFormatter["SUCCESS_RATE"](resource.successRate)}
width={type === "main" ? 132 : 64}
percent={resource.successRate * 100}
gapDegree={180} />
);
}
renderUnmeshedResources = unmeshedResources => {
return (
Unmeshed
{
_.map(unmeshedResources, r => {
let display = displayName(r);
return
{display}
;
})
}
);
}
renderCollapsedNeighbors = neighbors => {
return (
{
_.map(neighbors, r => {
let display = displayName(r);
return
{this.linkedResourceTitle(r, display)}
;
})
}
);
}
renderArrowCol = (numNeighbors, isOutbound) => {
let baseHeight = 180;
let width = 75;
let showArrow = numNeighbors > 0;
let isEven = numNeighbors % 2 === 0;
let middleElementIndex = isEven ? ((numNeighbors - 1) / 2) : _.floor(numNeighbors / 2);
let arrowTypes = _.map(_.times(numNeighbors), i => {
if (i < middleElementIndex) {
let height = (_.ceil(middleElementIndex - i) - 1) * baseHeight + (baseHeight / 2);
return { type: "up", inboundType: "down", height };
} else if (i === middleElementIndex) {
return { type: "flat", inboundType: "flat", height: baseHeight };
} else {
let height = (_.ceil(i - middleElementIndex) - 1) * baseHeight + (baseHeight / 2);
return { type: "down", inboundType: "up", height };
}
});
let height = numNeighbors * baseHeight;
let svg = (
{
_.map(arrowTypes, arrow => {
let arrowType = isOutbound ? arrow.type : arrow.inboundType;
return OctopusArms[arrowType](width, height, arrow.height, isOutbound);
})
}
);
return !showArrow ? null : svg;
}
render() {
let { resource, neighbors, unmeshedSources } = this.props;
if (_.isEmpty(resource)) {
return null;
}
let display = this.getNeighborDisplayData(neighbors);
let numUpstreams = _.size(display.upstreams.displayed) + (_.isEmpty(unmeshedSources) ? 0 : 1) +
(_.isEmpty(display.upstreams.collapsed) ? 0 : 1);
let hasUpstreams = numUpstreams > 0;
let numDownstreams = _.size(display.downstreams.displayed) + (_.isEmpty(display.downstreams.collapsed) ? 0 : 1);
let hasDownstreams = numDownstreams > 0;
return (
{_.map(display.upstreams.displayed, n => this.renderResourceSummary(n, "neighbor"))}
{_.isEmpty(unmeshedSources) ? null : this.renderUnmeshedResources(unmeshedSources)}
{_.isEmpty(display.upstreams.collapsed) ? null : this.renderCollapsedNeighbors(display.upstreams.collapsed)}
{this.renderArrowCol(numUpstreams, false)}
{this.renderResourceSummary(resource, "main")}
{this.renderArrowCol(numDownstreams, true)}
{_.map(display.downstreams.displayed, n => this.renderResourceSummary(n, "neighbor"))}
{_.isEmpty(display.downstreams.collapsed) ? null : this.renderCollapsedNeighbors(display.downstreams.collapsed)}
);
}
}