Adding Console command

This commit is contained in:
Anthony Laibe 2018-08-07 11:48:27 +01:00 committed by Pascal Precht
parent 89b64adc4a
commit 546d7af076
No known key found for this signature in database
GPG Key ID: 0EE28D8D6FD85D7D
9 changed files with 127 additions and 41 deletions

View File

@ -63,6 +63,13 @@ export const processes = {
failure: (error) => action(PROCESSES[FAILURE], {error})
};
export const COMMANDS = createRequestTypes('COMMANDS');
export const commands = {
post: (command) => action(COMMANDS[REQUEST], {command}),
success: (result) => action(COMMANDS[SUCCESS], {result}),
failure: (error) => action(COMMANDS[FAILURE], {error})
};
// Process logs
export const FETCH_PROCESS_LOGS = 'FETCH_PROCESS_LOGS';
export const RECEIVE_PROCESS_LOGS = 'RECEIVE_PROCESS_LOGS';

View File

@ -11,6 +11,20 @@ function get(path, params) {
});
}
function post(path, params) {
return axios.post(constants.httpEndpoint + path, params)
.then((response) => {
return {response};
})
.catch((error) => {
return {response: null, error: error.message || 'Something bad happened'};
});
}
export function postCommand(payload) {
return post('/command', payload);
}
export function fetchAccounts() {
return get('/blockchain/accounts');
}

View File

@ -1,27 +1,61 @@
import React from 'react';
import {Grid, Card} from 'tabler-react';
import PropTypes from "prop-types";
import React, {Component} from 'react';
import {Grid, Card, Form} from 'tabler-react';
const Console = () => (
const CommandResult = ({result}) => (
<p className="text__new-line">{result}</p>
);
CommandResult.propTypes = {
result: PropTypes.string
};
class Console extends Component {
constructor(props) {
super(props);
this.state = {value: ''};
}
handleSubmit(event) {
event.preventDefault();
this.props.postCommand(this.state.value);
this.setState({value: ''});
}
handleChange(event) {
this.setState({value: event.target.value});
}
render() {
return (
<Grid.Row cards>
<Grid.Col>
<Card>
<Card.Header>
<Card.Title>Console</Card.Title>
<Card.Title>Embark console</Card.Title>
</Card.Header>
<Card.Body>
<div className="log">
<p>Welcome!</p>
</div>
<div className="command-line">
<div className="form-group">
<input type="text" className="form-control" name="example-text-input"
placeholder="type a command (e.g help)" />
</div>
<div>
{this.props.commandResults &&
this.props.commandResults.map((result) => <CommandResult key={result} result={result} />)}
</div>
<Form onSubmit={(event) => this.handleSubmit(event)}>
<Form.Input value={this.state.value}
onChange={(event) => this.handleChange(event)}
name="command"
placeholder="Type a command (e.g help)" />
</Form>
</Card.Body>
</Card>
</Grid.Col>
</Grid.Row>
);
}
}
Console.propTypes = {
postCommand: PropTypes.func,
commandResults: PropTypes.arrayOf(PropTypes.string)
};
export default Console;

View File

@ -38,7 +38,7 @@ const Processes = ({processes}) => (
);
Processes.propTypes = {
processes: PropTypes.object,
processes: PropTypes.object
};
export default Processes;

View File

@ -2,6 +2,7 @@ import PropTypes from "prop-types";
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {Page} from "tabler-react";
import {commands as commandsAction} from "../actions";
import Processes from '../components/Processes';
import Console from '../components/Console';
@ -12,21 +13,25 @@ class HomeContainer extends Component {
<React.Fragment>
<Page.Title className="my-5">Dashboard</Page.Title>
{this.props.processes.data && <Processes processes={this.props.processes.data} />}
<Console />
<Console postCommand={this.props.postCommand} commandResults={this.props.commandResults} />
</React.Fragment>
);
}
}
HomeContainer.propTypes = {
processes: PropTypes.object
processes: PropTypes.object,
postCommand: PropTypes.func,
commandResults: PropTypes.arrayOf(PropTypes.string)
};
function mapStateToProps(state) {
return {processes: state.processes};
return {processes: state.processes, commandResults: state.commands.results};
}
export default connect(
mapStateToProps,
null,
{
postCommand: commandsAction.post
}
)(HomeContainer);

