/** @jsx React.DOM */ /* jshint quotmark:false */ // Unleash // - Menu // - FeatureList // - UnsavedFeature // - SavedFeature // var Timer = function(cb, interval) { this.cb = cb; this.interval = interval; this.timerId = null; }; Timer.prototype.start = function() { if (this.timerId != null) { console.warn("timer already started"); } console.log('starting timer'); this.timerId = setInterval(this.cb, this.interval); }; Timer.prototype.stop = function() { if (this.timerId == null) { console.warn('no timer running'); } else { console.log('stopping timer'); clearInterval(this.timerId); this.timerId = null; } }; var Menu = React.createClass({ render: function() { return ( ); } }); var UnsavedFeature = React.createClass({ render: function() { return (
); }, saveFeature: function(e) { e.preventDefault(); this.props.feature.name = this.refs.name.getDOMNode().value; this.props.feature.description = this.refs.description.getDOMNode().value; this.props.feature.strategy = this.refs.strategy.getDOMNode().value; this.props.feature.enabled = this.refs.enabled.getDOMNode().checked; this.props.onSubmit(this.props.feature); } }); var SavedFeature = React.createClass({ onChange: function(event) { this.props.onChange({ name: this.props.feature.name, field: 'enabled', value: event.target.checked }); }, render: function() { return (
{this.props.feature.name}
{this.props.feature.strategy}
); } }); var FeatureList = React.createClass({ render: function() { var featureNodes = []; this.props.unsavedFeatures.forEach(function(feature, idx) { var key = 'new-' + idx; featureNodes.push( ); }.bind(this)); this.props.savedFeatures.forEach(function(feature) { featureNodes.push( ); }.bind(this)); return (

Features

{featureNodes}
); } }); var ErrorMessages = React.createClass({ render: function() { if (!this.props.errors.length) { return
; } var errorNodes = this.props.errors.map(function(e) { return (
  • {e}
  • ); }); return (
      {errorNodes}
    ); } }); var Unleash = React.createClass({ getInitialState: function() { return { savedFeatures: [], unsavedFeatures: [], errors: [], poller: null }; }, componentDidMount: function () { this.loadFeaturesFromServer(); this.state.timer = new Timer(this.loadFeaturesFromServer, this.props.pollInterval); this.state.timer.start(); }, loadFeaturesFromServer: function () { reqwest('features').then(this.setFeatures, this.handleError); }, setFeatures: function (data) { this.setState({savedFeatures: data.features}); }, handleError: function (error) { this.state.errors.push(error); }, updateFeature: function (changeRequest) { var newFeatures = this.state.savedFeatures; newFeatures.forEach(function(f){ if(f.name === changeRequest.name) { f[changeRequest.field] = changeRequest.value; } }); this.setState({features: newFeatures}); this.state.timer.stop(); reqwest({ url: 'features/' + changeRequest.name, method: 'patch', type: 'json', contentType: 'application/json', data: JSON.stringify(changeRequest) }).then(function() { // all good this.state.timer.start(); }.bind(this), this.handleError); }, createFeature: function (feature) { var unsaved = [], state = this.state; this.state.unsavedFeatures.forEach(function(f) { // TODO: make sure we don't overwrite an existing feature if (f.name === feature.name) { state.savedFeatures.unshift(f); } else { unsaved.push(f); } }); this.setState({unsavedFeatures: unsaved}); reqwest({ url: 'features', method: 'post', type: 'json', contentType: 'application/json', data: JSON.stringify(feature) }).then(function(r) { console.log(r); }.bind(this), this.handleError); }, newFeature: function() { var blankFeature = { name: '', enabled: false, strategy: 'default', parameters: {} }; this.state.unsavedFeatures.push(blankFeature); this.forceUpdate(); }, render: function() { return (
    ); } }); React.renderComponent( , document.getElementById('content') );