mirror of https://github.com/embarklabs/embark.git
Adding new reducer and selector
This commit is contained in:
parent
bb844caa48
commit
1bd5174f61
|
@ -1,4 +1,3 @@
|
|||
// Accounts
|
||||
export const REQUEST = 'REQUEST';
|
||||
export const SUCCESS = 'SUCCESS';
|
||||
export const FAILURE = 'FAILURE';
|
||||
|
@ -24,7 +23,7 @@ export const accounts = {
|
|||
export const ACCOUNT = createRequestTypes('ACCOUNT');
|
||||
export const account = {
|
||||
request: (address) => action(ACCOUNT[REQUEST], {address}),
|
||||
success: (account) => action(ACCOUNT[SUCCESS], {account}),
|
||||
success: (account) => action(ACCOUNT[SUCCESS], {accounts: [account]}),
|
||||
failure: (error) => action(ACCOUNT[FAILURE], {error})
|
||||
};
|
||||
|
||||
|
@ -38,7 +37,7 @@ export const blocks = {
|
|||
export const BLOCK = createRequestTypes('BLOCK');
|
||||
export const block = {
|
||||
request: (blockNumber) => action(BLOCK[REQUEST], {blockNumber}),
|
||||
success: (block) => action(BLOCK[SUCCESS], {block}),
|
||||
success: (block) => action(BLOCK[SUCCESS], {blocks: [block]}),
|
||||
failure: (error) => action(BLOCK[FAILURE], {error})
|
||||
};
|
||||
|
||||
|
@ -52,7 +51,7 @@ export const transactions = {
|
|||
export const TRANSACTION = createRequestTypes('TRANSACTION');
|
||||
export const transaction = {
|
||||
request: (hash) => action(TRANSACTION[REQUEST], {hash}),
|
||||
success: (transaction) => action(TRANSACTION[SUCCESS], {transaction}),
|
||||
success: (transaction) => action(TRANSACTION[SUCCESS], {transactions: [transaction]}),
|
||||
failure: (error) => action(TRANSACTION[FAILURE], {error})
|
||||
};
|
||||
|
||||
|
@ -66,37 +65,41 @@ export const processes = {
|
|||
export const COMMANDS = createRequestTypes('COMMANDS');
|
||||
export const commands = {
|
||||
post: (command) => action(COMMANDS[REQUEST], {command}),
|
||||
success: (result) => action(COMMANDS[SUCCESS], {result}),
|
||||
success: (command) => action(COMMANDS[SUCCESS], {commands: [command]}),
|
||||
failure: (error) => action(COMMANDS[FAILURE], {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';
|
||||
// Contracts
|
||||
export const FETCH_CONTRACTS = 'FETCH_CONTRACTS';
|
||||
export const RECEIVE_CONTRACTS = 'RECEIVE_CONTRACTS';
|
||||
export const RECEIVE_CONTRACTS_ERROR = 'RECEIVE_CONTRACTS_ERROR';
|
||||
// Contract
|
||||
export const FETCH_CONTRACT = 'FETCH_CONTRACT';
|
||||
export const RECEIVE_CONTRACT = 'RECEIVE_CONTRACT';
|
||||
export const RECEIVE_CONTRACT_ERROR = 'RECEIVE_CONTRACT_ERROR';
|
||||
// Contract Profile
|
||||
export const FETCH_CONTRACT_PROFILE = 'FETCH_CONTRACT_PROFILE';
|
||||
export const RECEIVE_CONTRACT_PROFILE = 'RECEIVE_CONTRACT_PROFILE';
|
||||
export const RECEIVE_CONTRACT_PROFILE_ERROR = 'RECEIVE_CONTRACT_PROFILE_ERROR';
|
||||
export const PROCESS_LOGS = createRequestTypes('PROCESS_LOGS');
|
||||
export const processLogs = {
|
||||
request: (processName) => action(PROCESS_LOGS[REQUEST], {processName}),
|
||||
success: (processLogs) => action(PROCESS_LOGS[SUCCESS], {processLogs}),
|
||||
failure: (error) => action(PROCESS_LOGS[FAILURE], {error})
|
||||
};
|
||||
|
||||
export function fetchProcessLogs(processName) {
|
||||
return {
|
||||
type: FETCH_PROCESS_LOGS,
|
||||
processName
|
||||
};
|
||||
}
|
||||
export const CONTRACTS = createRequestTypes('CONTRACTS');
|
||||
export const contracts = {
|
||||
request: () => action(CONTRACTS[REQUEST]),
|
||||
success: (contracts) => action(CONTRACTS[SUCCESS], {contracts}),
|
||||
failure: (error) => action(CONTRACTS[FAILURE], {error})
|
||||
};
|
||||
|
||||
export const CONTRACT = createRequestTypes('CONTRACT');
|
||||
export const contract = {
|
||||
request: (contractName) => action(CONTRACT[REQUEST], {contractName}),
|
||||
success: (contract) => action(CONTRACT[SUCCESS], {contracts: [contract]}),
|
||||
failure: (error) => action(CONTRACT[FAILURE], {error})
|
||||
};
|
||||
|
||||
export const CONTRACT_PROFILE = createRequestTypes('CONTRACT_PROFILE');
|
||||
export const contractProfile = {
|
||||
request: (contractName) => action(CONTRACT_PROFILE[REQUEST], {contractName}),
|
||||
success: (contractProfile) => action(CONTRACT_PROFILE[SUCCESS], {contractProfiles: [contractProfile]}),
|
||||
failure: (error) => action(CONTRACT_PROFILE[FAILURE], {error})
|
||||
};
|
||||
|
||||
// Web Socket
|
||||
export const WATCH_NEW_PROCESS_LOGS = 'WATCH_NEW_PROCESS_LOGS';
|
||||
export const INIT_BLOCK_HEADER = 'INIT_BLOCK_HEADER';
|
||||
|
||||
export function listenToProcessLogs(processName) {
|
||||
return {
|
||||
|
@ -105,84 +108,8 @@ export function listenToProcessLogs(processName) {
|
|||
};
|
||||
}
|
||||
|
||||
export function receiveProcessLogs(processName, logs) {
|
||||
return {
|
||||
type: RECEIVE_PROCESS_LOGS,
|
||||
processName,
|
||||
logs
|
||||
};
|
||||
}
|
||||
|
||||
export function receiveProcessLogsError(error) {
|
||||
return {
|
||||
type: RECEIVE_PROCESS_LOGS_ERROR,
|
||||
error
|
||||
};
|
||||
}
|
||||
|
||||
export function initBlockHeader(){
|
||||
return {
|
||||
type: INIT_BLOCK_HEADER
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchContractProfile(contractName) {
|
||||
return {
|
||||
type: FETCH_CONTRACT_PROFILE,
|
||||
contractName
|
||||
};
|
||||
}
|
||||
|
||||
export function receiveContractProfile(contractProfile) {
|
||||
return {
|
||||
type: RECEIVE_CONTRACT_PROFILE,
|
||||
contractProfile
|
||||
};
|
||||
}
|
||||
|
||||
export function receiveContractProfileError() {
|
||||
return {
|
||||
type: RECEIVE_CONTRACT_PROFILE_ERROR
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchContract(contractName) {
|
||||
return {
|
||||
type: FETCH_CONTRACT,
|
||||
contractName
|
||||
};
|
||||
}
|
||||
|
||||
export function receiveContract(contract) {
|
||||
return {
|
||||
type: RECEIVE_CONTRACT,
|
||||
contract
|
||||
};
|
||||
}
|
||||
|
||||
export function receiveContractError() {
|
||||
return {
|
||||
type: RECEIVE_CONTRACT_ERROR
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export function fetchContracts() {
|
||||
return {
|
||||
type: FETCH_CONTRACTS
|
||||
};
|
||||
}
|
||||
|
||||
export function receiveContracts(contracts) {
|
||||
return {
|
||||
type: RECEIVE_CONTRACTS,
|
||||
contracts
|
||||
};
|
||||
}
|
||||
|
||||
export function receiveContractsError() {
|
||||
return {
|
||||
type: RECEIVE_CONTRACTS_ERROR
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -53,8 +53,20 @@ export function fetchProcesses() {
|
|||
return get('/processes');
|
||||
}
|
||||
|
||||
export function fetchProcessLogs(processName) {
|
||||
return axios.get(`${constants.httpEndpoint}/process-logs/${processName}`);
|
||||
export function fetchProcessLogs(payload) {
|
||||
return get(`/process-logs/${payload.processName}`);
|
||||
}
|
||||
|
||||
export function fetchContracts() {
|
||||
return get('/contracts');
|
||||
}
|
||||
|
||||
export function fetchContract(payload) {
|
||||
return get(`/contract/${payload.contractName}`);
|
||||
}
|
||||
|
||||
export function fetchContractProfile(payload) {
|
||||
return get(`/profiler/${payload.contractName}`);
|
||||
}
|
||||
|
||||
export function webSocketProcess(processName) {
|
||||
|
@ -64,15 +76,3 @@ export function webSocketProcess(processName) {
|
|||
export function webSocketBlockHeader() {
|
||||
return new WebSocket(`${constants.wsEndpoint}/blockchain/blockHeader`);
|
||||
}
|
||||
|
||||
export function fetchContract(contractName) {
|
||||
return axios.get(`${constants.httpEndpoint}/contract/${contractName}`);
|
||||
}
|
||||
|
||||
export function fetchContracts() {
|
||||
return axios.get(`${constants.httpEndpoint}/contracts`);
|
||||
}
|
||||
|
||||
export function fetchContractProfile(contractName) {
|
||||
return axios.get(`${constants.httpEndpoint}/profiler/${contractName}`);
|
||||
}
|
||||
|
|
|
@ -36,8 +36,7 @@ class Console extends Component {
|
|||
</Card.Header>
|
||||
<Card.Body>
|
||||
<div>
|
||||
{this.props.commandResults &&
|
||||
this.props.commandResults.map((result) => <CommandResult key={result} result={result} />)}
|
||||
{this.props.commands.map((command, index) => <CommandResult key={index} result={command.result} />)}
|
||||
</div>
|
||||
<Form onSubmit={(event) => this.handleSubmit(event)}>
|
||||
<Form.Input value={this.state.value}
|
||||
|
@ -55,7 +54,7 @@ class Console extends Component {
|
|||
|
||||
Console.propTypes = {
|
||||
postCommand: PropTypes.func,
|
||||
commandResults: PropTypes.arrayOf(PropTypes.string)
|
||||
commands: PropTypes.arrayOf(PropTypes.object)
|
||||
};
|
||||
|
||||
export default Console;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import PropTypes from "prop-types";
|
||||
import React from 'react';
|
||||
import {
|
||||
Page,
|
||||
|
@ -33,5 +34,9 @@ const Contract = ({contract}) => (
|
|||
</Page.Content>
|
||||
);
|
||||
|
||||
Contract.propTypes = {
|
||||
contract: PropTypes.object
|
||||
};
|
||||
|
||||
export default Contract;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import PropTypes from "prop-types";
|
||||
import React from 'react';
|
||||
import {NavLink, Route, Switch, withRouter} from 'react-router-dom';
|
||||
import {
|
||||
|
@ -59,4 +60,8 @@ const ContractLayout = (props) => (
|
|||
</Grid.Row>
|
||||
);
|
||||
|
||||
ContractLayout.propTypes = {
|
||||
match: PropTypes.object
|
||||
};
|
||||
|
||||
export default withRouter(ContractLayout);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import PropTypes from "prop-types";
|
||||
import React from 'react';
|
||||
import {
|
||||
Page,
|
||||
|
@ -6,8 +7,8 @@ import {
|
|||
Table
|
||||
} from "tabler-react";
|
||||
|
||||
const ContractProfile = ({contract}) => (
|
||||
<Page.Content title={contract.name}>
|
||||
const ContractProfile = ({contractProfile}) => (
|
||||
<Page.Content title={contractProfile.name}>
|
||||
<Grid.Row>
|
||||
<Grid.Col>
|
||||
<Card>
|
||||
|
@ -23,7 +24,7 @@ const ContractProfile = ({contract}) => (
|
|||
{content: "Gas Estimates"}
|
||||
]}
|
||||
bodyItems={
|
||||
contract.methods.map((method) => {
|
||||
contractProfile.methods.map((method) => {
|
||||
return ([
|
||||
{content: method.name},
|
||||
{content: (method.payable === true).toString()},
|
||||
|
@ -41,5 +42,9 @@ const ContractProfile = ({contract}) => (
|
|||
</Page.Content>
|
||||
);
|
||||
|
||||
ContractProfile.propTypes = {
|
||||
contractProfile: PropTypes.object
|
||||
};
|
||||
|
||||
export default ContractProfile;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import PropTypes from "prop-types";
|
||||
import React from 'react';
|
||||
import {
|
||||
Page,
|
||||
|
@ -25,7 +26,7 @@ const Contracts = ({contracts}) => (
|
|||
return ([
|
||||
{content: <Link to={`contracts/${contract.name}`}>{contract.name}</Link>},
|
||||
{content: contract.address},
|
||||
{content: contract.deploy}
|
||||
{content: contract.deploy.toString()}
|
||||
]);
|
||||
})
|
||||
}
|
||||
|
@ -36,5 +37,9 @@ const Contracts = ({contracts}) => (
|
|||
</Page.Content>
|
||||
);
|
||||
|
||||
Contracts.propTypes = {
|
||||
contracts: PropTypes.arrayOf(PropTypes.object)
|
||||
};
|
||||
|
||||
export default Contracts;
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from "react";
|
||||
|
||||
import Loading from '../components/Loading';
|
||||
import Error from '../components/Error';
|
||||
|
||||
const DataWrapper = ({error, loading, shouldRender, render, ...rest}) => {
|
||||
if (error) {
|
||||
return <Error error={error} />;
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
if (shouldRender) {
|
||||
return render(rest);
|
||||
}
|
||||
|
||||
return <React.Fragment />;
|
||||
};
|
||||
|
||||
DataWrapper.propTypes = {
|
||||
error: PropTypes.string,
|
||||
loading: PropTypes.bool,
|
||||
render: PropTypes.func,
|
||||
shouldRender: PropTypes.bool
|
||||
};
|
||||
|
||||
export default DataWrapper;
|
|
@ -1,30 +1,26 @@
|
|||
import React, {Component} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {Page} from "tabler-react";
|
||||
import Loading from "./Loading";
|
||||
|
||||
class Process extends Component {
|
||||
render() {
|
||||
const logs = this.props.logs;
|
||||
const {processLogs, process}= this.props;
|
||||
return (
|
||||
<Page.Content className="text-capitalize" title={this.props.processName}>
|
||||
<p className="text-capitalize">State: {this.props.state}</p>
|
||||
{!logs &&
|
||||
<Loading/>}
|
||||
{logs &&
|
||||
<Page.Content className="text-capitalize" title={process.name}>
|
||||
<p className="text-capitalize">State: {process.state}</p>
|
||||
<div className="logs">
|
||||
{
|
||||
logs.map((item, i) => <p key={i} className={item.logLevel}>{item.msg_clear || item.msg}</p>)
|
||||
processLogs.map((item, i) => <p key={i} className={item.logLevel}>{item.msg_clear || item.msg}</p>)
|
||||
}
|
||||
</div>}
|
||||
</Page.Content>);
|
||||
</div>
|
||||
</Page.Content>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Process.propTypes = {
|
||||
processName: PropTypes.string.isRequired,
|
||||
state: PropTypes.string.isRequired,
|
||||
logs: PropTypes.array
|
||||
process: PropTypes.object,
|
||||
processLogs: PropTypes.arrayOf(PropTypes.object)
|
||||
};
|
||||
|
||||
export default Process;
|
||||
|
|
|
@ -11,15 +11,15 @@ function stampClasses(state){
|
|||
});
|
||||
}
|
||||
|
||||
const Process = ({name, state}) => (
|
||||
const Process = ({process}) => (
|
||||
<Grid.Col sm={6} lg={3}>
|
||||
<Card className="p-3">
|
||||
<div className="d-flex align-items-center">
|
||||
<span className={stampClasses(state)}>
|
||||
<span className={stampClasses(process.state)}>
|
||||
<i className="fe fa-cube"></i>
|
||||
</span>
|
||||
<div>
|
||||
<h4 className="text-capitalize m-0"><Link to={`/embark/processes/${name}`}>{name}</Link></h4>
|
||||
<h4 className="text-capitalize m-0"><Link to={`/embark/processes/${process.name}`}>{process.name}</Link></h4>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
@ -27,18 +27,17 @@ const Process = ({name, state}) => (
|
|||
);
|
||||
|
||||
Process.propTypes = {
|
||||
name: PropTypes.string,
|
||||
state: PropTypes.string
|
||||
process: PropTypes.object
|
||||
};
|
||||
|
||||
const Processes = ({processes}) => (
|
||||
<Grid.Row cards>
|
||||
{Object.keys(processes).map((name) => <Process key={name} name={name} state={processes[name].state} />)}
|
||||
{processes.map((process) => <Process key={process.name} process={process} />)}
|
||||
</Grid.Row>
|
||||
);
|
||||
|
||||
Processes.propTypes = {
|
||||
processes: PropTypes.object
|
||||
processes: PropTypes.arrayOf(PropTypes.object)
|
||||
};
|
||||
|
||||
export default Processes;
|
||||
|
|
|
@ -1,40 +1,38 @@
|
|||
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 {NavLink, Route, Switch, withRouter, Redirect} from 'react-router-dom';
|
||||
import {
|
||||
Page,
|
||||
Grid,
|
||||
List
|
||||
} from "tabler-react";
|
||||
|
||||
import ProcessesContainer from '../containers/ProcessesContainer';
|
||||
import ProcessContainer from '../containers/ProcessContainer';
|
||||
import {getProcesses} from "../reducers/selectors";
|
||||
import Loading from "./Loading";
|
||||
|
||||
const routePrefix = '/embark/processes';
|
||||
|
||||
class ProcessesLayout extends Component {
|
||||
|
||||
|
||||
render() {
|
||||
if (!this.props.processes || !this.props.processes.data) {
|
||||
if (this.props.processes.length === 0) {
|
||||
return <Loading />;
|
||||
}
|
||||
const processNames = Object.keys(this.props.processes.data) || [];
|
||||
return (<Grid.Row>
|
||||
<Grid.Col md={3}>
|
||||
<Page.Title className="my-5">Processes</Page.Title>
|
||||
<div>
|
||||
<List.Group transparent={true}>
|
||||
{processNames.map((processName, index) => {
|
||||
{this.props.processes.map((process, index) => {
|
||||
return (<List.GroupItem
|
||||
className="d-flex align-items-center text-capitalize"
|
||||
to={`${routePrefix}/${processName}`}
|
||||
key={'process-' + processName}
|
||||
to={`${routePrefix}/${process.name}`}
|
||||
key={'process-' + process.name}
|
||||
active={index === 0 && this.props.match.isExact === true}
|
||||
RootComponent={withRouter(NavLink)}
|
||||
>
|
||||
{processName}
|
||||
{process.name}
|
||||
</List.GroupItem>);
|
||||
})}
|
||||
|
||||
|
@ -43,10 +41,8 @@ class ProcessesLayout extends Component {
|
|||
</Grid.Col>
|
||||
<Grid.Col md={9}>
|
||||
<Switch>
|
||||
<Route exact path={`${routePrefix}/`} component={ProcessesContainer} />
|
||||
{processNames.map((processName, index) => {
|
||||
return (<Route key={'procesRoute-' + index} exact path={`${routePrefix}/${processName}`} component={ProcessesContainer}/>);
|
||||
})}
|
||||
<Route exact path={`${routePrefix}/:processName`} component={() => <ProcessContainer />} />
|
||||
<Redirect exact from={`${routePrefix}/`} to={`${routePrefix}/${this.props.processes[0].name}`} />
|
||||
</Switch>
|
||||
</Grid.Col>
|
||||
</Grid.Row>);
|
||||
|
@ -54,12 +50,12 @@ class ProcessesLayout extends Component {
|
|||
}
|
||||
|
||||
ProcessesLayout.propTypes = {
|
||||
processes: PropTypes.object,
|
||||
processes: PropTypes.arrayOf(PropTypes.object),
|
||||
match: PropTypes.object
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {processes: state.processes};
|
||||
return {processes: getProcesses(state)};
|
||||
}
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -5,9 +5,9 @@ import {withRouter} from 'react-router-dom';
|
|||
|
||||
import {account as accountAction} from '../actions';
|
||||
import Account from '../components/Account';
|
||||
import NoMatch from "../components/NoMatch";
|
||||
import DataWrapper from "../components/DataWrapper";
|
||||
import Transactions from '../components/Transactions';
|
||||
import Error from '../components/Error';
|
||||
import {getAccount, getTransactionsByAccount} from "../reducers/selectors";
|
||||
|
||||
class AccountContainer extends Component {
|
||||
componentDidMount() {
|
||||
|
@ -15,37 +15,30 @@ class AccountContainer extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const {account, error} = this.props;
|
||||
if (error) {
|
||||
return <Error error={error} />;
|
||||
}
|
||||
|
||||
if (!account) {
|
||||
return <NoMatch />;
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Account account={account} />
|
||||
<Transactions transactions={account.transactions || []} />
|
||||
</React.Fragment>
|
||||
<DataWrapper shouldRender={this.props.account !== undefined } {...this.props} render={({account, transactions}) => (
|
||||
<React.Fragment>
|
||||
<Account account={account} />
|
||||
<Transactions transactions={transactions || []} />
|
||||
</React.Fragment>
|
||||
)} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state, props) {
|
||||
if(state.accounts.error) {
|
||||
return {error: state.accounts.error};
|
||||
}
|
||||
if(state.accounts.data) {
|
||||
return {account: state.accounts.data.find(account => account.address === props.match.params.address)};
|
||||
}
|
||||
return {};
|
||||
return {
|
||||
account: getAccount(state, props.match.params.address),
|
||||
transactions: getTransactionsByAccount(state, props.match.params.address),
|
||||
error: state.errorMessage,
|
||||
loading: state.loading
|
||||
};
|
||||
}
|
||||
|
||||
AccountContainer.propTypes = {
|
||||
match: PropTypes.object,
|
||||
account: PropTypes.object,
|
||||
transactions: PropTypes.arrayOf(PropTypes.object),
|
||||
fetchAccount: PropTypes.func,
|
||||
error: PropTypes.string
|
||||
};
|
||||
|
|
|
@ -4,8 +4,8 @@ import PropTypes from 'prop-types';
|
|||
|
||||
import {accounts as accountsAction} from '../actions';
|
||||
import Accounts from '../components/Accounts';
|
||||
import Loading from '../components/Loading';
|
||||
import Error from '../components/Error';
|
||||
import DataWrapper from "../components/DataWrapper";
|
||||
import {getAccounts} from "../reducers/selectors";
|
||||
|
||||
class AccountsContainer extends Component {
|
||||
componentDidMount() {
|
||||
|
@ -13,28 +13,23 @@ class AccountsContainer extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const {accounts} = this.props;
|
||||
if (accounts.error) {
|
||||
return <Error error={accounts.error} />;
|
||||
}
|
||||
|
||||
if (!accounts.data) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Accounts accounts={accounts.data} />
|
||||
<DataWrapper shouldRender={this.props.accounts.length > 0} {...this.props} render={({accounts}) => (
|
||||
<Accounts accounts={accounts} />
|
||||
)} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {accounts: state.accounts};
|
||||
return {accounts: getAccounts(state), error: state.errorMessage, loading: state.loading};
|
||||
}
|
||||
|
||||
AccountsContainer.propTypes = {
|
||||
accounts: PropTypes.object,
|
||||
fetchAccounts: PropTypes.func
|
||||
accounts: PropTypes.arrayOf(PropTypes.object),
|
||||
fetchAccounts: PropTypes.func,
|
||||
error: PropTypes.string,
|
||||
loading: PropTypes.bool
|
||||
};
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -5,9 +5,9 @@ import {withRouter} from 'react-router-dom';
|
|||
|
||||
import {block as blockAction} from '../actions';
|
||||
import Block from '../components/Block';
|
||||
import Error from "../components/Error";
|
||||
import NoMatch from "../components/NoMatch";
|
||||
import DataWrapper from "../components/DataWrapper";
|
||||
import Transactions from '../components/Transactions';
|
||||
import {getBlock, getTransactionsByBlock} from "../reducers/selectors";
|
||||
|
||||
class BlockContainer extends Component {
|
||||
componentDidMount() {
|
||||
|
@ -15,36 +15,30 @@ class BlockContainer extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const {block, error} = this.props;
|
||||
if (error) {
|
||||
return <Error error={error} />;
|
||||
}
|
||||
if (!block) {
|
||||
return <NoMatch />;
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Block block={block} />
|
||||
<Transactions transactions={block.transactions} />
|
||||
</React.Fragment>
|
||||
<DataWrapper shouldRender={this.props.block !== undefined } {...this.props} render={({block, transactions}) => (
|
||||
<React.Fragment>
|
||||
<Block block={block} />
|
||||
<Transactions transactions={transactions || []} />
|
||||
</React.Fragment>
|
||||
)} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state, props) {
|
||||
if(state.blocks.error) {
|
||||
return {error: state.blocks.error};
|
||||
}
|
||||
if(state.blocks.data) {
|
||||
return {block: state.blocks.data.find(block => block.number.toString() === props.match.params.blockNumber)};
|
||||
}
|
||||
return {};
|
||||
return {
|
||||
block: getBlock(state, props.match.params.blockNumber),
|
||||
transactions: getTransactionsByBlock(state, props.match.params.blockNumber),
|
||||
error: state.errorMessage,
|
||||
loading: state.loading
|
||||
};
|
||||
}
|
||||
|
||||
BlockContainer.propTypes = {
|
||||
match: PropTypes.object,
|
||||
block: PropTypes.object,
|
||||
transactions: PropTypes.arrayOf(PropTypes.object),
|
||||
fetchBlock: PropTypes.func,
|
||||
error: PropTypes.string
|
||||
};
|
||||
|
|
|
@ -4,9 +4,9 @@ import PropTypes from 'prop-types';
|
|||
|
||||
import {blocks as blocksAction} from '../actions';
|
||||
import Blocks from '../components/Blocks';
|
||||
import Loading from '../components/Loading';
|
||||
import LoadMore from '../components/LoadMore';
|
||||
import Error from '../components/Error';
|
||||
import DataWrapper from "../components/DataWrapper";
|
||||
import LoadMore from "../components/LoadMore";
|
||||
import {getBlocks} from "../reducers/selectors";
|
||||
|
||||
class BlocksContainer extends Component {
|
||||
componentDidMount() {
|
||||
|
@ -18,23 +18,19 @@ class BlocksContainer extends Component {
|
|||
}
|
||||
|
||||
loadMoreFrom() {
|
||||
let blocks = this.props.blocks.data;
|
||||
let blocks = this.props.blocks;
|
||||
if (blocks.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
return blocks[blocks.length - 1].number - 1;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {blocks} = this.props;
|
||||
if (blocks.error) {
|
||||
return <Error error={blocks.error} />;
|
||||
}
|
||||
|
||||
if (!blocks.data) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Blocks blocks={blocks.data}/>
|
||||
<DataWrapper shouldRender={this.props.blocks.length > 0} {...this.props} render={({blocks}) => (
|
||||
<Blocks blocks={blocks} />
|
||||
)} />
|
||||
{(this.loadMoreFrom() >= 0) ? <LoadMore loadMore={() => this.loadMore()} /> : <React.Fragment />}
|
||||
</React.Fragment>
|
||||
);
|
||||
|
@ -42,12 +38,14 @@ class BlocksContainer extends Component {
|
|||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {blocks: state.blocks};
|
||||
return {blocks: getBlocks(state), error: state.errorMessage, loading: state.loading};
|
||||
}
|
||||
|
||||
BlocksContainer.propTypes = {
|
||||
blocks: PropTypes.object,
|
||||
fetchBlocks: PropTypes.func
|
||||
blocks: PropTypes.arrayOf(PropTypes.object),
|
||||
fetchBlocks: PropTypes.func,
|
||||
error: PropTypes.string,
|
||||
loading: PropTypes.bool
|
||||
};
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -1,48 +1,45 @@
|
|||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { compose } from 'redux';
|
||||
import { fetchContract } from '../actions';
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import {withRouter} from 'react-router-dom';
|
||||
|
||||
import {contract as contractAction} from '../actions';
|
||||
import Contract from '../components/Contract';
|
||||
import { withRouter } from 'react-router'
|
||||
import DataWrapper from "../components/DataWrapper";
|
||||
import {getContract} from "../reducers/selectors";
|
||||
|
||||
class ContractContainer extends Component {
|
||||
componentWillMount() {
|
||||
componentDidMount() {
|
||||
this.props.fetchContract(this.props.match.params.contractName);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {contract} = this.props;
|
||||
if (!contract.data) {
|
||||
return (
|
||||
<h1>
|
||||
<i>Loading contract...</i>
|
||||
</h1>
|
||||
);
|
||||
}
|
||||
|
||||
if (contract.error) {
|
||||
return (
|
||||
<h1>
|
||||
<i>Error API...</i>
|
||||
</h1>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Contract contract={contract.data} />
|
||||
<DataWrapper shouldRender={this.props.contract !== undefined } {...this.props} render={({contract}) => (
|
||||
<Contract contract={contract} />
|
||||
)} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state, props) {
|
||||
return {
|
||||
contract: getContract(state, props.match.params.contractName),
|
||||
error: state.errorMessage,
|
||||
loading: state.loading
|
||||
};
|
||||
}
|
||||
|
||||
ContractContainer.propTypes = {
|
||||
match: PropTypes.object,
|
||||
contract: PropTypes.object,
|
||||
fetchContract: PropTypes.func,
|
||||
error: PropTypes.string
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return { contract: state.contract }
|
||||
};
|
||||
|
||||
export default compose(
|
||||
connect(
|
||||
mapStateToProps,
|
||||
{fetchContract}
|
||||
),
|
||||
withRouter
|
||||
)(ContractContainer);
|
||||
|
||||
export default withRouter(connect(
|
||||
mapStateToProps,
|
||||
{
|
||||
fetchContract: contractAction.request
|
||||
}
|
||||
)(ContractContainer));
|
||||
|
|
|
@ -1,48 +1,45 @@
|
|||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { compose } from 'redux';
|
||||
import { fetchContractProfile } from '../actions';
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import {withRouter} from 'react-router-dom';
|
||||
|
||||
import {contractProfile as contractProfileAction} from '../actions';
|
||||
import ContractProfile from '../components/ContractProfile';
|
||||
import { withRouter } from 'react-router';
|
||||
import DataWrapper from "../components/DataWrapper";
|
||||
import {getContractProfile} from "../reducers/selectors";
|
||||
|
||||
class ContractProfileContainer extends Component {
|
||||
componentWillMount() {
|
||||
componentDidMount() {
|
||||
this.props.fetchContractProfile(this.props.match.params.contractName);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { contractProfile } = this.props;
|
||||
if (!contractProfile.data) {
|
||||
return (
|
||||
<h1>
|
||||
<i>Loading contract profile...</i>
|
||||
</h1>
|
||||
);
|
||||
}
|
||||
|
||||
if (contractProfile.data.error) {
|
||||
return (
|
||||
<h1>
|
||||
<i>Error API...</i>
|
||||
</h1>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ContractProfile contract={contractProfile.data} />
|
||||
<DataWrapper shouldRender={this.props.contractProfile !== undefined } {...this.props} render={({contractProfile}) => (
|
||||
<ContractProfile contractProfile={contractProfile} />
|
||||
)} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return { contractProfile: state.contractProfile };
|
||||
function mapStateToProps(state, props) {
|
||||
return {
|
||||
contractProfile: getContractProfile(state, props.match.params.contractName),
|
||||
error: state.errorMessage,
|
||||
loading: state.loading
|
||||
};
|
||||
}
|
||||
|
||||
export default compose(
|
||||
connect(
|
||||
mapStateToProps,
|
||||
{ fetchContractProfile }
|
||||
),
|
||||
withRouter
|
||||
)(ContractProfileContainer);
|
||||
ContractProfileContainer.propTypes = {
|
||||
match: PropTypes.object,
|
||||
contractProfile: PropTypes.object,
|
||||
fetchContractProfile: PropTypes.func,
|
||||
error: PropTypes.string
|
||||
};
|
||||
|
||||
export default withRouter(connect(
|
||||
mapStateToProps,
|
||||
{
|
||||
fetchContractProfile: contractProfileAction.request
|
||||
}
|
||||
)(ContractProfileContainer));
|
||||
|
|
|
@ -1,45 +1,38 @@
|
|||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { fetchContracts } from '../actions';
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {contracts as contractsAction} from '../actions';
|
||||
import Contracts from '../components/Contracts';
|
||||
import DataWrapper from "../components/DataWrapper";
|
||||
import {getContracts} from "../reducers/selectors";
|
||||
|
||||
class ContractsContainer extends Component {
|
||||
componentWillMount() {
|
||||
componentDidMount() {
|
||||
this.props.fetchContracts();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { contracts } = this.props;
|
||||
if (!contracts.data) {
|
||||
return (
|
||||
<h1>
|
||||
<i>Loading contracts...</i>
|
||||
</h1>
|
||||
);
|
||||
}
|
||||
|
||||
if (contracts.error) {
|
||||
return (
|
||||
<h1>
|
||||
<i>Error API...</i>
|
||||
</h1>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Contracts contracts={contracts.data} />
|
||||
<DataWrapper shouldRender={this.props.contracts.length > 0} {...this.props} render={({contracts}) => (
|
||||
<Contracts contracts={contracts} />
|
||||
)} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return { contracts: state.contracts };
|
||||
return {contracts: getContracts(state), error: state.errorMessage, loading: state.loading};
|
||||
}
|
||||
|
||||
ContractsContainer.propTypes = {
|
||||
contracts: PropTypes.object,
|
||||
fetchContracts: PropTypes.func
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{
|
||||
fetchContracts
|
||||
fetchContracts: contractsAction.request
|
||||
},
|
||||
)(ContractsContainer);
|
||||
|
||||
|
|
|
@ -2,31 +2,40 @@ 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 {commands as commandsAction} from "../actions";
|
||||
import DataWrapper from "../components/DataWrapper";
|
||||
import Processes from '../components/Processes';
|
||||
import Console from '../components/Console';
|
||||
import {getProcesses, getCommands} from "../reducers/selectors";
|
||||
|
||||
class HomeContainer extends Component {
|
||||
render() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Page.Title className="my-5">Dashboard</Page.Title>
|
||||
{this.props.processes.data && <Processes processes={this.props.processes.data} />}
|
||||
<Console postCommand={this.props.postCommand} commandResults={this.props.commandResults} />
|
||||
<DataWrapper shouldRender={this.props.processes.length > 0 } {...this.props} render={({processes}) => (
|
||||
<Processes processes={processes} />
|
||||
)} />
|
||||
<Console postCommand={this.props.postCommand} commands={this.props.commands} />
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
HomeContainer.propTypes = {
|
||||
processes: PropTypes.object,
|
||||
processes: PropTypes.arrayOf(PropTypes.object),
|
||||
postCommand: PropTypes.func,
|
||||
commandResults: PropTypes.arrayOf(PropTypes.string)
|
||||
commands: PropTypes.arrayOf(PropTypes.object)
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {processes: state.processes, commandResults: state.commands.results};
|
||||
return {
|
||||
processes: getProcesses(state),
|
||||
commands: getCommands(state),
|
||||
error: state.errorMessage,
|
||||
loading: state.loading
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import {withRouter} from "react-router-dom";
|
||||
import {processLogs as processLogsAction, listenToProcessLogs} from '../actions';
|
||||
import DataWrapper from "../components/DataWrapper";
|
||||
import Process from "../components/Process";
|
||||
import {getProcess, getProcessLogsByProcess} from "../reducers/selectors";
|
||||
|
||||
class ProcessContainer extends Component {
|
||||
componentDidMount() {
|
||||
if (this.props.process.state === 'running' && this.props.processLogs.length === 0) {
|
||||
this.props.fetchProcessLogs(this.props.match.params.processName);
|
||||
this.props.listenToProcessLogs(this.props.match.params.processName);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<DataWrapper shouldRender={this.props.process !== undefined } {...this.props} render={({process, processLogs}) => (
|
||||
<div className="processes-container">
|
||||
<Process process={process}
|
||||
processLogs={processLogs}/>
|
||||
</div>
|
||||
)} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ProcessContainer.propTypes = {
|
||||
fetchProcessLogs: PropTypes.func,
|
||||
listenToProcessLogs: PropTypes.func,
|
||||
process: PropTypes.object,
|
||||
processLogs: PropTypes.arrayOf(PropTypes.object),
|
||||
error: PropTypes.string,
|
||||
loading: PropTypes.bool,
|
||||
match: PropTypes.object
|
||||
};
|
||||
|
||||
function mapStateToProps(state, props) {
|
||||
return {
|
||||
process: getProcess(state, props.match.params.processName),
|
||||
processLogs: getProcessLogsByProcess(state, props.match.params.processName),
|
||||
error: state.errorMessage,
|
||||
loading: state.loading
|
||||
};
|
||||
}
|
||||
|
||||
export default withRouter(connect(
|
||||
mapStateToProps,
|
||||
{
|
||||
fetchProcessLogs: processLogsAction.request,
|
||||
listenToProcessLogs
|
||||
}
|
||||
)(ProcessContainer));
|
|
@ -1,58 +0,0 @@
|
|||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import {fetchProcessLogs, listenToProcessLogs} from '../actions';
|
||||
|
||||
import Process from "../components/Process";
|
||||
|
||||
class ProcessesContainer extends Component {
|
||||
componentDidMount() {
|
||||
// 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() {
|
||||
if (!this.processName) {
|
||||
return '';
|
||||
}
|
||||
return (
|
||||
<div className="processes-container">
|
||||
<Process processName={this.processName}
|
||||
state={this.props.processes.data[this.processName].state}
|
||||
logs={this.props.processes.data[this.processName].logs}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ProcessesContainer.propTypes = {
|
||||
match: PropTypes.object,
|
||||
processes: PropTypes.object,
|
||||
fetchProcessLogs: PropTypes.func,
|
||||
listenToProcessLogs: PropTypes.func
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {processes: state.processes};
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{
|
||||
fetchProcessLogs,
|
||||
listenToProcessLogs
|
||||
}
|
||||
)(ProcessesContainer);
|
|
@ -4,9 +4,9 @@ import PropTypes from 'prop-types';
|
|||
import {withRouter} from 'react-router-dom';
|
||||
|
||||
import {transaction as transactionAction} from '../actions';
|
||||
import Error from "../components/Error";
|
||||
import NoMatch from "../components/NoMatch";
|
||||
import Transaction from '../components/Transaction';
|
||||
import DataWrapper from "../components/DataWrapper";
|
||||
import {getTransaction} from "../reducers/selectors";
|
||||
|
||||
class TransactionContainer extends Component {
|
||||
componentDidMount() {
|
||||
|
@ -14,35 +14,26 @@ class TransactionContainer extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const {transaction, error} = this.props;
|
||||
if (error) {
|
||||
return <Error error={error} />;
|
||||
}
|
||||
if (!transaction) {
|
||||
return <NoMatch />;
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<DataWrapper shouldRender={this.props.transaction !== undefined } {...this.props} render={({transaction}) => (
|
||||
<Transaction transaction={transaction} />
|
||||
</React.Fragment>
|
||||
)} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state, props) {
|
||||
if(state.transactions.error) {
|
||||
return {error: state.transactions.error};
|
||||
}
|
||||
if(state.transactions.data) {
|
||||
return {transaction: state.transactions.data.find(transaction => transaction.hash === props.match.params.hash)};
|
||||
}
|
||||
return {};
|
||||
return {
|
||||
transaction: getTransaction(state, props.match.params.hash),
|
||||
error: state.errorMessage,
|
||||
loading: state.loading
|
||||
};
|
||||
}
|
||||
|
||||
TransactionContainer.propTypes = {
|
||||
match: PropTypes.object,
|
||||
transaction: PropTypes.object,
|
||||
transactions: PropTypes.arrayOf(PropTypes.object),
|
||||
fetchTransaction: PropTypes.func,
|
||||
error: PropTypes.string
|
||||
};
|
||||
|
|
|
@ -3,10 +3,10 @@ import {connect} from 'react-redux';
|
|||
import PropTypes from 'prop-types';
|
||||
|
||||
import {transactions as transactionsAction} from '../actions';
|
||||
import LoadMore from "../components/LoadMore";
|
||||
import Transactions from '../components/Transactions';
|
||||
import Loading from '../components/Loading';
|
||||
import LoadMore from '../components/LoadMore';
|
||||
import Error from '../components/Error';
|
||||
import DataWrapper from "../components/DataWrapper";
|
||||
import {getTransactions} from "../reducers/selectors";
|
||||
|
||||
class TransactionsContainer extends Component {
|
||||
componentDidMount() {
|
||||
|
@ -18,23 +18,19 @@ class TransactionsContainer extends Component {
|
|||
}
|
||||
|
||||
loadMoreFrom() {
|
||||
let transactions = this.props.transactions.data;
|
||||
let transactions = this.props.transactions;
|
||||
if (transactions.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
return transactions[transactions.length - 1].blockNumber - 1;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {transactions} = this.props;
|
||||
if (transactions.error) {
|
||||
return <Error error={transactions.error} />;
|
||||
}
|
||||
|
||||
if (!transactions.data) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Transactions transactions={transactions.data}/>
|
||||
<DataWrapper shouldRender={this.props.transactions.length > 0} {...this.props} render={({transactions}) => (
|
||||
<Transactions transactions={transactions} />
|
||||
)} />
|
||||
{(this.loadMoreFrom() > 0) ? <LoadMore loadMore={() => this.loadMore()} /> : <React.Fragment />}
|
||||
</React.Fragment>
|
||||
);
|
||||
|
@ -42,12 +38,14 @@ class TransactionsContainer extends Component {
|
|||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {transactions: state.transactions};
|
||||
return {transactions: getTransactions(state), error: state.errorMessage, loading: state.loading};
|
||||
}
|
||||
|
||||
TransactionsContainer.propTypes = {
|
||||
transactions: PropTypes.object,
|
||||
fetchTransactions: PropTypes.func
|
||||
fetchTransactions: PropTypes.func,
|
||||
error: PropTypes.string,
|
||||
loading: PropTypes.bool
|
||||
};
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
import * as actions from "../actions";
|
||||
|
||||
function filterAccount(account, index, self) {
|
||||
return index === self.findIndex((a) => a.address === account.address);
|
||||
}
|
||||
|
||||
export default function accounts(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case actions.ACCOUNTS[actions.SUCCESS]:
|
||||
return {
|
||||
...state, error: null, data: [...action.accounts.data, ...state.data || []]
|
||||
.filter(filterAccount)
|
||||
};
|
||||
case actions.ACCOUNTS[actions.FAILURE]:
|
||||
return Object.assign({}, state, {error: action.error});
|
||||
case actions.ACCOUNT[actions.SUCCESS]:
|
||||
return {
|
||||
...state, error: null, data: [action.account.data, ...state.data || []]
|
||||
.filter(filterAccount)
|
||||
};
|
||||
case actions.ACCOUNT[actions.FAILURE]:
|
||||
return Object.assign({}, state, {error: action.error});
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
import * as actions from "../actions";
|
||||
|
||||
function sortBlock(a, b) {
|
||||
return b.number - a.number;
|
||||
}
|
||||
|
||||
function filterBlock(block, index, self) {
|
||||
return index === self.findIndex((t) => t.number === block.number);
|
||||
}
|
||||
|
||||
export default function blocks(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case actions.BLOCKS[actions.SUCCESS]:
|
||||
return {
|
||||
...state, error: null, data: [...action.blocks.data, ...state.data || []]
|
||||
.filter(filterBlock)
|
||||
.sort(sortBlock)
|
||||
};
|
||||
case actions.BLOCKS[actions.FAILURE]:
|
||||
return Object.assign({}, state, {error: action.error});
|
||||
case actions.BLOCK[actions.SUCCESS]:
|
||||
return {
|
||||
...state, error: null, data: [action.block.data, ...state.data || []]
|
||||
.filter(filterBlock)
|
||||
.sort(sortBlock)
|
||||
};
|
||||
case actions.BLOCK[actions.FAILURE]:
|
||||
return Object.assign({}, state, {error: action.error});
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
import {RECEIVE_CONTRACT_PROFILE, RECEIVE_CONTRACT_PROFILE_ERROR} from "../actions";
|
||||
|
||||
export default function contractProfile(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case RECEIVE_CONTRACT_PROFILE:
|
||||
return Object.assign({}, state, {data: action.contractProfile.data});
|
||||
case RECEIVE_CONTRACT_PROFILE_ERROR:
|
||||
return Object.assign({}, state, {error: true});
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
import {RECEIVE_CONTRACT, RECEIVE_CONTRACT_ERROR} from "../actions";
|
||||
|
||||
export default function contract(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case RECEIVE_CONTRACT:
|
||||
return Object.assign({}, state, {data: action.contract.data});
|
||||
case RECEIVE_CONTRACT_ERROR:
|
||||
return Object.assign({}, state, {error: true});
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
import {RECEIVE_CONTRACTS, RECEIVE_CONTRACTS_ERROR} from "../actions";
|
||||
|
||||
export default function contracts(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case RECEIVE_CONTRACTS:
|
||||
return Object.assign({}, state, {data: action.contracts.data});
|
||||
case RECEIVE_CONTRACTS_ERROR:
|
||||
return Object.assign({}, state, {error: true});
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
|
@ -1,22 +1,89 @@
|
|||
import {combineReducers} from 'redux';
|
||||
import processesReducer from './processesReducer';
|
||||
import accountsReducer from './accountsReducer';
|
||||
import blocksReducer from './blocksReducer';
|
||||
import transactionsReducer from './transactionsReducer';
|
||||
import commandsReducer from './commandsReducer';
|
||||
import contractsReducer from './contractsReducer';
|
||||
import contractReducer from './contractReducer';
|
||||
import contractProfileReducer from './contractProfileReducer';
|
||||
import {REQUEST} from "../actions";
|
||||
|
||||
const BN_FACTOR = 10000;
|
||||
|
||||
const entitiesDefaultState = {
|
||||
accounts: [],
|
||||
blocks: [],
|
||||
transactions: [],
|
||||
processes: [],
|
||||
processLogs: [],
|
||||
contracts: [],
|
||||
contractProfiles: [],
|
||||
commands: []
|
||||
};
|
||||
|
||||
const sorter = {
|
||||
blocks: function(a, b) {
|
||||
return b.number - a.number;
|
||||
},
|
||||
transactions: function(a, b) {
|
||||
return ((BN_FACTOR * b.blockNumber) + b.transactionIndex) - ((BN_FACTOR * a.blockNumber) + a.transactionIndex);
|
||||
},
|
||||
processLogs: function(a, b) {
|
||||
return a.timestamp - b.timestamp;
|
||||
}
|
||||
};
|
||||
|
||||
const filtrer = {
|
||||
processes: function(process, index, self) {
|
||||
return index === self.findIndex((t) => t.name === process.name);
|
||||
},
|
||||
contracts: function(contract, index, self) {
|
||||
return index === self.findIndex((t) => t.name === contract.name);
|
||||
},
|
||||
accounts: function(account, index, self) {
|
||||
return index === self.findIndex((t) => t.address === account.address);
|
||||
},
|
||||
blocks: function(block, index, self) {
|
||||
return index === self.findIndex((t) => t.number === block.number);
|
||||
},
|
||||
transactions: function(tx, index, self) {
|
||||
return index === self.findIndex((t) => (
|
||||
t.blockNumber === tx.blockNumber && t.transactionIndex === tx.transactionIndex
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
function entities(state = entitiesDefaultState, action) {
|
||||
for (let name of Object.keys(state)) {
|
||||
let filter = filtrer[name] || (() => true);
|
||||
let sort = sorter[name] || (() => true);
|
||||
if (action[name] && action[name].length > 1) {
|
||||
return {...state, [name]: [...action[name], ...state[name]].filter(filter).sort(sort)};
|
||||
}
|
||||
if (action[name] && action[name].length === 1) {
|
||||
let entity = action[name][0];
|
||||
let nested = Object.keys(state).reduce((acc, entityName) => {
|
||||
if (entity[entityName] && entity[entityName].length > 0) {
|
||||
let entityFilter = filtrer[entityName] || (() => true);
|
||||
let entitySort = sorter[entityName] || (() => true);
|
||||
acc[entityName] = [...entity[entityName], ...state[entityName]].filter(entityFilter).sort(entitySort);
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
return {
|
||||
...state, ...nested, [name]: [...action[name], ...state[name]].filter(filter).sort(sort)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
function errorMessage(state = null, action) {
|
||||
return action.error || state;
|
||||
}
|
||||
|
||||
function loading(_state = false, action) {
|
||||
return action.type.endsWith(REQUEST);
|
||||
}
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
accounts: accountsReducer,
|
||||
processes: processesReducer,
|
||||
contracts: contractsReducer,
|
||||
contract: contractReducer,
|
||||
contractProfile: contractProfileReducer,
|
||||
blocks: blocksReducer,
|
||||
transactions: transactionsReducer,
|
||||
commands: commandsReducer
|
||||
entities,
|
||||
loading,
|
||||
errorMessage
|
||||
});
|
||||
|
||||
export default rootReducer;
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
import * as actions from "../actions";
|
||||
|
||||
export default function processes(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case actions.PROCESSES[actions.SUCCESS]:
|
||||
return Object.assign({}, state, {data: action.processes.data});
|
||||
case actions.PROCESSES[actions.FAILURE]:
|
||||
return Object.assign({}, state, {error: action.error});
|
||||
case actions.RECEIVE_PROCESS_LOGS:
|
||||
return {
|
||||
...state,
|
||||
data: {
|
||||
...state.data,
|
||||
[action.processName]: {
|
||||
...state.data[action.processName],
|
||||
logs: action.logs.data
|
||||
}
|
||||
}
|
||||
};
|
||||
case actions.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 actions.WATCH_NEW_PROCESS_LOGS: {
|
||||
return {
|
||||
...state,
|
||||
data: {
|
||||
...state.data,
|
||||
[action.processName]: {
|
||||
...state.data[action.processName],
|
||||
isListening: true
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
case actions.RECEIVE_PROCESS_LOGS_ERROR:
|
||||
return Object.assign({}, state, {error: action.error});
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
export function getAccounts(state) {
|
||||
return state.entities.accounts;
|
||||
}
|
||||
|
||||
export function getAccount(state, address) {
|
||||
return state.entities.accounts.find((account) => account.address === address);
|
||||
}
|
||||
|
||||
export function getTransactions(state) {
|
||||
return state.entities.transactions;
|
||||
}
|
||||
|
||||
export function getTransaction(state, hash) {
|
||||
return state.entities.transactions.find((transaction) => transaction.hash === hash);
|
||||
}
|
||||
|
||||
export function getTransactionsByAccount(state, address) {
|
||||
return state.entities.transactions.filter((transaction) => transaction.from === address);
|
||||
}
|
||||
|
||||
export function getTransactionsByBlock(state, blockNumber) {
|
||||
return state.entities.transactions.filter((transaction) => transaction.blockNumber.toString() === blockNumber);
|
||||
}
|
||||
|
||||
export function getBlocks(state) {
|
||||
return state.entities.blocks;
|
||||
}
|
||||
|
||||
export function getBlock(state, number) {
|
||||
return state.entities.blocks.find((block) => block.number.toString() === number);
|
||||
}
|
||||
|
||||
export function getCommands(state) {
|
||||
return state.entities.commands;
|
||||
}
|
||||
|
||||
export function getProcesses(state) {
|
||||
return state.entities.processes;
|
||||
}
|
||||
|
||||
export function getProcess(state, name) {
|
||||
return state.entities.processes.find((process) => process.name === name);
|
||||
}
|
||||
|
||||
export function getProcessLogsByProcess(state, processName) {
|
||||
return state.entities.processLogs.filter((processLog => processLog.name === processName));
|
||||
}
|
||||
|
||||
export function getContracts(state) {
|
||||
return state.entities.contracts;
|
||||
}
|
||||
|
||||
export function getContract(state, contractName) {
|
||||
return state.entities.contracts.find((contract => contract.name === contractName));
|
||||
}
|
||||
|
||||
export function getContractProfile(state, contractName) {
|
||||
return state.entities.contractProfiles.find((contractProfile => contractProfile.name === contractName));
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
import * as actions from "../actions";
|
||||
|
||||
const BN_FACTOR = 10000;
|
||||
|
||||
function sortTransaction(a, b) {
|
||||
return ((BN_FACTOR * b.blockNumber) + b.transactionIndex) - ((BN_FACTOR * a.blockNumber) + a.transactionIndex);
|
||||
}
|
||||
|
||||
function filterTransaction(tx, index, self) {
|
||||
return index === self.findIndex((t) => (
|
||||
t.blockNumber === tx.blockNumber && t.transactionIndex === tx.transactionIndex
|
||||
));
|
||||
}
|
||||
|
||||
export default function transactions(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case actions.TRANSACTIONS[actions.SUCCESS]:
|
||||
return {
|
||||
...state, error: null, data: [...action.transactions.data, ...state.data || []]
|
||||
.filter(filterTransaction)
|
||||
.sort(sortTransaction)
|
||||
};
|
||||
case actions.TRANSACTIONS[actions.FAILURE]:
|
||||
return Object.assign({}, state, {error: action.error});
|
||||
case actions.TRANSACTION[actions.SUCCESS]:
|
||||
return {
|
||||
...state, error: null, data: [action.transaction.data, ...state.data || []]
|
||||
.filter(filterTransaction)
|
||||
.sort(sortTransaction)
|
||||
};
|
||||
case actions.TRANSACTION[actions.FAILURE]:
|
||||
return Object.assign({}, state, {error: action.error});
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
|
@ -3,12 +3,13 @@ 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, commands} = actions;
|
||||
const {account, accounts, block, blocks, transaction, transactions, processes, commands, processLogs,
|
||||
contracts, contract, contractProfile} = actions;
|
||||
|
||||
function *doRequest(entity, apiFn, payload) {
|
||||
const {response, error} = yield call(apiFn, payload);
|
||||
if(response) {
|
||||
yield put(entity.success(response));
|
||||
yield put(entity.success(response.data, payload));
|
||||
} else if (error) {
|
||||
yield put(entity.failure(error));
|
||||
}
|
||||
|
@ -22,6 +23,10 @@ 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 const fetchProcessLogs = doRequest.bind(null, processLogs, api.fetchProcessLogs);
|
||||
export const fetchContracts = doRequest.bind(null, contracts, api.fetchContracts);
|
||||
export const fetchContract = doRequest.bind(null, contract, api.fetchContract);
|
||||
export const fetchContractProfile = doRequest.bind(null, contractProfile, api.fetchContractProfile);
|
||||
|
||||
export function *watchFetchTransaction() {
|
||||
yield takeEvery(actions.TRANSACTION[actions.REQUEST], fetchTransaction);
|
||||
|
@ -55,17 +60,20 @@ export function *watchPostCommand() {
|
|||
yield takeEvery(actions.COMMANDS[actions.REQUEST], postCommand);
|
||||
}
|
||||
|
||||
export function *fetchProcessLogs(action) {
|
||||
try {
|
||||
const logs = yield call(api.fetchProcessLogs, action.processName);
|
||||
yield put(actions.receiveProcessLogs(action.processName, logs));
|
||||
} catch (e) {
|
||||
yield put(actions.receiveProcessLogsError(e));
|
||||
}
|
||||
export function *watchFetchProcessLogs() {
|
||||
yield takeEvery(actions.PROCESS_LOGS[actions.REQUEST], fetchProcessLogs);
|
||||
}
|
||||
|
||||
export function *watchFetchProcessLogs() {
|
||||
yield takeEvery(actions.FETCH_PROCESS_LOGS, fetchProcessLogs);
|
||||
export function *watchFetchContract() {
|
||||
yield takeEvery(actions.CONTRACT[actions.REQUEST], fetchContract);
|
||||
}
|
||||
|
||||
export function *watchFetchContracts() {
|
||||
yield takeEvery(actions.CONTRACTS[actions.REQUEST], fetchContracts);
|
||||
}
|
||||
|
||||
export function *watchFetchContractProfile() {
|
||||
yield takeEvery(actions.CONTRACT_PROFILE[actions.REQUEST], fetchContractProfile);
|
||||
}
|
||||
|
||||
function createChannel(socket) {
|
||||
|
@ -97,8 +105,8 @@ 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});
|
||||
const processLog = yield take(channel);
|
||||
yield put(processLogs.success([processLog]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,45 +114,6 @@ export function *watchListenToProcessLogs() {
|
|||
yield takeEvery(actions.WATCH_NEW_PROCESS_LOGS, listenToProcessLogs);
|
||||
}
|
||||
|
||||
export function *fetchContract(action) {
|
||||
try {
|
||||
const contract = yield call(api.fetchContract, action.contractName);
|
||||
yield put(actions.receiveContract(contract));
|
||||
} catch (e) {
|
||||
yield put(actions.receiveContractError());
|
||||
}
|
||||
}
|
||||
|
||||
export function *watchFetchContract() {
|
||||
yield takeEvery(actions.FETCH_CONTRACT, fetchContract);
|
||||
}
|
||||
|
||||
export function *fetchContracts() {
|
||||
try {
|
||||
const contracts = yield call(api.fetchContracts);
|
||||
yield put(actions.receiveContracts(contracts));
|
||||
} catch (e) {
|
||||
yield put(actions.receiveContractsError());
|
||||
}
|
||||
}
|
||||
|
||||
export function *watchFetchContracts() {
|
||||
yield takeEvery(actions.FETCH_CONTRACTS, fetchContracts);
|
||||
}
|
||||
|
||||
export function *fetchContractProfile(action) {
|
||||
try {
|
||||
const profile = yield call(api.fetchContractProfile, action.contractName);
|
||||
yield put(actions.receiveContractProfile(profile));
|
||||
} catch (e) {
|
||||
yield put(actions.receiveContractError());
|
||||
}
|
||||
}
|
||||
|
||||
export function *watchFetchContractProfile() {
|
||||
yield takeEvery(actions.FETCH_CONTRACT_PROFILE, fetchContractProfile);
|
||||
}
|
||||
|
||||
export default function *root() {
|
||||
yield all([
|
||||
fork(watchInitBlockHeader),
|
||||
|
|
|
@ -73,8 +73,8 @@ class ProcessLauncher {
|
|||
'ws',
|
||||
apiRoute,
|
||||
(ws, _req) => {
|
||||
self.events.on('process-log-' + self.name, function(logLevel, msg) {
|
||||
ws.send(JSON.stringify({msg, msg_clear: msg.stripColors, logLevel}), () => {});
|
||||
self.events.on('process-log-' + self.name, function(logLevel, msg, name, timestamp) {
|
||||
ws.send(JSON.stringify({msg, msg_clear: msg.stripColors, logLevel, name, timestamp}), () => {});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
@ -89,8 +89,9 @@ class ProcessLauncher {
|
|||
|
||||
// Translates logs from the child process to the logger
|
||||
_handleLog(msg) {
|
||||
this.events.emit('process-log-' + this.name, msg.type, msg.message);
|
||||
this.logs.push({msg: msg.message, msg_clear: msg.message.stripColors, logLevel: msg.logLevel});
|
||||
const timestamp = new Date().getTime();
|
||||
this.events.emit('process-log-' + this.name, msg.type, msg.message, this.name, timestamp);
|
||||
this.logs.push({msg: msg.message, msg_clear: msg.message.stripColors, logLevel: msg.logLevel, name: this.name, timestamp});
|
||||
if (this.silent && msg.type !== 'error') {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -17,13 +17,11 @@ class ProcessManager {
|
|||
'get',
|
||||
'/embark-api/processes',
|
||||
(req, res) => {
|
||||
let parsedProcesses = {};
|
||||
Object.keys(self.processes).forEach(processName => {
|
||||
parsedProcesses[processName] = {
|
||||
state: self.processes[processName].state
|
||||
};
|
||||
});
|
||||
res.send(parsedProcesses);
|
||||
const formatter = (acc, processName) => {
|
||||
acc.push({state: self.processes[processName].state, name: processName});
|
||||
return acc;
|
||||
};
|
||||
res.send(Object.keys(self.processes).reduce(formatter, []));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue