First iteration of Status page (WIP)

This commit is contained in:
Jaco Greeff 2017-04-21 15:20:43 +02:00
parent 2459501f4e
commit 5fc6a5627e
24 changed files with 126 additions and 89 deletions

View File

@ -1,7 +1,7 @@
[ [
{ {
"id": "viewHome", "id": "home",
"url": "viewHome", "url": "home",
"src": "Home", "src": "Home",
"name": "Home", "name": "Home",
"description": "Display a status of the node, recently accessed applications, accounts and news", "description": "Display a status of the node, recently accessed applications, accounts and news",
@ -9,5 +9,16 @@
"version": "2.0.0", "version": "2.0.0",
"visible": true, "visible": true,
"secure": true "secure": true
},
{
"id": "status",
"url": "status",
"src": "Status",
"name": "Status",
"description": "Display an overview of the node including settings, logs and connections",
"author": "Parity Team <admin@ethcore.io>",
"version": "2.0.0",
"visible": true,
"secure": true
} }
] ]

View File

@ -37,7 +37,6 @@ import muiTheme from '~/ui/Theme';
import MainApplication from './main'; import MainApplication from './main';
import { patchApi } from '~/util/tx'; import { patchApi } from '~/util/tx';
import { setApi } from '~/redux/providers/apiActions';
import './environment'; import './environment';
@ -70,9 +69,6 @@ ContractInstances.get(api);
const store = initStore(api, hashHistory); const store = initStore(api, hashHistory);
store.dispatch({ type: 'initAll', api });
store.dispatch(setApi(api));
window.secureApi = api; window.secureApi = api;
ReactDOM.render( ReactDOM.render(

View File

@ -63,6 +63,8 @@ export function personalAccountsInfo (accountsInfo) {
return (dispatch, getState) => { return (dispatch, getState) => {
const { api } = getState(); const { api } = getState();
console.log('_fetchOwners', api);
const _fetchOwners = Object const _fetchOwners = Object
.values(wallets) .values(wallets)
.map((wallet) => { .map((wallet) => {

View File

@ -21,7 +21,7 @@ import subscribeToEvents from '~/util/subscribe-to-events';
import registryABI from '~/contracts/abi/registry.json'; import registryABI from '~/contracts/abi/registry.json';
import { setReverse, startCachingReverses } from './actions'; import { setReverse } from './actions';
const STORE_KEY = '_parity::reverses'; const STORE_KEY = '_parity::reverses';
@ -83,12 +83,6 @@ export default (api) => (store) => {
return (next) => (action) => { return (next) => (action) => {
switch (action.type) { switch (action.type) {
case 'initAll':
next(action);
store.dispatch(startCachingReverses());
break;
case 'startCachingReverses': case 'startCachingReverses':
const { registry } = Contracts.get(api); const { registry } = Contracts.get(api);
const cached = read(store.getState().nodeStatus.netChain); const cached = read(store.getState().nodeStatus.netChain);
@ -120,6 +114,7 @@ export default (api) => (store) => {
}); });
break; break;
case 'stopCachingReverses': case 'stopCachingReverses':
if (subscription) { if (subscription) {
subscription.unsubscribe(); subscription.unsubscribe();

View File

@ -36,7 +36,8 @@ export function loadTokens (options = {}) {
log.debug('loading tokens', Object.keys(options).length ? options : ''); log.debug('loading tokens', Object.keys(options).length ? options : '');
return (dispatch, getState) => { return (dispatch, getState) => {
const { tokenReg } = Contracts.get(); const { api } = getState();
const { tokenReg } = Contracts.get(api);
tokenReg.getInstance() tokenReg.getInstance()
.then((tokenRegInstance) => { .then((tokenRegInstance) => {
@ -54,7 +55,7 @@ export function fetchTokens (_tokenIndexes, options = {}) {
return (dispatch, getState) => { return (dispatch, getState) => {
const { api, images } = getState(); const { api, images } = getState();
const { tokenReg } = Contracts.get(); const { tokenReg } = Contracts.get(api);
return tokenReg.getInstance() return tokenReg.getInstance()
.then((tokenRegInstance) => { .then((tokenRegInstance) => {

View File

@ -19,8 +19,10 @@ import { applyMiddleware, createStore } from 'redux';
import initMiddleware from './middleware'; import initMiddleware from './middleware';
import initReducers from './reducers'; import initReducers from './reducers';
import { load as loadWallet } from './providers/walletActions'; import { setApi } from './providers/apiActions';
import { startCachingReverses } from './providers/registry/actions';
import { init as initRequests } from './providers/requestsActions'; import { init as initRequests } from './providers/requestsActions';
import { load as loadWallet } from './providers/walletActions';
import { setupWorker } from './providers/workerWrapper'; import { setupWorker } from './providers/workerWrapper';
import { import {
@ -44,8 +46,12 @@ export default function (api, browserHistory, forEmbed = false) {
new PersonalProvider(store, api).start(); new PersonalProvider(store, api).start();
new SignerProvider(store, api).start(); new SignerProvider(store, api).start();
store.dispatch(setApi(api));
store.dispatch(startCachingReverses());
store.dispatch(loadWallet(api)); store.dispatch(loadWallet(api));
store.dispatch(initRequests(api)); store.dispatch(initRequests(api));
setupWorker(store); setupWorker(store);
return store; return store;

View File

@ -19,7 +19,7 @@ import {
Accounts, Account, Addresses, Address, Application, Accounts, Account, Addresses, Address, Application,
Contract, Contracts, Dapp, Dapps, Contract, Contracts, Dapp, Dapps,
Settings, SettingsBackground, SettingsParity, SettingsProxy, Settings, SettingsBackground, SettingsParity, SettingsProxy,
SettingsViews, Signer, Status, SettingsViews, Signer,
Vaults, Wallet, Web, WriteContract Vaults, Wallet, Web, WriteContract
} from '~/views'; } from '~/views';
import builtinDapps from '~/config/dappsBuiltin.json'; import builtinDapps from '~/config/dappsBuiltin.json';
@ -87,18 +87,14 @@ const settingsRoutes = [
{ path: 'parity', component: SettingsParity } { path: 'parity', component: SettingsParity }
]; ];
const statusRoutes = [
{ path: ':subpage', component: Status }
];
const routes = [ const routes = [
// Backward Compatible routes // Backward Compatible routes
{ path: '/account/:address', onEnter: handleDeprecatedRoute }, { path: '/account/:address', onEnter: handleDeprecatedRoute },
{ path: '/address/:address', onEnter: handleDeprecatedRoute }, { path: '/address/:address', onEnter: handleDeprecatedRoute },
{ path: '/contract/:address', onEnter: handleDeprecatedRoute }, { path: '/contract/:address', onEnter: handleDeprecatedRoute },
{ path: '/', onEnter: redirectTo('/home') }, { path: '/', onEnter: redirectTo('/apps') },
{ path: '/auth', onEnter: redirectTo('/home') }, { path: '/auth', onEnter: redirectTo('/apps') },
{ path: '/settings', onEnter: redirectTo('/settings/views') } { path: '/settings', onEnter: redirectTo('/settings/views') }
]; ];
@ -118,11 +114,6 @@ const childRoutes = [
indexRoute: { component: Contracts }, indexRoute: { component: Contracts },
childRoutes: contractsRoutes childRoutes: contractsRoutes
}, },
{
path: 'status',
indexRoute: { component: Status },
childRoutes: statusRoutes
},
{ {
path: 'settings', path: 'settings',
component: Settings, component: Settings,

View File

@ -25,7 +25,7 @@ export default class ContextProvider extends Component {
static propTypes = { static propTypes = {
api: PropTypes.object.isRequired, api: PropTypes.object.isRequired,
muiTheme: PropTypes.object.isRequired, muiTheme: PropTypes.object.isRequired,
store: PropTypes.object.isRequired, store: PropTypes.object,
children: PropTypes.node.isRequired children: PropTypes.node.isRequired
} }

View File

@ -278,7 +278,7 @@ export default class MethodDecodingStore {
return Promise.resolve(this._methods[signature]); return Promise.resolve(this._methods[signature]);
} }
this._methods[signature] = Contracts.get() this._methods[signature] = Contracts.get(this.api)
.signatureReg .signatureReg
.lookup(signature) .lookup(signature)
.then((method) => { .then((method) => {

View File

@ -89,8 +89,8 @@ export function subscribeToChanges (api, dappReg, callback) {
}); });
} }
export function fetchBuiltinApps () { export function fetchBuiltinApps (api) {
const { dappReg } = Contracts.get(); const { dappReg } = Contracts.get(api);
return Promise return Promise
.all(builtinApps.map((app) => dappReg.getImage(app.id))) .all(builtinApps.map((app) => dappReg.getImage(app.id)))
@ -127,8 +127,8 @@ export function fetchLocalApps (api) {
}); });
} }
export function fetchRegistryAppIds () { export function fetchRegistryAppIds (api) {
const { dappReg } = Contracts.get(); const { dappReg } = Contracts.get(api);
return dappReg return dappReg
.count() .count()

View File

@ -137,7 +137,7 @@ export default class DappsStore extends EventEmitter {
return Promise.resolve(this._cachedApps[BUILTIN_APPS_KEY]); return Promise.resolve(this._cachedApps[BUILTIN_APPS_KEY]);
} }
this._cachedApps[BUILTIN_APPS_KEY] = fetchBuiltinApps() this._cachedApps[BUILTIN_APPS_KEY] = fetchBuiltinApps(this._api)
.then((apps) => { .then((apps) => {
this._cachedApps[BUILTIN_APPS_KEY] = apps; this._cachedApps[BUILTIN_APPS_KEY] = apps;
return apps; return apps;
@ -155,7 +155,7 @@ export default class DappsStore extends EventEmitter {
return Promise.resolve(this._registryAppsIds); return Promise.resolve(this._registryAppsIds);
} }
this._registryAppsIds = fetchRegistryAppIds() this._registryAppsIds = fetchRegistryAppIds(this._api)
.then((appIds) => { .then((appIds) => {
this._registryAppsIds = appIds; this._registryAppsIds = appIds;
return this._registryAppsIds; return this._registryAppsIds;

View File

@ -15,7 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import React, { Component } from 'react'; import React, { Component, PropTypes } from 'react';
import ReactMarkdown from 'react-markdown'; import ReactMarkdown from 'react-markdown';
import { SectionList } from '~/ui'; import { SectionList } from '~/ui';
@ -28,7 +28,11 @@ const VERSION_ID = '1';
@observer @observer
export default class News extends Component { export default class News extends Component {
store = Store.get(); static contextTypes = {
api: PropTypes.object.isRequired
};
store = Store.get(this.context.api);
componentWillMount () { componentWillMount () {
return this.store.retrieveNews(VERSION_ID); return this.store.retrieveNews(VERSION_ID);

View File

@ -22,12 +22,16 @@ let instance = null;
export default class Store { export default class Store {
@observable newsItems = null; @observable newsItems = null;
constructor (api) {
this._api = api;
}
@action setNewsItems = (newsItems) => { @action setNewsItems = (newsItems) => {
this.newsItems = newsItems; this.newsItems = newsItems;
} }
retrieveNews (versionId) { retrieveNews (versionId) {
const contracts = Contracts.get(); const contracts = Contracts.get(this._api);
return contracts.registry return contracts.registry
.lookupMeta('paritynews', 'CONTENT') .lookupMeta('paritynews', 'CONTENT')
@ -57,9 +61,9 @@ export default class Store {
}); });
} }
static get () { static get (api) {
if (!instance) { if (!instance) {
instance = new Store(); instance = new Store(api);
} }
return instance; return instance;

View File

@ -26,10 +26,6 @@ import styles from './urls.css';
@observer @observer
export default class Urls extends Component { export default class Urls extends Component {
static contextTypes = {
router: PropTypes.object.isRequired
};
static propTypes = { static propTypes = {
extensionStore: PropTypes.object.isRequired, extensionStore: PropTypes.object.isRequired,
store: PropTypes.object.isRequired store: PropTypes.object.isRequired

View File

@ -24,7 +24,6 @@ injectTapEventPlugin();
import { api } from './parity'; import { api } from './parity';
import { initStore } from '~/redux'; import { initStore } from '~/redux';
import { setApi } from '~/redux/providers/apiActions';
import ContextProvider from '~/ui/ContextProvider'; import ContextProvider from '~/ui/ContextProvider';
import muiTheme from '~/ui/Theme'; import muiTheme from '~/ui/Theme';
@ -37,9 +36,6 @@ import './home.css';
const store = initStore(api, hashHistory); const store = initStore(api, hashHistory);
store.dispatch({ type: 'initAll', api });
store.dispatch(setApi(api));
ReactDOM.render( ReactDOM.render(
<ContextProvider api={ api } muiTheme={ muiTheme } store={ store }> <ContextProvider api={ api } muiTheme={ muiTheme } store={ store }>
<Home /> <Home />

View File

@ -16,7 +16,7 @@
import React from 'react'; import React from 'react';
import { AccountsIcon, AddressesIcon, AppsIcon, ContactsIcon, FingerprintIcon, SettingsIcon, StatusIcon } from '~/ui/Icons'; import { AccountsIcon, AddressesIcon, AppsIcon, ContactsIcon, FingerprintIcon, SettingsIcon } from '~/ui/Icons';
const defaultViews = { const defaultViews = {
accounts: { accounts: {
@ -48,13 +48,6 @@ const defaultViews = {
value: 'contract' value: 'contract'
}, },
status: {
active: false,
icon: <StatusIcon />,
route: '/status',
value: 'status'
},
signer: { signer: {
active: true, active: true,
fixed: true, fixed: true,

View File

@ -112,17 +112,6 @@ class Views extends Component {
/> />
) )
} }
{
this.renderView('status',
<FormattedMessage
id='settings.views.status.label'
/>,
<FormattedMessage
id='settings.views.status.description'
defaultMessage='See how the Parity node is performing in terms of connections to the network, logs from the actual running instance and details of mining (if enabled and configured).'
/>
)
}
{ {
this.renderView('signer', this.renderView('signer',
<FormattedMessage <FormattedMessage

View File

@ -49,7 +49,7 @@ export default class MiningSettings extends Component {
: ''; : '';
return ( return (
<div { ...this._testInherit() }> <div>
<ContainerTitle <ContainerTitle
title={ title={
<FormattedMessage <FormattedMessage

View File

@ -14,4 +14,34 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
export default from './status'; import ReactDOM from 'react-dom';
import React from 'react';
import { hashHistory } from 'react-router';
import injectTapEventPlugin from 'react-tap-event-plugin';
injectTapEventPlugin();
import { api } from './parity';
import ContractInstances from '~/contracts';
import { initStore } from '~/redux';
import ContextProvider from '~/ui/ContextProvider';
import muiTheme from '~/ui/Theme';
import Status from './status';
import '~/../assets/fonts/Roboto/font.css';
import '~/../assets/fonts/RobotoMono/font.css';
import './status.css';
ContractInstances.get(api);
const store = initStore(api, hashHistory);
ReactDOM.render(
<ContextProvider api={ api } muiTheme={ muiTheme } store={ store }>
<Status />
</ContextProvider>,
document.querySelector('#container')
);

View File

@ -0,0 +1,21 @@
// Copyright 2015-2017 Parity Technologies (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/>.
const api = window.parent.secureApi;
export {
api
};

View File

@ -25,7 +25,8 @@ import NodeStatus from './NodeStatus';
import styles from './status.css'; import styles from './status.css';
export default () => ( export default function Status () {
return (
<Page <Page
title={ title={
<FormattedMessage <FormattedMessage
@ -40,4 +41,5 @@ export default () => (
<Debug /> <Debug />
</div> </div>
</Page> </Page>
); );
}

View File

@ -26,7 +26,6 @@ export Dapps from './Dapps';
export ParityBar from './ParityBar'; export ParityBar from './ParityBar';
export Settings, { SettingsBackground, SettingsParity, SettingsProxy, SettingsViews } from './Settings'; export Settings, { SettingsBackground, SettingsParity, SettingsProxy, SettingsViews } from './Settings';
export Signer from './Signer'; export Signer from './Signer';
export Status from './Status';
export Vaults from './Vaults'; export Vaults from './Vaults';
export Wallet from './Wallet'; export Wallet from './Wallet';
export Web from './Web'; export Web from './Web';

View File

@ -35,6 +35,7 @@ const DAPPS_BUILTIN = require('../src/config/dappsBuiltin.json').map((dapp) => {
}); });
const DAPPS_VIEWS = require('../src/config/dappsViews.json').map((dapp) => { const DAPPS_VIEWS = require('../src/config/dappsViews.json').map((dapp) => {
dapp.srcPath = './views'; dapp.srcPath = './views';
dapp.commons = true;
return dapp; return dapp;
}); });
@ -167,7 +168,7 @@ module.exports = {
template: dapp.srcPath + '/index.ejs', template: dapp.srcPath + '/index.ejs',
favicon: FAVICON, favicon: FAVICON,
secure: dapp.secure, secure: dapp.secure,
chunks: [ isProd ? null : 'commons', dapp.url ] chunks: [ !isProd || dapp.commons ? 'commons' : null, dapp.url ]
}); });
}); });

View File

@ -16,6 +16,6 @@
module.exports = { module.exports = {
test: /\.js$/, test: /\.js$/,
include: /node_modules\/@parity\/(abi|api|jsonrpc|wordlist)/, include: /node_modules\/@parity\/(abi|api|jsonrpc|ui|wordlist)/,
use: 'babel-loader' use: 'babel-loader'
}; };