mirror of
https://github.com/Febbweiss/springboot-react-webpack.git
synced 2026-03-04 22:25:34 +00:00
Prepare ES6 migration
This commit is contained in:
10
package.json
10
package.json
@@ -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"
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
<div className="comment">
|
||||
<h2 className="commentAuthor">
|
||||
{this.props.author}
|
||||
</h2>
|
||||
<span dangerouslySetInnerHTML={this.rawMarkup()} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
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 (
|
||||
<form className="commentForm" onSubmit={this.handleSubmit}>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Your name"
|
||||
value={this.state.author}
|
||||
onChange={this.handleAuthorChange}
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Say something..."
|
||||
value={this.state.text}
|
||||
onChange={this.handleTextChange}
|
||||
/>
|
||||
<input type="submit" value="Post" />
|
||||
</form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
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 (
|
||||
<div className="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList data={this.state.data}/>
|
||||
<CommentForm onCommentSubmit={this.handleCommentSubmit}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
var CommentList = React.createClass({
|
||||
render: function() {
|
||||
var commentNodes = this.props.data.map( function(comment) {
|
||||
return (
|
||||
<Comment author={comment.author} key={comment.id}>{comment.text}</Comment>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<div className="commentList">
|
||||
{commentNodes}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
CommentBox: CommentBox,
|
||||
CommentList: CommentList,
|
||||
CommentForm: CommentForm,
|
||||
Comment: Comment
|
||||
};
|
||||
@@ -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 || [];
|
||||
global.renderClient = function renderClient(comments) {
|
||||
const data = comments || [];
|
||||
ReactDOM.render(
|
||||
<App.CommentBox data={data} url="/api/comments" pollInterval={2000}/>,
|
||||
<CommentBox data={data} url="/api/comments" pollInterval={2000} />,
|
||||
document.getElementById('content')
|
||||
);
|
||||
};
|
||||
|
||||
global.renderServer = function (comments) {
|
||||
var data = Java.from(comments);
|
||||
global.renderServer = function renderServer(comments) {
|
||||
const data = Java.from(comments);
|
||||
return ReactDOMServer.renderToString(
|
||||
<App.CommentBox data={data} url="/api/comments" pollInterval={2000} />
|
||||
<CommentBox data={data} url="/api/comments" pollInterval={2000} />
|
||||
);
|
||||
};
|
||||
|
||||
if( !global.nashorn ) {
|
||||
renderClient(initialData);
|
||||
};
|
||||
if (!global.nashorn) {
|
||||
global.renderClient(global.initialData);
|
||||
}
|
||||
|
||||
23
src/main/resources/static/js/comment.jsx
Normal file
23
src/main/resources/static/js/comment.jsx
Normal file
@@ -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 (
|
||||
<div className="comment">
|
||||
<h2 className="commentAuthor">
|
||||
{this.props.author}
|
||||
</h2>
|
||||
<span dangerouslySetInnerHTML={this.rawMarkup()} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
Comment.propTypes = {
|
||||
author: React.PropTypes.string,
|
||||
children: React.PropTypes.node,
|
||||
};
|
||||
65
src/main/resources/static/js/comment_box.jsx
Normal file
65
src/main/resources/static/js/comment_box.jsx
Normal file
@@ -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 (
|
||||
<div className="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList data={this.state.data} />
|
||||
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
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,
|
||||
};
|
||||
47
src/main/resources/static/js/comment_form.jsx
Normal file
47
src/main/resources/static/js/comment_form.jsx
Normal file
@@ -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 (
|
||||
<form className="commentForm" onSubmit={this.handleSubmit}>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Your name"
|
||||
value={this.state.author}
|
||||
onChange={this.handleAuthorChange}
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Say something..."
|
||||
value={this.state.text}
|
||||
onChange={this.handleTextChange}
|
||||
/>
|
||||
<input type="submit" value="Post" />
|
||||
</form>
|
||||
);
|
||||
}
|
||||
}
|
||||
CommentForm.propTypes = {
|
||||
author: React.PropTypes.string,
|
||||
text: React.PropTypes.string,
|
||||
onCommentSubmit: React.PropTypes.func,
|
||||
};
|
||||
@@ -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');
|
||||
import 'bootstrap/dist/css/bootstrap.css';
|
||||
|
||||
@@ -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
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user