mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-03 10:11:03 +00:00
Make Resource view nodes clickable (#2679)
* Made Resource view nodes clickable. * Remove selection when clicking on the background. * Use opacity instead of the blue overlay for selected nodes.
This commit is contained in:
@@ -323,13 +323,14 @@ export function setResourceView() {
|
||||
};
|
||||
}
|
||||
|
||||
export function clickNode(nodeId, label, origin) {
|
||||
export function clickNode(nodeId, label, origin, topologyId = null) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: ActionTypes.CLICK_NODE,
|
||||
origin,
|
||||
label,
|
||||
nodeId
|
||||
nodeId,
|
||||
topologyId,
|
||||
});
|
||||
updateRoute(getState);
|
||||
getNodeDetails(getState, dispatch);
|
||||
|
||||
@@ -8,9 +8,22 @@ import {
|
||||
resourcesZoomLimitsSelector,
|
||||
resourcesZoomStateSelector,
|
||||
} from '../selectors/resource-view/zoom';
|
||||
import { clickBackground } from '../actions/app-actions';
|
||||
|
||||
|
||||
class NodesResources extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.handleMouseClick = this.handleMouseClick.bind(this);
|
||||
}
|
||||
|
||||
handleMouseClick() {
|
||||
if (this.props.selectedNodeId) {
|
||||
this.props.clickBackground();
|
||||
}
|
||||
}
|
||||
|
||||
renderLayers(transform) {
|
||||
return this.props.layersTopologyIds.map((topologyId, index) => (
|
||||
<NodesResourcesLayer
|
||||
@@ -26,6 +39,7 @@ class NodesResources extends React.Component {
|
||||
return (
|
||||
<div className="nodes-resources">
|
||||
<ZoomableCanvas
|
||||
onClick={this.handleMouseClick}
|
||||
bounded forwardTransform fixVertical
|
||||
zoomLimitsSelector={resourcesZoomLimitsSelector}
|
||||
zoomStateSelector={resourcesZoomStateSelector}>
|
||||
@@ -38,10 +52,12 @@ class NodesResources extends React.Component {
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
selectedNodeId: state.get('selectedNodeId'),
|
||||
layersTopologyIds: layersTopologyIdsSelector(state),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mapStateToProps
|
||||
mapStateToProps,
|
||||
{ clickBackground }
|
||||
)(NodesResources);
|
||||
|
||||
@@ -19,9 +19,11 @@ class NodesResourcesLayer extends React.Component {
|
||||
<g className="node-resources-metric-boxes">
|
||||
{layoutNodes.toIndexedSeq().map(node => (
|
||||
<NodeResourcesMetricBox
|
||||
id={node.get('id')}
|
||||
key={node.get('id')}
|
||||
color={node.get('color')}
|
||||
label={node.get('label')}
|
||||
topologyId={topologyId}
|
||||
metricSummary={node.get('metricSummary')}
|
||||
width={node.get('width')}
|
||||
height={node.get('height')}
|
||||
|
||||
@@ -2,7 +2,10 @@ import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import NodeResourcesMetricBoxInfo from './node-resources-metric-box-info';
|
||||
import { clickNode } from '../../actions/app-actions';
|
||||
import { trackMixpanelEvent } from '../../utils/tracking-utils';
|
||||
import { applyTransform } from '../../utils/transform-utils';
|
||||
import { RESOURCE_VIEW_MODE } from '../../constants/naming';
|
||||
import {
|
||||
RESOURCES_LAYER_TITLE_WIDTH,
|
||||
RESOURCES_LABEL_MIN_SIZE,
|
||||
@@ -48,12 +51,33 @@ class NodeResourcesMetricBox extends React.Component {
|
||||
super(props, context);
|
||||
|
||||
this.state = transformedDimensions(props);
|
||||
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
this.saveNodeRef = this.saveNodeRef.bind(this);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.setState(transformedDimensions(nextProps));
|
||||
}
|
||||
|
||||
handleClick(ev) {
|
||||
ev.stopPropagation();
|
||||
trackMixpanelEvent('scope.node.click', {
|
||||
layout: RESOURCE_VIEW_MODE,
|
||||
topologyId: this.props.topologyId,
|
||||
});
|
||||
this.props.clickNode(
|
||||
this.props.id,
|
||||
this.props.label,
|
||||
this.nodeRef.getBoundingClientRect(),
|
||||
this.props.topologyId
|
||||
);
|
||||
}
|
||||
|
||||
saveNodeRef(ref) {
|
||||
this.nodeRef = ref;
|
||||
}
|
||||
|
||||
defaultRectProps(relativeHeight = 1) {
|
||||
const { x, y, width, height } = this.state;
|
||||
const translateY = height * (1 - relativeHeight);
|
||||
@@ -70,8 +94,9 @@ class NodeResourcesMetricBox extends React.Component {
|
||||
|
||||
render() {
|
||||
const { x, y, width } = this.state;
|
||||
const { label, color, metricSummary } = this.props;
|
||||
const { id, selectedNodeId, label, color, metricSummary } = this.props;
|
||||
const { showCapacity, relativeConsumption, type } = metricSummary.toJS();
|
||||
const opacity = (selectedNodeId && selectedNodeId !== id) ? 0.35 : 1;
|
||||
|
||||
const showInfo = width >= RESOURCES_LABEL_MIN_SIZE;
|
||||
const showNode = width >= 1; // hide the thin nodes
|
||||
@@ -85,7 +110,9 @@ class NodeResourcesMetricBox extends React.Component {
|
||||
metricSummary.get('humanizedAbsoluteConsumption');
|
||||
|
||||
return (
|
||||
<g className="node-resources-metric-box">
|
||||
<g
|
||||
className="node-resources-metric-box" style={{ opacity }}
|
||||
onClick={this.handleClick} ref={this.saveNodeRef}>
|
||||
<title>{label} - {type} usage at {resourceUsageTooltipInfo}</title>
|
||||
{showCapacity && <rect className="frame" {...this.defaultRectProps()} />}
|
||||
<rect className="bar" fill={color} {...this.defaultRectProps(relativeConsumption)} />
|
||||
@@ -104,8 +131,11 @@ class NodeResourcesMetricBox extends React.Component {
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
contrastMode: state.get('contrastMode'),
|
||||
selectedNodeId: state.get('selectedNodeId'),
|
||||
viewportWidth: state.getIn(['viewport', 'width']),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(NodeResourcesMetricBox);
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{ clickNode }
|
||||
)(NodeResourcesMetricBox);
|
||||
|
||||
@@ -102,7 +102,7 @@ class ZoomableCanvas extends React.Component {
|
||||
const transform = forwardTransform ? '' : transformToString(this.state);
|
||||
|
||||
return (
|
||||
<g className="zoomable-canvas">
|
||||
<div className="zoomable-canvas">
|
||||
<svg id="canvas" width="100%" height="100%" onClick={this.props.onClick}>
|
||||
<Logo transform="translate(24,24) scale(0.25)" />
|
||||
<g className="zoom-content" transform={transform}>
|
||||
@@ -115,7 +115,7 @@ class ZoomableCanvas extends React.Component {
|
||||
maxScale={this.state.maxScale}
|
||||
scale={this.state.scaleX}
|
||||
/>}
|
||||
</g>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -300,8 +300,8 @@ export function rootReducer(state = initialState, action) {
|
||||
{
|
||||
id: action.nodeId,
|
||||
label: action.label,
|
||||
topologyId: action.topologyId || state.get('currentTopologyId'),
|
||||
origin,
|
||||
topologyId: state.get('currentTopologyId')
|
||||
}
|
||||
);
|
||||
state = state.set('selectedNodeId', action.nodeId);
|
||||
|
||||
@@ -1125,12 +1125,14 @@
|
||||
|
||||
.node-resources {
|
||||
&-metric-box {
|
||||
@extend .palable;
|
||||
cursor: pointer;
|
||||
fill: rgba(150, 150, 150, 0.4);
|
||||
|
||||
&-info {
|
||||
background-color: rgba(white, 0.6);
|
||||
border-radius: 2px;
|
||||
cursor: default;
|
||||
cursor: inherit;
|
||||
padding: 5px;
|
||||
|
||||
.wrapper {
|
||||
|
||||
Reference in New Issue
Block a user