diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 17e366db..9072b3df 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -17,3 +17,4 @@ //= require lib/backbone //= require backbone/kandan //= require_tree . + diff --git a/app/assets/javascripts/backbone/broadcasters/faye.js.coffee b/app/assets/javascripts/backbone/broadcasters/faye.js.coffee new file mode 100644 index 00000000..0fbf69c6 --- /dev/null +++ b/app/assets/javascripts/backbone/broadcasters/faye.js.coffee @@ -0,0 +1,18 @@ +class Kandan.Broadcasters.FayeBroadcaster + + constructor: ()-> + @faye_client = new Faye.Client("/remote/faye") + @faye_client.disable('websocket') + auth_extension = { + outgoing: (message, callback)-> + if message.channel == "/meta/subscribe" + # TODO move fetching auth token to a helper + message['ext'] = {auth_token: $.data(document, 'current_user').auth_token} + callback(message) + } + @faye_client.addExtension(auth_extension) + + subscribe: (channel)-> + console.log "Subscribing to #{channel}" + @faye_client.subscribe channel, (data)=> + console.log data.user.first_name, "says", data.content diff --git a/app/assets/javascripts/backbone/kandan.js.coffee b/app/assets/javascripts/backbone/kandan.js.coffee index 6408eb4f..ece7b17e 100644 --- a/app/assets/javascripts/backbone/kandan.js.coffee +++ b/app/assets/javascripts/backbone/kandan.js.coffee @@ -10,12 +10,40 @@ window.Kandan = Collections: {} Views: {} Routers: {} + Broadcasters: {} init: -> - # new Kandan.Routers.Main() # Backbone.history.start({pushState: true}) - chat_area = new Kandan.Views.ChatArea() - $('.container').html(chat_area.render().el) - # $('.container').append(chat_box) + channels = new Kandan.Collections.Channels() + channels.fetch({success: ()=> + + chat_area = new Kandan.Views.ChatArea({channels: channels}) + $('.container').html(chat_area.render().el) + + chatbox = new Kandan.Views.Chatbox() + $('.container').append(chatbox.render().el) + + # TODO move this to a helper + # can also be done by checking the active tab in the post event in the Chatbox view + $('#channels').tabs({ + select: (event, ui)-> + channel_id = $("#channels .ui-tabs-panel").eq("#{ui.index}").data('channel_id') + console.log "set channelID to", channel_id + # TODO move setting current channel ID to a seperate helper + $('.chatbox').data('active_channel_id', channel_id) + }) + + # TODO move broadcast subscription to a helper + # TODO change this to use the broadcaster from the settings + # TODO set as global to debug. remove later. + window.broadcaster = new Kandan.Broadcasters.FayeBroadcaster() + for channel in channels.models + window.broadcaster.subscribe "/channels/#{channel.get('id')}" + + # TODO move this to a helper + $('.chatbox').data('active_channel_id', + $("#channels .ui-tabs-panel").eq($('#channels').tabs('option', 'selected')).data('channel_id')) + }) + $(document).ready -> Kandan.init() diff --git a/app/assets/javascripts/backbone/views/chatarea.js.coffee b/app/assets/javascripts/backbone/views/chatarea.js.coffee index 3454be98..3b04ec96 100644 --- a/app/assets/javascripts/backbone/views/chatarea.js.coffee +++ b/app/assets/javascripts/backbone/views/chatarea.js.coffee @@ -3,16 +3,11 @@ class Kandan.Views.ChatArea extends Backbone.View template: JST['chatarea'] # className: 'channels' - initialize: ()-> - @channels = new Kandan.Collections.Channels() render: -> - @channels.fetch({success: ()=> - $(@el).html(@template({channels: @channels})) - for channel in @channels.models - view = new Kandan.Views.ListActivities({channel: channel}) - $(@el).append(view.render().el) - $('#channels').tabs() - }) + $(@el).html(@template({channels: @options.channels})) + for channel in @options.channels.models + view = new Kandan.Views.ListActivities({channel: channel}) + $(@el).append(view.render().el) $(@el).attr('id', 'channels') @ \ No newline at end of file diff --git a/app/assets/javascripts/backbone/views/chatbox.js.coffee b/app/assets/javascripts/backbone/views/chatbox.js.coffee new file mode 100644 index 00000000..3a461232 --- /dev/null +++ b/app/assets/javascripts/backbone/views/chatbox.js.coffee @@ -0,0 +1,27 @@ +class Kandan.Views.Chatbox extends Backbone.View + + template: JST['chatbox'] + tagName: 'div' + className: 'chatbox-area' + + events: + "keypress .chatbox": 'postMessage' + + postMessage: (event)-> + + if event.keyCode== 13 + $chatbox = $(".chatbox") + activity = new Kandan.Models.Activity({ + 'content': $chatbox.val(), + 'action': 'message', + 'channel_id': $chatbox.data('active_channel_id') + }) + + activity.save({success: ()-> + console.log "posted! enjoy your day" + }) + + + render: ()-> + $(@el).html(@template()) + @ diff --git a/app/assets/javascripts/backbone/views/list_activities.js.coffee b/app/assets/javascripts/backbone/views/list_activities.js.coffee index 30e78134..eea89900 100644 --- a/app/assets/javascripts/backbone/views/list_activities.js.coffee +++ b/app/assets/javascripts/backbone/views/list_activities.js.coffee @@ -7,4 +7,5 @@ class Kandan.Views.ListActivities extends Backbone.View activity_view = new Kandan.Views.Activity({activity: activity}) $(@el).append(activity_view.render().el) $(@el).attr('id', "channels-#{@options.channel.get('id')}") + $(@el).data('channel_id', @options.channel.get('id')) @ \ No newline at end of file diff --git a/app/assets/templates/chatbox.jst.eco b/app/assets/templates/chatbox.jst.eco new file mode 100644 index 00000000..a7a01685 --- /dev/null +++ b/app/assets/templates/chatbox.jst.eco @@ -0,0 +1 @@ + diff --git a/app/controllers/activities_controller.rb b/app/controllers/activities_controller.rb index b7725a95..b6fe7acb 100644 --- a/app/controllers/activities_controller.rb +++ b/app/controllers/activities_controller.rb @@ -10,6 +10,7 @@ def index def create @activity = Channel.find(params[:channel_id]).activities.build(params[:activity]) + @activity.user_id = current_user.id if @activity.action == "message" if @activity.save respond_to do |format| format.json { render :json => @activity, :status => :created } diff --git a/app/models/activity_observer.rb b/app/models/activity_observer.rb index b2a54873..55ce4aac 100644 --- a/app/models/activity_observer.rb +++ b/app/models/activity_observer.rb @@ -1,7 +1,9 @@ class ActivityObserver < ActiveRecord::Observer def after_save(activity) - faye_channel = "/channels/#{activity.channel.to_param}/messages" - Kandan::Config.broadcaster.broadcast(faye_channel, activity.attributes) + faye_channel = "/channels/#{activity.channel.to_param}" + # TODO move this to a rabl template + broadcast_data = activity.attributes.merge({:user => activity.user.attributes}) + Kandan::Config.broadcaster.broadcast(faye_channel, broadcast_data) end end diff --git a/config.ru b/config.ru index 0d92bdaf..716293d2 100644 --- a/config.ru +++ b/config.ru @@ -3,13 +3,35 @@ require ::File.expand_path('../config/environment', __FILE__) require 'faye' +# TODO move this to the lib dir +class DeviseAuth + def incoming(message, callback) + if message['channel'] == "/meta/subscribe" + auth_token = message['ext']['auth_token'] + user = User.find_by_authentication_token(auth_token) + if user + return callback.call(message) + else + message['error'] = "Invalid auth token" + end + end + puts "Message: #{message.inspect}" + callback.call(message) + end + + #TODO disable publishing by users +end + + faye_server = Faye::RackAdapter.new(:mount => "/faye", :timeout => 5) +faye_server.add_extension(DeviseAuth.new) # TODO send pull request to faye to get this fixed # by adding a rack_prefix option # which should then make the faye server object available # via the get_client() method on the server + FAYE_CLIENT = faye_server.get_client faye_server.bind(:subscribe) do |client_id| @@ -18,6 +40,7 @@ end faye_server.bind(:disconnect) do |client_id| puts "DISCONNECT #{client_id}" + User end run Rack::URLMap.new({ diff --git a/lib/broadcasters/faye.rb b/lib/broadcasters/faye.rb index fafb62a3..a58e0342 100644 --- a/lib/broadcasters/faye.rb +++ b/lib/broadcasters/faye.rb @@ -3,7 +3,9 @@ class Faye class << self def broadcast(channel, message) # NOTE FAYE_CLIENT is set in the config.ru file due to the faye bug - if defined?(FAYE_CLIENT) && (not FAYE_CLIENT.nil?) + puts "CHECKING TO BEGIN BROADCAST" + if defined?(FAYE_CLIENT) + puts "BROADCASTING... to #{channel}" FAYE_CLIENT.publish channel, message else puts "OOPS! FAYE_CLIENT is not defined"