Added loading entities

Moved functionality out of FiddleDeployButton component

Added loading entities (WIP) to separate loading messages
This commit is contained in:
emizzle 2018-08-20 22:52:30 +10:00 committed by Pascal Precht
parent bf46b91166
commit 4d195657dd
No known key found for this signature in database
GPG Key ID: 0EE28D8D6FD85D7D
8 changed files with 73 additions and 53 deletions

View File

@ -8,6 +8,7 @@
"classnames": "^2.2.6", "classnames": "^2.2.6",
"connected-react-router": "^4.3.0", "connected-react-router": "^4.3.0",
"history": "^4.7.2", "history": "^4.7.2",
"lodash": "^4.17.10",
"prop-types": "^15.6.2", "prop-types": "^15.6.2",
"react": "^16.4.1", "react": "^16.4.1",
"react-ace": "^6.1.4", "react-ace": "^6.1.4",

View File

@ -170,14 +170,14 @@ export const ensRecords = {
export const FIDDLE = createRequestTypes('FIDDLE'); export const FIDDLE = createRequestTypes('FIDDLE');
export const fiddle = { export const fiddle = {
request: (codeToCompile) => action(FIDDLE[REQUEST], {codeToCompile}), request: (codeToCompile) => action(FIDDLE[REQUEST], {codeToCompile, loading: 'Compiling...'}),
success: (fiddle) => action(FIDDLE[SUCCESS], {fiddles: [fiddle]}), success: (fiddle) => action(FIDDLE[SUCCESS], {fiddles: [fiddle]}),
failure: (error) => action(FIDDLE[FAILURE], {error}) failure: (error) => action(FIDDLE[FAILURE], {error})
}; };
export const FIDDLE_DEPLOY = createRequestTypes('FIDDLE_DEPLOY'); export const FIDDLE_DEPLOY = createRequestTypes('FIDDLE_DEPLOY');
export const fiddleDeploy = { export const fiddleDeploy = {
request: (compiledCode) => action(FIDDLE_DEPLOY[REQUEST], {compiledCode}), request: (compiledCode) => action(FIDDLE_DEPLOY[REQUEST], {compiledCode, loading: 'Deploying...'}),
success: () => action(FIDDLE_DEPLOY[SUCCESS]), success: () => action(FIDDLE_DEPLOY[SUCCESS]),
failure: (error) => action(FIDDLE_DEPLOY[FAILURE], {error}) failure: (error) => action(FIDDLE_DEPLOY[FAILURE], {error})
}; };

View File

@ -1,47 +1,29 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import {Button} from 'tabler-react'; import {Button} from 'tabler-react';
import {fiddleDeploy as fiddleDeployAction} from '../actions';
import {connect} from 'react-redux';
import {getFiddle} from '../reducers/selectors';
class FiddleDeployButton extends Component{ class FiddleDeployButton extends Component{
handleClick(){
this.props.postFiddleDeploy(this.props.fiddle);
}
render (){ render (){
return ( return (
<Button <Button
color="success" color="dark"
onClick={(e) => this.handleClick(e)}> size="sm"
icon="upload-cloud"
onClick={(e) => this.props.onDeployClick(e)}>
Deploy Deploy
</Button> </Button>
); );
} }
} }
function mapStateToProps(state) {
return {
fiddle: getFiddle(state),
error: state.errorMessage,
loading: state.loading,
compiledContract: state.compiledContract
};
}
FiddleDeployButton.propTypes = { FiddleDeployButton.propTypes = {
fiddle: PropTypes.object, fiddle: PropTypes.object,
postFiddleDeploy: PropTypes.func, onDeployClick: PropTypes.func,
loading: PropTypes.bool, loading: PropTypes.bool,
compiledContract: PropTypes.object, compiledContract: PropTypes.object,
error: PropTypes.string error: PropTypes.string
}; };
export default connect( export default FiddleDeployButton;
mapStateToProps,
{
postFiddleDeploy: fiddleDeployAction.request
},
)(FiddleDeployButton);

View File

@ -1,6 +1,6 @@
/* eslint {jsx-a11y/anchor-has-content:"off"} */ /* eslint {jsx-a11y/anchor-has-content:"off"} */
import React, {Component} from 'react'; import React, {Component} from 'react';
import {Card, List, Badge, Icon} from 'tabler-react'; import {Card, List, Badge, Icon, Dimmer} from 'tabler-react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classNames from 'classnames'; import classNames from 'classnames';
@ -24,7 +24,7 @@ class FiddleResults extends Component {
this.setState(updatedState); this.setState(updatedState);
} }
_getFormatted(errors, errorType){ _getFormatted(errors, errorType, loading){
const color = (errorType === "error" ? "danger" : errorType); const color = (errorType === "error" ? "danger" : errorType);
const isFullscreen = Boolean(this.state[errorType + 'sFullscreen']); const isFullscreen = Boolean(this.state[errorType + 'sFullscreen']);
const classes = classNames({ const classes = classNames({
@ -46,15 +46,17 @@ class FiddleResults extends Component {
</Card.Options> </Card.Options>
</Card.Header> </Card.Header>
<Card.Body> <Card.Body>
<List.Group> <Dimmer active={loading ? "active" : ""} loader>
{errors.map(error => { return error.node; })} <List.Group>
</List.Group> {errors.map(error => { return error.node; })}
</List.Group>
</Dimmer>
</Card.Body> </Card.Body>
</Card>; </Card>;
} }
render() { render() {
const {warnings, errors, fatal} = this.props; const {warnings, errors, fatal, isLoading} = this.props;
let renderings = []; let renderings = [];
if(fatal){ if(fatal){
@ -80,13 +82,13 @@ class FiddleResults extends Component {
if (errors.length) renderings.push( if (errors.length) renderings.push(
<React.Fragment key="errors"> <React.Fragment key="errors">
<a id="errors" aria-hidden="true"/> <a id="errors" aria-hidden="true"/>
{this._getFormatted(errors, "error")} {this._getFormatted(errors, "error", isLoading)}
</React.Fragment> </React.Fragment>
); );
if (warnings.length) renderings.push( if (warnings.length) renderings.push(
<React.Fragment key="warnings"> <React.Fragment key="warnings">
<a id="warnings" aria-hidden="true"/> <a id="warnings" aria-hidden="true"/>
{this._getFormatted(warnings, "warning")} {this._getFormatted(warnings, "warning", isLoading)}
</React.Fragment> </React.Fragment>
); );
} }
@ -102,7 +104,8 @@ class FiddleResults extends Component {
FiddleResults.propTypes = { FiddleResults.propTypes = {
errors: PropTypes.array, errors: PropTypes.array,
warnings: PropTypes.array, warnings: PropTypes.array,
fatal: PropTypes.string fatal: PropTypes.string,
isLoading: PropTypes.bool
}; };
export default FiddleResults; export default FiddleResults;

View File

@ -6,7 +6,7 @@ import FiddleDeployButton from './FiddleDeployButton';
class FiddleResultsSummary extends Component{ class FiddleResultsSummary extends Component{
render(){ render(){
const {warnings, errors, isFetching, hasResult, fatal} = this.props; const {warnings, errors, isLoading, loadingMessage, hasResult, fatal} = this.props;
let renderings = []; let renderings = [];
if(fatal) { if(fatal) {
renderings.push( renderings.push(
@ -15,9 +15,9 @@ class FiddleResultsSummary extends Component{
</React.Fragment> </React.Fragment>
); );
} }
else if(isFetching){ else if(isLoading){
renderings.push( renderings.push(
<React.Fragment key="compiling"><div className="loader"></div><span className="loader-text">Compiling...</span></React.Fragment> <React.Fragment key="loading"><div className="loader"></div><span className="loader-text">{loadingMessage}</span></React.Fragment>
); );
} }
else { else {
@ -25,7 +25,7 @@ class FiddleResultsSummary extends Component{
renderings.push( renderings.push(
<React.Fragment key="success"> <React.Fragment key="success">
<Badge className="badge-link" color="success">Compiled</Badge> <Badge className="badge-link" color="success">Compiled</Badge>
<FiddleDeployButton /> <FiddleDeployButton onDeployClick={this.props.onDeployClick} />
</React.Fragment> </React.Fragment>
); );
} }
@ -41,9 +41,9 @@ class FiddleResultsSummary extends Component{
); );
} }
return ( return (
<div className={"compilation-summary " + ((hasResult || isFetching) ? "visible" : "")}> <div className={"compilation-summary " + ((hasResult || isLoading) ? "visible" : "")}>
{renderings} {renderings}
{!(hasResult || isFetching) ? "&nbsp;" : ""} {!(hasResult || isLoading) ? "&nbsp;" : ""}
</div> </div>
); );
} }
@ -52,9 +52,11 @@ class FiddleResultsSummary extends Component{
FiddleResultsSummary.propTypes = { FiddleResultsSummary.propTypes = {
errors: PropTypes.array, errors: PropTypes.array,
warnings: PropTypes.array, warnings: PropTypes.array,
isFetching: PropTypes.bool, isLoading: PropTypes.bool,
loadingMessage: PropTypes.string,
hasResult: PropTypes.bool, hasResult: PropTypes.bool,
fatal: PropTypes.string fatal: PropTypes.string,
onDeployClick: PropTypes.func
}; };
export default FiddleResultsSummary; export default FiddleResultsSummary;

View File

@ -3,7 +3,7 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import {fiddle as fiddleAction} from '../actions'; import {fiddle as fiddleAction, fiddleDeploy as fiddleDeployAction} from '../actions';
import Fiddle from '../components/Fiddle'; import Fiddle from '../components/Fiddle';
import FiddleResults from '../components/FiddleResults'; import FiddleResults from '../components/FiddleResults';
import FiddleResultsSummary from '../components/FiddleResultsSummary'; import FiddleResultsSummary from '../components/FiddleResultsSummary';
@ -74,8 +74,12 @@ class FiddleContainer extends Component {
scrollToComponent(this.ace); scrollToComponent(this.ace);
} }
_onDeployClick(){
this.props.postFiddleDeploy(this.props.fiddle);
}
render() { render() {
const {fiddle, loading, error} = this.props; const {fiddle, loading, loadingMessage, error} = this.props;
let renderings = []; let renderings = [];
let warnings = []; let warnings = [];
let errors = []; let errors = [];
@ -88,9 +92,11 @@ class FiddleContainer extends Component {
<FiddleResultsSummary <FiddleResultsSummary
errors={errors} errors={errors}
warnings={warnings} warnings={warnings}
isFetching={loading} isLoading={loading}
loadingMessage={loadingMessage}
hasResult={Boolean(fiddle)} hasResult={Boolean(fiddle)}
fatal={error} fatal={error}
onDeployClick={this._onDeployClick}
/> />
<Fiddle <Fiddle
value={this.state.value} value={this.state.value}
@ -113,6 +119,7 @@ class FiddleContainer extends Component {
errors={errors} errors={errors}
warnings={warnings} warnings={warnings}
fatal={error} fatal={error}
isLoading={loading}
/>); />);
} }
@ -126,9 +133,11 @@ class FiddleContainer extends Component {
} }
} }
function mapStateToProps(state) { function mapStateToProps(state) {
const fiddle = getFiddle(state);
return { return {
fiddle: getFiddle(state), fiddle: fiddle.data,
error: state.errorMessage, error: fiddle.error,
loadingMessage: fiddle.loading,
loading: state.loading loading: state.loading
}; };
} }
@ -136,13 +145,16 @@ function mapStateToProps(state) {
FiddleContainer.propTypes = { FiddleContainer.propTypes = {
fiddle: PropTypes.object, fiddle: PropTypes.object,
error: PropTypes.string, error: PropTypes.string,
loading: PropTypes.bool,
loadingMessage: PropTypes.string,
postFiddle: PropTypes.func, postFiddle: PropTypes.func,
loading: PropTypes.bool postFiddleDeploy: PropTypes.func
}; };
export default connect( export default connect(
mapStateToProps, mapStateToProps,
{ {
postFiddle: fiddleAction.request postFiddle: fiddleAction.request,
postFiddleDeploy: fiddleDeployAction.request
}, },
)(FiddleContainer); )(FiddleContainer);

View File

@ -114,6 +114,19 @@ function errorEntities(state = {}, action) {
return {...state, ...newState}; return {...state, ...newState};
} }
function loadingEntities(state = {}, action) {
if (!action.type.endsWith(REQUEST)) {
return state;
}
let newState = {};
for (let name of Object.keys(entitiesDefaultState)) {
if (action[name] && action[name].length > 0) {
newState[name] = action[name][0].loading || "Loading...";
}
}
return {...state, ...newState};
}
function loading(_state = false, action) { function loading(_state = false, action) {
return action.type.endsWith(REQUEST); return action.type.endsWith(REQUEST);
} }
@ -122,7 +135,8 @@ const rootReducer = combineReducers({
entities, entities,
loading, loading,
errorMessage, errorMessage,
errorEntities errorEntities,
loadingEntities
}); });
export default rootReducer; export default rootReducer;

View File

@ -1,3 +1,5 @@
import _ from 'lodash';
export function getAccounts(state) { export function getAccounts(state) {
return state.entities.accounts; return state.entities.accounts;
} }
@ -103,7 +105,11 @@ export function getMessages(state) {
} }
export function getFiddle(state) { export function getFiddle(state) {
return state.entities.fiddles[state.entities.fiddles.length - 1]; return {
data: _.last(state.entities.fiddles),
error: _.last(state.errorEntities.fiddles),
loading: _.last(state.loadingEntities)
};
} }
export function getEnsRecords(state) { export function getEnsRecords(state) {