Merge pull request #16 from status-im/features/process-list

Add process container UI
This commit is contained in:
Iuri Matias 2018-08-01 15:18:48 -04:00 committed by GitHub
commit 33254cbbf4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 166 additions and 30 deletions

View File

@ -4,14 +4,23 @@
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"extends": [
"eslint:recommended",
"plugin:react/recommended"
],
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2017
"ecmaVersion": 2017,
"ecmaFeatures": {
"jsx": true
}
},
"globals": {
"__": true
},
"plugins": [
"react"
],
"rules": {
"accessor-pairs": "error",
"array-bracket-newline": "error",
@ -111,6 +120,7 @@
"no-confusing-arrow": "error",
"no-console": "off",
"no-continue": "off",
"no-debugger": "warn",
"no-div-regex": "error",
"no-duplicate-imports": "error",
"no-else-return": "off",
@ -241,7 +251,7 @@
"error",
"last"
],
"sort-imports": "error",
"sort-imports": "off",
"sort-keys": "off",
"sort-vars": "off",
"space-before-blocks": "off",

View File

@ -1,22 +1,46 @@
// Accounts
export const FETCH_ACCOUNTS = 'FETCH_ACCOUNTS';
export const RECEIVE_ACCOUNTS = 'RECEIVE_ACCOUNTS';
export const RECEIVE_ACCOUNTS_ERROR = 'RECEIVE_ACCOUNTS_ERROR';
// Processes
export const FETCH_PROCESSES = 'FETCH_PROCESSES';
export const RECEIVE_PROCESSES = 'RECEIVE_PROCESSES';
export const RECEIVE_PROCESSES_ERROR = 'RECEIVE_PROCESSES_ERROR';
export function fetchAccounts() {
return {
type: FETCH_ACCOUNTS
};
};
}
export function receiveAccounts(accounts) {
return {
type: RECEIVE_ACCOUNTS,
accounts: accounts
};
accounts
};
}
export function receiveAccountsError() {
return {
type: RECEIVE_ACCOUNTS_ERROR
};
}
export function fetchProcesses() {
return {
type: FETCH_PROCESSES
};
}
export function receiveProcesses(processes) {
return {
type: RECEIVE_PROCESSES,
processes
};
}
export function receiveProcessesError() {
return {
type: RECEIVE_PROCESSES_ERROR
};
}

View File

@ -2,4 +2,8 @@ import axios from "axios";
export function fetchAccounts() {
return axios.get('http://localhost:8000/embark-api/blockchain/accounts');
};
}
export function fetchProcesses() {
return axios.get('http://localhost:8000/embark-api/processes');
}

View File

