From 74cc6e5b3a9517132f39d2d075f3b07244f03a1c Mon Sep 17 00:00:00 2001 From: fecaille Date: Wed, 6 Apr 2016 14:47:06 +0200 Subject: [PATCH] Prepare ES6 migration --- .eslintrc | 3 + package.json | 14 +- src/main/resources/static/js/app.jsx | 135 ------------------ src/main/resources/static/js/app.render.jsx | 41 +++--- src/main/resources/static/js/comment.jsx | 23 +++ src/main/resources/static/js/comment_box.jsx | 65 +++++++++ src/main/resources/static/js/comment_form.jsx | 47 ++++++ src/main/resources/static/js/vendors.js | 10 +- webpack.config.js | 9 +- 9 files changed, 178 insertions(+), 169 deletions(-) create mode 100644 .eslintrc delete mode 100644 src/main/resources/static/js/app.jsx create mode 100644 src/main/resources/static/js/comment.jsx create mode 100644 src/main/resources/static/js/comment_box.jsx create mode 100644 src/main/resources/static/js/comment_form.jsx diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..b0c0c8b --- /dev/null +++ b/.eslintrc @@ -0,0 +1,3 @@ +{ + "extends": "airbnb" +} diff --git a/package.json b/package.json index 7876824..2fbaf4a 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "springboot-react-webpack-demo", "version": "1.0.0", "dependencies": { - "bootstrap": "^3.3.6", + "bootstrap": "^3.3.6", "jquery": "^2.2.2", "marked": "^0.3.5", "react": "^0.14.7", @@ -10,10 +10,15 @@ }, "devDependencies": { "babel-core": "^6.7.4", + "babel-eslint": "^6.0.2", "babel-loader": "^6.2.4", "babel-preset-es2015": "^6.6.0", "babel-preset-react": "^6.5.0", "css-loader": "^0.23.1", + "eslint": "^2.5.3", + "eslint-config-airbnb": "^6.2.0", + "eslint-loader": "^1.3.0", + "eslint-plugin-react": "^4.2.3", "extract-text-webpack-plugin": "^1.0.1", "file-loader": "^0.8.5", "html-loader": "^0.4.3", @@ -27,8 +32,9 @@ "webpack-dev-server": "^1.14.1" }, "scripts": { - "watch": "NODE_ENV=development webpack-dev-server --hot --inline", - "dev-build": "NODE_ENV=development webpack --d --progress --colors", - "prod-build": "webpack -d -p --colors" + "dev-build": "NODE_ENV=development webpack --d --progress --colors", + "lint": "eslint --ignore-pattern **/nashorn-*.js --ext .js,.jsx src/main/resources/static/js/**", + "prod-build": "webpack -d -p --colors", + "watch": "NODE_ENV=development webpack-dev-server --hot --inline" } } diff --git a/src/main/resources/static/js/app.jsx b/src/main/resources/static/js/app.jsx deleted file mode 100644 index 57c3111..0000000 --- a/src/main/resources/static/js/app.jsx +++ /dev/null @@ -1,135 +0,0 @@ -'use strict'; - -var React = require('react'), - marked = require('marked'), - $ = require('jquery'); - -var Comment = React.createClass({ - rawMarkup: function() { - var rawMarkup = marked(this.props.children.toString(), {sanitize: true}); - return { __html: rawMarkup }; - }, - render: function() { - return ( -
-

- {this.props.author} -

- -
- ); - } -}); - -var CommentForm = React.createClass({ - getInitialState: function() { - return {author: '', text: ''}; - }, - handleAuthorChange: function(e) { - this.setState({author: e.target.value}); - }, - handleTextChange: function(e) { - this.setState({text: e.target.value}); - }, - handleSubmit: function(e) { - e.preventDefault(); - var author = this.state.author.trim(); - var text = this.state.text.trim(); - if( !text || !author ) { - return; - } - this.props.onCommentSubmit({author: author, text: text}) - this.setState({author: '', text: ''}); - }, - render: function() { - return ( -
- - - -
- ); - } -}); - -var CommentBox = React.createClass({ - getInitialState: function() { - return {data: this.props.data || []}; - }, - loadCommentsFromServer: function() { - $.ajax({ - url: this.props.url, - dataType: 'json', - cache: false, - success: function(data) { - this.setState({data: data}); - }.bind(this), - error: function(xhr, status, err) { - console.error(this.props.url, status, err.toString()); - }.bind(this) - }); - }, - handleCommentSubmit: function(comment) { - var comments = this.state.data; - comment.id = Date.now(); - var newComments = comments.concat([comment]); - this.setState({data: newComments}); - $.ajax({ - url: this.props.url, - method: 'POST', - dataType: 'json', - data: comment, - success: function(data) { - this.setState({data: data}); - }.bind(this), - error: function(xhr, status, err) { - this.setState({data: comments}); - console.error(this.props.url, status, err.toString()); - }.bind(this) - }); - }, - componentDidMount: function() { - this.loadCommentsFromServer(); - setInterval(this.loadCommentsFromServer, this.props.pollInterval); - }, - render: function() { - return ( -
-

Comments

- - -
- ); - } -}); -var CommentList = React.createClass({ - render: function() { - var commentNodes = this.props.data.map( function(comment) { - return ( - {comment.text} - ); - }); - return ( -
- {commentNodes} -
- ) - } -}); - -module.exports = { - CommentBox: CommentBox, - CommentList: CommentList, - CommentForm: CommentForm, - Comment: Comment -}; \ No newline at end of file diff --git a/src/main/resources/static/js/app.render.jsx b/src/main/resources/static/js/app.render.jsx index beed912..9d34e8c 100644 --- a/src/main/resources/static/js/app.render.jsx +++ b/src/main/resources/static/js/app.render.jsx @@ -1,32 +1,27 @@ -"use strict"; - - import React from 'react'; import ReactDOM from 'react-dom'; import ReactDOMServer from 'react-dom/server'; -import App from './app.jsx'; -import $ from 'jquery'; +import CommentBox from './comment_box.jsx'; +import 'bootstrap/dist/css/bootstrap.css'; +import '../css/comments.css'; +import '../css/comments.less'; -require('bootstrap/dist/css/bootstrap.css'); -require('../css/comments.css'); -require('../css/comments.less'); - -global.renderClient = function (comments) { - var data = comments || []; - ReactDOM.render( - , - document.getElementById('content') - ); +global.renderClient = function renderClient(comments) { + const data = comments || []; + ReactDOM.render( + , + document.getElementById('content') + ); }; -global.renderServer = function (comments) { - var data = Java.from(comments); - return ReactDOMServer.renderToString( - - ); +global.renderServer = function renderServer(comments) { + const data = Java.from(comments); + return ReactDOMServer.renderToString( + + ); }; -if( !global.nashorn ) { - renderClient(initialData); -}; \ No newline at end of file +if (!global.nashorn) { + global.renderClient(global.initialData); +} diff --git a/src/main/resources/static/js/comment.jsx b/src/main/resources/static/js/comment.jsx new file mode 100644 index 0000000..a7429c0 --- /dev/null +++ b/src/main/resources/static/js/comment.jsx @@ -0,0 +1,23 @@ +import React from 'react'; +import marked from 'marked'; + +class Comment extends React.Component { + rawMarkup() { + const rawMarkup = marked(this.props.children.toString(), { sanitize: true }); + return { __html: rawMarkup }; + } + render() { + return ( +
+

+ {this.props.author} +

+ +
+ ); + } +} +Comment.propTypes = { + author: React.PropTypes.string, + children: React.PropTypes.node, +}; diff --git a/src/main/resources/static/js/comment_box.jsx b/src/main/resources/static/js/comment_box.jsx new file mode 100644 index 0000000..6480ddd --- /dev/null +++ b/src/main/resources/static/js/comment_box.jsx @@ -0,0 +1,65 @@ +import React from 'react'; +import $ from 'jquery'; +import CommentForm from './comment_form.jsx'; +import CommentList from './comment_list.jsx'; + +class CommentBox extends React.Component { + componentDidMount() { + this.loadCommentsFromServer(); + setInterval(this.loadCommentsFromServer, this.props.pollInterval); + } + getInitialStatefunction() { + return { data: this.props.data || [] }; + } + loadCommentsFromServer() { + $.ajax({ + url: this.props.url, + dataType: 'json', + cache: false, + success: function success(data) { + this.setState({ data }); + }.bind(this), + error: function error(xhr, status, err) { + console.error(this.props.url, status, err.toString()); + }.bind(this), + }); + } + handleCommentSubmit(comment) { + const comments = this.state.data; + const copy = comment; + copy.id = Date.now(); + const newComments = comments.concat([copy]); + this.setState({ data: newComments }); + $.ajax({ + url: this.props.url, + method: 'POST', + dataType: 'json', + data: comment, + success: function success(data) { + this.setState({ data }); + }.bind(this), + error: function error(xhr, status, err) { + this.setState({ data: comments }); + console.error(this.props.url, status, err.toString()); + }.bind(this), + }); + } + render() { + return ( +
+

Comments

+ + +
+ ); + } +} +CommentBox.propTypes = { + data: React.PropTypes.shape({ + id: React.PropTypes.number, + author: React.PropTypes.string, + text: React.PropTypes.string, + }), + pollInterval: React.PropTypes.numbe, + url: React.PropTypes.string, +}; diff --git a/src/main/resources/static/js/comment_form.jsx b/src/main/resources/static/js/comment_form.jsx new file mode 100644 index 0000000..0809a24 --- /dev/null +++ b/src/main/resources/static/js/comment_form.jsx @@ -0,0 +1,47 @@ +import React from 'react'; + +class CommentForm extends React.Component { + getInitialState() { + return { author: '', text: '' }; + } + handleAuthorChange(e) { + this.setState({ author: e.target.value }); + } + handleTextChange(e) { + this.setState({ text: e.target.value }); + } + handleSubmit(e) { + e.preventDefault(); + const author = this.state.author.trim(); + const text = this.state.text.trim(); + if (!text || !author) { + return; + } + this.props.onCommentSubmit({ author, text }); + this.setState({ author: '', text: '' }); + } + render() { + return ( +
+ + + +
+ ); + } +} +CommentForm.propTypes = { + author: React.PropTypes.string, + text: React.PropTypes.string, + onCommentSubmit: React.PropTypes.func, +}; diff --git a/src/main/resources/static/js/vendors.js b/src/main/resources/static/js/vendors.js index 4b36877..57b10a4 100644 --- a/src/main/resources/static/js/vendors.js +++ b/src/main/resources/static/js/vendors.js @@ -1,7 +1,5 @@ -"use strict"; +import 'react'; +import 'react-dom'; +import 'jquery'; -require('react'); -require('react-dom'); -require('jquery'); - -require('bootstrap/dist/css/bootstrap.css'); \ No newline at end of file +import 'bootstrap/dist/css/bootstrap.css'; diff --git a/webpack.config.js b/webpack.config.js index 72995bd..0859a9f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -39,6 +39,13 @@ var config = { publicPath: 'http://localhost:' + dev_port + '/' }, module: { + preLoaders: [ + { + test: /\.jsx$|\.js$/, + loader: 'eslint-loader', + include: __dirname + '/src/main/resources/static/js' + } + ], loaders: [ { test: /\.jsx?$/, @@ -83,7 +90,7 @@ var config = { return []; }, htmlLoader: { - removeAttributeQuotes: false, + removeAttributeQuotes: false } };