Files
weave-scope/client/app/scripts/selectors/node-metric.js
Roland Schilter 8188b7aed2 Append links directly to metrics
The initial idea was to keep it separate since the unattached
links were also to be displayed distinctively from the metrics.
With the new design, unattached links are rendered in the same
list as metrics with attached links.

Therefore, we treat unattached metric links as an empty metric.
2017-08-11 16:45:13 +01:00

121 lines
3.8 KiB
JavaScript

import { createSelector } from 'reselect';
import { createMapSelector, createListSelector } from 'reselect-map';
import { fromJS, Map as makeMap, List as makeList } from 'immutable';
import { modulo } from '../utils/math-utils';
import { isGraphViewModeSelector, isResourceViewModeSelector } from '../selectors/topology';
import { RESOURCE_VIEW_METRICS } from '../constants/resources';
// Resource view uses the metrics of the nodes from the cache, while the graph and table
// view are looking at the current nodes (which are among other things filtered by topology
// options which are currently ignored in the resource view).
export const availableMetricsSelector = createSelector(
[
isGraphViewModeSelector,
isResourceViewModeSelector,
state => state.get('nodes'),
],
(isGraphView, isResourceView, nodes) => {
// In graph view, we always look through the fresh state
// of topology nodes to get all the available metrics.
if (isGraphView) {
return nodes
.valueSeq()
.flatMap(n => n.get('metrics', makeList()))
.filter(m => !m.get('valueEmpty'))
.map(m => makeMap({ id: m.get('id'), label: m.get('label') }))
.toSet()
.toList()
.sortBy(m => m.get('label'));
}
// In resource view, we're displaying only the hardcoded CPU and Memory metrics.
// TODO: Make this dynamic as well.
if (isResourceView) {
return fromJS(RESOURCE_VIEW_METRICS);
}
// Don't show any metrics in the table view mode.
return makeList();
}
);
export const availableMetricTypesSelector = createListSelector(
[
availableMetricsSelector,
],
metric => metric.get('label')
);
export const pinnedMetricSelector = createSelector(
[
availableMetricsSelector,
state => state.get('pinnedMetricType'),
],
(availableMetrics, metricType) => availableMetrics.find(m => m.get('label') === metricType)
);
export const nextPinnedMetricTypeSelector = createSelector(
[
availableMetricTypesSelector,
state => state.get('pinnedMetricType'),
],
(metricTypes, pinnedMetricType) => {
const currentIndex = metricTypes.indexOf(pinnedMetricType);
const nextIndex = modulo(currentIndex + 1, metricTypes.count());
return metricTypes.get(pinnedMetricType ? nextIndex : 0);
}
);
export const previousPinnedMetricTypeSelector = createSelector(
[
availableMetricTypesSelector,
state => state.get('pinnedMetricType'),
],
(metricTypes, pinnedMetricType) => {
const currentIndex = metricTypes.indexOf(pinnedMetricType);
const previousIndex = modulo(currentIndex - 1, metricTypes.count());
return metricTypes.get(pinnedMetricType ? previousIndex : 0);
}
);
export const selectedMetricTypeSelector = createSelector(
[
state => state.get('pinnedMetricType'),
state => state.get('hoveredMetricType'),
],
(pinnedMetricType, hoveredMetricType) => hoveredMetricType || pinnedMetricType
);
const selectedMetricIdSelector = createSelector(
[
availableMetricsSelector,
selectedMetricTypeSelector,
],
(availableMetrics, metricType) =>
(availableMetrics.find(m => m.get('label') === metricType) || makeMap()).get('id')
);
const topCardNodeSelector = createSelector(
[
state => state.get('nodeDetails')
],
nodeDetails => nodeDetails.last()
);
export const nodeMetricSelector = createMapSelector(
[
state => state.get('nodes'),
selectedMetricIdSelector,
topCardNodeSelector,
],
(node, selectedMetricId, 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') === selectedMetricId)
.first();
}
);