From eea7b8a7c74b372e169af007e1b27e46027ff634 Mon Sep 17 00:00:00 2001 From: Aurélien Bompard Date: Mar 03 2017 17:29:14 +0000 Subject: [PATCH 1/3] Split out the Feed widget to make it more independant This allows more React-based widgets to coexist without bundling the React libraries twice. --- diff --git a/hubs/static/client/app/__tests__/Feed.test.js b/hubs/static/client/app/__tests__/Feed.test.js index ae93f29..76daf32 100644 --- a/hubs/static/client/app/__tests__/Feed.test.js +++ b/hubs/static/client/app/__tests__/Feed.test.js @@ -1,11 +1,11 @@ /* eslint-env jasmine, jest */ -jest.unmock('../components/Feed.jsx'); +jest.unmock('../widgets/feed/Feed.jsx'); import React from 'react'; import TestUtils from 'react-addons-test-utils'; -import Feed from '../components/Feed.jsx'; +import Feed from '../widgets/feed/Feed.jsx'; describe('Feed', () => { const matches = [{ diff --git a/hubs/static/client/app/components/Feed.jsx b/hubs/static/client/app/components/Feed.jsx deleted file mode 100644 index b196bdb..0000000 --- a/hubs/static/client/app/components/Feed.jsx +++ /dev/null @@ -1,51 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; - -import Panel from './Panel.jsx'; - -export default class Feed extends React.Component { - constructor(props) { - super(props); - this.state = { - matches: this.props.matches, - messageLimit: this.props.options.messageLimit, - sse: true, - }; - // If it wasn't instantiated with a url or an error happened, bail - if (!this.props.url || !this.state.sse) { - return; - } - this.source = (!!window.EventSource) ? new EventSource(this.props.url) : null; - if (!this.source) { - return; - } - this.source.addEventListener('error', () => { - this.state.sse = false; - }, false); - window.onbeforeunload = () => { - this.source.close(); - }; - this.source.onmessage = resp => { - const data = JSON.parse(resp.data); - if (this.state.matches.length >= this.state.messageLimit) { - this.state.matches.pop(); - } - this.state.matches.unshift(data); - this.setState({ matches: this.state.matches }); - }; - } - render() { - const feedNodes = this.state.matches.map((match, idx) => { - return ; - }); - return ( -
- {feedNodes} -
- ); - } -} - -window.Feed = Feed; -window.React = React; -window.ReactDOM = ReactDOM; diff --git a/hubs/static/client/app/index.jsx b/hubs/static/client/app/index.jsx deleted file mode 100644 index 7641684..0000000 --- a/hubs/static/client/app/index.jsx +++ /dev/null @@ -1,5 +0,0 @@ -/* This import is needed even though it's not used - * since the feed component places itself on window. - * The feed will not work without it. - */ -import Feed from './components/Feed.jsx'; // eslint-disable-line diff --git a/hubs/static/client/app/widgets/feed/Feed.jsx b/hubs/static/client/app/widgets/feed/Feed.jsx new file mode 100644 index 0000000..beec5f7 --- /dev/null +++ b/hubs/static/client/app/widgets/feed/Feed.jsx @@ -0,0 +1,53 @@ +import React from 'react'; +import Panel from '../../components/Panel.jsx'; + + +class Feed extends React.Component { + + constructor(props) { + super(props); + this.state = { + matches: this.props.matches, + messageLimit: this.props.options.messageLimit, + sse: true, + }; + // If it wasn't instantiated with a url or an error happened, bail + if (!this.props.url || !this.state.sse) { + return; + } + this.source = (!!window.EventSource) ? new EventSource(this.props.url) : null; + if (!this.source) { + return; + } + this.source.addEventListener('error', () => { + this.state.sse = false; + }, false); + window.onbeforeunload = () => { + this.source.close(); + }; + this.source.onmessage = resp => { + const data = JSON.parse(resp.data); + if (this.state.matches.length >= this.state.messageLimit) { + this.state.matches.pop(); + } + this.state.matches.unshift(data); + this.setState({ matches: this.state.matches }); + }; + } + + render() { + const feedNodes = this.state.matches.map((match, idx) => { + return ; + }); + return ( +
+ {feedNodes} +
+ ); + } + +} + +// Don't use the ES6 "export default" construct: +// http://stackoverflow.com/questions/40294870/module-exports-vs-export-default-in-node-js-and-es6 +module.exports = Feed diff --git a/hubs/static/client/webpack.config.js b/hubs/static/client/webpack.config.js index 065ce2f..f97606a 100644 --- a/hubs/static/client/webpack.config.js +++ b/hubs/static/client/webpack.config.js @@ -3,16 +3,22 @@ const path = require('path'); const PATHS = { app: path.join(__dirname, 'app'), - build: path.join(__dirname, '../js') + build: path.join(__dirname, '..', 'js', 'build') }; const config = { entry: { - app: path.join(PATHS.app, 'index.jsx') + Feed: path.join(PATHS.app, 'widgets', 'feed', 'Feed.jsx'), }, output: { path: PATHS.build, - filename: 'hubs.js' + filename: '[name].js', + library: '[name]', + }, + externals: { + 'jquery': 'jQuery', + 'react': 'React', + 'react-dom': 'ReactDOM', }, module : { loaders : [{ @@ -21,7 +27,8 @@ const config = { exclude: /(node_modules|bowercomponents)/, include : PATHS.app }] - } + }, + plugins: [ new webpack.optimize.CommonsChunkPlugin("common.js") ] }; module.exports = config; diff --git a/hubs/static/js/build/.gitignore b/hubs/static/js/build/.gitignore new file mode 100644 index 0000000..a6c7c28 --- /dev/null +++ b/hubs/static/js/build/.gitignore @@ -0,0 +1 @@ +*.js diff --git a/hubs/templates/hubs.html b/hubs/templates/hubs.html index de71ed6..8f73175 100644 --- a/hubs/templates/hubs.html +++ b/hubs/templates/hubs.html @@ -199,6 +199,8 @@ {{ super() }} + {% if edit %} + + {% endblock %} diff --git a/hubs/templates/stream.html b/hubs/templates/stream.html index 8586d2a..f9e00c5 100644 --- a/hubs/templates/stream.html +++ b/hubs/templates/stream.html @@ -66,10 +66,12 @@ {% block jscripts %} {{ super() }} - + + + src ="{{url_for('static', filename='js/build/Feed.js')}}"> {% endblock %} From 5178274b913855137854ca17b9d684cdfb84c317 Mon Sep 17 00:00:00 2001 From: Aurélien Bompard Date: Mar 03 2017 17:29:14 +0000 Subject: [PATCH 2/3] Fix the syntax of the eslintrc file --- diff --git a/hubs/static/client/.eslintrc.json b/hubs/static/client/.eslintrc.json index 62ca52c..434bab5 100644 --- a/hubs/static/client/.eslintrc.json +++ b/hubs/static/client/.eslintrc.json @@ -1,9 +1,8 @@ { - "extends": "airbnb", "rules": { "arrow-body-style": "off", - "func-names": "off" + "func-names": "off", "react/prefer-stateless-function": "off", - "react/prop-types": "off", + "react/prop-types": "off" } } From 2a9d397089abdfc3c8cb3e43092b243c1813afb9 Mon Sep 17 00:00:00 2001 From: Aurélien Bompard Date: Mar 03 2017 17:29:14 +0000 Subject: [PATCH 3/3] Make the JS setup_feed function independant from template tags This will allow moving it to an external JS file. --- diff --git a/hubs/models.py b/hubs/models.py index 2b7b6d5..f476bb6 100644 --- a/hubs/models.py +++ b/hubs/models.py @@ -274,11 +274,6 @@ class Hub(BASE): if w.plugin in hubs.widgets.registry and not w.left], key=lambda w: w.index) - @property - def widgets_idx(self): - """Returns the list of indices for this hub's widgets.""" - return [w.idx for w in self.widgets] - def __json__(self): return { 'name': self.name, diff --git a/hubs/templates/stream.html b/hubs/templates/stream.html index f9e00c5..e33c301 100644 --- a/hubs/templates/stream.html +++ b/hubs/templates/stream.html @@ -73,55 +73,56 @@ {% endblock %}