diff --git a/client/app/scripts/charts/node-container.js b/client/app/scripts/charts/node-container.js
index 73b7ed74e..f87d89c59 100644
--- a/client/app/scripts/charts/node-container.js
+++ b/client/app/scripts/charts/node-container.js
@@ -1,33 +1,103 @@
import React from 'react';
-import { Motion } from 'react-motion';
+import { connect } from 'react-redux';
+import { List as makeList } from 'immutable';
+import { GraphNode } from 'weaveworks-ui-components';
-import { weakSpring } from 'weaveworks-ui-components/lib/utils/animation';
+import {
+ getMetricValue,
+ getMetricColor,
+} from '../utils/metric-utils';
+import { clickNode, enterNode, leaveNode } from '../actions/app-actions';
+import { trackAnalyticsEvent } from '../utils/tracking-utils';
+import { getNodeColor } from '../utils/color-utils';
+import MatchedResults from '../components/matched-results';
+import { GRAPH_VIEW_MODE } from '../constants/naming';
-import Node from './node';
+import NodeNetworksOverlay from './node-networks-overlay';
+class NodeContainer extends React.Component {
+ saveRef = (ref) => {
+ this.ref = ref;
+ };
-const transformedNode = (otherProps, { x, y, k }) => (
-
-
-
-);
+ handleMouseClick = (nodeId, ev) => {
+ ev.stopPropagation();
+ trackAnalyticsEvent('scope.node.click', {
+ layout: GRAPH_VIEW_MODE,
+ topologyId: this.props.currentTopology.get('id'),
+ parentTopologyId: this.props.currentTopology.get('parentId'),
+ });
+ this.props.clickNode(nodeId, this.props.label, this.ref.getBoundingClientRect());
+ };
-export default class NodeContainer extends React.PureComponent {
- render() {
- const {
- dx, dy, isAnimated, scale, ...forwardedProps
- } = this.props;
-
- if (!isAnimated) {
- // Show static node for optimized rendering
- return transformedNode(forwardedProps, { x: dx, y: dy, k: scale });
- }
+ renderPrependedInfo = () => {
+ const { showingNetworks, networks } = this.props;
+ if (!showingNetworks) return null;
return (
- // Animate the node if the layout is sufficiently small
-
- {interpolated => transformedNode(forwardedProps, interpolated)}
-
+
+ );
+ };
+
+ renderAppendedInfo = () => {
+ const matchedMetadata = this.props.matches.get('metadata', makeList());
+ const matchedParents = this.props.matches.get('parents', makeList());
+ const matchedDetails = matchedMetadata.concat(matchedParents);
+ return (
+
+ );
+ };
+
+ render() {
+ const {
+ rank, label, pseudo, metric, showingNetworks, networks
+ } = this.props;
+ const { hasMetric, height, formattedValue } = getMetricValue(metric);
+ const metricFormattedValue = !pseudo && hasMetric ? formattedValue : '';
+ const labelOffset = (showingNetworks && networks) ? 10 : 0;
+
+ return (
+
);
}
}
+
+function mapStateToProps(state) {
+ return {
+ searchTerms: [state.get('searchQuery')],
+ exportingGraph: state.get('exportingGraph'),
+ showingNetworks: state.get('showingNetworks'),
+ currentTopology: state.get('currentTopology'),
+ contrastMode: state.get('contrastMode'),
+ };
+}
+
+export default connect(
+ mapStateToProps,
+ { clickNode, enterNode, leaveNode }
+)(NodeContainer);
diff --git a/client/app/scripts/charts/node-networks-overlay.js b/client/app/scripts/charts/node-networks-overlay.js
index 0522a83e0..6d57c3426 100644
--- a/client/app/scripts/charts/node-networks-overlay.js
+++ b/client/app/scripts/charts/node-networks-overlay.js
@@ -4,7 +4,6 @@ import { List as makeList } from 'immutable';
import { connect } from 'react-redux';
import { getNetworkColor } from '../utils/color-utils';
-import { NODE_BASE_SIZE } from '../constants/styles';
// Min size is about a quarter of the width, feels about right.
const minBarWidth = 0.25;
@@ -14,7 +13,7 @@ const borderRadius = 0.01;
const offset = 0.67;
const x = scaleBand();
-function NodeNetworksOverlay({ stack, networks = makeList(), contrastMode }) {
+function NodeNetworksOverlay({ networks = makeList() }) {
const barWidth = Math.max(1, minBarWidth * networks.size);
const yPosition = offset - (barHeight * 0.5);
@@ -38,9 +37,8 @@ function NodeNetworksOverlay({ stack, networks = makeList(), contrastMode }) {
/>
));
- const translateY = stack && contrastMode ? 0.15 : 0;
return (
-
+
{bars.toJS()}
);
diff --git a/client/app/scripts/charts/node-shape-stack.js b/client/app/scripts/charts/node-shape-stack.js
deleted file mode 100644
index d150d5d14..000000000
--- a/client/app/scripts/charts/node-shape-stack.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import React from 'react';
-
-import { NODE_BASE_SIZE } from '../constants/styles';
-
-export default function NodeShapeStack(props) {
- const verticalDistance = NODE_BASE_SIZE * (props.contrastMode ? 0.12 : 0.1);
- const verticalTranslate = t => `translate(0, ${t * verticalDistance})`;
- const Shape = props.shape;
-
- // Stack three shapes on top of one another pretending they are never highlighted.
- // Instead, fake the highlight of the whole stack with a vertically stretched shape
- // drawn in the background. This seems to give a good approximation of the stack
- // highlight and prevents us from needing to do some render-heavy SVG clipping magic.
- return (
-
-
-
-
-
-
-
-
- );
-}
diff --git a/client/app/scripts/charts/node-shapes.js b/client/app/scripts/charts/node-shapes.js
deleted file mode 100644
index 2946910ae..000000000
--- a/client/app/scripts/charts/node-shapes.js
+++ /dev/null
@@ -1,91 +0,0 @@
-import React from 'react';
-import classNames from 'classnames';
-
-import { NODE_BASE_SIZE } from '../constants/styles';
-import {
- getMetricValue,
- getMetricColor,
- getClipPathDefinition,
-} from '../utils/metric-utils';
-import {
- pathElement,
- circleElement,
- rectangleElement,
- circleShapeProps,
- triangleShapeProps,
- squareShapeProps,
- pentagonShapeProps,
- hexagonShapeProps,
- heptagonShapeProps,
- octagonShapeProps,
- cloudShapeProps,
- cylinderShapeProps,
- dottedCylinderShapeProps,
- sheetShapeProps
-} from '../utils/node-shape-utils';
-import { encodeIdAttribute } from '../utils/dom-utils';
-
-
-function NodeShape(shapeType, shapeElement, shapeProps, {
- id, highlighted, color, metric
-}) {
- const { height, hasMetric, formattedValue } = getMetricValue(metric);
- const className = classNames('shape', `shape-${shapeType}`, { metrics: hasMetric });
- const metricStyle = { fill: getMetricColor(metric) };
- const clipId = encodeIdAttribute(`metric-clip-${id}`);
-
- return (
-
- {highlighted && shapeElement({
- className: 'highlight-border',
- transform: `scale(${NODE_BASE_SIZE * 0.5})`,
- ...shapeProps,
- })}
- {highlighted && shapeElement({
- className: 'highlight-shadow',
- transform: `scale(${NODE_BASE_SIZE * 0.5})`,
- ...shapeProps,
- })}
- {shapeElement({
- className: 'background',
- transform: `scale(${NODE_BASE_SIZE * 0.48})`,
- ...shapeProps,
- })}
- {hasMetric && getClipPathDefinition(clipId, height, 0.48)}
- {hasMetric && shapeElement({
- className: 'metric-fill',
- transform: `scale(${NODE_BASE_SIZE * 0.48})`,
- clipPath: `url(#${clipId})`,
- style: metricStyle,
- ...shapeProps,
- })}
- {shapeElement({
- className: 'shadow',
- transform: `scale(${NODE_BASE_SIZE * 0.49})`,
- ...shapeProps,
- })}
- {shapeElement({
- className: 'border',
- transform: `scale(${NODE_BASE_SIZE * 0.5})`,
- stroke: color,
- ...shapeProps,
- })}
- {hasMetric && highlighted ?
- {formattedValue} :
-
- }
-
- );
-}
-
-export const NodeShapeCircle = props => NodeShape('circle', circleElement, circleShapeProps, props);
-export const NodeShapeTriangle = props => NodeShape('triangle', pathElement, triangleShapeProps, props);
-export const NodeShapeSquare = props => NodeShape('square', rectangleElement, squareShapeProps, props);
-export const NodeShapePentagon = props => NodeShape('pentagon', pathElement, pentagonShapeProps, props);
-export const NodeShapeHexagon = props => NodeShape('hexagon', pathElement, hexagonShapeProps, props);
-export const NodeShapeHeptagon = props => NodeShape('heptagon', pathElement, heptagonShapeProps, props);
-export const NodeShapeOctagon = props => NodeShape('octagon', pathElement, octagonShapeProps, props);
-export const NodeShapeCloud = props => NodeShape('cloud', pathElement, cloudShapeProps, props);
-export const NodeShapeCylinder = props => NodeShape('cylinder', pathElement, cylinderShapeProps, props);
-export const NodeShapeDottedCylinder = props => NodeShape('dottedcylinder', pathElement, dottedCylinderShapeProps, props);
-export const NodeShapeSheet = props => NodeShape('sheet', pathElement, sheetShapeProps, props);
diff --git a/client/app/scripts/charts/node.js b/client/app/scripts/charts/node.js
deleted file mode 100644
index 8f0cb2c07..000000000
--- a/client/app/scripts/charts/node.js
+++ /dev/null
@@ -1,191 +0,0 @@
-import React from 'react';
-import { connect } from 'react-redux';
-import classnames from 'classnames';
-import { Map as makeMap, List as makeList } from 'immutable';
-
-import { clickNode, enterNode, leaveNode } from '../actions/app-actions';
-import { getNodeColor } from '../utils/color-utils';
-import MatchedText from '../components/matched-text';
-import MatchedResults from '../components/matched-results';
-import { trackAnalyticsEvent } from '../utils/tracking-utils';
-import { GRAPH_VIEW_MODE } from '../constants/naming';
-import { NODE_BASE_SIZE } from '../constants/styles';
-
-import NodeShapeStack from './node-shape-stack';
-import NodeNetworksOverlay from './node-networks-overlay';
-import {
- NodeShapeCircle,
- NodeShapeTriangle,
- NodeShapeSquare,
- NodeShapePentagon,
- NodeShapeHexagon,
- NodeShapeHeptagon,
- NodeShapeOctagon,
- NodeShapeCloud,
- NodeShapeCylinder,
- NodeShapeDottedCylinder,
- NodeShapeSheet
-} from './node-shapes';
-
-
-const labelWidth = 1.2 * NODE_BASE_SIZE;
-const nodeShapes = {
- circle: NodeShapeCircle,
- triangle: NodeShapeTriangle,
- square: NodeShapeSquare,
- pentagon: NodeShapePentagon,
- hexagon: NodeShapeHexagon,
- heptagon: NodeShapeHeptagon,
- octagon: NodeShapeOctagon,
- cloud: NodeShapeCloud,
- cylinder: NodeShapeCylinder,
- dottedcylinder: NodeShapeDottedCylinder,
- storagesheet: NodeShapeSheet
-};
-
-function stackedShape(Shape) {
- const factory = React.createFactory(NodeShapeStack);
- return props => factory(Object.assign({}, props, {shape: Shape}));
-}
-
-function getNodeShape({ shape, stack }) {
- const nodeShape = nodeShapes[shape];
- if (!nodeShape) {
- throw new Error(`Unknown shape: ${shape}!`);
- }
- return stack ? stackedShape(nodeShape) : nodeShape;
-}
-
-
-class Node extends React.Component {
- constructor(props, context) {
- super(props, context);
- this.state = {
- hovered: false,
- };
-
- this.handleMouseClick = this.handleMouseClick.bind(this);
- this.handleMouseEnter = this.handleMouseEnter.bind(this);
- this.handleMouseLeave = this.handleMouseLeave.bind(this);
- this.saveShapeRef = this.saveShapeRef.bind(this);
- }
-
- renderSvgLabels(labelClassName, labelMinorClassName, labelOffsetY) {
- const { label, labelMinor } = this.props;
- return (
-
- {label}
-
- {labelMinor}
-
-
- );
- }
-
- renderStandardLabels(labelClassName, labelMinorClassName, labelOffsetY, mouseEvents) {
- const { label, labelMinor, matches = makeMap() } = this.props;
- const matchedMetadata = matches.get('metadata', makeList());
- const matchedParents = matches.get('parents', makeList());
- const matchedNodeDetails = matchedMetadata.concat(matchedParents);
-
- return (
-
-
-
- );
- }
-
- render() {
- const {
- focused, highlighted, networks, pseudo, rank, label, transform,
- exportingGraph, showingNetworks, stack, id, metric
- } = this.props;
- const { hovered } = this.state;
-
- const color = getNodeColor(rank, label, pseudo);
- const truncate = !focused && !hovered;
- const labelOffsetY = (showingNetworks && networks) ? 40 : 28;
-
- const nodeClassName = classnames('node', { highlighted, hovered, pseudo });
- const labelClassName = classnames('node-label', { truncate });
- const labelMinorClassName = classnames('node-label-minor', { truncate });
-
- const NodeShapeType = getNodeShape(this.props);
- const mouseEvents = {
- onClick: this.handleMouseClick,
- onMouseEnter: this.handleMouseEnter,
- onMouseLeave: this.handleMouseLeave,
- };
-
- return (
-
- {exportingGraph ?
- this.renderSvgLabels(labelClassName, labelMinorClassName, labelOffsetY) :
- this.renderStandardLabels(labelClassName, labelMinorClassName, labelOffsetY, mouseEvents)}
-
-
-
-
-
- {showingNetworks && }
-
- );
- }
-
- saveShapeRef(ref) {
- this.shapeRef = ref;
- }
-
- handleMouseClick(ev) {
- ev.stopPropagation();
- trackAnalyticsEvent('scope.node.click', {
- layout: GRAPH_VIEW_MODE,
- topologyId: this.props.currentTopology.get('id'),
- parentTopologyId: this.props.currentTopology.get('parentId'),
- });
- this.props.clickNode(this.props.id, this.props.label, this.shapeRef.getBoundingClientRect());
- }
-
- handleMouseEnter() {
- this.props.enterNode(this.props.id);
- this.setState({ hovered: true });
- }
-
- handleMouseLeave() {
- this.props.leaveNode(this.props.id);
- this.setState({ hovered: false });
- }
-}
-
-function mapStateToProps(state) {
- return {
- exportingGraph: state.get('exportingGraph'),
- showingNetworks: state.get('showingNetworks'),
- currentTopology: state.get('currentTopology'),
- contrastMode: state.get('contrastMode'),
- };
-}
-
-export default connect(
- mapStateToProps,
- { clickNode, enterNode, leaveNode }
-)(Node);
diff --git a/client/app/scripts/charts/nodes-chart-elements.js b/client/app/scripts/charts/nodes-chart-elements.js
index 003a0c16f..de3034850 100644
--- a/client/app/scripts/charts/nodes-chart-elements.js
+++ b/client/app/scripts/charts/nodes-chart-elements.js
@@ -21,6 +21,7 @@ import {
layoutEdgesSelector
} from '../selectors/graph-view/layout';
+import { NODE_BASE_SIZE } from '../constants/styles';
import {
BLURRED_EDGES_LAYER,
BLURRED_NODES_LAYER,
@@ -148,7 +149,7 @@ class NodesChartElements extends React.Component {
}
renderNode(node) {
- const { isAnimated, contrastMode } = this.props;
+ const { isAnimated } = this.props;
return (
);
}
diff --git a/client/app/scripts/components/matched-results.js b/client/app/scripts/components/matched-results.js
index 7a85c251e..996056636 100644
--- a/client/app/scripts/components/matched-results.js
+++ b/client/app/scripts/components/matched-results.js
@@ -1,6 +1,5 @@
import React from 'react';
-
-import MatchedText from './matched-text';
+import { MatchedText } from 'weaveworks-ui-components';
const SHOW_ROW_COUNT = 2;
const MAX_MATCH_LENGTH = 24;
@@ -13,10 +12,12 @@ const Match = match => (
{match.label}:
+ truncate={match.truncate}
+ />
);
diff --git a/client/app/scripts/utils/metric-utils.js b/client/app/scripts/utils/metric-utils.js
index 85bc71633..f30f6cabc 100644
--- a/client/app/scripts/utils/metric-utils.js
+++ b/client/app/scripts/utils/metric-utils.js
@@ -23,7 +23,7 @@ const loadScale = scaleLog().domain([0.01, 100]).range([0, 1]);
export function getMetricValue(metric) {
if (!metric) {
- return {height: 0, value: null, formattedValue: 'n/a'};
+ return { height: 0, value: null, formattedValue: 'n/a' };
}
const m = metric.toJS();
const { value } = m;
@@ -35,7 +35,7 @@ export function getMetricValue(metric) {
max = null;
}
- let displayedValue = Number(value).toFixed(1);
+ let displayedValue = Number(value);
if (displayedValue > 0 && (!max || displayedValue < max)) {
const baseline = 0.1;
displayedValue = (valuePercentage * (1 - (baseline * 2))) + baseline;
diff --git a/client/app/scripts/utils/node-shape-utils.js b/client/app/scripts/utils/node-shape-utils.js
deleted file mode 100644
index c37f2fa1a..000000000
--- a/client/app/scripts/utils/node-shape-utils.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import React from 'react';
-import range from 'lodash/range';
-import { line, curveCardinalClosed } from 'd3-shape';
-
-import { UNIT_CLOUD_PATH, UNIT_CYLINDER_PATH, SHEET } from '../constants/styles';
-
-
-export const pathElement = React.createFactory('path');
-export const circleElement = React.createFactory('circle');
-export const rectangleElement = React.createFactory('rect');
-
-function curvedUnitPolygonPath(n) {
- const curve = curveCardinalClosed.tension(0.65);
- const spline = line().curve(curve);
- const innerAngle = (2 * Math.PI) / n;
- return spline(range(0, n).map(k => [
- Math.sin(k * innerAngle),
- -Math.cos(k * innerAngle),
- ]));
-}
-
-export const circleShapeProps = { r: 1 };
-export const triangleShapeProps = { d: curvedUnitPolygonPath(3) };
-export const squareShapeProps = {
- width: 1.8, height: 1.8, rx: 0.4, ry: 0.4, x: -0.9, y: -0.9
-};
-export const pentagonShapeProps = { d: curvedUnitPolygonPath(5) };
-export const hexagonShapeProps = { d: curvedUnitPolygonPath(6) };
-export const heptagonShapeProps = { d: curvedUnitPolygonPath(7) };
-export const octagonShapeProps = { d: curvedUnitPolygonPath(8) };
-export const cloudShapeProps = { d: UNIT_CLOUD_PATH };
-export const cylinderShapeProps = { d: UNIT_CYLINDER_PATH };
-export const dottedCylinderShapeProps = { d: UNIT_CYLINDER_PATH };
-export const sheetShapeProps = { d: SHEET };
diff --git a/client/app/styles/_base.scss b/client/app/styles/_base.scss
index 27a43d13e..41112a716 100644
--- a/client/app/styles/_base.scss
+++ b/client/app/styles/_base.scss
@@ -435,97 +435,8 @@ a {
fill: $text-secondary-color;
}
- .nodes-chart-elements .node {
- text-align: center;
-
- .node-label {
- color: $text-color;
- }
-
- .node-label-minor {
- line-height: 125%;
- }
-
- .node-labels-container {
- transform: scale($node-text-scale);
- pointer-events: none;
- }
-
- .node-label-wrapper {
- //
- // Base line height doesn't hop across foreignObject =/
- //
- line-height: 150%;
-
- //
- // inline-block so wrapper is only as wide as content.
- //
- display: inline-block;
-
- //
- // - inline-block gets a different baseline depending on overflow value
- // - this element gets its overflow value changed sometimes.
- // - explicitly set the baseline so the text doesn't jump up and down.
- // http://stackoverflow.com/questions/9273016
- //
- vertical-align: top;
-
- cursor: pointer;
- pointer-events: all;
- font-size: $font-size-small;
- width: 100%;
- }
-
- .node-label-minor {
- color: $text-secondary-color;
- font-size: $font-size-tiny;
- }
-
- .node-label, .node-label-minor {
- span {
- border-radius: $border-radius-soft;
- }
- span:not(.match) {
- padding: 0 0.25em;
- background-color: $label-background-color;
- }
- span:empty {
- padding: 0;
- }
- }
- .matched-results {
- background-color: $label-background-color;
- }
-
- &.pseudo {
- cursor: default;
-
- .node-label {
- fill: $text-secondary-color;
- }
-
- .node-label-minor {
- fill: $text-tertiary-color;
- }
-
- .node {
- opacity: $node-pseudo-opacity;
- }
-
- .border {
- opacity: $node-pseudo-opacity;
- stroke: $text-tertiary-color;
- }
- }
-
- .node-label, .node-label-minor {
- text-align: center;
- }
-
- .match {
- background-color: transparentize($color-blue-400, 0.25);
- border: 1px solid $color-blue-400;
- }
+ .nodes-chart-elements .matched-results {
+ background-color: $label-background-color;
}
.edge {
@@ -555,85 +466,6 @@ a {
}
}
- .stack .highlight-only {
- .background { display: none; }
- .shadow { display: none; }
- .border { display: none; }
- .node { display: none; }
- }
-
- .stack .shape .metric-fill {
- display: none;
- }
-
- .shape {
- transform: scale(1);
- cursor: pointer;
-
- .highlight-border {
- fill: none;
- stroke: $color-blue-400;
- stroke-width: 0.7 + $node-highlight-stroke-width * 2;
- stroke-opacity: $node-highlight-stroke-opacity;
- }
-
- .highlight-shadow {
- fill: none;
- stroke: $color-white;
- stroke-width: 0.7;
- stroke-opacity: $node-highlight-shadow-opacity;
- }
-
- .background {
- stroke: none;
- fill: $background-lighter-color;
- }
-
- .metric-fill {
- stroke: none;
- fill-opacity: 0.7;
- }
-
- .border {
- fill: none;
- stroke-opacity: 1;
- stroke-width: $node-border-stroke-width;
- }
-
- &.metrics .border {
- stroke-opacity: 0.3;
- }
-
- .shadow {
- fill: none;
- stroke: $background-color;
- stroke-width: $node-shadow-stroke-width;
- }
-
- .node {
- fill: $text-color;
- stroke: $background-lighter-color;
- stroke-width: 0.05;
- }
-
- text {
- transform: scale($node-text-scale);
- font-size: $font-size-tiny;
- dominant-baseline: middle;
- text-anchor: middle;
- }
- }
-
- .shape-dottedcylinder {
- .border{
- stroke-dasharray: 0.07;
- }
- }
-
- .stack .shape .border {
- stroke-width: $node-border-stroke-width * 0.8;
- }
-
.edge-marker {
color: $edge-color;
fill: $edge-color;
diff --git a/client/package.json b/client/package.json
index 4c4694623..23dda0451 100644
--- a/client/package.json
+++ b/client/package.json
@@ -44,7 +44,7 @@
"reselect": "3.0.1",
"reselect-map": "1.0.3",
"styled-components": "2.2.4",
- "weaveworks-ui-components": "0.11.8",
+ "weaveworks-ui-components": "0.11.14",
"whatwg-fetch": "2.0.3",
"xterm": "3.3.0"
},
diff --git a/client/yarn.lock b/client/yarn.lock
index 7d47e3e9b..3ed9021f1 100644
--- a/client/yarn.lock
+++ b/client/yarn.lock
@@ -8397,9 +8397,9 @@ wd@^0.4.0:
underscore.string "~3.0.3"
vargs "~0.1.0"
-weaveworks-ui-components@0.11.8:
- version "0.11.8"
- resolved "https://registry.yarnpkg.com/weaveworks-ui-components/-/weaveworks-ui-components-0.11.8.tgz#4e649e418f5fb1746b908cc4edaa77ebadaf75e8"
+weaveworks-ui-components@0.11.14:
+ version "0.11.14"
+ resolved "https://registry.yarnpkg.com/weaveworks-ui-components/-/weaveworks-ui-components-0.11.14.tgz#5f72f8a5059bc9f28295b91164c17e0780906f9e"
dependencies:
classnames "2.2.5"
d3-drag "1.2.1"