diff --git a/client/app/scripts/actions/app-actions.js b/client/app/scripts/actions/app-actions.js
index a3c98cd650..d829ebffc3 100644
--- a/client/app/scripts/actions/app-actions.js
+++ b/client/app/scripts/actions/app-actions.js
@@ -4,10 +4,6 @@ import { find } from 'lodash';
import ActionTypes from '../constants/action-types';
import { saveGraph } from '../utils/file-utils';
import { updateRoute } from '../utils/router-utils';
-import {
- isNodesDeltaPaused,
- getUpdateBufferSize,
-} from '../utils/update-buffer-utils';
import {
doControlRequest,
getAllNodes,
@@ -21,6 +17,7 @@ import {
} from '../utils/web-api-utils';
import { storageSet } from '../utils/storage-utils';
import { loadTheme } from '../utils/contrast-utils';
+import { isPausedSelector } from '../selectors/timeline';
import {
availableMetricTypesSelector,
nextPinnedMetricTypeSelector,
@@ -32,11 +29,14 @@ import {
isResourceViewModeSelector,
resourceViewAvailableSelector,
} from '../selectors/topology';
+
+import { NODES_DELTA_BUFFER_SIZE_LIMIT } from '../constants/limits';
+import { NODES_DELTA_BUFFER_FEED_INTERVAL } from '../constants/timer';
import {
GRAPH_VIEW_MODE,
TABLE_VIEW_MODE,
RESOURCE_VIEW_MODE,
- } from '../constants/naming';
+} from '../constants/naming';
const log = debug('scope:app-actions');
@@ -88,8 +88,7 @@ function bufferDeltaUpdate(delta) {
return;
}
- const bufferLength = 100;
- if (getUpdateBufferSize(getState()) >= bufferLength) {
+ if (getState().get('nodesDeltaBuffer').size >= NODES_DELTA_BUFFER_SIZE_LIMIT) {
dispatch({ type: ActionTypes.CONSOLIDATE_NODES_DELTA_BUFFER });
}
@@ -97,7 +96,7 @@ function bufferDeltaUpdate(delta) {
type: ActionTypes.ADD_TO_NODES_DELTA_BUFFER,
delta,
});
- log('Buffering node delta, new size', getUpdateBufferSize(getState()));
+ log('Buffering node delta, new size', getState().get('nodesDeltaBuffer').size);
};
}
@@ -626,7 +625,7 @@ export function receiveNodesDelta(delta) {
const hasChanges = delta.add || delta.update || delta.remove;
if (hasChanges || movingInTime) {
- if (state.get('updatePausedAt') !== null) {
+ if (isPausedSelector(state)) {
dispatch(bufferDeltaUpdate(delta));
} else {
dispatch({
@@ -640,20 +639,19 @@ export function receiveNodesDelta(delta) {
function maybeUpdateFromNodesDeltaBuffer() {
return (dispatch, getState) => {
- const state = getState();
- if (isNodesDeltaPaused(state)) {
+ if (isPausedSelector(getState())) {
dispatch(resetNodesDeltaBuffer());
} else {
- if (getUpdateBufferSize(state) > 0) {
- const delta = state.get('nodesDeltaBuffer').first();
+ if (!getState().get('nodesDeltaBuffer').isEmpty()) {
+ const delta = getState().get('nodesDeltaBuffer').first();
dispatch({ type: ActionTypes.POP_NODES_DELTA_BUFFER });
dispatch(receiveNodesDelta(delta));
}
- if (getUpdateBufferSize(state) > 0) {
- const feedInterval = 1000;
+ if (!getState().get('nodesDeltaBuffer').isEmpty()) {
nodesDeltaBufferUpdateTimer = setTimeout(
() => dispatch(maybeUpdateFromNodesDeltaBuffer()),
- feedInterval);
+ NODES_DELTA_BUFFER_FEED_INTERVAL,
+ );
}
}
};
diff --git a/client/app/scripts/components/pause-button.js b/client/app/scripts/components/pause-button.js
index e363c5db57..328334d19e 100644
--- a/client/app/scripts/components/pause-button.js
+++ b/client/app/scripts/components/pause-button.js
@@ -3,20 +3,20 @@ import moment from 'moment';
import classNames from 'classnames';
import { connect } from 'react-redux';
-import { getUpdateBufferSize } from '../utils/update-buffer-utils';
+import { isPausedSelector } from '../selectors/timeline';
import { clickPauseUpdate, clickResumeUpdate } from '../actions/app-actions';
class PauseButton extends React.Component {
render() {
- const isPaused = this.props.updatePausedAt !== null;
- const updateCount = this.props.updateCount;
- const hasUpdates = updateCount > 0;
- const title = isPaused ?
- `Paused ${moment(this.props.updatePausedAt).fromNow()}` :
- 'Pause updates (freezes the nodes in their current layout)';
+ const { isPaused, hasUpdates, updateCount, updatePausedAt } = this.props;
const action = isPaused ? this.props.clickResumeUpdate : this.props.clickPauseUpdate;
const className = classNames('button pause-button', { active: isPaused });
+
+ const title = isPaused ?
+ `Paused ${moment(updatePausedAt).fromNow()}` :
+ 'Pause updates (freezes the nodes in their current layout)';
+
let label = '';
if (hasUpdates && isPaused) {
label = `Paused +${updateCount}`;
@@ -37,8 +37,10 @@ class PauseButton extends React.Component {
function mapStateToProps(state) {
return {
- updateCount: getUpdateBufferSize(state),
+ hasUpdates: !state.get('nodesDeltaBuffer').isEmpty(),
+ updateCount: state.get('nodesDeltaBuffer').size,
updatePausedAt: state.get('updatePausedAt'),
+ isPaused: isPausedSelector(state),
};
}
diff --git a/client/app/scripts/components/timeline-control.js b/client/app/scripts/components/timeline-control.js
index 0e1e7b3860..813c33559f 100644
--- a/client/app/scripts/components/timeline-control.js
+++ b/client/app/scripts/components/timeline-control.js
@@ -20,83 +20,51 @@ const sliderRanges = {
last15Minutes: {
label: 'Last 15 minutes',
getStart: () => moment().utc().subtract(15, 'minutes'),
- getEnd: () => moment().utc(),
},
last1Hour: {
label: 'Last 1 hour',
getStart: () => moment().utc().subtract(1, 'hour'),
- getEnd: () => moment().utc(),
},
last6Hours: {
label: 'Last 6 hours',
getStart: () => moment().utc().subtract(6, 'hours'),
- getEnd: () => moment().utc(),
},
last24Hours: {
label: 'Last 24 hours',
getStart: () => moment().utc().subtract(24, 'hours'),
- getEnd: () => moment().utc(),
},
last7Days: {
label: 'Last 7 days',
getStart: () => moment().utc().subtract(7, 'days'),
- getEnd: () => moment().utc(),
},
last30Days: {
label: 'Last 30 days',
getStart: () => moment().utc().subtract(30, 'days'),
- getEnd: () => moment().utc(),
},
last90Days: {
label: 'Last 90 days',
getStart: () => moment().utc().subtract(90, 'days'),
- getEnd: () => moment().utc(),
},
last1Year: {
label: 'Last 1 year',
getStart: () => moment().subtract(1, 'year'),
- getEnd: () => moment().utc(),
},
todaySoFar: {
label: 'Today so far',
getStart: () => moment().utc().startOf('day'),
- getEnd: () => moment().utc(),
},
thisWeekSoFar: {
label: 'This week so far',
getStart: () => moment().utc().startOf('week'),
- getEnd: () => moment().utc(),
},
thisMonthSoFar: {
label: 'This month so far',
getStart: () => moment().utc().startOf('month'),
- getEnd: () => moment().utc(),
},
thisYearSoFar: {
label: 'This year so far',
getStart: () => moment().utc().startOf('year'),
- getEnd: () => moment().utc(),
},
- // yesterday: {
- // label: 'Yesterday',
- // getStart: () => moment().utc().subtract(1, 'day').startOf('day'),
- // getEnd: () => moment().utc().subtract(1, 'day').endOf('day'),
- // },
- // previousWeek: {
- // label: 'Previous week',
- // getStart: () => moment().utc().subtract(1, 'week').startOf('week'),
- // getEnd: () => moment().utc().subtract(1, 'week').endOf('week'),
- // },
- // previousMonth: {
- // label: 'Previous month',
- // getStart: () => moment().utc().subtract(1, 'month').startOf('month'),
- // getEnd: () => moment().utc().subtract(1, 'month').endOf('month'),
- // },
- // previousYear: {
- // label: 'Previous year',
- // getStart: () => moment().utc().subtract(1, 'year').startOf('year'),
- // getEnd: () => moment().utc().subtract(1, 'year').endOf('year'),
- // },
};
class TimelineControl extends React.Component {
@@ -105,7 +73,7 @@ class TimelineControl extends React.Component {
this.state = {
showTimelinePanel: false,
- offsetMilliseconds: 0,
+ millisecondsInPast: 0,
rangeOptionSelected: sliderRanges.last1Hour,
};
@@ -130,42 +98,46 @@ class TimelineControl extends React.Component {
this.setState({ showTimelinePanel: !this.state.showTimelinePanel });
}
- handleSliderChange(value) {
- const offsetMilliseconds = this.getRangeMilliseconds() - value;
+ handleSliderChange(sliderValue) {
+ const millisecondsInPast = this.getRangeMilliseconds() - sliderValue;
this.props.startMovingInTime();
- this.debouncedUpdateTimestamp(offsetMilliseconds);
- this.setState({ offsetMilliseconds });
+ this.debouncedUpdateTimestamp(millisecondsInPast);
+ this.setState({ millisecondsInPast });
}
- getRangeMilliseconds() {
- const range = this.state.rangeOptionSelected;
- return range.getEnd().diff(range.getStart());
+ handleRangeOptionClick(rangeOption) {
+ this.setState({ rangeOptionSelected: rangeOption });
+
+ const rangeMilliseconds = this.getRangeMilliseconds(rangeOption);
+ if (this.state.millisecondsInPast > rangeMilliseconds) {
+ this.updateTimestamp(rangeMilliseconds);
+ this.setState({ millisecondsInPast: rangeMilliseconds });
+ }
+ }
+
+ getRangeMilliseconds(rangeOption) {
+ rangeOption = rangeOption || this.state.rangeOptionSelected;
+ return moment().diff(rangeOption.getStart());
}
jumpToNow() {
this.setState({
showTimelinePanel: false,
- offsetMilliseconds: 0,
+ millisecondsInPast: 0,
rangeOptionSelected: sliderRanges.last1Hour,
});
this.props.startMovingInTime();
this.updateTimestamp(null);
}
- getTotalOffset() {
- const { rangeOptionSelected, offsetMilliseconds } = this.state;
- const rangeBehindMilliseconds = moment().utc().diff(rangeOptionSelected.getEnd());
- return offsetMilliseconds + rangeBehindMilliseconds;
- }
-
- renderRangeOption(option) {
- const handleClick = () => { this.setState({ rangeOptionSelected: option }); };
- const selected = (this.state.rangeOptionSelected.label === option.label);
+ renderRangeOption(rangeOption) {
+ const handleClick = () => { this.handleRangeOptionClick(rangeOption); };
+ const selected = (this.state.rangeOptionSelected.label === rangeOption.label);
const className = classNames('option', { selected });
return (
-
- {option.label}
+
+ {rangeOption.label}
);
}
@@ -179,13 +151,13 @@ class TimelineControl extends React.Component {
}
renderTimelineSlider() {
- const { offsetMilliseconds } = this.state;
+ const { millisecondsInPast } = this.state;
const rangeMilliseconds = this.getRangeMilliseconds();
return (