diff --git a/Gemfile b/Gemfile index 7fea0bd..84017a6 100644 --- a/Gemfile +++ b/Gemfile @@ -89,3 +89,4 @@ gem 'haml-rails' # for extension font gem 'font-awesome-sass' +gem "websocket-rails" diff --git a/Gemfile.lock b/Gemfile.lock index fcd6477..822106b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -59,12 +59,19 @@ GEM coffee-script-source (1.9.1.1) columnize (0.9.0) crass (1.0.2) + daemons (1.2.3) debug_inspector (0.0.2) + em-synchrony (1.0.4) + eventmachine (>= 1.0.0.beta.1) erubis (2.7.0) escape_utils (1.1.0) + eventmachine (1.0.7) execjs (2.5.2) faraday (0.9.1) multipart-post (>= 1.2, < 3) + faye-websocket (0.10.0) + eventmachine (>= 0.12.0) + websocket-driver (>= 0.5.1) font-awesome-sass (4.3.2.1) sass (~> 3.2) gemoji (2.1.0) @@ -84,6 +91,7 @@ GEM html2haml (>= 1.0.1) railties (>= 4.0.1) hashie (3.4.2) + hiredis (0.6.0) html-pipeline (1.11.0) activesupport (>= 2) nokogiri (~> 1.4) @@ -173,6 +181,9 @@ GEM thor (>= 0.18.1, < 2.0) rake (10.4.2) rdoc (4.2.0) + redis (3.2.1) + redis-objects (1.2.0) + redis (>= 3.0.2) rinku (1.7.3) ruby_parser (3.7.0) sexp_processor (~> 4.1) @@ -204,6 +215,10 @@ GEM activesupport (>= 3.0) sprockets (>= 2.8, < 4.0) sqlite3 (1.3.10) + thin (1.6.3) + daemons (~> 1.0, >= 1.0.9) + eventmachine (~> 1.0) + rack (~> 1.0) thor (0.19.1) thread_safe (0.3.5) tilt (1.4.1) @@ -217,6 +232,18 @@ GEM binding_of_caller (>= 0.7.2) railties (>= 4.0) sprockets-rails (>= 2.0, < 4.0) + websocket-driver (0.6.2) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.2) + websocket-rails (0.7.0) + em-synchrony + faye-websocket + hiredis + rack + rails + redis + redis-objects + thin yajl-ruby (1.2.1) PLATFORMS @@ -250,6 +277,7 @@ DEPENDENCIES sqlite3 uglifier (>= 1.3.0) web-console (~> 2.0) + websocket-rails BUNDLED WITH 1.10.4 diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index fd5b7d6..ec5dc99 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -15,3 +15,4 @@ //= require_tree . //= require bootstrap-sprockets //= require jquery-textcomplete +//= require websocket_rails/main diff --git a/app/assets/javascripts/minutes.coffee b/app/assets/javascripts/minutes.coffee index 818bf48..d1f639c 100644 --- a/app/assets/javascripts/minutes.coffee +++ b/app/assets/javascripts/minutes.coffee @@ -460,4 +460,9 @@ ready = -> else alert "No valid range is specified." + # Receiver + receiver = new WebSocketRails(location.host + '/websocket') + receiver.bind 'convert_markdown', (data) -> + $("#realtime-preview").html(data) + $(document).ready(ready) diff --git a/app/controllers/jay_markdown_controller.rb b/app/controllers/jay_markdown_controller.rb new file mode 100644 index 0000000..6a9d0e2 --- /dev/null +++ b/app/controllers/jay_markdown_controller.rb @@ -0,0 +1,10 @@ +require "markdown_converter" + +class JayMarkdownController < WebsocketRails::BaseController + + def convert + markdown = message() + html = ::JayFlavoredMarkdownConverter.new(markdown).content + broadcast_message(:convert_markdown, html) + end +end diff --git a/app/controllers/minutes_controller.rb b/app/controllers/minutes_controller.rb index fec8347..94a66f3 100644 --- a/app/controllers/minutes_controller.rb +++ b/app/controllers/minutes_controller.rb @@ -76,6 +76,9 @@ def destroy end end + def realtime_preview + end + # for ajax search def search_by_tag unless tag = Tag.find_by(name: params[:tag_name]) diff --git a/app/views/minutes/realtime_preview.html.haml b/app/views/minutes/realtime_preview.html.haml new file mode 100644 index 0000000..08e2a90 --- /dev/null +++ b/app/views/minutes/realtime_preview.html.haml @@ -0,0 +1,2 @@ +%h1 Realtime Preview +.markdown-body#realtime-preview diff --git a/config/environments/development.rb b/config/environments/development.rb index b55e214..0e9e384 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -38,4 +38,7 @@ # Raises error for missing translations # config.action_view.raise_on_missing_translations = true + + # For websocket-rails + config.middleware.delete Rack::Lock end diff --git a/config/events.rb b/config/events.rb new file mode 100644 index 0000000..286ef25 --- /dev/null +++ b/config/events.rb @@ -0,0 +1,16 @@ +WebsocketRails::EventMap.describe do + # You can use this file to map incoming events to controller actions. + # One event can be mapped to any number of controller actions. The + # actions will be executed in the order they were subscribed. + # + # Uncomment and edit the next line to handle the client connected event: + # subscribe :client_connected, :to => Controller, :with_method => :method_name + # + # Here is an example of mapping namespaced events: + # namespace :product do + # subscribe :new, :to => ProductController, :with_method => :new_product + # end + # The above will handle an event triggered on the client like `product.new`. + + subscribe :convert_markdown, :to => JayMarkdownController, :with_method => :convert +end diff --git a/config/initializers/websocket_rails.rb b/config/initializers/websocket_rails.rb new file mode 100644 index 0000000..314da41 --- /dev/null +++ b/config/initializers/websocket_rails.rb @@ -0,0 +1,63 @@ +WebsocketRails.setup do |config| + + # Uncomment to override the default log level. The log level can be + # any of the standard Logger log levels. By default it will mirror the + # current Rails environment log level. + # config.log_level = :debug + + # Uncomment to change the default log file path. + # config.log_path = "#{Rails.root}/log/websocket_rails.log" + + # Set to true if you wish to log the internal websocket_rails events + # such as the keepalive `websocket_rails.ping` event. + # config.log_internal_events = false + + # Change to true to enable standalone server mode + # Start the standalone server with rake websocket_rails:start_server + # * Requires Redis + config.standalone = false + + # Change to true to enable channel synchronization between + # multiple server instances. + # * Requires Redis. + config.synchronize = false + + # Prevent Thin from daemonizing (default is true) + # config.daemonize = false + + # Uncomment and edit to point to a different redis instance. + # Will not be used unless standalone or synchronization mode + # is enabled. + # config.redis_options = {:host => 'localhost', :port => '6379'} + + # By default, all subscribers in to a channel will be removed + # when that channel is made private. If you don't wish active + # subscribers to be removed from a previously public channel + # when making it private, set the following to true. + # config.keep_subscribers_when_private = false + + # Set to true if you wish to broadcast channel subscriber_join and + # subscriber_part events. All subscribers of a channel will be + # notified when other clients join and part the channel. If you are + # using the UserManager, the current_user object will be sent along + # with the event. + # config.broadcast_subscriber_events = true + + # Used as the key for the WebsocketRails.users Hash. This method + # will be called on the `current_user` object in your controller + # if one exists. If `current_user` does not exist or does not + # respond to the identifier, the key will default to `connection.id` + # config.user_identifier = :id + + # Uncomment and change this option to override the class associated + # with your `current_user` object. This class will be used when + # synchronization is enabled and you trigger events from background + # jobs using the WebsocketRails.users UserManager. + # config.user_class = User + + # Supporting HTTP streaming on Internet Explorer versions 8 & 9 + # requires CORS to be enabled for GET "/websocket" request. + # List here the origin domains allowed to perform the request. + # config.allowed_origins = ['http://localhost:3000'] + +end diff --git a/config/routes.rb b/config/routes.rb index 6d92f63..94faa79 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -7,6 +7,7 @@ get "/sessions/logout", to: "sessions#logout" post "/minutes/preview", to: "minutes#preview" + get "/minutes/realtime_preview", to: "minutes#realtime_preview" get "/minutes/search_by_tag", to: "minutes#search_by_tag" resources :minutes