mirror of https://github.com/embarklabs/embark.git
Use process log ids
This commit is contained in:
parent
5d29ab1d42
commit
de009db74f
|
@ -1,3 +1,5 @@
|
|||
import {EMBARK_PROCESS_NAME} from '../constants';
|
||||
|
||||
export const REQUEST = 'REQUEST';
|
||||
export const SUCCESS = 'SUCCESS';
|
||||
export const FAILURE = 'FAILURE';
|
||||
|
@ -92,28 +94,21 @@ export const processes = {
|
|||
|
||||
export const COMMANDS = createRequestTypes('COMMANDS');
|
||||
export const commands = {
|
||||
post: (command) => action(COMMANDS[REQUEST], {command, noLoading: true}),
|
||||
success: (command) => action(COMMANDS[SUCCESS], {commands: [{timestamp: new Date().getTime(), ...command}]}),
|
||||
post: (command) => action(COMMANDS[REQUEST], {command}),
|
||||
success: (command, payload) => {
|
||||
return action(COMMANDS[SUCCESS], {processLogs: [{
|
||||
timestamp: new Date().getTime(),
|
||||
name: EMBARK_PROCESS_NAME,
|
||||
msg: `${payload.command} > ${command.result}`
|
||||
}]})
|
||||
},
|
||||
failure: (error) => action(COMMANDS[FAILURE], {error})
|
||||
};
|
||||
|
||||
export const PROCESS_LOGS = createRequestTypes('PROCESS_LOGS');
|
||||
export const processLogs = {
|
||||
request: (processName, limit) => action(PROCESS_LOGS[REQUEST], {processName, limit}),
|
||||
success: (processLogs, payload) => {
|
||||
return action(PROCESS_LOGS[SUCCESS],
|
||||
{
|
||||
ws: !!payload.ws,
|
||||
processLogs: [
|
||||
{
|
||||
process: payload.processName,
|
||||
timestamp: new Date().getTime(),
|
||||
logs: processLogs
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
},
|
||||
request: (processName) => action(PROCESS_LOGS[REQUEST], {processName}),
|
||||
success: (processLogs) => action(PROCESS_LOGS[SUCCESS], {processLogs}),
|
||||
failure: (error) => action(PROCESS_LOGS[FAILURE], {error})
|
||||
};
|
||||
|
||||
|
@ -154,7 +149,7 @@ export const contractFile = {
|
|||
|
||||
export const CONTRACT_FUNCTION = createRequestTypes('CONTRACT_FUNCTION');
|
||||
export const contractFunction = {
|
||||
post: (contractName, method, inputs, gasPrice) => action(CONTRACT_FUNCTION[REQUEST], {contractName, method, inputs, gasPrice, noLoading: true}),
|
||||
post: (contractName, method, inputs, gasPrice) => action(CONTRACT_FUNCTION[REQUEST], {contractName, method, inputs, gasPrice}),
|
||||
success: (result, payload) => action(CONTRACT_FUNCTION[SUCCESS], {contractFunctions: [{...result, ...payload}]}),
|
||||
failure: (error) => action(CONTRACT_FUNCTION[FAILURE], {error})
|
||||
};
|
||||
|
|
|
@ -6,14 +6,6 @@ import Convert from 'ansi-to-html';
|
|||
|
||||
const convert = new Convert();
|
||||
|
||||
const CommandResult = ({result}) => (
|
||||
<p className="text__new-line">{result}</p>
|
||||
);
|
||||
|
||||
CommandResult.propTypes = {
|
||||
result: PropTypes.string
|
||||
};
|
||||
|
||||
class Console extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
@ -31,52 +23,25 @@ class Console extends Component {
|
|||
this.setState({value: event.target.value});
|
||||
}
|
||||
|
||||
getProcessLogs(processName){
|
||||
const log = this.props.processLogs
|
||||
.reverse()
|
||||
.filter(item => item.process === processName);
|
||||
|
||||
if(!log.length) return [];
|
||||
// the selector should have reduced `processLogs` down to one
|
||||
// record per process, and therefore after filtering, the array
|
||||
// should have only one item
|
||||
return log[0].logs;
|
||||
}
|
||||
|
||||
renderCommandsResult(){
|
||||
const {commands} = this.props;
|
||||
return (
|
||||
this.props.isEmbark() &&
|
||||
commands.map((command, index) => {
|
||||
return <CommandResult key={index} result={command.result}/>;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
renderTabs() {
|
||||
const {processes} = this.props;
|
||||
return processes
|
||||
.sort((a, b) => { // ensure the "Embark" tab is displayed first
|
||||
if (a.name === 'embark') return -1;
|
||||
if (b.name === 'embark') return 1;
|
||||
return 0;
|
||||
})
|
||||
.map(process => (
|
||||
<Tab title={process.name} key={process.name} onClick={(e, x) => this.clickTab(e, x)}>
|
||||
<Logs>
|
||||
{
|
||||
this.getProcessLogs(process.name)
|
||||
.map((item, i) => <p key={i} className={item.logLevel}
|
||||
dangerouslySetInnerHTML={{__html: convert.toHtml(item.msg)}}></p>)
|
||||
}
|
||||
</Logs>
|
||||
</Tab>
|
||||
const {processLogs, processes} = this.props;
|
||||
return processes.map(process => (
|
||||
<Tab title={process.name} key={process.name}>
|
||||
<Logs>
|
||||
{
|
||||
processLogs
|
||||
.filter((item) => item.name === process.name)
|
||||
.reverse()
|
||||
.map((item, i) => <p key={i} className={item.logLevel}
|
||||
dangerouslySetInnerHTML={{__html: convert.toHtml(item.msg)}}></p>)
|
||||
}
|
||||
</Logs>
|
||||
</Tab>
|
||||
));
|
||||
}
|
||||
|
||||
render() {
|
||||
const tabs = this.renderTabs();
|
||||
const commandsResult = this.renderCommandsResult();
|
||||
const {value} = this.state;
|
||||
|
||||
return (
|
||||
|
@ -93,7 +58,6 @@ class Console extends Component {
|
|||
</TabbedHeader>
|
||||
<TabbedContainer selectedTitle={this.props.activeProcess}>
|
||||
{tabs}
|
||||
{commandsResult}
|
||||
</TabbedContainer>
|
||||
</React.Fragment>
|
||||
</Card.Body>
|
||||
|
@ -115,10 +79,9 @@ class Console extends Component {
|
|||
Console.propTypes = {
|
||||
postCommand: PropTypes.func,
|
||||
isEmbark: PropTypes.func,
|
||||
commands: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
processes: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
processLogs: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
updateTab: PropTypes.func
|
||||
};
|
||||
|
||||
export default Console;
|
||||
export default Console;
|
|
@ -0,0 +1 @@
|
|||
export const EMBARK_PROCESS_NAME = 'embark';
|
|
@ -7,10 +7,8 @@ import {commands as commandsAction, listenToProcessLogs, processLogs as processL
|
|||
import DataWrapper from "../components/DataWrapper";
|
||||
import Processes from '../components/Processes';
|
||||
import Console from '../components/Console';
|
||||
import {getProcesses, getCommands, getProcessLogs} from "../reducers/selectors";
|
||||
|
||||
const EMBARK_PROCESS_NAME = 'embark';
|
||||
const LOG_LIMIT = 50;
|
||||
import {getProcesses, getProcessLogs} from "../reducers/selectors";
|
||||
import {EMBARK_PROCESS_NAME} from '../constants';
|
||||
|
||||
class HomeContainer extends Component {
|
||||
constructor(props) {
|
||||
|
@ -31,8 +29,12 @@ class HomeContainer extends Component {
|
|||
this.props.stopProcessLogs(this.state.activeProcess)
|
||||
}
|
||||
|
||||
this.props.fetchProcessLogs(processName, LOG_LIMIT);
|
||||
if (processName !== EMBARK_PROCESS_NAME) {
|
||||
if (processName === EMBARK_PROCESS_NAME) {
|
||||
if (this.props.processes.length === 0) {
|
||||
this.props.fetchProcessLogs(processName);
|
||||
}
|
||||
} else {
|
||||
this.props.fetchProcessLogs(processName);
|
||||
this.props.listenToProcessLogs(processName);
|
||||
}
|
||||
|
||||
|
@ -50,7 +52,6 @@ class HomeContainer extends Component {
|
|||
<DataWrapper shouldRender={this.props.processes.length > 0 } {...this.props} render={({processes, postCommand, processLogs}) => (
|
||||
<Console activeProcess={this.state.activeProcess}
|
||||
postCommand={postCommand}
|
||||
commands={this.props.commands}
|
||||
processes={processes}
|
||||
processLogs={processLogs}
|
||||
isEmbark={() => this.isEmbark}
|
||||
|
@ -64,7 +65,6 @@ class HomeContainer extends Component {
|
|||
HomeContainer.propTypes = {
|
||||
processes: PropTypes.arrayOf(PropTypes.object),
|
||||
postCommand: PropTypes.func,
|
||||
commands: PropTypes.arrayOf(PropTypes.object),
|
||||
error: PropTypes.string,
|
||||
loading: PropTypes.bool
|
||||
};
|
||||
|
@ -72,7 +72,6 @@ HomeContainer.propTypes = {
|
|||
function mapStateToProps(state) {
|
||||
return {
|
||||
processes: getProcesses(state),
|
||||
commands: getCommands(state),
|
||||
error: state.errorMessage,
|
||||
processLogs: getProcessLogs(state),
|
||||
loading: state.loading
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {combineReducers} from 'redux';
|
||||
import {REQUEST, SUCCESS, FAILURE, CONTRACT_COMPILE, FILES, LOGOUT, AUTHENTICATE,
|
||||
FETCH_CREDENTIALS, UPDATE_BASE_ETHER, PROCESS_LOGS} from "../actions";
|
||||
FETCH_CREDENTIALS, UPDATE_BASE_ETHER} from "../actions";
|
||||
import {EMBARK_PROCESS_NAME} from '../constants';
|
||||
|
||||
const BN_FACTOR = 10000;
|
||||
const VOID_ADDRESS = '0x0000000000000000000000000000000000000000';
|
||||
|
@ -19,7 +20,6 @@ const entitiesDefaultState = {
|
|||
contractDeploys: [],
|
||||
contractCompiles: [],
|
||||
contractLogs: [],
|
||||
commands: [],
|
||||
messages: [],
|
||||
messageChannels: [],
|
||||
versions: [],
|
||||
|
@ -37,7 +37,22 @@ const sorter = {
|
|||
transactions: function(a, b) {
|
||||
return ((BN_FACTOR * b.blockNumber) + b.transactionIndex) - ((BN_FACTOR * a.blockNumber) + a.transactionIndex);
|
||||
},
|
||||
processes: function(a, b) {
|
||||
if (a.name === EMBARK_PROCESS_NAME) return -1;
|
||||
if (b.name === EMBARK_PROCESS_NAME) return 1;
|
||||
return 0;
|
||||
},
|
||||
processLogs: function(a, b) {
|
||||
if (a.name !== b.name) {
|
||||
if(a.name < b.name) return -1;
|
||||
if(a.name > b.name) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (a.id === undefined && b.id === undefined) {
|
||||
return b.timestamp - a.timestamp;
|
||||
}
|
||||
|
||||
return b.id - a.id;
|
||||
},
|
||||
contractLogs: function(a, b) {
|
||||
|
@ -46,9 +61,6 @@ const sorter = {
|
|||
messages: function(a, b) {
|
||||
return a.time - b.time;
|
||||
},
|
||||
commands: function(a, b) {
|
||||
return a.timestamp - b.timestamp;
|
||||
},
|
||||
files: function(a, b) {
|
||||
if (a.name < b.name) return -1;
|
||||
if (a.name > b.name) return 1;
|
||||
|
@ -61,7 +73,10 @@ const filtrer = {
|
|||
return index === self.findIndex((t) => t.name === process.name);
|
||||
},
|
||||
processLogs: function(processLog, index, self) {
|
||||
return index === self.findIndex((p) => p.id === processLog.id) && index <= MAX_ELEMENTS
|
||||
if (processLog.id !== undefined) {
|
||||
return index === self.findIndex((p) => p.id === processLog.id) && index <= MAX_ELEMENTS
|
||||
}
|
||||
return true;
|
||||
},
|
||||
contracts: function(contract, index, self) {
|
||||
return index === self.findIndex((t) => t.className === contract.className);
|
||||
|
@ -103,12 +118,6 @@ const filtrer = {
|
|||
};
|
||||
|
||||
function entities(state = entitiesDefaultState, action) {
|
||||
if (action.type === PROCESS_LOGS[SUCCESS] && action.ws === true){
|
||||
const process = action.processLogs[0].process;
|
||||
let processLogs = state.processLogs.filter(logs => logs.process === process).sort((a, b) => b.timestamp - a.timestamp)[0];
|
||||
processLogs.logs.push(action.processLogs[0].logs[0]);
|
||||
return {...state};
|
||||
}
|
||||
if (action.type === FILES[SUCCESS]) {
|
||||
return {...state, files: action.files};
|
||||
}
|
||||
|
@ -155,7 +164,7 @@ function errorEntities(state = {}, action) {
|
|||
}
|
||||
|
||||
function loading(_state = false, action) {
|
||||
return action.type.endsWith(REQUEST) && !action.noLoading;
|
||||
return action.type.endsWith(REQUEST);
|
||||
}
|
||||
|
||||
function compilingContract(state = false, action) {
|
||||
|
|
|
@ -44,23 +44,12 @@ 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 getProcessLogs(state) {
|
||||
const processLogsObj = state.entities.processLogs.reduce((processLogs, processLog) => {
|
||||
const existingProcessLog = processLogs[processLog.process];
|
||||
if(!existingProcessLog || processLog.timestamp > existingProcessLog.timestamp){
|
||||
processLogs[processLog.process] = processLog;
|
||||
}
|
||||
return processLogs;
|
||||
}, {});
|
||||
return Object.values(processLogsObj);
|
||||
return state.entities.processLogs;
|
||||
}
|
||||
|
||||
export function getContractLogsByContract(state, contractName) {
|
||||
|
|
|
@ -241,7 +241,7 @@ export function *listenToProcessLogs(action) {
|
|||
return;
|
||||
}
|
||||
|
||||
yield put(actions.processLogs.success([processLog], {processName: action.processName, ws: true}));
|
||||
yield put(actions.processLogs.success([processLog]));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ export function fetchProcesses() {
|
|||
}
|
||||
|
||||
export function fetchProcessLogs(payload) {
|
||||
return get(`/process-logs/${payload.processName}`, {params: payload, processName: payload.processName, credentials: payload.credentials});
|
||||
return get(`/process-logs/${payload.processName}`, ...arguments);
|
||||
}
|
||||
|
||||
export function fetchContractLogs() {
|
||||
|
|
|
@ -84,7 +84,7 @@ class ProcessLauncher {
|
|||
self.embark.registerAPICall(
|
||||
'get',
|
||||
apiRoute,
|
||||
(req, res) => {
|
||||
(_req, res) => {
|
||||
const result = self.logs.map((log, id) => Object.assign(log, {id})).slice(-50);
|
||||
res.send(JSON.stringify(result));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue