require 'opal' require 'opal-jquery' require "json" require 'react' class Window def self.set_interval(delay, &block) `window.setInterval(function(){#{block.call}}, #{delay.to_i})` end end class Comment include React::Component def render converter = Native(`new Showdown.converter()`) raw_markup = converter.makeHtml(params[:children].to_s) div class_name: "comment" do h2(class_name: "commentAuthor") { params[:author] } span(dangerously_set_inner_HTML: {__html: raw_markup}.to_n) end end end class CommentList include React::Component def render div class_name: "commentList" do params[:data].each_with_index.map do |comment, idx| present(Comment, author: comment["author"], key: idx) { comment["text"] } end end end end class CommentForm include React::Component def render f = form(class_name: "commentForm") do input type: "text", placeholder: "Your name", ref: "author" input type: "text", placeholder: "Say something...", ref: "text" input type: "submit", value: "Post" end f.on(:submit) do |event| event.prevent_default author = self.refs[:author].dom_node.value.strip text = self.refs[:text].dom_node.value.strip return if !text || !author self.emit(:comment_submit, {author: author, text: text}) self.refs[:author].dom_node.value = "" self.refs[:text].dom_node.value = "" end end end class CommentBox include React::Component after_mount :load_comments_from_server, :start_polling define_state(:data) { [] } def load_comments_from_server HTTP.get(params[:url]) do |response| if response.ok? self.data = JSON.parse(response.body) else puts "failed with status #{response.status_code}" end end end def start_polling Window.set_interval(params[:poll_interval]) { load_comments_from_server } end def handle_comment_submit(comment) comments = self.data comments.push(comment) self.data = comments HTTP.post(params[:url], payload: comment) do |response| if response.ok? self.data = JSON.parse(response.body) else puts "failed with status #{response.status_code}" end end end def render div class_name: "commentBox" do h1 { "Comments" } present CommentList, data: self.data present(CommentForm).on(:comment_submit) {|c| handle_comment_submit(c) } end end end Document.ready? do React.render React.create_element(CommentBox, url: "comments.json", poll_interval: 2000), `document.getElementById('content')` end