Mode configuration backported to beta (#3213)

* Mode improvements for UI (#3109)

* `--mode=off` now works.

* Add Mode::Off as a persistent CLI option.

* "last" not "auto" as default.

* Commit accidentally unsaved file.

* Whitespace

[ci:skip]

* Mode CLI parse fix

* or offline

* Save mode when it gets changed.

* Fix Offline mode

* Fix up mode operations.

* Make passive default, but not overriding.

* Fix test

* Maybe not everyone wants to run an archive node...

* Parity configuration settings, i.e. mode (#3212)

* Add initial page

* Add parity icon

* opacity for parity icon

* Mode selector

* Actually set mode when value changes


Former-commit-id: 64386d94adfa58aa30bab2005eeb64f6343c8248
This commit is contained in:
Arkadiy Paronyan
2016-11-05 14:37:45 +01:00
committed by Gav Wood
parent 8b5a9b701a
commit e727d92e0f
27 changed files with 325 additions and 105 deletions

View File

@@ -31,7 +31,7 @@ import ContractInstances from './contracts';
import { initStore } from './redux';
import { ContextProvider, muiTheme } from './ui';
import { Accounts, Account, Addresses, Address, Application, Contract, Contracts, Dapp, Dapps, Settings, SettingsBackground, SettingsProxy, SettingsViews, Signer, Status } from './views';
import { Accounts, Account, Addresses, Address, Application, Contract, Contracts, Dapp, Dapps, Settings, SettingsBackground, SettingsParity, SettingsProxy, SettingsViews, Signer, Status } from './views';
import { setApi } from './redux/providers/apiActions';
@@ -79,6 +79,7 @@ ReactDOM.render(
<Route path='background' component={ SettingsBackground } />
<Route path='proxy' component={ SettingsProxy } />
<Route path='views' component={ SettingsViews } />
<Route path='parity' component={ SettingsParity } />
</Route>
<Route path='signer' component={ Signer } />
<Route path='status' component={ Status } />

View File

@@ -166,7 +166,7 @@ export default {
},
mode: {
desc: 'Get the mode. Results one of: "active", "passive", "dark", "off".',
desc: 'Get the mode. Results one of: "active", "passive", "dark", "offline".',
params: [],
returns: {
type: String,
@@ -330,7 +330,7 @@ export default {
params: [
{
type: String,
desc: 'The mode to set, one of "active", "passive", "dark", "off"'
desc: 'The mode to set, one of "active", "passive", "dark", "offline"'
}
],
returns: {

View File

@@ -0,0 +1,17 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
export default from './parity';

View File

@@ -0,0 +1,116 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import React, { Component, PropTypes } from 'react';
import { MenuItem } from 'material-ui';
import { Select, Container, ContainerTitle } from '../../../ui';
import layout from '../layout.css';
const MODES = {
'active': 'Parity continuously syncs the chain',
'passive': 'Parity syncs initially, then sleeps and wakes regularly to resync',
'dark': 'Parity syncs only when the RPC is active',
'offline': 'Parity doesn\'t sync'
};
export default class Parity extends Component {
static contextTypes = {
api: PropTypes.object.isRequired
}
state = {
mode: 'active'
}
componentWillMount () {
this.loadMode();
}
render () {
return (
<Container>
<ContainerTitle title='Parity' />
<div className={ layout.layout }>
<div className={ layout.overview }>
<div>Control the Parity node settings and mode of operation via this interface.</div>
</div>
<div className={ layout.details }>
{ this.renderModes() }
</div>
</div>
</Container>
);
}
renderModes () {
const modes = Object
.keys(MODES)
.map((mode) => {
const description = MODES[mode];
return (
<MenuItem
key={ mode }
value={ mode }
label={ description }>
{ description }
</MenuItem>
);
});
const { mode } = this.state;
return (
<Select
label='mode of operation'
hint='the syning mode for the Parity node'
value={ mode }
onChange={ this.onChangeMode }>
{ modes }
</Select>
);
}
onChangeMode = (event, index, mode) => {
const { api } = this.context;
api.ethcore
.setMode(mode)
.then((result) => {
if (result) {
this.setState({ mode });
}
})
.catch((error) => {
console.warn('onChangeMode', error);
});
}
loadMode () {
const { api } = this.context;
api.ethcore
.mode()
.then((mode) => {
this.setState({ mode });
})
.catch((error) => {
console.warn('loadMode', error);
});
}
}

View File

@@ -17,6 +17,7 @@
import settingsReducer from './reducers';
import { toggleView, updateBackground } from './actions';
import SettingsBackground from './Background';
import SettingsParity from './Parity';
import SettingsProxy from './Proxy';
import SettingsViews, { defaultViews } from './Views';
@@ -24,6 +25,7 @@ export default from './settings';
export {
SettingsBackground,
SettingsParity,
SettingsProxy,
SettingsViews,
defaultViews,

View File

@@ -61,3 +61,13 @@
vertical-align: top;
display: inline-block;
}
.imageIcon {
height: 20px;
margin: 2px 0.5em 2px 0 !important;
opacity: 0.5;
}
.tabactive .imageIcon {
opacity: 1;
}

View File

@@ -14,8 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
// 0xecf69634885f27a8f78161e530f15a8d3b57d39e755c222c92cf297b6e25aaaa
import React, { Component, PropTypes } from 'react';
import { Tab, Tabs } from 'material-ui';
import ActionSettingsEthernet from 'material-ui/svg-icons/action/settings-ethernet';
@@ -23,6 +21,7 @@ import ImageBlurOn from 'material-ui/svg-icons/image/blur-on';
import ImageRemoveRedEye from 'material-ui/svg-icons/image/remove-red-eye';
import { Actionbar, Page } from '../../ui';
import imagesEthcoreBlock from '../../../assets/images/parity-logo-white-no-text.svg';
import styles from './settings.css';
@@ -37,11 +36,23 @@ export default class Settings extends Component {
render () {
const { children } = this.props;
const hash = (window.location.hash || '').split('?')[0].split('/')[2];
const isProxied = window.location.hostname.indexOf('.parity') !== -1;
let proxy = null;
if (!isProxied) {
proxy = this.renderTab(hash, 'proxy', <ActionSettingsEthernet />);
}
return (
<div className={ styles.layout }>
<Actionbar title='settings' className={ styles.bar }>
{ this.renderTabs() }
<Tabs className={ styles.tabs } value={ hash }>
{ this.renderTab(hash, 'views', <ImageRemoveRedEye />) }
{ this.renderTab(hash, 'background', <ImageBlurOn />) }
{ proxy }
{ this.renderTab(hash, 'parity', <img src={ imagesEthcoreBlock } className={ styles.imageIcon } />) }
</Tabs>
</Actionbar>
<Page>
{ children }
@@ -50,41 +61,15 @@ export default class Settings extends Component {
);
}
renderTabs () {
const hash = (window.location.hash || '').split('?')[0].split('/')[2];
const isProxied = window.location.hostname.indexOf('.parity') !== -1;
let proxy = null;
if (!isProxied) {
proxy = (
<Tab
className={ hash === 'proxy' ? styles.tabactive : styles.tab }
value='proxy'
key='proxy'
icon={ <ActionSettingsEthernet /> }
label={ <div className={ styles.menu }>proxy</div> }
onActive={ this.onActivate('proxy') } />
);
}
renderTab (hash, section, icon) {
return (
<Tabs className={ styles.tabs } value={ hash }>
<Tab
className={ hash === 'views' ? styles.tabactive : styles.tab }
value='views'
key='views'
icon={ <ImageRemoveRedEye /> }
label={ <div className={ styles.menu }>views</div> }
onActive={ this.onActivate('views') } />
<Tab
className={ hash === 'background' ? styles.tabactive : styles.tab }
value='background'
key='background'
icon={ <ImageBlurOn /> }
label={ <div className={ styles.menu }>background</div> }
onActive={ this.onActivate('background') } />
{ proxy }
</Tabs>
<Tab
className={ hash === section ? styles.tabactive : styles.tab }
value={ section }
key={ section }
icon={ icon }
label={ <div className={ styles.menu }>{ section }</div> }
onActive={ this.onActivate(section) } />
);
}

View File

@@ -926,6 +926,16 @@
],
"outputFormatter": null
},
{
"name": "ethcore_setMode",
"desc": "Changes current operating mode",
"params": [
"`DATA`- Mode name"
],
"returns": "`Boolean` - whether the call was successful",
"inputFormatters": null,
"outputFormatter": null
},
{
"name": "ethcore_setMinGasPrice",
"desc": "Changes minimal gas price for transaction to be accepted to the queue.",
@@ -1030,6 +1040,14 @@
"inputFormatters": [],
"outputFormatter": null
},
{
"name": "ethcore_mode",
"desc": "Returns current mode",
"params": [],
"returns": "`DATA` - Mode",
"inputFormatters": [],
"outputFormatter": null
},
{
"name": "trace_filter",
"desc": "Returns traces matching given filter",

View File

@@ -24,7 +24,7 @@ import Contracts from './Contracts';
import Dapp from './Dapp';
import Dapps from './Dapps';
import ParityBar from './ParityBar';
import Settings, { SettingsBackground, SettingsProxy, SettingsViews } from './Settings';
import Settings, { SettingsBackground, SettingsParity, SettingsProxy, SettingsViews } from './Settings';
import Signer from './Signer';
import Status from './Status';
@@ -41,6 +41,7 @@ export {
ParityBar,
Settings,
SettingsBackground,
SettingsParity,
SettingsProxy,
SettingsViews,
Signer,