diff --git a/.gitignore b/.gitignore index 58436cf..0c1f172 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,7 @@ .classpath .project .settings -src/main/resources/static -src/main/webapp/js/.module-cache +src/main/resources/static/js/.module-cache src/test/resources/static/js/compiled src/test/resources/static/js/.module-cache target diff --git a/pom.xml b/pom.xml index a8f2197..5ffaf35 100644 --- a/pom.xml +++ b/pom.xml @@ -311,6 +311,24 @@ ${project.basedir}/src/test/resources/jasmine/ReactJsSpecRunner.htmltemplate + + + org.cloudfoundry + cf-maven-plugin + 1.1.3 + + diff --git a/src/main/resources/static/css/comments.css b/src/main/resources/static/css/comments.css new file mode 100644 index 0000000..3578e80 --- /dev/null +++ b/src/main/resources/static/css/comments.css @@ -0,0 +1,12 @@ +#content { + margin-top: 60px; +} + +.footer { + position: absolute; + bottom: 0; + width: 100%; + height: 60px; + background-color: #101010; + color: #9d9d9d; +} \ No newline at end of file diff --git a/src/main/resources/static/js/app.jsx b/src/main/resources/static/js/app.jsx new file mode 100644 index 0000000..f4dc3da --- /dev/null +++ b/src/main/resources/static/js/app.jsx @@ -0,0 +1,123 @@ +'use strict'; + +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: []}; + }, + 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} +
+ ) + } +}); \ 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 new file mode 100644 index 0000000..9709ace --- /dev/null +++ b/src/main/resources/static/js/app.render.jsx @@ -0,0 +1,4 @@ +ReactDOM.render( + , + document.getElementById('content') +); \ No newline at end of file