View File

@ -20,3 +20,7 @@
.logs .trace {
color: #8f98a2;
}
.text__new-line {
white-space: pre-line;
}

View File

@ -0,0 +1,14 @@
import * as actions from "../actions";
export default function commands(state = {}, action) {
switch (action.type) {
case actions.COMMANDS[actions.SUCCESS]:
return {
...state, error: null, results: [...state.results || [], action.result.data.result]
};
case actions.COMMANDS[actions.FAILURE]:
return Object.assign({}, state, {error: action.error});
default:
return state;
}
}

View File

@ -3,12 +3,14 @@ import processesReducer from './processesReducer';
import accountsReducer from './accountsReducer';
import blocksReducer from './blocksReducer';
import transactionsReducer from './transactionsReducer';
import commandsReducer from './commandsReducer';
const rootReducer = combineReducers({
accounts: accountsReducer,
processes: processesReducer,
blocks: blocksReducer,
transactions: transactionsReducer
transactions: transactionsReducer,
commands: commandsReducer
});
export default rootReducer;

View File

@ -3,24 +3,25 @@ import * as api from '../api';
import {eventChannel} from 'redux-saga';
import {all, call, fork, put, takeEvery, take} from 'redux-saga/effects';
const {account, accounts, block, blocks, transaction, transactions, processes} = actions;
const {account, accounts, block, blocks, transaction, transactions, processes, commands} = actions;
function *fetchEntity(entity, apiFn, id) {
const {response, error} = yield call(apiFn, id);
function *doRequest(entity, apiFn, payload) {
const {response, error} = yield call(apiFn, payload);
if(response) {
yield put(entity.success(response));
} else {
} else if (error) {
yield put(entity.failure(error));
}
}
export const fetchAccount = fetchEntity.bind(null, account, api.fetchAccount);
export const fetchBlock = fetchEntity.bind(null, block, api.fetchBlock);
export const fetchTransaction = fetchEntity.bind(null, transaction, api.fetchTransaction);
export const fetchAccounts = fetchEntity.bind(null, accounts, api.fetchAccounts);
export const fetchBlocks = fetchEntity.bind(null, blocks, api.fetchBlocks);
export const fetchTransactions = fetchEntity.bind(null, transactions, api.fetchTransactions);
export const fetchProcesses = fetchEntity.bind(null, processes, api.fetchProcesses);
export const fetchAccount = doRequest.bind(null, account, api.fetchAccount);
export const fetchBlock = doRequest.bind(null, block, api.fetchBlock);
export const fetchTransaction = doRequest.bind(null, transaction, api.fetchTransaction);
export const fetchAccounts = doRequest.bind(null, accounts, api.fetchAccounts);
export const fetchBlocks = doRequest.bind(null, blocks, api.fetchBlocks);
export const fetchTransactions = doRequest.bind(null, transactions, api.fetchTransactions);
export const fetchProcesses = doRequest.bind(null, processes, api.fetchProcesses);
export const postCommand = doRequest.bind(null, commands, api.postCommand);
export function *watchFetchTransaction() {
yield takeEvery(actions.TRANSACTION[actions.REQUEST], fetchTransaction);
@ -50,6 +51,10 @@ export function *watchFetchProcesses() {
yield takeEvery(actions.PROCESSES[actions.REQUEST], fetchProcesses);
}
export function *watchPostCommand() {
yield takeEvery(actions.COMMANDS[actions.REQUEST], postCommand);
}
export function *fetchProcessLogs(action) {
try {
const logs = yield call(api.fetchProcessLogs, action.processName);
@ -112,6 +117,7 @@ export default function *root() {
fork(watchFetchBlocks),
fork(watchFetchBlock),
fork(watchFetchTransactions),
fork(watchFetchTransaction)
fork(watchFetchTransaction),
fork(watchPostCommand)
]);
}