Grey out bottom of stack when there aren't 3 nodes in the stack

E.g. greying out the bottom 2/3 visual nodes if the stack actually only
has a single node.

- Server returns "node_count" for agg nodes.
This commit is contained in:
Simon Howe
2016-02-16 11:30:00 +01:00
parent 24d06d534f
commit 2c626776a1
9 changed files with 86 additions and 16 deletions

View File

@@ -1,14 +1,22 @@
import React from 'react';
export default function NodeShapeCircle({highlighted, size, color}) {
export default function NodeShapeCircle({onlyHighlight, highlighted, size, color}) {
const hightlightNode = <circle r={size * 0.7} className="highlighted" />;
if (onlyHighlight) {
return (
<g className="shape">
{highlighted && hightlightNode}
</g>
);
}
return (
<g className="shape">
{highlighted &&
<circle r={size * 0.7} className="highlighted"></circle>}
<circle r={size * 0.5} className="border" stroke={color}></circle>
<circle r={size * 0.45} className="shadow"></circle>
<circle r={Math.max(2, size * 0.125)} className="node"></circle>
{highlighted && hightlightNode}
<circle r={size * 0.5} className="border" stroke={color} />
<circle r={size * 0.45} className="shadow" />
<circle r={Math.max(2, size * 0.125)} className="node" />
</g>
);
}

View File

@@ -1,29 +1,39 @@
import React from 'react';
import _ from 'lodash';
function dissoc(obj, key) {
const newObj = _.clone(obj);
delete newObj[key];
return newObj;
}
export default function NodeShapeStack(props) {
const propsNoHighlight = _.clone(props);
const Shape = props.shape;
delete propsNoHighlight.highlighted;
const propsNoHighlight = dissoc(props, 'highlighted');
const propsOnlyHighlight = Object.assign({}, props, {onlyHighlight: true});
const Shape = props.shape;
const nodeCount = props.nodeCount;
const [dx, dy] = [0, 6];
const ds = 0.075;
const dsx = (props.size * 2 + dx) / (props.size * 2);
const dsy = (props.size * 2 + dy) / (props.size * 2);
const hls = [dsx, dsy];
const propsWithGrey = Object.assign({}, propsNoHighlight, {color: '#aaa', className: 'mock'});
const propsForIndex = i => (nodeCount < i ? propsWithGrey : propsNoHighlight);
return (
<g transform={`translate(${dx * -1}, ${dy * -1})`} className="stack">
<g transform={`translate(${dx * 2}, ${dy * 2}) scale(${1 - (2 * ds)}, ${1 - (2 * ds)})`}>
<Shape {...propsNoHighlight} />
<Shape {...propsForIndex(3)} />
</g>
<g transform={`translate(${dx * 1}, ${dy * 1}) scale(${1 - (1 * ds)}, ${1 - (1 * ds)})`}>
<Shape {...propsNoHighlight} />
<Shape {...propsForIndex(2)} />
</g>
<g transform={`translate(${dx * 0.5}, ${dy * 0.5}) scale(${hls})`} className="stack">
<Shape {...propsOnlyHighlight} />
</g>
<Shape {...propsNoHighlight} />
<Shape {...propsForIndex(1)} />
</g>
);
}

View File

@@ -150,6 +150,7 @@ export default class NodesChart extends React.Component {
id={node.get('id')}
label={node.get('label')}
pseudo={node.get('pseudo')}
nodeCount={node.get('nodeCount')}
subLabel={node.get('subLabel')}
rank={node.get('rank')}
selectedNodeScale={selectedNodeScale}
@@ -246,6 +247,7 @@ export default class NodesChart extends React.Component {
label: node.get('label_major'),
pseudo: node.get('pseudo'),
subLabel: node.get('label_minor'),
nodeCount: node.get('node_count'),
rank: node.get('rank'),
shape: node.get('shape'),
stack: node.get('stack'),

View File

@@ -7,15 +7,21 @@ const log = debug('scope:debug-panel');
import { receiveNodesDelta } from '../actions/app-actions';
import AppStore from '../stores/app-store';
const SHAPES = ['circle', 'hexagon', 'square'];
const NODE_COUNTS = [1, 2, 3];
const STACK_VARIANTS = [true, false];
const sample = function(collection) {
return _.range(_.random(4)).map(() => _.sample(collection));
};
const deltaAdd = function(name, adjacency = []) {
const deltaAdd = function(name, adjacency = [], shape = 'circle', stack = false, nodeCount = 1) {
return {
'adjacency': adjacency,
'controls': {},
'shape': shape,
'stack': stack,
'node_count': nodeCount,
'id': name,
'label_major': name,
'label_minor': 'weave-1',
@@ -26,6 +32,23 @@ const deltaAdd = function(name, adjacency = []) {
};
};
function addAllVariants() {
const newNodes = _.flattenDeep(SHAPES.map(s => {
return STACK_VARIANTS.map(stack => {
if (!stack) return [deltaAdd([s, 1, stack].join('-'), [], s, stack, 1)];
return NODE_COUNTS.map(n => {
return deltaAdd([s, n, stack].join('-'), [], s, stack, n);
});
});
}));
console.log(newNodes);
receiveNodesDelta({
add: newNodes
});
}
function addNodes(n) {
const ns = AppStore.getNodes();
const nodeNames = ns.keySeq().toJS();
@@ -33,7 +56,11 @@ function addNodes(n) {
const allNodes = _(nodeNames).concat(newNodeNames).value();
receiveNodesDelta({
add: newNodeNames.map((name) => deltaAdd(name, sample(allNodes)))
add: newNodeNames.map((name) => deltaAdd(name,
sample(allNodes)),
_.sample(SHAPES),
_.sample(STACK_VARIANTS),
_.sample(NODE_COUNTS))
});
}
@@ -65,6 +92,7 @@ export class DebugToolbar extends React.Component {
<button onClick={() => addNodes(10)}>+10</button>
<input type="number" onChange={this.onChange} value={this.state.nodesToAdd} />
<button onClick={() => addNodes(this.state.nodesToAdd)}>+</button>
<button onClick={() => addAllVariants()}>Variants</button>
</div>
);
}

View File

@@ -39,6 +39,7 @@ function makeNode(node) {
id: node.id,
label_major: node.label_major,
label_minor: node.label_minor,
node_count: node.node_count,
rank: node.rank,
pseudo: node.pseudo,
stack: node.stack,

View File

@@ -131,6 +131,7 @@ var (
Pseudo: false,
Shape: square,
Stack: true,
NodeCount: 2,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ClientProcess1NodeID],
fixture.Report.Process.Nodes[fixture.ClientProcess2NodeID],
@@ -149,6 +150,7 @@ var (
Pseudo: false,
Shape: square,
Stack: true,
NodeCount: 1,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ServerProcessNodeID],
),
@@ -166,6 +168,7 @@ var (
Pseudo: false,
Shape: square,
Stack: true,
NodeCount: 1,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.NonContainerProcessNodeID],
),
@@ -245,6 +248,7 @@ var (
Pseudo: false,
Shape: hexagon,
Stack: true,
NodeCount: 1,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ClientProcess1NodeID],
fixture.Report.Process.Nodes[fixture.ClientProcess2NodeID],
@@ -264,6 +268,7 @@ var (
Pseudo: false,
Shape: hexagon,
Stack: true,
NodeCount: 1,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ServerProcessNodeID],
fixture.Report.Container.Nodes[fixture.ServerContainerNodeID],
@@ -375,6 +380,7 @@ var (
Rank: "ping/pong-a",
Pseudo: false,
Shape: pentagon,
NodeCount: 1,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ClientProcess1NodeID],
fixture.Report.Process.Nodes[fixture.ClientProcess2NodeID],
@@ -395,6 +401,7 @@ var (
Rank: "ping/pong-b",
Pseudo: false,
Shape: pentagon,
NodeCount: 1,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ServerProcessNodeID],
fixture.Report.Container.Nodes[fixture.ServerContainerNodeID],
@@ -445,6 +452,7 @@ var (
Pseudo: false,
Shape: pentagon,
Stack: true,
NodeCount: 2,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ClientProcess1NodeID],
fixture.Report.Process.Nodes[fixture.ClientProcess2NodeID],

View File

@@ -514,6 +514,7 @@ func MapCountProcessName(n RenderableNode, _ report.Networks) RenderableNodes {
}
processes, _ := n.Node.Counters.Lookup(processesKey)
n.NodeCount = processes
if processes == 1 {
n.LabelMinor = "1 process"
} else {
@@ -744,6 +745,7 @@ func MapCountContainers(n RenderableNode, _ report.Networks) RenderableNodes {
}
containers, _ := n.Node.Counters.Lookup(ContainersKey)
n.NodeCount = containers
if containers == 1 {
n.LabelMinor = "1 container"
} else {
@@ -760,6 +762,7 @@ func MapCountPods(n RenderableNode, _ report.Networks) RenderableNodes {
}
pods, _ := n.Node.Counters.Lookup(podsKey)
n.NodeCount = pods
if pods == 1 {
n.LabelMinor = "1 pod"
} else {

View File

@@ -17,6 +17,7 @@ type RenderableNode struct {
ControlNode string `json:"-"` // ID of node from which to show the controls in the UI
Shape string `json:"shape"` // Shape node should be rendered as
Stack bool `json:"stack"` // Should UI render this node as a stack?
NodeCount int `json:"node_count,omitempty"` // Number of nodes represented by this stack.
report.EdgeMetadata `json:"metadata"` // Numeric sums
report.Node
@@ -42,6 +43,7 @@ func NewRenderableNode(id string) RenderableNode {
EdgeMetadata: report.EdgeMetadata{},
Node: report.MakeNode(),
Shape: Circle,
NodeCount: 0,
}
}
@@ -57,6 +59,7 @@ func NewRenderableNodeWith(id, major, minor, rank string, node RenderableNode) R
EdgeMetadata: node.EdgeMetadata.Copy(),
Node: node.Node.Copy(),
Shape: Circle,
NodeCount: 0,
}
}
@@ -73,6 +76,7 @@ func NewDerivedNode(id string, node RenderableNode) RenderableNode {
Node: node.Node.Copy(),
ControlNode: "", // Do not propagate ControlNode when making a derived node!
Shape: Circle,
NodeCount: 0,
}
}
@@ -87,6 +91,7 @@ func newDerivedPseudoNode(id, major string, node RenderableNode) RenderableNode
EdgeMetadata: node.EdgeMetadata.Copy(),
Node: node.Node.Copy(),
Shape: Circle,
NodeCount: 0,
}
}
@@ -128,6 +133,10 @@ func (rn RenderableNode) Merge(other RenderableNode) RenderableNode {
panic(result.ID)
}
if result.NodeCount == 0 {
result.NodeCount = other.NodeCount
}
result.Stack = result.Stack || rn.Stack
result.Children = rn.Children.Merge(other.Children)
result.EdgeMetadata = rn.EdgeMetadata.Merge(other.EdgeMetadata)
@@ -150,6 +159,7 @@ func (rn RenderableNode) Copy() RenderableNode {
ControlNode: rn.ControlNode,
Shape: rn.Shape,
Stack: rn.Stack,
NodeCount: rn.NodeCount,
}
}

View File

@@ -148,7 +148,7 @@ function lint_files {
function list_files {
if [ $# -gt 0 ]; then
find "$@" -type f | grep -vE '(^\./\.git|^\./\.pkg|/vendor/)'
find "$@" -type f | grep -vE '(^\./\.git|^\./\.pkg|/vendor/|/client/node_modules/)'
else
git diff --cached --name-only
fi