From e7ecae51b70ec0dfcc2d5cf3d91c9f0970eeccbb Mon Sep 17 00:00:00 2001 From: Jari Bakken Date: Thu, 30 Oct 2014 18:25:38 +0100 Subject: [PATCH] Move components to separate files. --- .jshintrc | 2 +- unleash-server/package.json | 2 +- unleash-server/public/js/app.jsx | 7 + .../public/js/components/ErrorMessages.jsx | 21 ++ .../public/js/components/FeatureList.jsx | 52 +++ unleash-server/public/js/components/Menu.jsx | 14 + .../public/js/components/SavedFeature.jsx | 32 ++ .../public/js/components/Unleash.jsx | 131 +++++++ .../public/js/components/UnsavedFeature.jsx | 68 ++++ unleash-server/public/js/unleash.jsx | 336 ------------------ unleash-server/public/js/utils/Timer.js | 26 ++ unleash-server/webpack.config.js | 2 +- 12 files changed, 354 insertions(+), 339 deletions(-) create mode 100644 unleash-server/public/js/app.jsx create mode 100644 unleash-server/public/js/components/ErrorMessages.jsx create mode 100644 unleash-server/public/js/components/FeatureList.jsx create mode 100644 unleash-server/public/js/components/Menu.jsx create mode 100644 unleash-server/public/js/components/SavedFeature.jsx create mode 100644 unleash-server/public/js/components/Unleash.jsx create mode 100644 unleash-server/public/js/components/UnsavedFeature.jsx delete mode 100644 unleash-server/public/js/unleash.jsx create mode 100644 unleash-server/public/js/utils/Timer.js diff --git a/.jshintrc b/.jshintrc index 5688a3d2a1..6cd19abfe9 100644 --- a/.jshintrc +++ b/.jshintrc @@ -30,7 +30,7 @@ "nonbsp" : true, "nonew" : true, "plusplus" : false, - "quotmark" : true, + "quotmark" : false, "undef" : true, "unused" : true, "strict" : false, diff --git a/unleash-server/package.json b/unleash-server/package.json index 8f5bed7838..bd87f88f83 100644 --- a/unleash-server/package.json +++ b/unleash-server/package.json @@ -20,7 +20,7 @@ "start": "NODE_ENV=production node server.js", "build": "./node_modules/.bin/webpack", "dev": "NODE_ENV=development supervisor --ignore ./node_modules/,./public/js server.js", - "test": "jshint server.js lib test && jsxhint public/js/*.jsx && mocha test test/* && npm run coverage", + "test": "jshint server.js lib test && jsxhint public/js/**/*.jsx && mocha test test/* && npm run coverage", "tdd": "mocha --watch test test/*", "test-bamboo-ci": "mocha test test/*", "coverage": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec", diff --git a/unleash-server/public/js/app.jsx b/unleash-server/public/js/app.jsx new file mode 100644 index 0000000000..cd8a0dae76 --- /dev/null +++ b/unleash-server/public/js/app.jsx @@ -0,0 +1,7 @@ +var React = require('react'); +var Unleash = require('./components/Unleash'); + +React.render( + , + document.getElementById('content') +); \ No newline at end of file diff --git a/unleash-server/public/js/components/ErrorMessages.jsx b/unleash-server/public/js/components/ErrorMessages.jsx new file mode 100644 index 0000000000..153348ef0b --- /dev/null +++ b/unleash-server/public/js/components/ErrorMessages.jsx @@ -0,0 +1,21 @@ +var React = require('react'); + +var ErrorMessages = React.createClass({ + render: function() { + if (!this.props.errors.length) { + return
; + } + + var errorNodes = this.props.errors.map(function(e) { + return (
  • {e}
  • ); + }); + + return ( +
    +
      {errorNodes}
    +
    + ); + } +}); + +module.exports = ErrorMessages; \ No newline at end of file diff --git a/unleash-server/public/js/components/FeatureList.jsx b/unleash-server/public/js/components/FeatureList.jsx new file mode 100644 index 0000000000..542f2d1c5c --- /dev/null +++ b/unleash-server/public/js/components/FeatureList.jsx @@ -0,0 +1,52 @@ +var React = require('react'); +var SavedFeature = require('./SavedFeature'); +var UnsavedFeature = require('./UnsavedFeature'); + +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} +
    +
    +
    + ); + } +}); + +module.exports = FeatureList; \ No newline at end of file diff --git a/unleash-server/public/js/components/Menu.jsx b/unleash-server/public/js/components/Menu.jsx new file mode 100644 index 0000000000..9516df1d19 --- /dev/null +++ b/unleash-server/public/js/components/Menu.jsx @@ -0,0 +1,14 @@ +var React = require('react'); + +var Menu = React.createClass({ + render: function() { return ( + + ); + } +}); + +module.exports = Menu; \ No newline at end of file diff --git a/unleash-server/public/js/components/SavedFeature.jsx b/unleash-server/public/js/components/SavedFeature.jsx new file mode 100644 index 0000000000..aef57f663a --- /dev/null +++ b/unleash-server/public/js/components/SavedFeature.jsx @@ -0,0 +1,32 @@ +var React = require('react'); + +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} +
    +
    + ); + } +}); + +module.exports = SavedFeature; \ No newline at end of file diff --git a/unleash-server/public/js/components/Unleash.jsx b/unleash-server/public/js/components/Unleash.jsx new file mode 100644 index 0000000000..7502377326 --- /dev/null +++ b/unleash-server/public/js/components/Unleash.jsx @@ -0,0 +1,131 @@ +var React = require('react'); +var reqwest = require('reqwest'); +var Timer = require('../utils/Timer'); +var Menu = require('./Menu'); +var ErrorMessages = require('./ErrorMessages'); +var FeatureList = require('./FeatureList'); + +var Unleash = React.createClass({ + getInitialState: function() { + return { + savedFeatures: [], + unsavedFeatures: [], + errors: [], + timer: null + }; + }, + + componentDidMount: function () { + this.loadFeaturesFromServer(); + this.state.timer = new Timer(this.loadFeaturesFromServer, this.props.pollInterval); + this.state.timer.start(); + }, + + componentWillUnmount: function () { + if (this.state.timer != null) { + this.state.timer.stop(); + } + }, + + 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.statusText); + }.bind(this), this.handleError); + }, + + newFeature: function() { + var blankFeature = { + name: '', + enabled: false, + strategy: 'default', + parameters: {} + }; + + this.state.unsavedFeatures.push(blankFeature); + this.forceUpdate(); + }, + + cancelNewFeature: function (feature) { + var unsaved = []; + + this.state.unsavedFeatures.forEach(function (f) { + if (f.name !== feature.name) { + unsaved.push(f); + } + }); + + this.setState({unsavedFeatures: unsaved}); + }, + + render: function() { + return ( +
    + + + +
    + ); + } +}); + +module.exports = Unleash; \ No newline at end of file diff --git a/unleash-server/public/js/components/UnsavedFeature.jsx b/unleash-server/public/js/components/UnsavedFeature.jsx new file mode 100644 index 0000000000..7ac66da90d --- /dev/null +++ b/unleash-server/public/js/components/UnsavedFeature.jsx @@ -0,0 +1,68 @@ +var React = require('react'); + +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); + }, + + cancelFeature: function(e) { + e.preventDefault(); + this.props.onCancel(this.props.feature); + } +}); + +module.exports = UnsavedFeature; \ No newline at end of file diff --git a/unleash-server/public/js/unleash.jsx b/unleash-server/public/js/unleash.jsx deleted file mode 100644 index 468b79e86d..0000000000 --- a/unleash-server/public/js/unleash.jsx +++ /dev/null @@ -1,336 +0,0 @@ -/* jshint quotmark:false */ - -var React = require('react'); -var reqwest = require('reqwest'); - -// 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); - }, - - cancelFeature: function(e) { - e.preventDefault(); - this.props.onCancel(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: [], - timer: null - }; - }, - - componentDidMount: function () { - this.loadFeaturesFromServer(); - this.state.timer = new Timer(this.loadFeaturesFromServer, this.props.pollInterval); - this.state.timer.start(); - }, - - componentWillUnmount: function () { - if (this.state.timer != null) { - this.state.timer.stop(); - } - }, - - 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.statusText); - }.bind(this), this.handleError); - }, - - newFeature: function() { - var blankFeature = { - name: '', - enabled: false, - strategy: 'default', - parameters: {} - }; - - this.state.unsavedFeatures.push(blankFeature); - this.forceUpdate(); - }, - - cancelNewFeature: function (feature) { - var unsaved = []; - - this.state.unsavedFeatures.forEach(function (f) { - if (f.name !== feature.name) { - unsaved.push(f); - } - }); - - this.setState({unsavedFeatures: unsaved}); - }, - - render: function() { - return ( -
    - - - -
    - ); - } -}); - - -React.render( - , - document.getElementById('content') -); \ No newline at end of file diff --git a/unleash-server/public/js/utils/Timer.js b/unleash-server/public/js/utils/Timer.js new file mode 100644 index 0000000000..8e366fbbb1 --- /dev/null +++ b/unleash-server/public/js/utils/Timer.js @@ -0,0 +1,26 @@ +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; + } +}; + +module.exports = Timer; \ No newline at end of file diff --git a/unleash-server/webpack.config.js b/unleash-server/webpack.config.js index 4fd587cfca..67c64c6e61 100644 --- a/unleash-server/webpack.config.js +++ b/unleash-server/webpack.config.js @@ -3,7 +3,7 @@ module.exports = { context: __dirname + '/public', - entry: './js/unleash', + entry: './js/app', output: { path: __dirname + '/public/js',