diff --git a/embark-ui/src/actions/index.js b/embark-ui/src/actions/index.js
index c5543c64..59e6fc48 100644
--- a/embark-ui/src/actions/index.js
+++ b/embark-ui/src/actions/index.js
@@ -63,6 +63,8 @@ export const RECEIVE_PROCESSES_ERROR = 'RECEIVE_PROCESSES_ERROR';
// Process logs
export const FETCH_PROCESS_LOGS = 'FETCH_PROCESS_LOGS';
export const RECEIVE_PROCESS_LOGS = 'RECEIVE_PROCESS_LOGS';
+export const WATCH_NEW_PROCESS_LOGS = 'WATCH_NEW_PROCESS_LOGS';
+export const RECEIVE_NEW_PROCESS_LOG = 'RECEIVE_NEW_PROCESS_LOG';
export const RECEIVE_PROCESS_LOGS_ERROR = 'RECEIVE_PROCESS_LOGS_ERROR';
// BlockHeader
export const INIT_BLOCK_HEADER = 'INIT_BLOCK_HEADER';
@@ -94,6 +96,13 @@ export function fetchProcessLogs(processName) {
};
}
+export function listenToProcessLogs(processName) {
+ return {
+ type: WATCH_NEW_PROCESS_LOGS,
+ processName
+ };
+}
+
export function receiveProcessLogs(processName, logs) {
return {
type: RECEIVE_PROCESS_LOGS,
diff --git a/embark-ui/src/api/index.js b/embark-ui/src/api/index.js
index 65e67739..c1cdfaf1 100644
--- a/embark-ui/src/api/index.js
+++ b/embark-ui/src/api/index.js
@@ -43,6 +43,10 @@ export function fetchProcessLogs(processName) {
return axios.get(`${constants.httpEndpoint}/process-logs/${processName}`);
}
+export function webSocketProcess(processName) {
+ return new WebSocket(constants.wsEndpoint + '/process-logs/' + processName);
+}
+
export function webSocketBlockHeader() {
return new WebSocket(`${constants.wsEndpoint}/blockchain/blockHeader`);
}
diff --git a/embark-ui/src/components/Process.js b/embark-ui/src/components/Process.js
index 18000340..7a73e064 100644
--- a/embark-ui/src/components/Process.js
+++ b/embark-ui/src/components/Process.js
@@ -1,86 +1,30 @@
import React, {Component} from 'react';
-import connect from "react-redux/es/connect/connect";
-import {fetchProcessLogs} from "../actions";
-import constants from '../constants';
import PropTypes from 'prop-types';
+import {Page} from "tabler-react";
+import Loading from "./Loading";
class Process extends Component {
- constructor(props) {
- super(props);
- this.state = {
- logs: []
- };
- this.gotOriginalLogs = false;
- }
-
- componentDidMount() {
- const self = this;
-
- this.props.fetchProcessLogs(self.props.processName);
-
- this.ws = new WebSocket(constants.wsEndpoint + '/process-logs/' + self.props.processName);
-
- this.ws.onmessage = function(evt) {
- const log = JSON.parse(evt.data);
- const logs = self.state.logs;
- logs.push(log);
- self.setState({
- logs
- });
- };
-
- this.ws.onclose = function() {
- console.log(self.props.processName + "Log process connection is closed");
- };
-
- window.onbeforeunload = function(_event) {
- this.ws.close();
- };
- }
-
- shouldComponentUpdate(nextProps, _nextState) {
- if (!this.gotOriginalLogs && nextProps.logs && nextProps.logs[this.props.processName]) {
- const logs = nextProps.logs[this.props.processName].concat(this.state.logs);
- this.gotOriginalLogs = true;
- this.setState({
- logs
- });
- }
- return true;
- }
-
- componentWillUnmount() {
- this.ws.close();
- this.ws = null;
- }
-
render() {
+ const logs = this.props.logs;
return (
-
- State: {this.props.state}
+
+ State: {this.props.state}
+ {!logs &&
+ }
+ {logs &&
{
- this.state.logs.map((item, i) =>
{item.msg_clear || item.msg}
)
+ logs.map((item, i) =>
{item.msg_clear || item.msg}
)
}
-
- );
+ }
+ );
}
}
Process.propTypes = {
processName: PropTypes.string.isRequired,
state: PropTypes.string.isRequired,
- fetchProcessLogs: PropTypes.func,
- logs: PropTypes.object
+ logs: PropTypes.array
};
-function mapStateToProps(state) {
- return {logs: state.processes.logs};
-}
-
-export default connect(
- mapStateToProps,
- {
- fetchProcessLogs
- }
-)(Process);
+export default Process;
diff --git a/embark-ui/src/components/ProcessesLayout.js b/embark-ui/src/components/ProcessesLayout.js
new file mode 100644
index 00000000..25e93774
--- /dev/null
+++ b/embark-ui/src/components/ProcessesLayout.js
@@ -0,0 +1,68 @@
+import PropTypes from "prop-types";
+import React, {Component} from 'react';
+import connect from "react-redux/es/connect/connect";
+import {NavLink, Route, Switch, withRouter} from 'react-router-dom';
+import {
+ Page,
+ Grid,
+ List
+} from "tabler-react";
+
+import ProcessesContainer from '../containers/ProcessesContainer';
+import Loading from "./Loading";
+
+const routePrefix = '/embark/processes';
+
+class ProcessesLayout extends Component {
+
+
+ render() {
+ if (!this.props.processes || !this.props.processes.data) {
+ return ;
+ }
+ const processNames = Object.keys(this.props.processes.data) || [];
+ return (
+
+ Processes
+
+
+ {processNames.map((processName, index) => {
+ return (
+ {processName}
+ );
+ })}
+
+
+
+
+
+
+
+ {processNames.map((processName, index) => {
+ return ();
+ })}
+
+
+ );
+ }
+}
+
+ProcessesLayout.propTypes = {
+ processes: PropTypes.object,
+ match: PropTypes.object
+};
+
+function mapStateToProps(state) {
+ return {processes: state.processes};
+}
+
+export default connect(
+ mapStateToProps
+)(ProcessesLayout);
+
diff --git a/embark-ui/src/containers/AppContainer.js b/embark-ui/src/containers/AppContainer.js
index 94c83767..962baa73 100644
--- a/embark-ui/src/containers/AppContainer.js
+++ b/embark-ui/src/containers/AppContainer.js
@@ -6,11 +6,12 @@ import React, {Component} from 'react';
import history from '../history';
import Layout from '../components/Layout';
import routes from '../routes';
-import {initBlockHeader} from '../actions';
+import {initBlockHeader, fetchProcesses} from '../actions';
class AppContainer extends Component {
componentDidMount() {
this.props.initBlockHeader();
+ this.props.fetchProcesses();
}
render() {
@@ -25,12 +26,14 @@ class AppContainer extends Component {
}
AppContainer.propTypes = {
- initBlockHeader: PropTypes.func
+ initBlockHeader: PropTypes.func,
+ fetchProcesses: PropTypes.func
};
export default connect(
null,
{
- initBlockHeader
+ initBlockHeader,
+ fetchProcesses
},
)(AppContainer);
diff --git a/embark-ui/src/containers/ProcessesContainer.js b/embark-ui/src/containers/ProcessesContainer.js
index c98bc026..9f5c3256 100644
--- a/embark-ui/src/containers/ProcessesContainer.js
+++ b/embark-ui/src/containers/ProcessesContainer.js
@@ -1,48 +1,48 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
-import {Tabs, Tab} from 'tabler-react';
import PropTypes from 'prop-types';
+import {fetchProcessLogs, listenToProcessLogs} from '../actions';
-import {fetchProcesses} from '../actions';
-import Loading from '../components/Loading';
-
-import "./css/processContainer.css";
import Process from "../components/Process";
class ProcessesContainer extends Component {
componentDidMount() {
- this.props.fetchProcesses();
+ // Get correct process name
+ const pathParts = this.props.match.path.split('/');
+ this.processName = pathParts[pathParts.length - 1];
+ // If we are not in a specific process page (eg: processes/ root), get first process
+ if (Object.keys(this.props.processes.data).indexOf(this.processName) < 0) {
+ this.processName = Object.keys(this.props.processes.data)[0];
+ }
+
+ // Fetch logs for the process
+ this.props.fetchProcessLogs(this.processName);
+
+ // Only start watching if we are not already watching
+ if (!this.props.processes.data[this.processName].isListening) {
+ this.props.listenToProcessLogs(this.processName);
+ }
}
render() {
- const {processes} = this.props;
- if (!processes.data) {
- return ;
+ if (!this.processName) {
+ return '';
}
-
- const processNames = Object.keys(processes.data);
return (
- {processes.error &&
- Error: {processes.error.message || processes.error}
-
}
-
- {processNames && processNames.length &&
- {processNames.map(processName => {
- return (
-
- );
- })}
- }
-
+
);
}
}
ProcessesContainer.propTypes = {
+ match: PropTypes.object,
processes: PropTypes.object,
- fetchProcesses: PropTypes.func
+ fetchProcessLogs: PropTypes.func,
+ listenToProcessLogs: PropTypes.func
};
function mapStateToProps(state) {
@@ -52,6 +52,7 @@ function mapStateToProps(state) {
export default connect(
mapStateToProps,
{
- fetchProcesses
+ fetchProcessLogs,
+ listenToProcessLogs
}
)(ProcessesContainer);
diff --git a/embark-ui/src/containers/css/processContainer.css b/embark-ui/src/general.css
similarity index 60%
rename from embark-ui/src/containers/css/processContainer.css
rename to embark-ui/src/general.css
index 1510241f..60588a99 100644
--- a/embark-ui/src/containers/css/processContainer.css
+++ b/embark-ui/src/general.css
@@ -1,9 +1,4 @@
-
-.processes-container .nav-link {
- text-transform: capitalize;
-}
-
-.processes-container .logs {
+.logs {
margin: 10px 0;
background-color: #333333;
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
@@ -13,15 +8,19 @@
border-radius: 8px;
}
-.processes-container .logs .error {
+.logs .error {
color: #dc3546;
}
-.processes-container .logs .warn {
+.logs .warn {
color: #fec107;
}
-.processes-container .logs .debug {
+.logs .debug {
color: #b7c1cc;
}
-.processes-container .logs .trace {
+.logs .trace {
color: #8f98a2;
}
+
+.capitalize {
+ text-transform: capitalize;
+}
diff --git a/embark-ui/src/index.js b/embark-ui/src/index.js
index 346c9426..40ff2c2d 100644
--- a/embark-ui/src/index.js
+++ b/embark-ui/src/index.js
@@ -3,6 +3,7 @@ import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import "tabler-react/dist/Tabler.css";
+import "./general.css";
import AppContainer from './containers/AppContainer';
import registerServiceWorker from './registerServiceWorker';
diff --git a/embark-ui/src/reducers/processesReducer.js b/embark-ui/src/reducers/processesReducer.js
index a7ddae2e..288c1df8 100644
--- a/embark-ui/src/reducers/processesReducer.js
+++ b/embark-ui/src/reducers/processesReducer.js
@@ -1,4 +1,11 @@
-import {RECEIVE_PROCESSES, RECEIVE_PROCESSES_ERROR, RECEIVE_PROCESS_LOGS, RECEIVE_PROCESS_LOGS_ERROR} from "../actions";
+import {
+ RECEIVE_PROCESSES,
+ RECEIVE_PROCESSES_ERROR,
+ RECEIVE_PROCESS_LOGS,
+ RECEIVE_PROCESS_LOGS_ERROR,
+ RECEIVE_NEW_PROCESS_LOG,
+ WATCH_NEW_PROCESS_LOGS
+} from "../actions";
export default function processes(state = {}, action) {
switch (action.type) {
@@ -9,11 +16,40 @@ export default function processes(state = {}, action) {
case RECEIVE_PROCESS_LOGS:
return {
...state,
- logs: {
- ...state.logs,
- [action.processName]: action.logs.data
+ data: {
+ ...state.data,
+ [action.processName]: {
+ ...state.data[action.processName],
+ logs: action.logs.data
+ }
}
};
+ case RECEIVE_NEW_PROCESS_LOG: {
+ const logs = state.data[action.processName].logs || [];
+ logs.push(action.log);
+ return {
+ ...state,
+ data: {
+ ...state.data,
+ [action.processName]: {
+ ...state.data[action.processName],
+ logs: logs
+ }
+ }
+ };
+ }
+ case WATCH_NEW_PROCESS_LOGS: {
+ return {
+ ...state,
+ data: {
+ ...state.data,
+ [action.processName]: {
+ ...state.data[action.processName],
+ isListening: true
+ }
+ }
+ };
+ }
case RECEIVE_PROCESS_LOGS_ERROR:
return Object.assign({}, state, {error: action.error});
default:
diff --git a/embark-ui/src/routes.js b/embark-ui/src/routes.js
index 0797357d..c7cee5aa 100644
--- a/embark-ui/src/routes.js
+++ b/embark-ui/src/routes.js
@@ -4,15 +4,14 @@ import {Route, Switch} from 'react-router-dom';
import Home from './components/Home';
import NoMatch from './components/NoMatch';
import ExplorerLayout from './components/ExplorerLayout';
-
-import ProcessesContainer from './containers/ProcessesContainer';
+import ProcessesLayout from './components/ProcessesLayout';
const routes = (
-
+
diff --git a/embark-ui/src/sagas/index.js b/embark-ui/src/sagas/index.js
index f3c8c254..3139ff37 100644
--- a/embark-ui/src/sagas/index.js
+++ b/embark-ui/src/sagas/index.js
@@ -96,6 +96,19 @@ export function *watchInitBlockHeader() {
yield takeEvery(actions.INIT_BLOCK_HEADER, initBlockHeader);
}
+export function *listenToProcessLogs(action) {
+ const socket = api.webSocketProcess(action.processName);
+ const channel = yield call(createChannel, socket);
+ while (true) {
+ const log = yield take(channel);
+ yield put({type: actions.RECEIVE_NEW_PROCESS_LOG, processName: action.processName, log});
+ }
+}
+
+export function *watchListenToProcessLogs() {
+ yield takeEvery(actions.WATCH_NEW_PROCESS_LOGS, listenToProcessLogs);
+}
+
export default function *root() {
yield all([
fork(watchInitBlockHeader),
@@ -103,6 +116,7 @@ export default function *root() {
fork(watchFetchAccount),
fork(watchFetchProcesses),
fork(watchFetchProcessLogs),
+ fork(watchListenToProcessLogs),
fork(watchFetchBlocks),
fork(watchFetchBlock),
fork(watchFetchTransactions),