mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-01 00:08:27 +01:00
Added ErrorStore
This commit is contained in:
parent
96600c5598
commit
8ba685b67a
@ -2,6 +2,7 @@ var React = require('react');
|
|||||||
var TabView = require('./components/TabView');
|
var TabView = require('./components/TabView');
|
||||||
var Menu = require('./components/Menu');
|
var Menu = require('./components/Menu');
|
||||||
var UserStore = require('./stores/UserStore');
|
var UserStore = require('./stores/UserStore');
|
||||||
|
var ErrorMessages = require('./components/ErrorMessages');
|
||||||
var LogEntriesComponent = React.createFactory(require('./components/log/LogEntriesComponent'));
|
var LogEntriesComponent = React.createFactory(require('./components/log/LogEntriesComponent'));
|
||||||
var FeatureTogglesComponent = React.createFactory(require('./components/feature/FeatureTogglesComponent'));
|
var FeatureTogglesComponent = React.createFactory(require('./components/feature/FeatureTogglesComponent'));
|
||||||
var StrategiesComponent = React.createFactory(require('./components/strategy/StrategiesComponent'));
|
var StrategiesComponent = React.createFactory(require('./components/strategy/StrategiesComponent'));
|
||||||
@ -37,10 +38,10 @@ React.render(
|
|||||||
<Menu />
|
<Menu />
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<div className="page">
|
<div className="page">
|
||||||
|
<ErrorMessages />
|
||||||
<TabView tabPanes={tabPanes} />
|
<TabView tabPanes={tabPanes} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>,
|
||||||
,
|
|
||||||
document.getElementById('content')
|
document.getElementById('content')
|
||||||
);
|
);
|
||||||
|
@ -1,37 +1,38 @@
|
|||||||
var React = require('react');
|
var React = require('react');
|
||||||
|
var Ui = require('./ErrorMessages.ui');
|
||||||
|
var ErrorStore = require('../stores/ErrorStore');
|
||||||
|
var ErrorActions = require('../stores/ErrorActions');
|
||||||
|
|
||||||
var ErrorMessages = React.createClass({
|
var ErrorMessages = React.createClass({
|
||||||
render: function() {
|
getInitialState: function() {
|
||||||
if (!this.props.errors.length) {
|
return {
|
||||||
return <div/>;
|
errors: ErrorStore.getErrors()
|
||||||
}
|
};
|
||||||
|
},
|
||||||
|
|
||||||
var errorNodes = this.props.errors.map(function(e, i) {
|
onStoreChange: function() {
|
||||||
return (<li key={e + i} className="largetext">{e}</li>);
|
this.setState({
|
||||||
|
errors: ErrorStore.getErrors()
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
componentDidMount: function() {
|
||||||
|
this.unsubscribe = ErrorStore.listen(this.onStoreChange);
|
||||||
|
},
|
||||||
|
|
||||||
|
componentWillUnmount: function() {
|
||||||
|
this.unsubscribe();
|
||||||
|
},
|
||||||
|
|
||||||
|
onClearErrors: function() {
|
||||||
|
ErrorActions.clear();
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function() {
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<Ui errors={this.state.errors} onClearErrors={this.onClearErrors}></Ui>
|
||||||
<div className="mod shadow mtm mrn">
|
|
||||||
<div className="inner bg-red-lt">
|
|
||||||
<div className="bd">
|
|
||||||
<div className="media centerify">
|
|
||||||
<div className="imgExt">
|
|
||||||
<a onClick={this.props.onClearErrors}
|
|
||||||
className="icon-kryss1 linkblock sharp">
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div className="bd">
|
|
||||||
<ul>{errorNodes}</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = ErrorMessages;
|
module.exports = ErrorMessages;
|
||||||
|
|
||||||
|
36
public/js/components/ErrorMessages.ui.jsx
Normal file
36
public/js/components/ErrorMessages.ui.jsx
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
var React = require('react');
|
||||||
|
|
||||||
|
var ErrorMessages = React.createClass({
|
||||||
|
render: function() {
|
||||||
|
if (!this.props.errors.length) {
|
||||||
|
return <div/>;
|
||||||
|
}
|
||||||
|
|
||||||
|
var errorNodes = this.props.errors.map(function(e, i) {
|
||||||
|
return (<li key={e + i} className="largetext">{e}</li>);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="container">
|
||||||
|
<div className="mod shadow mtm mrn">
|
||||||
|
<div className="inner bg-red-lt">
|
||||||
|
<div className="bd">
|
||||||
|
<div className="media centerify">
|
||||||
|
<div className="imgExt">
|
||||||
|
<a onClick={this.props.onClearErrors}
|
||||||
|
className="icon-kryss1 linkblock sharp">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div className="bd">
|
||||||
|
<ul>{errorNodes}</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = ErrorMessages;
|
@ -24,7 +24,7 @@ var ArchiveFeatureComponent = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onRevive: function(item) {
|
onRevive: function(item) {
|
||||||
FeatureActions.revive(item);
|
FeatureActions.revive.triggerPromise(item);
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function () {
|
render: function () {
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
var React = require('react');
|
var React = require('react');
|
||||||
var ErrorMessages = require('../ErrorMessages');
|
|
||||||
var FeatureList = require('./FeatureList');
|
var FeatureList = require('./FeatureList');
|
||||||
var FeatureForm = require('./FeatureForm');
|
var FeatureForm = require('./FeatureForm');
|
||||||
var FeatureActions = require('../../stores/FeatureToggleActions');
|
var FeatureActions = require('../../stores/FeatureToggleActions');
|
||||||
|
var ErrorActions = require('../../stores/ErrorActions');
|
||||||
var FeatureToggleStore = require('../../stores/FeatureToggleStore');
|
var FeatureToggleStore = require('../../stores/FeatureToggleStore');
|
||||||
|
|
||||||
var FeatureTogglesComponent = React.createClass({
|
var FeatureTogglesComponent = React.createClass({
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
features: FeatureToggleStore.getFeatureToggles(),
|
features: FeatureToggleStore.getFeatureToggles(),
|
||||||
errors: [],
|
|
||||||
createView: false
|
createView: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -26,76 +25,31 @@ var FeatureTogglesComponent = React.createClass({
|
|||||||
this.unsubscribe();
|
this.unsubscribe();
|
||||||
},
|
},
|
||||||
|
|
||||||
handleError: function (error) {
|
|
||||||
console.log(error);
|
|
||||||
if (this.isClientError(error)) {
|
|
||||||
var errors = JSON.parse(error.responseText)
|
|
||||||
errors.forEach(function(e) { this.addError(e.msg); }.bind(this))
|
|
||||||
} else if (error.status === 0) {
|
|
||||||
this.addError("server unreachable");
|
|
||||||
} else {
|
|
||||||
this.addError(error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
updateFeature: function (feature) {
|
updateFeature: function (feature) {
|
||||||
FeatureActions.update.triggerPromise(feature)
|
FeatureActions.update.triggerPromise(feature);
|
||||||
.catch(this.handleError);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
archiveFeature: function (feature) {
|
archiveFeature: function (feature) {
|
||||||
FeatureActions.archive.triggerPromise(feature)
|
FeatureActions.archive.triggerPromise(feature);
|
||||||
.catch(this.handleError);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
createFeature: function (feature) {
|
createFeature: function (feature) {
|
||||||
FeatureActions.create.triggerPromise(feature)
|
FeatureActions.create.triggerPromise(feature)
|
||||||
.then(this.cancelNewFeature)
|
.then(this.cancelNewFeature);
|
||||||
.catch(this.handleError);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
newFeature: function() {
|
newFeature: function() {
|
||||||
this.setState({createView: true});
|
this.setState({createView: true});
|
||||||
},
|
},
|
||||||
|
|
||||||
cancelNewFeature: function (feature) {
|
cancelNewFeature: function () {
|
||||||
this.setState({createView: false});
|
this.setState({createView: false});
|
||||||
},
|
ErrorActions.clear();
|
||||||
|
|
||||||
clearErrors: function() {
|
|
||||||
this.setState({errors: []});
|
|
||||||
},
|
|
||||||
|
|
||||||
addError: function(msg) {
|
|
||||||
var errors = this.state.errors;
|
|
||||||
if (errors[errors.length - 1] !== msg) {
|
|
||||||
errors.push(msg);
|
|
||||||
this.setState(errors);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
isClientError: function(error) {
|
|
||||||
try {
|
|
||||||
return error.status >= 400 &&
|
|
||||||
error.status < 500 &&
|
|
||||||
JSON.parse(error.responseText);
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof SyntaxError) {
|
|
||||||
// fall through;
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<ErrorMessages
|
|
||||||
errors={this.state.errors}
|
|
||||||
onClearErrors={this.clearErrors} />
|
|
||||||
|
|
||||||
{this.state.createView ? this.renderCreateView() : this.renderCreateButton()}
|
{this.state.createView ? this.renderCreateView() : this.renderCreateButton()}
|
||||||
|
|
||||||
@ -111,11 +65,11 @@ var FeatureTogglesComponent = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
renderCreateView: function() {
|
renderCreateView: function() {
|
||||||
return <FeatureForm onCancel={this.cancelNewFeature} onSubmit={this.createFeature} />
|
return <FeatureForm onCancel={this.cancelNewFeature} onSubmit={this.createFeature} />;
|
||||||
},
|
},
|
||||||
|
|
||||||
renderCreateButton: function() {
|
renderCreateButton: function() {
|
||||||
return <button className="mal" onClick={this.newFeature}>Create feature toggle</button>
|
return <button className="mal" onClick={this.newFeature}>Create feature toggle</button>;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
var React = require('react'),
|
var React = require('react');
|
||||||
LogEntryList = require('./LogEntryList'),
|
var LogEntryList = require('./LogEntryList');
|
||||||
eventStore = require('../../stores/EventStore'),
|
var eventStore = require('../../stores/EventStore');
|
||||||
ErrorMessages = require('../ErrorMessages');
|
var ErrorActions = require('../../stores/ErrorActions');
|
||||||
|
|
||||||
var LogEntriesComponent = React.createClass({
|
var LogEntriesComponent = React.createClass({
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
createView: false,
|
createView: false,
|
||||||
events: [],
|
events: []
|
||||||
errors: []
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -19,25 +18,13 @@ var LogEntriesComponent = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
initError: function() {
|
initError: function() {
|
||||||
this.onError("Could not load events from server");
|
ErrorActions.error("Could not load events from server");
|
||||||
},
|
|
||||||
|
|
||||||
clearErrors: function() {
|
|
||||||
this.setState({errors: []});
|
|
||||||
},
|
|
||||||
|
|
||||||
onError: function(error) {
|
|
||||||
var errors = this.state.errors.concat([error]);
|
|
||||||
this.setState({errors: errors});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<ErrorMessages errors={this.state.errors} onClearErrors={this.clearErrors} />
|
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<LogEntryList events={this.state.events} />
|
<LogEntryList events={this.state.events} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
var React = require('react'),
|
var React = require('react');
|
||||||
StrategyList = require('./StrategyList'),
|
var StrategyList = require('./StrategyList');
|
||||||
StrategyForm = require('./StrategyForm'),
|
var StrategyForm = require('./StrategyForm');
|
||||||
strategyStore = require('../../stores/StrategyStore'),
|
var strategyStore = require('../../stores/StrategyStore');
|
||||||
ErrorMessages = require('../ErrorMessages');
|
var ErrorActions = require('../../stores/ErrorActions');
|
||||||
|
|
||||||
var StrategiesComponent = React.createClass({
|
var StrategiesComponent = React.createClass({
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
createView: false,
|
createView: false,
|
||||||
strategies: [],
|
strategies: []
|
||||||
errors: []
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -17,10 +16,10 @@ var StrategiesComponent = React.createClass({
|
|||||||
this.fetchStrategies();
|
this.fetchStrategies();
|
||||||
},
|
},
|
||||||
|
|
||||||
fetchStrategies: function(res) {
|
fetchStrategies: function() {
|
||||||
strategyStore.getStrategies()
|
strategyStore.getStrategies()
|
||||||
.then(function(res) {
|
.then(function(res) {
|
||||||
this.setState({strategies: res.strategies})
|
this.setState({strategies: res.strategies});
|
||||||
}.bind(this))
|
}.bind(this))
|
||||||
.catch(this.initError);
|
.catch(this.initError);
|
||||||
|
|
||||||
@ -30,13 +29,8 @@ var StrategiesComponent = React.createClass({
|
|||||||
this.onError("Could not load inital strategies from server");
|
this.onError("Could not load inital strategies from server");
|
||||||
},
|
},
|
||||||
|
|
||||||
clearErrors: function() {
|
|
||||||
this.setState({errors: []});
|
|
||||||
},
|
|
||||||
|
|
||||||
onError: function(error) {
|
onError: function(error) {
|
||||||
var errors = this.state.errors.concat([error]);
|
ErrorActions.error(error);
|
||||||
this.setState({errors: errors});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onNewStrategy: function() {
|
onNewStrategy: function() {
|
||||||
@ -73,24 +67,28 @@ var StrategiesComponent = React.createClass({
|
|||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<ErrorMessages errors={this.state.errors} onClearErrors={this.clearErrors} />
|
|
||||||
|
|
||||||
{this.state.createView ? this.renderCreateView() : this.renderCreateButton()}
|
{this.state.createView ? this.renderCreateView() : this.renderCreateButton()}
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
<StrategyList
|
||||||
<StrategyList strategies={this.state.strategies} onRemove={this.onRemove} />
|
strategies={this.state.strategies}
|
||||||
|
onRemove={this.onRemove} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
renderCreateView: function() {
|
renderCreateView: function() {
|
||||||
return (<StrategyForm onCancelNewStrategy={this.onCancelNewStrategy} onSave={this.onSave} />)
|
return (
|
||||||
|
<StrategyForm
|
||||||
|
onCancelNewStrategy={this.onCancelNewStrategy}
|
||||||
|
onSave={this.onSave}
|
||||||
|
/>);
|
||||||
},
|
},
|
||||||
|
|
||||||
renderCreateButton: function() {
|
renderCreateButton: function() {
|
||||||
return (
|
return (
|
||||||
<button className="mal" onClick={this.onNewStrategy}>Create strategy</button>
|
<button className="mal" onClick={this.onNewStrategy}>
|
||||||
|
Create strategy
|
||||||
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
8
public/js/stores/ErrorActions.js
Normal file
8
public/js/stores/ErrorActions.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
var Reflux = require('reflux');
|
||||||
|
|
||||||
|
var ErrorActions = Reflux.createActions([
|
||||||
|
"clear",
|
||||||
|
"error"
|
||||||
|
]);
|
||||||
|
|
||||||
|
module.exports = ErrorActions;
|
65
public/js/stores/ErrorStore.js
Normal file
65
public/js/stores/ErrorStore.js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
var Reflux = require('reflux');
|
||||||
|
var FeatureActions = require('./FeatureToggleActions');
|
||||||
|
var ErrorActions = require('./ErrorActions');
|
||||||
|
|
||||||
|
// Creates a DataStore
|
||||||
|
var FeatureStore = Reflux.createStore({
|
||||||
|
// Initial setup
|
||||||
|
init: function() {
|
||||||
|
this.listenTo(FeatureActions.create.failed, this.onError);
|
||||||
|
this.listenTo(FeatureActions.update.failed, this.onError);
|
||||||
|
this.listenTo(FeatureActions.archive.failed, this.onError);
|
||||||
|
this.listenTo(FeatureActions.revive.failed, this.onError);
|
||||||
|
this.listenTo(ErrorActions.error, this.onError);
|
||||||
|
this.listenTo(ErrorActions.clear, this.onClear);
|
||||||
|
this.errors = [];
|
||||||
|
},
|
||||||
|
|
||||||
|
onError: function (error) {
|
||||||
|
if (this.isClientError(error)) {
|
||||||
|
var errors = JSON.parse(error.responseText);
|
||||||
|
errors.forEach(function(e) { this.addError(e.msg); }.bind(this));
|
||||||
|
} else if (error.status === 0) {
|
||||||
|
this.addError("server unreachable");
|
||||||
|
} else {
|
||||||
|
this.addError(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onClear: function() {
|
||||||
|
this.errors = [];
|
||||||
|
this.trigger([]);
|
||||||
|
},
|
||||||
|
|
||||||
|
addError: function(msg) {
|
||||||
|
var errors = this.errors;
|
||||||
|
if (errors[errors.length - 1] !== msg) {
|
||||||
|
errors.push(msg);
|
||||||
|
this.errors = errors;
|
||||||
|
this.trigger(errors);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
isClientError: function(error) {
|
||||||
|
try {
|
||||||
|
return error.status >= 400 &&
|
||||||
|
error.status < 500 &&
|
||||||
|
JSON.parse(error.responseText);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof SyntaxError) {
|
||||||
|
// fall through;
|
||||||
|
console.log("Syntax error!");
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
getErrors: function() {
|
||||||
|
return this.errors;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = FeatureStore;
|
@ -20,14 +20,18 @@ var FeatureStore = Reflux.createStore({
|
|||||||
this.listenTo(FeatureActions.revive.completed, this.onRevive);
|
this.listenTo(FeatureActions.revive.completed, this.onRevive);
|
||||||
|
|
||||||
//TODO: this should not be part of the store!
|
//TODO: this should not be part of the store!
|
||||||
this.timer = new Timer(this.loadDataFromServer, 30*1000);
|
this.timer = new Timer(this.loadDataFromServer, 3*1000);
|
||||||
this.timer.start();
|
this.timer.start();
|
||||||
},
|
},
|
||||||
|
|
||||||
loadDataFromServer: function() {
|
loadDataFromServer: function() {
|
||||||
//TODO: this should not be part of the store!
|
//TODO: this should not be part of the store!
|
||||||
Server.getFeatures(function(err, featureToggles) {
|
Server.getFeatures(function(err, featureToggles) {
|
||||||
|
if(err) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
this.setToggles(featureToggles);
|
this.setToggles(featureToggles);
|
||||||
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user