Skip to content

Commit

Permalink
Small styling changes
Browse files Browse the repository at this point in the history
  • Loading branch information
fbarl committed Jun 6, 2017
1 parent 4435342 commit 6f43bd9
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 56 deletions.
2 changes: 0 additions & 2 deletions client/app/scripts/actions/app-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -464,11 +464,9 @@ export function websocketQueryTimestamp(queryTimestamp) {
return (dispatch, getState) => {
dispatch({
type: ActionTypes.WEBSOCKET_QUERY_TIMESTAMP,
requestTimestamp,
queryTimestamp,
});
updateWebsocketChannel(getState(), dispatch);
// update all request workers with new options
dispatch(resetNodesDeltaBuffer());
};
}
Expand Down
6 changes: 3 additions & 3 deletions client/app/scripts/components/nodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ class Nodes extends React.Component {

render() {
const { topologiesLoaded, nodesLoaded, topologies, currentTopology, isGraphViewMode,
isTableViewMode, isResourceViewMode, blurred } = this.props;
isTableViewMode, isResourceViewMode, movingInTime } = this.props;

const className = classNames('nodes-wrapper', { blurred });
const className = classNames('nodes-wrapper', { blurred: movingInTime });

// TODO: Rename view mode components.
return (
Expand Down Expand Up @@ -89,7 +89,7 @@ function mapStateToProps(state) {
topologyNodeCountZero: isTopologyNodeCountZero(state),
nodesDisplayEmpty: isNodesDisplayEmpty(state),
topologyEmpty: isTopologyEmpty(state),
blurred: state.get('websocketMovingInTime'),
movingInTime: state.get('websocketMovingInTime'),
currentTopology: state.get('currentTopology'),
nodesLoaded: state.get('nodesLoaded') || state.get('websocketMovingInTime'),
topologies: state.get('topologies'),
Expand Down
4 changes: 3 additions & 1 deletion client/app/scripts/components/pause-button.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import moment from 'moment';
import classNames from 'classnames';
import { connect } from 'react-redux';

import { getUpdateBufferSize } from '../utils/update-buffer-utils';
Expand All @@ -15,6 +16,7 @@ class PauseButton extends React.Component {
`Paused ${moment(this.props.updatePausedAt).fromNow()}` :
'Pause updates (freezes the nodes in their current layout)';
const action = isPaused ? this.props.clickResumeUpdate : this.props.clickPauseUpdate;
const className = classNames('button pause-button', { active: isPaused });
let label = '';
if (hasUpdates && isPaused) {
label = `Paused +${updateCount}`;
Expand All @@ -25,7 +27,7 @@ class PauseButton extends React.Component {
}

return (
<a className="button pause-button" onClick={action} title={title}>
<a className={className} onClick={action} title={title}>
{label !== '' && <span className="pause-text">{label}</span>}
<span className="fa fa-pause" />
</a>
Expand Down
85 changes: 56 additions & 29 deletions client/app/scripts/components/timeline-control.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ import { connect } from 'react-redux';
import { debounce } from 'lodash';

import PauseButton from './pause-button';
import TopologyTimestampInfo from './topology-timestamp-info';
import { websocketQueryTimestamp, startMovingInTime } from '../actions/app-actions';
import TopologyTimestampButton from './topology-timestamp-button';
import {
websocketQueryTimestamp,
clickResumeUpdate,
startMovingInTime,
} from '../actions/app-actions';

import { TIMELINE_DEBOUNCE_INTERVAL } from '../constants/timer';


Expand Down Expand Up @@ -94,7 +99,7 @@ const sliderRanges = {
// },
};

class TimelineControl extends React.PureComponent {
class TimelineControl extends React.Component {
constructor(props, context) {
super(props, context);

Expand All @@ -118,6 +123,7 @@ class TimelineControl extends React.PureComponent {

updateTimestamp(timestamp) {
this.props.websocketQueryTimestamp(timestamp);
this.props.clickResumeUpdate();
}

toggleTimelinePanel() {
Expand Down Expand Up @@ -147,6 +153,12 @@ class TimelineControl extends React.PureComponent {
this.updateTimestamp(moment());
}

getTotalOffset() {
const { rangeOptionSelected, offsetMilliseconds } = this.state;
const rangeBehindMilliseconds = moment().diff(rangeOptionSelected.getEnd());
return offsetMilliseconds + rangeBehindMilliseconds;
}

renderRangeOption(option) {
const handleClick = () => { this.setState({ rangeOptionSelected: option }); };
const selected = (this.state.rangeOptionSelected.label === option.label);
Expand All @@ -159,24 +171,37 @@ class TimelineControl extends React.PureComponent {
);
}

getTotalOffset() {
const { rangeOptionSelected, offsetMilliseconds } = this.state;
const rangeBehindMilliseconds = moment().diff(rangeOptionSelected.getEnd());
return offsetMilliseconds + rangeBehindMilliseconds;
renderJumpToNowButton() {
return (
<a className="button jump-to-now" title="Jump to now" onClick={this.jumpToNow}>
<span className="fa fa-step-forward" />
</a>
);
}

renderTimelineSlider() {
const { offsetMilliseconds } = this.state;
const rangeMilliseconds = this.getRangeMilliseconds();

return (
<Slider
onChange={this.handleSliderChange}
value={rangeMilliseconds - offsetMilliseconds}
max={rangeMilliseconds}
/>
);
}

render() {
const { movingInTime } = this.props;
const { showTimelinePanel, offsetMilliseconds } = this.state;
const rangeMilliseconds = this.getRangeMilliseconds();

const showingCurrent = (this.getTotalOffset() === 0);
const timeStatusClassName = classNames('time-status', { 'showing-current': showingCurrent });
const toggleButtonClassName = classNames('button toggle', { selected: showTimelinePanel });

return (
<div className="timeline-control">
{showTimelinePanel && <div className="timeline-panel">
<strong>Explore</strong>
<span className="caption">Explore</span>
<div className="options">
<div className="column">
{this.renderRangeOption(sliderRanges.last15Minutes)}
Expand All @@ -197,35 +222,37 @@ class TimelineControl extends React.PureComponent {
{this.renderRangeOption(sliderRanges.thisYearSoFar)}
</div>
</div>
<strong>Move the slider to travel in time</strong>
<Slider
onChange={this.handleSliderChange}
value={rangeMilliseconds - offsetMilliseconds}
max={rangeMilliseconds}
/>
<span className="slider-tip">Move the slider to travel back in time</span>
{this.renderTimelineSlider()}
</div>}
<div className={timeStatusClassName}>
<a className={toggleButtonClassName} onClick={this.toggleTimelinePanel}>
<TopologyTimestampInfo />
<span className="fa fa-clock-o" />
</a>
<div className="time-status">
{movingInTime && <div className="timeline-jump-loader">
<span className="fa fa-circle-o-notch fa-spin" />
</div>}
<TopologyTimestampButton
onClick={this.toggleTimelinePanel}
selected={showTimelinePanel}
offset={offsetMilliseconds}
/>
{!showingCurrent && this.renderJumpToNowButton()}
<PauseButton />
{!showingCurrent && <a
className="button jump-to-now"
title="Jump to now"
onClick={this.jumpToNow}>
<span className="fa fa-step-forward" />
</a>}
</div>
</div>
);
}
}

function mapStateToProps(state) {
return {
movingInTime: state.get('websocketMovingInTime'),
};
}

export default connect(
null,
mapStateToProps,
{
websocketQueryTimestamp,
clickResumeUpdate,
startMovingInTime,
}
)(TimelineControl);
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react';
import moment from 'moment';
import classNames from 'classnames';
import { connect } from 'react-redux';


const TIMESTAMP_TICK_INTERVAL = 500;

class TopologyTimestampInfo extends React.PureComponent {
class TopologyTimestampButton extends React.PureComponent {
constructor(props, context) {
super(props, context);

Expand All @@ -25,7 +26,7 @@ class TopologyTimestampInfo extends React.PureComponent {
}

getFreshState() {
const { updatePausedAt, websocketQueryPastAt, websocketQueryPastRequestMadeAt } = this.props;
const { updatePausedAt, offset } = this.props;

let timestamp = updatePausedAt;
let showingCurrentState = false;
Expand All @@ -34,8 +35,7 @@ class TopologyTimestampInfo extends React.PureComponent {
timestamp = moment().utc();
showingCurrentState = true;

if (websocketQueryPastAt) {
const offset = moment(websocketQueryPastRequestMadeAt).diff(moment(websocketQueryPastAt));
if (offset >= 1000) {
timestamp = timestamp.subtract(offset);
showingCurrentState = false;
}
Expand All @@ -45,27 +45,32 @@ class TopologyTimestampInfo extends React.PureComponent {

renderTimestamp() {
return (
<time>{this.state.timestamp.format('MMMM Do YYYY, h:mm:ss a')}</time>
<time>{this.state.timestamp.format('MMMM Do YYYY, h:mm:ss a')} UTC</time>
);
}

render() {
const { selected, onClick } = this.props;
const { showingCurrentState } = this.state;
const className = classNames('button topology-timestamp-button', {
selected, current: showingCurrentState,
});

return (
<span className="topology-timestamp-info">
{showingCurrentState ? 'now' : this.renderTimestamp()}
</span>
<a className={className} onClick={onClick}>
<span className="topology-timestamp-info">
{showingCurrentState ? 'now' : this.renderTimestamp()}
</span>
<span className="fa fa-clock-o" />
</a>
);
}
}

function mapStateToProps(state) {
return {
updatePausedAt: state.get('updatePausedAt'),
websocketQueryPastAt: state.get('websocketQueryPastAt'),
websocketQueryPastRequestMadeAt: state.get('websocketQueryPastRequestMadeAt'),
};
}

export default connect(mapStateToProps)(TopologyTimestampInfo);
export default connect(mapStateToProps)(TopologyTimestampButton);
3 changes: 0 additions & 3 deletions client/app/scripts/reducers/root.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ export const initialState = makeMap({
websocketClosed: false,
websocketMovingInTime: false,
websocketQueryPastAt: null,
websocketQueryPastRequestMadeAt: null,
zoomCache: makeMap(),
serviceImages: makeMap()
});
Expand Down Expand Up @@ -357,8 +356,6 @@ export function rootReducer(state = initialState, action) {
}

case ActionTypes.WEBSOCKET_QUERY_TIMESTAMP: {
const websocketPastRequestMadeAt = action.queryTimestamp ? action.requestTimestamp : null;
state = state.set('websocketQueryPastRequestMadeAt', websocketPastRequestMadeAt);
return state.set('websocketQueryPastAt', action.queryTimestamp);
}

Expand Down
20 changes: 13 additions & 7 deletions client/app/styles/_base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
border: 1px solid $text-tertiary-color;
}

.active {
&.active {
@extend .blinkable;
border: 1px solid $text-tertiary-color;
}
Expand Down Expand Up @@ -217,35 +217,41 @@
.timeline-control {
@extend .overlay-wrapper;
display: block;
right: 450px;
right: 500px;

.time-status {
display: flex;
align-items: center;
justify-content: flex-end;

.timeline-jump-loader {
font-size: 1rem;
}

.topology-timestamp-info, .pause-text {
font-size: 115%;
margin-right: 5px;
}

.button { margin-left: 0.5em; }
.jump-to-now { @extend .blinkable; }

&:not(.showing-current) .topology-timestamp-info {
.topology-timestamp-button:not(.current) {
@extend .blinkable;
font-weight: bold;
}
}

.timeline-panel {
strong {
width: 355px;

.caption, .slider-tip {
display: inline-block;
font-size: 0.8125rem;
font-weight: normal;
padding: 5px 10px;
text-decoration: underline;
}

.slider-tip { font-style: italic; }

.options {
display: flex;
padding: 2px 0 10px;
Expand Down

0 comments on commit 6f43bd9

Please sign in to comment.