mirror of
https://github.com/weaveworks/scope.git
synced 2026-07-21 22:36:39 +00:00
Added dynamic contrast-mode toggle
This commit is contained in:
committed by
jpellizzari
parent
cc59b4736e
commit
63dc4e1b3e
@@ -643,6 +643,17 @@ export function receiveNotFound(nodeId) {
|
||||
};
|
||||
}
|
||||
|
||||
export function toggleContrastMode(enabled) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: ActionTypes.TOGGLE_CONTRAST_MODE,
|
||||
enabled,
|
||||
});
|
||||
|
||||
updateRoute(getState);
|
||||
};
|
||||
}
|
||||
|
||||
export function route(urlState) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({
|
||||
@@ -664,6 +675,10 @@ export function route(urlState) {
|
||||
state.get('nodeDetails'),
|
||||
dispatch
|
||||
);
|
||||
|
||||
if (urlState.contrastMode) {
|
||||
dispatch(toggleContrastMode(true));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import Topologies from './topologies';
|
||||
import TopologyOptions from './topology-options';
|
||||
import { getApiDetails, getTopologies } from '../utils/web-api-utils';
|
||||
import { focusSearch, pinNextMetric, hitBackspace, hitEnter, hitEsc, unpinMetric,
|
||||
selectMetric, toggleHelp, toggleGridMode } from '../actions/app-actions';
|
||||
selectMetric, toggleHelp, toggleGridMode, toggleContrastMode } from '../actions/app-actions';
|
||||
import Details from './details';
|
||||
import Nodes from './nodes';
|
||||
import GridModeSelector from './grid-mode-selector';
|
||||
@@ -153,11 +153,12 @@ function mapStateToProps(state) {
|
||||
showingMetricsSelector: state.get('availableCanvasMetrics').count() > 0,
|
||||
showingNetworkSelector: state.get('availableNetworks').count() > 0,
|
||||
showingTerminal: state.get('controlPipes').size > 0,
|
||||
urlState: getUrlState(state)
|
||||
urlState: getUrlState(state),
|
||||
contrastMode: state.get('contrastMode')
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export default connect(
|
||||
mapStateToProps
|
||||
mapStateToProps,
|
||||
dispatch => ({ dispatch, toggleContrastMode })
|
||||
)(App);
|
||||
|
||||
@@ -4,19 +4,22 @@ import moment from 'moment';
|
||||
|
||||
import Plugins from './plugins';
|
||||
import { getUpdateBufferSize } from '../utils/update-buffer-utils';
|
||||
import { contrastModeUrl, isContrastMode } from '../utils/contrast-utils';
|
||||
import { clickDownloadGraph, clickForceRelayout, clickPauseUpdate,
|
||||
clickResumeUpdate, toggleHelp, toggleTroubleshootingMenu } from '../actions/app-actions';
|
||||
import { basePathSlash } from '../utils/web-api-utils';
|
||||
clickResumeUpdate, toggleHelp, toggleTroubleshootingMenu, toggleContrastMode } from '../actions/app-actions';
|
||||
|
||||
class Footer extends React.Component {
|
||||
render() {
|
||||
const { hostname, updatePausedAt, version, versionUpdate } = this.props;
|
||||
const contrastMode = isContrastMode();
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.handleContrastClick = this.handleContrastClick.bind(this);
|
||||
}
|
||||
handleContrastClick(e) {
|
||||
e.preventDefault();
|
||||
this.props.toggleContrastMode(!this.props.contrastMode);
|
||||
}
|
||||
render() {
|
||||
const { hostname, updatePausedAt, version, versionUpdate, contrastMode } = this.props;
|
||||
|
||||
// link url to switch contrast with current UI state
|
||||
const otherContrastModeUrl = contrastMode
|
||||
? basePathSlash(window.location.pathname) : contrastModeUrl;
|
||||
const otherContrastModeTitle = contrastMode
|
||||
? 'Switch to normal contrast' : 'Switch to high contrast';
|
||||
const forceRelayoutTitle = 'Force re-layout (might reduce edge crossings, '
|
||||
@@ -76,7 +79,7 @@ class Footer extends React.Component {
|
||||
title={forceRelayoutTitle}>
|
||||
<span className="fa fa-refresh" />
|
||||
</a>
|
||||
<a className="footer-icon" href={otherContrastModeUrl} title={otherContrastModeTitle}>
|
||||
<a onClick={this.handleContrastClick} className="footer-icon" title={otherContrastModeTitle}>
|
||||
<span className="fa fa-adjust" />
|
||||
</a>
|
||||
<a
|
||||
@@ -101,7 +104,8 @@ function mapStateToProps(state) {
|
||||
hostname: state.get('hostname'),
|
||||
updatePausedAt: state.get('updatePausedAt'),
|
||||
version: state.get('version'),
|
||||
versionUpdate: state.get('versionUpdate')
|
||||
versionUpdate: state.get('versionUpdate'),
|
||||
contrastMode: state.get('contrastMode')
|
||||
};
|
||||
}
|
||||
|
||||
@@ -113,6 +117,7 @@ export default connect(
|
||||
clickPauseUpdate,
|
||||
clickResumeUpdate,
|
||||
toggleHelp,
|
||||
toggleTroubleshootingMenu
|
||||
toggleTroubleshootingMenu,
|
||||
toggleContrastMode
|
||||
}
|
||||
)(Footer);
|
||||
|
||||
@@ -58,6 +58,7 @@ const ACTION_TYPES = [
|
||||
'SET_RECEIVED_NODES_DELTA',
|
||||
'SORT_ORDER_CHANGED',
|
||||
'SET_GRID_MODE',
|
||||
'TOGGLE_CONTRAST_MODE'
|
||||
];
|
||||
|
||||
export default zipObject(ACTION_TYPES, ACTION_TYPES);
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import 'babel-polyfill';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
import '../styles/contrast.scss';
|
||||
import '../images/favicon.ico';
|
||||
import configureStore from './stores/configureStore';
|
||||
|
||||
const store = configureStore();
|
||||
|
||||
function renderApp() {
|
||||
const App = require('./components/app').default;
|
||||
ReactDOM.render((
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider>
|
||||
), document.getElementById('app'));
|
||||
}
|
||||
|
||||
renderApp();
|
||||
if (module.hot) {
|
||||
module.hot.accept('./components/app', renderApp);
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax, import/no-unresolved */
|
||||
import debug from 'debug';
|
||||
import { size, each, includes } from 'lodash';
|
||||
import { fromJS, is as isDeepEqual, List as makeList, Map as makeMap,
|
||||
@@ -30,6 +31,7 @@ const topologySorter = topology => topology.get('rank');
|
||||
export const initialState = makeMap({
|
||||
availableCanvasMetrics: makeList(),
|
||||
availableNetworks: makeList(),
|
||||
contrastMode: false,
|
||||
controlPipes: makeOrderedMap(), // pipeId -> controlPipe
|
||||
controlStatus: makeMap(),
|
||||
currentTopology: null,
|
||||
@@ -721,6 +723,33 @@ export function rootReducer(state = initialState, action) {
|
||||
return state.set('showingTroubleshootingMenu', !state.get('showingTroubleshootingMenu'));
|
||||
}
|
||||
|
||||
case ActionTypes.TOGGLE_CONTRAST_MODE: {
|
||||
const modules = [
|
||||
require.resolve('../../styles/main.scss'),
|
||||
require.resolve('../../styles/contrast.scss')
|
||||
];
|
||||
// Bust the webpack require cache to for a re-download of the stylesheets
|
||||
modules.forEach((i) => {
|
||||
const children = require.cache[i] ? require.cache[i].children : [];
|
||||
children.forEach((c) => {
|
||||
delete require.cache[c];
|
||||
});
|
||||
delete require.cache[i];
|
||||
});
|
||||
|
||||
if (action.enabled) {
|
||||
require.ensure([], () => {
|
||||
require('../../styles/contrast.scss');
|
||||
});
|
||||
} else {
|
||||
require.ensure([], () => {
|
||||
require('../../styles/main.scss');
|
||||
});
|
||||
}
|
||||
|
||||
return state.set('contrastMode', action.enabled);
|
||||
}
|
||||
|
||||
default: {
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
export const contrastModeUrl = 'contrast.html';
|
||||
|
||||
const contrastMode = window.location.pathname.indexOf(contrastModeUrl) > -1;
|
||||
import { parseHashState } from './router-utils';
|
||||
|
||||
export function isContrastMode() {
|
||||
return contrastMode;
|
||||
return parseHashState().contrastMode;
|
||||
}
|
||||
|
||||
@@ -19,11 +19,18 @@ function encodeURL(url) {
|
||||
.replace(new RegExp(SLASH, 'g'), SLASH_REPLACEMENT);
|
||||
}
|
||||
|
||||
function decodeURL(url) {
|
||||
export function decodeURL(url) {
|
||||
return decodeURIComponent(url.replace(new RegExp(SLASH_REPLACEMENT, 'g'), SLASH))
|
||||
.replace(new RegExp(PERCENT_REPLACEMENT, 'g'), PERCENT);
|
||||
}
|
||||
|
||||
export function parseHashState(hash = window.location.hash) {
|
||||
const urlStateString = hash
|
||||
.replace('#!/state/', '')
|
||||
.replace('#!/', '') || '{}';
|
||||
return JSON.parse(decodeURL(urlStateString));
|
||||
}
|
||||
|
||||
function shouldReplaceState(prevState, nextState) {
|
||||
// Opening a new terminal while an existing one is open.
|
||||
const terminalToTerminal = (prevState.controlPipe && nextState.controlPipe);
|
||||
@@ -50,7 +57,8 @@ export function getUrlState(state) {
|
||||
gridSortedBy: state.get('gridSortedBy'),
|
||||
gridSortedDesc: state.get('gridSortedDesc'),
|
||||
topologyId: state.get('currentTopologyId'),
|
||||
topologyOptions: state.get('topologyOptions').toJS() // all options
|
||||
topologyOptions: state.get('topologyOptions').toJS(), // all options,
|
||||
contrastMode: state.get('contrastMode')
|
||||
};
|
||||
|
||||
if (state.get('showingNetworks')) {
|
||||
@@ -67,10 +75,7 @@ export function updateRoute(getState) {
|
||||
const state = getUrlState(getState());
|
||||
const stateUrl = encodeURL(JSON.stringify(state));
|
||||
const dispatch = false;
|
||||
const urlStateString = window.location.hash
|
||||
.replace('#!/state/', '')
|
||||
.replace('#!/', '') || '{}';
|
||||
const prevState = JSON.parse(decodeURL(urlStateString));
|
||||
const prevState = parseHashState();
|
||||
|
||||
// back up state in storage as well
|
||||
storageSet(STORAGE_STATE_KEY, stateUrl);
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 741 B |
@@ -2,7 +2,6 @@ const webpack = require('webpack');
|
||||
const autoprefixer = require('autoprefixer');
|
||||
const path = require('path');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
|
||||
/**
|
||||
* This is the Webpack configuration file for local development.
|
||||
* It contains local-specific configuration which includes:
|
||||
@@ -28,10 +27,6 @@ module.exports = {
|
||||
'./app/scripts/main.dev',
|
||||
'webpack-hot-middleware/client'
|
||||
],
|
||||
'contrast-app': [
|
||||
'./app/scripts/contrast-main',
|
||||
'webpack-hot-middleware/client'
|
||||
],
|
||||
'terminal-app': [
|
||||
'./app/scripts/terminal-main',
|
||||
'webpack-hot-middleware/client'
|
||||
@@ -45,7 +40,7 @@ module.exports = {
|
||||
// Used by Webpack Dev Middleware
|
||||
output: {
|
||||
publicPath: '',
|
||||
path: '/',
|
||||
path: path.join(__dirname, 'build'),
|
||||
filename: '[name].js'
|
||||
},
|
||||
|
||||
@@ -56,11 +51,6 @@ module.exports = {
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new webpack.NoErrorsPlugin(),
|
||||
new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]),
|
||||
new HtmlWebpackPlugin({
|
||||
chunks: ['vendors', 'contrast-app'],
|
||||
template: 'app/html/index.html',
|
||||
filename: 'contrast.html'
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
chunks: ['vendors', 'terminal-app'],
|
||||
template: 'app/html/index.html',
|
||||
|
||||
@@ -31,7 +31,6 @@ module.exports = {
|
||||
|
||||
entry: {
|
||||
app: './app/scripts/main',
|
||||
'contrast-app': './app/scripts/contrast-main',
|
||||
'terminal-app': './app/scripts/terminal-main',
|
||||
// keep only some in here, to make vendors and app bundles roughly same size
|
||||
vendors: ['babel-polyfill', 'classnames', 'immutable',
|
||||
@@ -112,12 +111,6 @@ module.exports = {
|
||||
}
|
||||
}),
|
||||
new ExtractTextPlugin('style-[name]-[chunkhash].css'),
|
||||
new HtmlWebpackPlugin({
|
||||
hash: true,
|
||||
chunks: ['vendors', 'contrast-app'],
|
||||
template: 'app/html/index.html',
|
||||
filename: 'contrast.html'
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
hash: true,
|
||||
chunks: ['vendors', 'terminal-app'],
|
||||
|
||||
Reference in New Issue
Block a user