From 67c3c50b9b39dfcc551898c57a4bbf87fe5ba6a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivar=20Conradi=20=C3=98sthus?= Date: Tue, 24 Mar 2015 21:25:32 +0100 Subject: [PATCH 1/5] Move to react-router. Replaced our home built tab-view with the react-router. This makes routing super simple for us. https://github.com/rackt/react-router/ relates to #95 --- package.json | 1 + public/js/UnleashApp.jsx | 82 +++++++++++++++++++------------- public/js/components/Menu.jsx | 3 +- public/js/components/TabView.jsx | 62 ------------------------ webpack.config.js | 2 +- 5 files changed, 54 insertions(+), 96 deletions(-) delete mode 100644 public/js/components/TabView.jsx diff --git a/package.json b/package.json index 34ccfa1c7b..ab8b89bec0 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "nconf": "0.7.1", "pg": "4.3.0", "react": "^0.13.1", + "react-router": "^0.13.2", "reflux": "^0.2.5", "reqwest": "^1.1.4", "webpack": "1.7.3", diff --git a/public/js/UnleashApp.jsx b/public/js/UnleashApp.jsx index fb804ed8a9..2ec4379c05 100644 --- a/public/js/UnleashApp.jsx +++ b/public/js/UnleashApp.jsx @@ -1,52 +1,56 @@ var React = require('react'); -var TabView = require('./components/TabView'); -var Menu = require('./components/Menu'); var UserStore = require('./stores/UserStore'); +var Menu = require('./components/Menu'); var ErrorMessages = require('./components/ErrorMessages'); var initalizer = require('./stores/initalizer'); -var LogEntriesComponent = React.createFactory(require('./components/log/LogEntriesComponent')); -var FeatureTogglesComponent = React.createFactory(require('./components/feature/FeatureTogglesComponent')); -var StrategiesComponent = React.createFactory(require('./components/strategy/StrategiesComponent')); -var ArchiveFeatureComponent = React.createFactory(require('./components/feature/ArchiveFeatureComponent')); +var LogEntriesComponent = require('./components/log/LogEntriesComponent'); +var FeatureTogglesComponent = require('./components/feature/FeatureTogglesComponent'); +var StrategiesComponent = require('./components/strategy/StrategiesComponent'); +var ArchiveFeatureComponent = require('./components/feature/ArchiveFeatureComponent'); +var Router = require('react-router'); +var DefaultRoute = Router.DefaultRoute; +var Link = Router.Link; +var Route = Router.Route; +var RouteHandler = Router.RouteHandler; UserStore.init(); -var tabPanes = [ -{ - name: 'Feature Toggles', - slug: 'feature-toggles', - content: FeatureTogglesComponent -}, -{ - name: 'Strategies', - slug: 'strategies', - content: StrategiesComponent -}, -{ - name: "Log", - slug: 'log', - content: LogEntriesComponent -}, -{ - name: "Archive", - slug: 'archive', - content: ArchiveFeatureComponent -} -]; - - var UnleashApp = React.createClass({ + contextTypes: { + router: React.PropTypes.func + }, + componentWillMount: function() { initalizer(30); }, + render: function () { return (
- + + + Features + + + Strategies + + + Log + + + Archive + +
- +
+
+
+ +
+
+
@@ -54,4 +58,18 @@ var UnleashApp = React.createClass({ } }); +var routes = ( + + + + + + +); + +Router.run(routes, function (Handler) { + React.render(, document.getElementById('content')); +}); + + module.exports = UnleashApp; diff --git a/public/js/components/Menu.jsx b/public/js/components/Menu.jsx index 49442f3f05..d00572f313 100644 --- a/public/js/components/Menu.jsx +++ b/public/js/components/Menu.jsx @@ -10,7 +10,7 @@ var Menu = React.createClass({
- + - - {tabPane.name} - - - ); - }.bind(this)); - - return ( -
-
    - {tabNodes} -
-
-
-
-
-
- {new this.state.activeTab.content()} -
-
-
-
-
-
- ); - } -}); - -module.exports = TabView; diff --git a/webpack.config.js b/webpack.config.js index efbae1e6d8..97421d878c 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -7,7 +7,7 @@ var js_root = path.join(path.join(root, 'public'), 'js'); module.exports = { context: js_root, - entry: 'app', + entry: 'UnleashApp', output: { path: js_root, From 0c75f92e4c1181b5ea1826b0b2ea6fb560acbe92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivar=20Conradi=20=C3=98sthus?= Date: Tue, 24 Mar 2015 21:30:26 +0100 Subject: [PATCH 2/5] removed unused file --- public/js/app.jsx | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 public/js/app.jsx diff --git a/public/js/app.jsx b/public/js/app.jsx deleted file mode 100644 index 4cf42046b0..0000000000 --- a/public/js/app.jsx +++ /dev/null @@ -1,3 +0,0 @@ -var React = require('react'); -var UnleashApp = require('./UnleashApp'); -React.render(, document.getElementById('content')); From c6c858e94ac9fbdaa0f50f323056d91ce2af1793 Mon Sep 17 00:00:00 2001 From: ivaosthu Date: Fri, 27 Mar 2015 10:55:42 +0100 Subject: [PATCH 3/5] Clean up entry point --- public/js/UnleashApp.jsx | 48 +++++++++++----------------------------- public/js/app.jsx | 10 +++++++++ public/js/routes.jsx | 20 +++++++++++++++++ webpack.config.js | 2 +- 4 files changed, 44 insertions(+), 36 deletions(-) create mode 100644 public/js/app.jsx create mode 100644 public/js/routes.jsx diff --git a/public/js/UnleashApp.jsx b/public/js/UnleashApp.jsx index 2ec4379c05..b407773a5c 100644 --- a/public/js/UnleashApp.jsx +++ b/public/js/UnleashApp.jsx @@ -1,20 +1,11 @@ var React = require('react'); -var UserStore = require('./stores/UserStore'); +var Router = require('react-router'); var Menu = require('./components/Menu'); var ErrorMessages = require('./components/ErrorMessages'); var initalizer = require('./stores/initalizer'); -var LogEntriesComponent = require('./components/log/LogEntriesComponent'); -var FeatureTogglesComponent = require('./components/feature/FeatureTogglesComponent'); -var StrategiesComponent = require('./components/strategy/StrategiesComponent'); -var ArchiveFeatureComponent = require('./components/feature/ArchiveFeatureComponent'); -var Router = require('react-router'); -var DefaultRoute = Router.DefaultRoute; var Link = Router.Link; -var Route = Router.Route; var RouteHandler = Router.RouteHandler; -UserStore.init(); - var UnleashApp = React.createClass({ contextTypes: { router: React.PropTypes.func @@ -24,22 +15,22 @@ var UnleashApp = React.createClass({ initalizer(30); }, + renderLink: function(id, label) { + return ( + + {label} + + ); + }, + render: function () { return (
- - Features - - - Strategies - - - Log - - - Archive - + {this.renderLink("features", "Toggles")} + {this.renderLink("strategies", "Strategies")} + {this.renderLink("log", "Log")} + {this.renderLink("archive", "Archive")}
@@ -58,18 +49,5 @@ var UnleashApp = React.createClass({ } }); -var routes = ( - - - - - - -); - -Router.run(routes, function (Handler) { - React.render(, document.getElementById('content')); -}); - module.exports = UnleashApp; diff --git a/public/js/app.jsx b/public/js/app.jsx new file mode 100644 index 0000000000..948026dd48 --- /dev/null +++ b/public/js/app.jsx @@ -0,0 +1,10 @@ +var React = require('react'); +var Router = require('react-router'); +var UserStore = require('./stores/UserStore'); +var routes = require('./routes'); + +UserStore.init(); + +Router.run(routes, function (Handler) { + React.render(, document.getElementById('content')); +}); diff --git a/public/js/routes.jsx b/public/js/routes.jsx new file mode 100644 index 0000000000..7b0d3fd2d8 --- /dev/null +++ b/public/js/routes.jsx @@ -0,0 +1,20 @@ +var React = require('react'); +var Router = require('react-router'); +var UnleashApp = require('./UnleashApp'); +var LogEntriesComponent = require('./components/log/LogEntriesComponent'); +var FeatureTogglesComponent = require('./components/feature/FeatureTogglesComponent'); +var StrategiesComponent = require('./components/strategy/StrategiesComponent'); +var ArchiveFeatureComponent = require('./components/feature/ArchiveFeatureComponent'); +var DefaultRoute = Router.DefaultRoute; +var Route = Router.Route; + +var routes = ( + + + + + + +); + +module.exports = routes; diff --git a/webpack.config.js b/webpack.config.js index 97421d878c..efbae1e6d8 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -7,7 +7,7 @@ var js_root = path.join(path.join(root, 'public'), 'js'); module.exports = { context: js_root, - entry: 'UnleashApp', + entry: 'app', output: { path: js_root, From 5964c374bc11c846c2f154507f75ff6e3390662b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivar=20Conradi=20=C3=98sthus?= Date: Fri, 27 Mar 2015 22:19:56 +0100 Subject: [PATCH 4/5] Application states should be loaded as high up as possible --- public/js/UnleashApp.jsx | 46 ++++++++++++++++++- .../feature/ArchiveFeatureComponent-test.js | 9 +--- .../feature/ArchiveFeatureComponent.jsx | 22 +-------- .../feature/FeatureTogglesComponent.jsx | 21 ++------- .../strategy/StrategiesComponent.jsx | 18 +------- 5 files changed, 53 insertions(+), 63 deletions(-) diff --git a/public/js/UnleashApp.jsx b/public/js/UnleashApp.jsx index b407773a5c..724bcbdd2f 100644 --- a/public/js/UnleashApp.jsx +++ b/public/js/UnleashApp.jsx @@ -3,6 +3,9 @@ var Router = require('react-router'); var Menu = require('./components/Menu'); var ErrorMessages = require('./components/ErrorMessages'); var initalizer = require('./stores/initalizer'); +var FeatureToggleStore = require('./stores/FeatureToggleStore'); +var StrategyStore = require('./stores/StrategyStore'); +var ArchiveStore = require('./stores/ArchivedToggleStore'); var Link = Router.Link; var RouteHandler = Router.RouteHandler; @@ -11,6 +14,43 @@ var UnleashApp = React.createClass({ router: React.PropTypes.func }, + getInitialState: function() { + return { + features: FeatureToggleStore.getFeatureToggles(), + strategies: StrategyStore.getStrategies(), + archivedFeatures: ArchiveStore.getArchivedToggles() + }; + }, + + onFeatureToggleChange: function() { + this.setState({ + features: FeatureToggleStore.getFeatureToggles() + }); + }, + + onStrategiesChange: function() { + this.setState({ + strategies: StrategyStore.getStrategies() + }); + }, + + onArchiveChange: function() { + this.setState({ + archivedFeatures: ArchiveStore.getArchivedToggles() + }); + }, + + componentDidMount: function() { + this.unsubscribeFS = FeatureToggleStore.listen(this.onFeatureToggleChange); + this.unsubscribeSS = StrategyStore.listen(this.onStrategiesChange); + this.unsubscribeAS = ArchiveStore.listen(this.onArchiveChange); + }, + componentWillUnmount: function() { + this.unsubscribeFS(); + this.unsubscribeSS(); + this.unsubscribeAS(); + }, + componentWillMount: function() { initalizer(30); }, @@ -38,7 +78,11 @@ var UnleashApp = React.createClass({
- +
diff --git a/public/js/__tests__/components/feature/ArchiveFeatureComponent-test.js b/public/js/__tests__/components/feature/ArchiveFeatureComponent-test.js index a219abd55c..7a874aec6d 100644 --- a/public/js/__tests__/components/feature/ArchiveFeatureComponent-test.js +++ b/public/js/__tests__/components/feature/ArchiveFeatureComponent-test.js @@ -16,13 +16,8 @@ describe("FeatureForm", function () { { name: "featureY" } ]; - Server.getArchivedFeatures.mockImplementation(function(cb) { - cb(null, archivedToggles); - }); - - FeatureToggleStore.initStore(archivedToggles); - - Component = TestUtils.renderIntoDocument(); + Component = TestUtils.renderIntoDocument( + ); }); afterEach(function() { diff --git a/public/js/components/feature/ArchiveFeatureComponent.jsx b/public/js/components/feature/ArchiveFeatureComponent.jsx index 3730d0d0cb..6d0304e44b 100644 --- a/public/js/components/feature/ArchiveFeatureComponent.jsx +++ b/public/js/components/feature/ArchiveFeatureComponent.jsx @@ -1,27 +1,7 @@ var React = require("react"); var FeatureActions = require('../../stores/FeatureToggleActions'); -var FeatureToggleStore = require('../../stores/ArchivedToggleStore'); var ArchiveFeatureComponent = React.createClass({ - getInitialState: function() { - return { - archivedFeatures: FeatureToggleStore.getArchivedToggles() - }; - }, - - onStoreChange: function() { - this.setState({ - archivedFeatures: FeatureToggleStore.getArchivedToggles() - }); - }, - - componentDidMount: function() { - this.unsubscribe = FeatureToggleStore.listen(this.onStoreChange); - }, - - componentWillUnmount: function() { - this.unsubscribe(); - }, onRevive: function(item) { FeatureActions.revive.triggerPromise(item); @@ -39,7 +19,7 @@ var ArchiveFeatureComponent = React.createClass({ - {this.state.archivedFeatures.map(this.renderArchivedItem)} + {this.props.archivedFeatures.map(this.renderArchivedItem)}
diff --git a/public/js/components/feature/FeatureTogglesComponent.jsx b/public/js/components/feature/FeatureTogglesComponent.jsx index 683d362d3a..37661e1130 100644 --- a/public/js/components/feature/FeatureTogglesComponent.jsx +++ b/public/js/components/feature/FeatureTogglesComponent.jsx @@ -3,29 +3,14 @@ var FeatureList = require('./FeatureList'); var FeatureForm = require('./FeatureForm'); var FeatureActions = require('../../stores/FeatureToggleActions'); var ErrorActions = require('../../stores/ErrorActions'); -var FeatureToggleStore = require('../../stores/FeatureToggleStore'); -var StrategyStore = require('../../stores/StrategyStore'); var FeatureTogglesComponent = React.createClass({ getInitialState: function() { return { - features: FeatureToggleStore.getFeatureToggles(), createView: false }; }, - onFeatureToggleChange: function() { - this.setState({ - features: FeatureToggleStore.getFeatureToggles() - }); - }, - componentDidMount: function() { - this.unsubscribe = FeatureToggleStore.listen(this.onFeatureToggleChange); - }, - componentWillUnmount: function() { - this.unsubscribe(); - }, - updateFeature: function (feature) { FeatureActions.update.triggerPromise(feature); }, @@ -55,13 +40,13 @@ var FeatureTogglesComponent = React.createClass({ {this.state.createView ? this.renderCreateView() : this.renderCreateButton()} + strategies={this.props.strategies} />
); }, @@ -70,7 +55,7 @@ var FeatureTogglesComponent = React.createClass({ return ; + strategies={this.props.strategies} />; }, renderCreateButton: function() { diff --git a/public/js/components/strategy/StrategiesComponent.jsx b/public/js/components/strategy/StrategiesComponent.jsx index e913f6c03b..79fecd29f3 100644 --- a/public/js/components/strategy/StrategiesComponent.jsx +++ b/public/js/components/strategy/StrategiesComponent.jsx @@ -1,29 +1,15 @@ var React = require('react'); var StrategyList = require('./StrategyList'); var StrategyForm = require('./StrategyForm'); -var StrategyStore = require('../../stores/StrategyStore'); var StrategyActions = require('../../stores/StrategyActions'); var StrategiesComponent = React.createClass({ getInitialState: function() { return { - createView: false, - strategies: StrategyStore.getStrategies() + createView: false }; }, - onStoreChange: function() { - this.setState({ - strategies: StrategyStore.getStrategies() - }); - }, - componentDidMount: function() { - this.unsubscribe = StrategyStore.listen(this.onStoreChange); - }, - componentWillUnmount: function() { - this.unsubscribe(); - }, - onNewStrategy: function() { this.setState({createView: true}); }, @@ -48,7 +34,7 @@ var StrategiesComponent = React.createClass({ this.renderCreateView() : this.renderCreateButton()}
); From 0693cc40d3947fe1100afa892e53944ed2d11347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivar=20Conradi=20=C3=98sthus?= Date: Sat, 28 Mar 2015 09:51:31 +0100 Subject: [PATCH 5/5] Added headers to all pages --- public/js/components/feature/ArchiveFeatureComponent.jsx | 3 ++- public/js/components/feature/FeatureTogglesComponent.jsx | 2 ++ public/js/components/log/LogEntriesComponent.jsx | 1 + public/js/components/strategy/StrategiesComponent.jsx | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/public/js/components/feature/ArchiveFeatureComponent.jsx b/public/js/components/feature/ArchiveFeatureComponent.jsx index 6d0304e44b..5f6cb200d4 100644 --- a/public/js/components/feature/ArchiveFeatureComponent.jsx +++ b/public/js/components/feature/ArchiveFeatureComponent.jsx @@ -10,7 +10,8 @@ var ArchiveFeatureComponent = React.createClass({ render: function () { return (
-

Archived feature toggles

+

Archived Feature Toggles

+
diff --git a/public/js/components/feature/FeatureTogglesComponent.jsx b/public/js/components/feature/FeatureTogglesComponent.jsx index 37661e1130..85bdbeba0f 100644 --- a/public/js/components/feature/FeatureTogglesComponent.jsx +++ b/public/js/components/feature/FeatureTogglesComponent.jsx @@ -37,6 +37,8 @@ var FeatureTogglesComponent = React.createClass({ return (
+

Feature Toggles

+ {this.state.createView ? this.renderCreateView() : this.renderCreateButton()} +

Log


diff --git a/public/js/components/strategy/StrategiesComponent.jsx b/public/js/components/strategy/StrategiesComponent.jsx index 79fecd29f3..866d1fcf7c 100644 --- a/public/js/components/strategy/StrategiesComponent.jsx +++ b/public/js/components/strategy/StrategiesComponent.jsx @@ -30,6 +30,7 @@ var StrategiesComponent = React.createClass({ render: function() { return (
+

Activation Strategies

{this.state.createView ? this.renderCreateView() : this.renderCreateButton()}