mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-03 10:11:03 +00:00
Adds < and > keyboard shortcuts for next/prev metric-on-canvas
This commit is contained in:
@@ -3,6 +3,7 @@ import debug from 'debug';
|
||||
import AppDispatcher from '../dispatcher/app-dispatcher';
|
||||
import ActionTypes from '../constants/action-types';
|
||||
import { saveGraph } from '../utils/file-utils';
|
||||
import { modulo } from '../utils/math-utils';
|
||||
import { updateRoute } from '../utils/router-utils';
|
||||
import { bufferDeltaUpdate, resumeUpdate,
|
||||
resetUpdateBuffer } from '../utils/update-buffer-utils';
|
||||
@@ -19,6 +20,17 @@ export function selectMetric(metricId) {
|
||||
});
|
||||
}
|
||||
|
||||
export function lockNextMetric(delta) {
|
||||
const metrics = AppStore.getAvailableCanvasMetrics().map(m => m.id);
|
||||
const currentIndex = metrics.indexOf(AppStore.getSelectedMetric());
|
||||
const nextMetric = metrics[modulo(currentIndex + delta, metrics.length)];
|
||||
|
||||
AppDispatcher.dispatch({
|
||||
type: ActionTypes.LOCK_METRIC,
|
||||
metricId: nextMetric
|
||||
});
|
||||
}
|
||||
|
||||
export function lockMetric(metricId) {
|
||||
AppDispatcher.dispatch({
|
||||
type: ActionTypes.LOCK_METRIC,
|
||||
|
||||
@@ -8,7 +8,7 @@ import Status from './status.js';
|
||||
import Topologies from './topologies.js';
|
||||
import TopologyOptions from './topology-options.js';
|
||||
import { getApiDetails, getTopologies } from '../utils/web-api-utils';
|
||||
import { hitEsc } from '../actions/app-actions';
|
||||
import { lockNextMetric, hitEsc } from '../actions/app-actions';
|
||||
import Details from './details';
|
||||
import Nodes from './nodes';
|
||||
import MetricSelector from './metric-selector';
|
||||
@@ -17,6 +17,8 @@ import { getRouter } from '../utils/router-utils';
|
||||
import { showingDebugToolbar, DebugToolbar } from './debug-toolbar.js';
|
||||
|
||||
const ESC_KEY_CODE = 27;
|
||||
const RIGHT_ANGLE_KEY_IDENTIFIER = 'U+003C';
|
||||
const LEFT_ANGLE_KEY_IDENTIFIER = 'U+003E';
|
||||
|
||||
function getStateFromStores() {
|
||||
return {
|
||||
@@ -32,6 +34,7 @@ function getStateFromStores() {
|
||||
highlightedNodeIds: AppStore.getHighlightedNodeIds(),
|
||||
hostname: AppStore.getHostname(),
|
||||
lockedMetric: AppStore.getLockedMetric(),
|
||||
availableCanvasMetrics: AppStore.getAvailableCanvasMetrics(),
|
||||
nodeDetails: AppStore.getNodeDetails(),
|
||||
nodes: AppStore.getNodes(),
|
||||
selectedNodeId: AppStore.getSelectedNodeId(),
|
||||
@@ -73,6 +76,10 @@ export default class App extends React.Component {
|
||||
onKeyPress(ev) {
|
||||
if (ev.keyCode === ESC_KEY_CODE) {
|
||||
hitEsc();
|
||||
} else if (ev.keyIdentifier === RIGHT_ANGLE_KEY_IDENTIFIER) {
|
||||
lockNextMetric(-1);
|
||||
} else if (ev.keyIdentifier === LEFT_ANGLE_KEY_IDENTIFIER) {
|
||||
lockNextMetric(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +127,7 @@ export default class App extends React.Component {
|
||||
|
||||
<Sidebar>
|
||||
<MetricSelector
|
||||
availableCanvasMetrics={this.state.availableCanvasMetrics}
|
||||
lockedMetric={this.state.lockedMetric}
|
||||
selectedMetric={this.state.selectedMetric}
|
||||
/>
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import { selectMetric, lockMetric } from '../actions/app-actions';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const METRICS = {
|
||||
'CPU': 'process_cpu_usage_percent',
|
||||
'Memory': 'process_memory_usage_bytes',
|
||||
'Open Files': 'open_files_count'
|
||||
};
|
||||
|
||||
// docker_cpu_total_usage
|
||||
// docker_memory_usage
|
||||
|
||||
@@ -21,26 +14,25 @@ function onMouseClick(k) {
|
||||
}
|
||||
|
||||
function onMouseOut(k) {
|
||||
console.log('onMouseOut', k);
|
||||
selectMetric(k);
|
||||
}
|
||||
|
||||
export default function MetricSelector({selectedMetric, lockedMetric}) {
|
||||
export default function MetricSelector({availableCanvasMetrics, selectedMetric, lockedMetric}) {
|
||||
return (
|
||||
<div
|
||||
className="available-metrics"
|
||||
onMouseLeave={() => onMouseOut(lockedMetric)}>
|
||||
{_.map(METRICS, (key, name) => {
|
||||
{availableCanvasMetrics.map(({id, label}) => {
|
||||
return (
|
||||
<div
|
||||
key={key}
|
||||
key={id}
|
||||
className={classNames('sidebar-item', {
|
||||
'locked': (key === lockedMetric),
|
||||
'selected': (key === selectedMetric)
|
||||
'locked': (id === lockedMetric),
|
||||
'selected': (id === selectedMetric)
|
||||
})}
|
||||
onMouseOver={() => onMouseOver(key)}
|
||||
onClick={() => onMouseClick(key)}>
|
||||
{name}
|
||||
onMouseOver={() => onMouseOver(id)}
|
||||
onClick={() => onMouseClick(id)}>
|
||||
{label}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -61,6 +61,12 @@ let websocketClosed = true;
|
||||
|
||||
let selectedMetric = 'process_cpu_usage_percent';
|
||||
let lockedMetric = selectedMetric;
|
||||
const availableCanvasMetrics = [
|
||||
{label: 'CPU', id: 'process_cpu_usage_percent'},
|
||||
{label: 'Memory', id: 'process_memory_usage_bytes'},
|
||||
{label: 'Open Files', id: 'open_files_count'}
|
||||
];
|
||||
|
||||
|
||||
const topologySorter = topology => topology.get('rank');
|
||||
|
||||
@@ -175,6 +181,10 @@ export class AppStore extends Store {
|
||||
return selectedMetric;
|
||||
}
|
||||
|
||||
getAvailableCanvasMetrics() {
|
||||
return availableCanvasMetrics;
|
||||
}
|
||||
|
||||
getControlStatus() {
|
||||
return controlStatus.toJS();
|
||||
}
|
||||
@@ -419,6 +429,7 @@ export class AppStore extends Store {
|
||||
}
|
||||
case ActionTypes.LOCK_METRIC: {
|
||||
lockedMetric = payload.metricId;
|
||||
selectedMetric = payload.metricId;
|
||||
this.__emitChange();
|
||||
break;
|
||||
}
|
||||
|
||||
6
client/app/scripts/utils/math-utils.js
Normal file
6
client/app/scripts/utils/math-utils.js
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
// http://stackoverflow.com/questions/4467539/javascript-modulo-not-behaving
|
||||
export function modulo(i, n) {
|
||||
return ((i % n) + n) % n;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import d3 from 'd3';
|
||||
|
||||
const formatLargeValue = d3.format('s');
|
||||
|
||||
function toHtml(text, unit) {
|
||||
function renderHtml(text, unit) {
|
||||
return (
|
||||
<span className="metric-formatted">
|
||||
<span className="metric-value">{text}</span>
|
||||
@@ -18,7 +18,6 @@ function makeFormatters(renderFn) {
|
||||
const formatters = {
|
||||
filesize(value) {
|
||||
const obj = filesize(value, {output: 'object'});
|
||||
console.log('rendering', value);
|
||||
return renderFn(obj.value, obj.suffix);
|
||||
},
|
||||
|
||||
@@ -45,7 +44,7 @@ function makeFormatters(renderFn) {
|
||||
}
|
||||
|
||||
|
||||
const formatters = makeFormatters(toHtml);
|
||||
const formatters = makeFormatters(renderHtml);
|
||||
const svgFormatters = makeFormatters((text, unit) => `${text}${unit}`);
|
||||
|
||||
export function formatMetric(value, opts, svg) {
|
||||
|
||||
Reference in New Issue
Block a user