@ -1,6 +1,7 @@
import React from 'react';
import {NavLink, withRouter} from "react-router-dom";
import {Site, Nav, Button, Container} from "tabler-react";
import PropTypes from 'prop-types';
import logo from '../images/logo.png';
@ -8,7 +9,8 @@ const navBarItems = [
{value: "Home", to: "/embark", icon: "home", LinkComponent: withRouter(NavLink)},
{value: "Contracts", to: "/embark/contracts", icon: "box", LinkComponent: withRouter(NavLink)},
{value: "Explorer", to: "/embark/explorer/accounts", icon: "activity", LinkComponent: withRouter(NavLink)},
{ value: "Documentation", to: "/embark/documentation", icon: "file-text", LinkComponent: withRouter(NavLink) },
{value: "Processes", to: "/embark/processes", icon: "cpu", LinkComponent: withRouter(NavLink)},
{value: "Documentation", to: "/embark/documentation", icon: "file-text", LinkComponent: withRouter(NavLink)}
];
const Layout = (props) => (
@ -40,4 +42,8 @@ const Layout = (props) => (
</Site.Wrapper>
);
Layout.propTypes = {
children: PropTypes.element
};
export default Layout;

View File

@ -3,7 +3,7 @@ import React, { Component } from 'react';
import history from '../history';
import Layout from '../components/Layout';
import routes from '../routes'
import routes from '../routes';
class AppContainer extends Component {
render() {

View File

@ -0,0 +1,59 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {fetchProcesses} from '../actions';
import {Tabs, Tab} from 'tabler-react';
import PropTypes from 'prop-types';
import "./css/processContainer.css";
class ProcessesContainer extends Component {
componentDidMount() {
this.props.fetchProcesses();
}
render() {
const {processes} = this.props;
if (!processes.data) {
return (
<h1>
<i>Loading processes...</i>
</h1>
);
}
if (processes.error) {
return (
<h1>
<i>Error loading processes: {processes.error.message || processes.error}</i>
</h1>
);
}
const processNames = Object.keys(processes.data);
return (
<div className="processes-container">
<Tabs initialTab={processNames[0]}>
{processNames.map(processName => {
return (<Tab key={processName} title={processName}>State: {processes.data[processName].state}</Tab>);
})}
</Tabs>
</div>
);
}
}
ProcessesContainer.propTypes = {
processes: PropTypes.object,
fetchProcesses: PropTypes.func
};
function mapStateToProps(state) {
return {processes: state.processes};
}
export default connect(
mapStateToProps,
{
fetchProcesses
}
)(ProcessesContainer);

View File

@ -0,0 +1,4 @@
.processes-container .nav-link {
text-transform: capitalize;
}

View File

@ -1,5 +1,6 @@
import {combineReducers} from 'redux';
import {RECEIVE_ACCOUNTS, RECEIVE_ACCOUNTS_ERROR} from "../actions";
import processesReducer from './processesReducer';
function accounts(state = {}, action) {
switch (action.type) {
@ -10,7 +11,7 @@ function accounts(state = {}, action) {
default:
return state;
}
};
}
const rootReducer = combineReducers({accounts});
const rootReducer = combineReducers({accounts, processes: processesReducer});
export default rootReducer;

View File

@ -0,0 +1,12 @@
import {RECEIVE_PROCESSES, RECEIVE_PROCESSES_ERROR} from "../actions";
export default function processes(state = {}, action) {
switch (action.type) {
case RECEIVE_PROCESSES:
return Object.assign({}, state, {data: action.processes.data});
case RECEIVE_PROCESSES_ERROR:
return Object.assign({}, state, {error: true});
default:
return state;
}
}

View File

@ -2,6 +2,7 @@ import React from 'react';
import {Route, Switch} from 'react-router';
import Home from './components/Home';
import AccountsContainer from './containers/AccountsContainer';
import ProcessesContainer from './containers/ProcessesContainer';
import NoMatch from './components/NoMatch';
const routes = (
@ -9,9 +10,10 @@ const routes = (
<Switch>
<Route exact path="/embark" component={Home} />
<Route path="/embark/explorer/accounts" component={AccountsContainer} />
<Route path="/embark/processes" component={ProcessesContainer} />
<Route component={NoMatch} />
</Switch>
</React.Fragment>
)
);
export default routes
export default routes;

View File

@ -1,6 +1,6 @@
import {all, call, fork, put, takeEvery} from 'redux-saga/effects';
import * as actions from '../actions';
import * as api from '../api';
import {all, call, fork, put, takeEvery} from 'redux-saga/effects';
export function *fetchAccounts() {
try {
@ -15,6 +15,19 @@ export function *watchFetchAccounts() {
yield takeEvery(actions.FETCH_ACCOUNTS, fetchAccounts);
}
export default function *root() {
yield all([fork(watchFetchAccounts)]);
export function *fetchProcesses() {
try {
const processes = yield call(api.fetchProcesses);
yield put(actions.receiveProcesses(processes));
} catch (e) {
yield put(actions.receiveProcessesError());
}
}
export function *watchFetchProcesses() {
yield takeEvery(actions.FETCH_PROCESSES, fetchProcesses);
}
export default function *root() {
yield all([fork(watchFetchAccounts), fork(watchFetchProcesses)]);
}

View File

@ -20,7 +20,7 @@ class ProcessManager {
let parsedProcesses = {};
Object.keys(self.processes).forEach(processName => {
parsedProcesses[processName] = {
state: self.processes[processName]
state: self.processes[processName].state
};
});
res.send(parsedProcesses);

View File

@ -105,6 +105,7 @@
"license": "MIT",
"devDependencies": {
"eslint": "4.13.1",
"eslint-plugin-react": "^7.10.0",
"mocha-sinon": "^1.1.4",
"sinon": "^4.5.0"
}