mirror of
https://github.com/weaveworks/scope.git
synced 2026-04-22 02:18:15 +00:00
Moved the node layout metrics computation to selectors.
This commit is contained in:
@@ -152,10 +152,14 @@ class Node extends React.PureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(
|
||||
state => ({
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
exportingGraph: state.get('exportingGraph'),
|
||||
showingNetworks: state.get('showingNetworks'),
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{ clickNode, enterNode, leaveNode }
|
||||
)(Node);
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { fromJS, List as makeList } from 'immutable';
|
||||
import { List as makeList } from 'immutable';
|
||||
|
||||
import { nodeMetricsSelector } from '../selectors/metrics';
|
||||
import { currentTopologySearchNodeMatchesSelector } from '../selectors/search';
|
||||
import { getAdjacentNodes } from '../utils/topology-utils';
|
||||
import NodeContainer from './node-container';
|
||||
|
||||
class NodesChartNodes extends React.Component {
|
||||
render() {
|
||||
const { adjacentNodes, highlightedNodeIds, layoutNodes, isAnimated, mouseOverNodeId,
|
||||
selectedScale, searchQuery, selectedMetric, selectedNetwork, selectedNodeId,
|
||||
topCardNode, searchNodeMatches } = this.props;
|
||||
const { adjacentNodes, highlightedNodeIds, layoutNodes, isAnimated,
|
||||
mouseOverNodeId, nodeMetrics, selectedScale, searchQuery, selectedNetwork,
|
||||
selectedNodeId, searchNodeMatches } = this.props;
|
||||
|
||||
// highlighter functions
|
||||
const setHighlighted = node => node.set('highlighted',
|
||||
@@ -37,15 +38,6 @@ class NodesChartNodes extends React.Component {
|
||||
return 1;
|
||||
};
|
||||
|
||||
// TODO: think about pulling this up into the store.
|
||||
const metric = (node) => {
|
||||
const isHighlighted = topCardNode && topCardNode.details && topCardNode.id === node.get('id');
|
||||
const sourceNode = isHighlighted ? fromJS(topCardNode.details) : node;
|
||||
return sourceNode.get('metrics') && sourceNode.get('metrics')
|
||||
.filter(m => m.get('id') === selectedMetric)
|
||||
.first();
|
||||
};
|
||||
|
||||
const nodesToRender = layoutNodes.toIndexedSeq()
|
||||
.map(setHighlighted)
|
||||
.map(setFocused)
|
||||
@@ -67,7 +59,7 @@ class NodesChartNodes extends React.Component {
|
||||
label={node.get('label')}
|
||||
pseudo={node.get('pseudo')}
|
||||
subLabel={node.get('subLabel')}
|
||||
metric={metric(node)}
|
||||
metric={nodeMetrics.get(node.get('id'))}
|
||||
rank={node.get('rank')}
|
||||
isAnimated={isAnimated}
|
||||
scale={node.get('focused') ? selectedScale : 1}
|
||||
@@ -79,16 +71,19 @@ class NodesChartNodes extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(
|
||||
state => ({
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
adjacentNodes: getAdjacentNodes(state),
|
||||
nodeMetrics: nodeMetricsSelector(state),
|
||||
highlightedNodeIds: state.get('highlightedNodeIds'),
|
||||
mouseOverNodeId: state.get('mouseOverNodeId'),
|
||||
selectedMetric: state.get('selectedMetric'),
|
||||
selectedNetwork: state.get('selectedNetwork'),
|
||||
selectedNodeId: state.get('selectedNodeId'),
|
||||
searchNodeMatches: currentTopologySearchNodeMatchesSelector(state),
|
||||
searchQuery: state.get('searchQuery'),
|
||||
topCardNode: state.get('nodeDetails').last()
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
)(NodesChartNodes);
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Map as makeMap } from 'immutable';
|
||||
import { event as d3Event, select } from 'd3-selection';
|
||||
import { zoom, zoomIdentity } from 'd3-zoom';
|
||||
|
||||
import { nodeAdjacenciesSelector } from '../selectors/nodes-chart';
|
||||
import { nodeAdjacenciesSelector } from '../selectors/nodes';
|
||||
import { clickBackground } from '../actions/app-actions';
|
||||
import Logo from '../components/logo';
|
||||
import NodesChartElements from './nodes-chart-elements';
|
||||
|
||||
@@ -5,7 +5,7 @@ import { connect } from 'react-redux';
|
||||
import { List as makeList, Map as makeMap } from 'immutable';
|
||||
import NodeDetailsTable from '../components/node-details/node-details-table';
|
||||
import { clickNode, sortOrderChanged } from '../actions/app-actions';
|
||||
import { nodesSelector } from '../selectors/nodes-chart';
|
||||
import { shownNodesSelector } from '../selectors/nodes';
|
||||
|
||||
import { currentTopologySearchNodeMatchesSelector } from '../selectors/search';
|
||||
import { getNodeColor } from '../utils/color-utils';
|
||||
@@ -144,13 +144,12 @@ class NodesGrid extends React.Component {
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
nodes: nodesSelector(state),
|
||||
nodes: shownNodesSelector(state),
|
||||
gridSortedBy: state.get('gridSortedBy'),
|
||||
gridSortedDesc: state.get('gridSortedDesc'),
|
||||
currentTopology: state.get('currentTopology'),
|
||||
currentTopologyId: state.get('currentTopologyId'),
|
||||
searchNodeMatches: currentTopologySearchNodeMatchesSelector(state),
|
||||
// searchNodeMatches: state.getIn(['searchNodeMatches', state.get('currentTopologyId')]),
|
||||
searchQuery: state.get('searchQuery'),
|
||||
selectedNodeId: state.get('selectedNodeId')
|
||||
};
|
||||
|
||||
@@ -67,7 +67,9 @@ function addMetrics(availableMetrics, node, v) {
|
||||
]);
|
||||
|
||||
return Object.assign({}, node, {
|
||||
metrics: metrics.map(m => Object.assign({}, m, {label: 'zing', max: 100, value: v})).toJS()
|
||||
metrics: metrics.map(m => Object.assign({}, m, {
|
||||
id: 'zing', label: 'zing', max: 100, value: v
|
||||
})).toJS()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
26
client/app/scripts/selectors/metrics.js
Normal file
26
client/app/scripts/selectors/metrics.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import { createMapSelector } from 'reselect-map';
|
||||
import { fromJS } from 'immutable';
|
||||
|
||||
|
||||
const topCardNodeSelector = createSelector(
|
||||
[
|
||||
state => state.get('nodeDetails')
|
||||
],
|
||||
nodeDetails => nodeDetails.last()
|
||||
);
|
||||
|
||||
export const nodeMetricsSelector = createMapSelector(
|
||||
[
|
||||
state => state.get('nodes'),
|
||||
state => state.get('selectedMetric'),
|
||||
topCardNodeSelector,
|
||||
],
|
||||
(node, selectedMetric, topCardNode) => {
|
||||
const isHighlighted = topCardNode && topCardNode.details && topCardNode.id === node.get('id');
|
||||
const sourceNode = isHighlighted ? fromJS(topCardNode.details) : node;
|
||||
return sourceNode.get('metrics') && sourceNode.get('metrics')
|
||||
.filter(m => m.get('id') === selectedMetric)
|
||||
.first();
|
||||
}
|
||||
);
|
||||
@@ -2,19 +2,16 @@ import { createSelector } from 'reselect';
|
||||
import { Map as makeMap } from 'immutable';
|
||||
|
||||
|
||||
const allNodesSelector = state => state.get('nodes');
|
||||
|
||||
export const nodesSelector = createSelector(
|
||||
export const shownNodesSelector = createSelector(
|
||||
[
|
||||
allNodesSelector,
|
||||
state => state.get('nodes'),
|
||||
],
|
||||
allNodes => allNodes.filter(node => !node.get('filtered'))
|
||||
nodes => nodes.filter(node => !node.get('filtered'))
|
||||
);
|
||||
|
||||
|
||||
export const nodeAdjacenciesSelector = createSelector(
|
||||
[
|
||||
nodesSelector,
|
||||
shownNodesSelector,
|
||||
],
|
||||
nodes => nodes.map(node => makeMap({
|
||||
id: node.get('id'),
|
||||
@@ -5,37 +5,35 @@ import { Map as makeMap } from 'immutable';
|
||||
import { parseQuery, searchTopology, getSearchableFields } from '../utils/search-utils';
|
||||
|
||||
|
||||
const allNodesSelector = state => state.get('nodes');
|
||||
const nodesByTopologySelector = state => state.get('nodesByTopology');
|
||||
const currentTopologyIdSelector = state => state.get('currentTopologyId');
|
||||
const searchQuerySelector = state => state.get('searchQuery');
|
||||
|
||||
const parsedSearchQuerySelector = createSelector(
|
||||
[
|
||||
searchQuerySelector
|
||||
state => state.get('searchQuery')
|
||||
],
|
||||
searchQuery => parseQuery(searchQuery)
|
||||
);
|
||||
|
||||
export const searchNodeMatchesSelector = createMapSelector(
|
||||
[
|
||||
nodesByTopologySelector,
|
||||
state => state.get('nodesByTopology'),
|
||||
parsedSearchQuerySelector,
|
||||
],
|
||||
// TODO: Bring map selectors one level deeper here so that `searchTopology` is
|
||||
// not executed against all the topology nodes every time a small change occurs.
|
||||
(nodes, parsed) => (parsed ? searchTopology(nodes, parsed) : makeMap())
|
||||
);
|
||||
|
||||
export const currentTopologySearchNodeMatchesSelector = createSelector(
|
||||
[
|
||||
state => state.get('currentTopologyId'),
|
||||
searchNodeMatchesSelector,
|
||||
currentTopologyIdSelector,
|
||||
],
|
||||
(nodesByTopology, currentTopologyId) => nodesByTopology.get(currentTopologyId) || makeMap()
|
||||
(currentTopologyId, nodesByTopology) => nodesByTopology.get(currentTopologyId) || makeMap()
|
||||
);
|
||||
|
||||
export const searchableFieldsSelector = createSelector(
|
||||
[
|
||||
allNodesSelector,
|
||||
state => state.get('nodes'),
|
||||
],
|
||||
// TODO: Bring this function in the selectors.
|
||||
getSearchableFields
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user