Permalink
Browse files

more setup and config

  • Loading branch information...
1 parent 256734e commit ab8283b6a15d2e7842ff378bbdbdd5547b0f84d9 J Brien Dilts committed Oct 15, 2008
View
5 README
@@ -1,3 +1,8 @@
Juggernaut Powered Chat Room for Redmine
+INSTALLATION:
+
+sudo gem install juggernaut
+./script/plugin install http://juggernaut.rubyforge.org/svn/trunk/juggernaut
+
DETAILS: COMING SOON
View
5 app/controllers/chat_rooms_controller.rb
@@ -1,6 +1,7 @@
class ChatRoomsController < ApplicationController
- before_filter :is_logged_in?
- # GET /chat_rooms
+ unloadable
+
+ before_filter :require_login, :except => [:broadcast] # GET /chat_rooms
# GET /chat_rooms.xml
def index
@chat_rooms = ChatRoom.find(:all)
View
2 app/helpers/chat_users_helper.rb
@@ -1,2 +1,2 @@
-module DevsHelper
+module UsersHelper
end
View
2 app/views/chat_rooms/new.html.erb
@@ -1,6 +1,6 @@
<h1>New chat_room</h1>
-<% form_for(@chat_room) do |f| %>
+<% form_for(@chat_room, {:controller => 'chat_rooms'}) do |f| %>
<%= f.error_messages %>
<p>
View
11 db/migrate/20081014160039_create_redmine_chat_plugin.rb
@@ -1,4 +1,4 @@
-class CreateRedmineDevChat < ActiveRecord::Migration
+class CreateRedmineChatPlugin < ActiveRecord::Migration
def self.up
create_table "chat_users", :force => true do |t|
t.integer :user_id
@@ -16,10 +16,17 @@ def self.up
t.boolean :notice, :default => false
t.boolean :timestamp, :default => false
end
+
+ create_table "chat_rooms", :force => true do |t|
+ t.string "name"
+ t.string "description"
+ t.timestamps
+ end
end
def self.down
- drop_table :chat_devs
+ drop_table :chat_users
drop_table :chat_messages
+ drop_table :chat_rooms
end
end
View
BIN engine_plugins/.DS_Store
Binary file not shown.
View
21 engine_plugins/juggernaut/LICENSE
@@ -1,21 +0,0 @@
-Copyright (c) 2005 Alexander MacCaw
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
View
233 engine_plugins/juggernaut/README
@@ -1,233 +0,0 @@
-Juggernaut
-===========
-
-=CONTACT DETAILS
-
- Author: Alex MacCaw
- E-Mail Address: info@alexmaccaw.co.uk
- License: MIT
- Website: http://juggernaut.rubyforge.org
- Blog: http://www.eribium.org
-
-=DESCRIPTION
-
-The Juggernaut plugin for Ruby on Rails aims to revolutionize your Rails app by letting the server initiate a connection and push data to the client. In other words your app can have a real time connection to the server with the advantage of instant updates. Although the obvious use of this is for chat, the most exciting prospect for me is collaborative cms and wikis.
-
-What Happens:
-
- 1. Client A opens socket connection to the socket server
- 2. Client B makes Ajax call to Rails
- 3. Rails sends message to the socket server
- 4. Socket server broadcasts message to clients
-
-Juggernaut Features:
-
- * Allows a real time connection with a client - Rails can literally push javascript in real time to the client which is then evaluated.
- * Push server - written in Ruby.
- * Integrated, as a plugin, into Rails.
- * Subscribers can subscribe to multiple channels, and broadcasters can broadcast to multiple channels.
- * Subscribers can provide a 'unique_id' and broadcasters can send data to specific clients.
- * Add and remove channels at runtime
- * Uses Flash 8 - installed on more than 98% of computers.
- * Supports all the major browsers (uses ExternalInterface): Firefox 1+, IE 6+ and Safari 2+.
-
-Requirements:
-
- * Rails 2.0.2 or edge
- * json gem (gem install json)
- * EventMachine gem (gem install eventmachine)
- * juggernaut gem (gem install juggernaut)
-
-
-===============================================
-INSTALLATION
-===============================================
-
- 1. From your Rails Dir:
- script/plugin install http://juggernaut.rubyforge.org/svn/trunk/juggernaut
- 2. Make sure to include the appropriate JavaScripts in your views/layouts
- in the header of your views
- <%= javascript_include_tag 'prototype', :juggernaut %>
- 3. Add this to your view/layout head:
- <%= juggernaut %>
- 4. Make sure the juggernaut gem is installed (gem install juggernaut) and run:
- juggernaut -g juggernaut.yml
- juggernaut -c juggernaut.yml
- 5. Run script/server and visit the Jugged up page.
- 6. Then, to send data to juggernaut, execute this in the console:
- Juggernaut.send_to_all("alert('hi from juggernaut')")
-
-Usage
-
-To demonstrate Juggernaut I'll walk you through building a simple chat.
-
-Start the push server going by running:
-juggernaut -g juggernaut.yml
-juggernaut -c juggernaut.yml
-
-The chat controller:
-
-class ChatController < ApplicationController
- def index
- end
-
- def send_data
- render :juggernaut do |page|
- page.insert_html :top, 'chat_data', "<li>#{h params[:chat_input]}</li>"
- end
- render :nothing => true
- end
-end
-
-
-The index.html.erb
-
- <html>
- <head>
- <%= javascript_include_tag :defaults, :juggernaut %>
- <%= juggernaut %>
- </head>
- <body>
- <%= form_remote_tag(
- :url => { :action => :send_data },
- :complete => "$('chat_input').value = ''" ) %>
- <%= text_field_tag( 'chat_input', '', { :size => 20, :id => 'chat_input'} ) %>
- <%= submit_tag "Add" %>
- </form>
- <ul id="chat_data" style="list-style:none">
- </ul>
- </body>
- </html>
-
-Start the webserver going with:
-ruby script/server
-
-Try it and see what you think. If it doesn't work please visit the faq.
-
-Other ways of rendering to juggernaut:
-
-render :juggernaut do |page|
- page.alert('hi')
-end
-
-render_juggernaut(:action => 'whatever')
-
-===============================================
-More usage information, examples and support
-===============================================
-
-=== Channel Usage ===
-
-<%= juggernaut(:channels => ['one', 'two', 'three']) %>
-render :juggernaut => {:type => :send_to_channels, :channels => ['one']} do |page|
- page.alert('hi')
-end
-
-Client id usage:
-<%= juggernaut(:client_id => session[:user_id]) %>
-render :juggernaut => {:type => :send_to_clients, :client_ids => [1, 2, 3]} do |page|
- page.alert('hi')
-end
-
-Other juggernaut render options:
-OPTION_TYPE PARAMS
-:send_to_all
-:send_to_channels :channels
-:send_to_channel :channel
-:send_to_client :client_id
-:send_to_clients :client_ids
-:send_to_client_on_channel :client_id, :channel
-:send_to_clients_on_channel :client_ids, :channel
-:send_to_client_on_channels :client_id, :channels
-:send_to_clients_on_channels :client_ids, :channels
-
-You can also call these methods directly on the Juggernaut class:
-Juggernaut.send_to_clients('data', [1,2,3])
-
-For authentication options and callbacks see the juggernaut.yml configuration file.
-
-Usage and examples: http://ncavig.com/blog/
-Support and forums: http://groups.google.com/group/Juggernaut-for-Rails?hl=en
-
-=== Getting remote clients to connect ===
-
-Firstly you will need to configure juggernaut_hosts.yml in your Rails app to point to the proper IP of the push server (rather than 127.0.0.1).
-For example:
-:hosts:
- - :port: 5001
- :host: 129.168.0.2
- :environment: :production
-
-Ok, remote clients that visit pages on this server (once you restart it) will connect to the proper push server IP. BUT, if you're using IP based
-authentication (recommended) you'll find that the broadcast authentication fails.
-You'll need to add the Rails IP to juggernaut.yml, like so:
-
-:allowed_ips:
- - 127.0.0.1
- - 192.168.0.4 # IP of the Rails app
-
-===============================================
-Jquery
-===============================================
-
-To get Juggernaut working with Jquery (Prototype is used by default) follow the tutorial above with the following differences.
-
->>Javascripts
-
- You must have jquery.js (version 1.2.6 tested) and the jquery-json plugin (http://www.jdempster.com/wp-content/uploads/2007/08/jquery.json.js) in the /javascripts directory.
-
- You need the jquerynaut.js file in the /javascripts/juggernaut directory (found in /lib in the media directory)
-
-
->>The chat controller:
-
- class ChatController < ApplicationController
- def index
- end
-
- def send_data
- render :juggernaut do |page|
- page["#chat_data"].prepend "<li>#{h params[:chat_input]}</li>"
- end
- render :nothing => true
- end
-
- end
-
-
->>The index.html.erb
-
- <html>
- <head>
- <%= javascript_include_tag 'jquery', 'json', 'juggernaut/juggernaut', 'juggernaut/jquerynaut', 'juggernaut/swfobject' %>
- <%= juggernaut %>
- </head>
- <body>
- <form action="/chat/send_data" method="get">
- <div style="margin:0;padding:0">
- <input id="chat_input" name="chat_input" size="20" type="text" value="" />
- <input name="commit" type="submit" value="Add" />
- </form>
-
- <script>
- $(document).ready(function(){
- $('form').submit(function(){
- $.get('/chat/send_data', { chat_input: $('#chat_input').val() } )
- return false;
- })
- })
- </script>
- <ul id="chat_data" style="list-style:none"></ul>
- </body>
- </html>
-
-
-
-===============================================
-Troubleshooting
-===============================================
-
-Check out the support forums on google groups:
-http://groups.google.com/group/Juggernaut-for-Rails
-
-
View
19 engine_plugins/juggernaut/init.rb
@@ -1,19 +0,0 @@
-require 'juggernaut'
-require 'juggernaut_helper'
-
-# ActionView::Helpers::AssetTagHelper::register_javascript_include_default('juggernaut')
-# ActionView::Helpers::AssetTagHelper::register_javascript_include_default('swfobject')
-
-ActionView::Base.send(:include, Juggernaut::JuggernautHelper)
-
-ActionController::Base.class_eval do
- alias_method :render_without_juggernaut, :render
- include Juggernaut::RenderExtension
- alias_method :render, :render_with_juggernaut
-end
-
-ActionView::Base.class_eval do
- alias_method :render_without_juggernaut, :render
- include Juggernaut::RenderExtension
- alias_method :render, :render_with_juggernaut
-end
View
203 engine_plugins/juggernaut/lib/juggernaut.rb
@@ -1,203 +0,0 @@
-require "yaml"
-require "socket"
-
-module Juggernaut
- CONFIG = YAML::load(ERB.new(IO.read("#{RAILS_ROOT}/config/juggernaut_hosts.yml")).result).freeze
- CR = "\0"
-
- class << self
-
- def send_to_all(data)
- fc = {
- :command => :broadcast,
- :body => data,
- :type => :to_channels,
- :channels => []
- }
- send_data(fc)
- end
-
- def send_to_channels(data, channels)
- fc = {
- :command => :broadcast,
- :body => data,
- :type => :to_channels,
- :channels => channels
- }
- send_data(fc)
- end
- alias send_to_channel send_to_channels
-
- def send_to_clients(data, client_ids)
- fc = {
- :command => :broadcast,
- :body => data,
- :type => :to_clients,
- :client_ids => client_ids
- }
- send_data(fc)
- end
- alias send_to_client send_to_clients
-
- def send_to_clients_on_channels(data, client_ids, channels)
- fc = {
- :command => :broadcast,
- :body => data,
- :type => :to_clients,
- :client_ids => client_ids,
- :channels => channels
- }
- send_data(fc)
- end
- alias send_to_client_on_channel send_to_clients_on_channels
- alias send_to_client_on_channel send_to_clients_on_channels
-
- def remove_channels_from_clients(client_ids, channels)
- fc = {
- :command => :query,
- :type => :remove_channels_from_client,
- :client_ids => client_ids,
- :channels => channels
- }
- send_data(fc)
- end
- alias remove_channel_from_client remove_channels_from_clients
- alias remove_channels_from_client remove_channels_from_clients
-
- def remove_all_channels(channels)
- fc = {
- :command => :query,
- :type => :remove_all_channels,
- :channels => channels
- }
- send_data(fc)
- end
-
- def show_clients
- fc = {
- :command => :query,
- :type => :show_clients
- }
- send_data(fc, true).flatten
- end
-
- def show_client(client_id)
- fc = {
- :command => :query,
- :type => :show_client,
- :client_id => client_id
- }
- send_data(fc, true).flatten[0]
- end
-
- def show_clients_for_channels(channels)
- fc = {
- :command => :query,
- :type => :show_clients_for_channels,
- :channels => channels
- }
- send_data(fc, true).flatten
- end
- alias show_clients_for_channel show_clients_for_channels
-
- def send_data(hash, response = false)
- hash[:channels] = hash[:channels].to_a if hash[:channels]
- hash[:client_ids] = hash[:client_ids].to_a if hash[:client_ids]
-
- res = []
- hosts.each do |address|
- begin
- hash[:secret_key] = address[:secret_key] if address[:secret_key]
-
- @socket = TCPSocket.new(address[:host], address[:port])
- # the \0 is to mirror flash
- @socket.print(hash.to_json + CR)
- @socket.flush
- res << @socket.readline(CR) if response
- ensure
- @socket.close if @socket and !@socket.closed?
- end
- end
- res.collect {|r| ActiveSupport::JSON.decode(r.chomp!(CR)) } if response
- end
-
- private
-
- def hosts
- CONFIG[:hosts].select {|h|
- !h[:environment] or h[:environment].to_s == ENV['RAILS_ENV']
- }
- end
-
- end
-
- module RenderExtension
- def self.included(base)
- base.send :include, InstanceMethods
- end
-
- module InstanceMethods
- # We can't protect these as ActionMailer complains
- # protected
-
- def render_with_juggernaut(options = nil, old_local_assigns={}, &block)
- if options == :juggernaut or (options.is_a?(Hash) and options[:juggernaut])
- add_variables_to_assigns
- @template.send! :evaluate_assigns
-
- generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(@template, &block)
- render_for_juggernaut(generator.to_s, options.is_a?(Hash) ? options[:juggernaut] : nil)
- else
- render_without_juggernaut(options, old_local_assigns, &block)
- end
- end
-
- def render_juggernaut(*args)
- juggernaut_options = args.last.is_a?(Hash) ? args.pop : {}
- render_for_juggernaut(render_to_string(*args), juggernaut_options)
- end
-
- def render_for_juggernaut(data, options = {})
- if !options or !options.is_a?(Hash)
- return Juggernaut.send_to_all(data)
- end
-
- case options[:type]
- when :send_to_all
- Juggernaut.send_to_all(data)
- when :send_to_channels:
- juggernaut_needs options, :channels
- Juggernaut.send_to_channels(data, options[:channels])
- when :send_to_channel:
- juggernaut_needs options, :channel
- Juggernaut.send_to_channel(data, options[:channel])
- when :send_to_client:
- juggernaut_needs options, :client_id
- Juggernaut.send_to_client(data, options[:client_id])
- when :send_to_clients:
- juggernaut_needs options, :client_ids
- Juggernaut.send_to_clients(data, options[:client_ids])
- when :send_to_client_on_channel:
- juggernaut_needs options, :client_id, :channels
- Juggernaut.send_to_clients_on_channel(data, options[:client_id], options[:channels])
- when :send_to_clients_on_channel:
- juggernaut_needs options, :client_ids, :channel
- Juggernaut.send_to_clients_on_channel(data, options[:client_ids], options[:channel])
- when :send_to_client_on_channels:
- juggernaut_needs options, :client_ids, :channel
- Juggernaut.send_to_clients_on_channel(data, options[:client_id], options[:channels])
- when :send_to_clients_on_channels:
- juggernaut_needs options, :client_ids, :channel
- Juggernaut.send_to_clients_on_channel(data, options[:client_ids], options[:channels])
- end
- end
-
- def juggernaut_needs(options, *args)
- args.each do |a|
- raise "You must specify #{a}" unless options[a]
- end
- end
-
- end
- end
-end
View
37 engine_plugins/juggernaut/lib/juggernaut_helper.rb
@@ -1,37 +0,0 @@
-module Juggernaut # :nodoc:
- module JuggernautHelper
-
- def juggernaut(options = {})
- hosts = Juggernaut::CONFIG[:hosts].select {|h| !h[:environment] or h[:environment] == ENV['RAILS_ENV'].to_sym }
- random_host = hosts[rand(hosts.length)]
- options = {
- :host => (random_host[:public_host] || random_host[:host]),
- :port => (random_host[:public_port] || random_host[:port]),
- :width => '0px',
- :height => '0px',
- :session_id => session.session_id,
- :swf_address => "/juggernaut/juggernaut.swf",
- :ei_swf_address => "/juggernaut/expressinstall.swf",
- :flash_version => 8,
- :flash_color => "#fff",
- :swf_name => "juggernaut_flash",
- :bridge_name => "juggernaut",
- :debug => (RAILS_ENV == 'development'),
- :reconnect_attempts => 3,
- :reconnect_intervals => 3
- }.merge(options)
- javascript_tag "new Juggernaut(#{options.to_json});"
- end
-
- def expand_javascript_sources(sources, recursive = false)
- if sources.include?(:juggernaut)
- sources = sources[0..(sources.index(:juggernaut))] +
- ['juggernaut/swfobject', 'juggernaut/juggernaut'] +
- sources[(sources.index(:juggernaut) + 1)..sources.length]
- sources.delete(:juggernaut)
- end
- super(sources)
- end
-
- end
-end
View
BIN engine_plugins/juggernaut/media/expressinstall.swf
Binary file not shown.
View
3,549 engine_plugins/juggernaut/media/jquery.js
0 additions, 3,549 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
30 engine_plugins/juggernaut/media/jquerynaut.js
@@ -1,30 +0,0 @@
-// Simply overwrites prototype specific functions
-// with jquery specific versions
-
-Juggernaut.fn.fire_event = function(fx_name) {
- $(document).trigger("juggernaut:" + fx_name);
- }
-
-Juggernaut.fn.bindToWindow = function() {
- $(window).bind("load", this, function(e) {
- juggernaut = e.data;
- e.data.appendFlashObject()
- });
- }
-
-Juggernaut.toJSON = function(hash) {
- return $.toJSON(hash) ;
- }
-
-Juggernaut.parseJSON = function(string) {
- return $.parseJSON(string);
- }
-
-Juggernaut.fn.swf = function(){
- return $('#' + this.options.swf_name)[0];
- }
-
-Juggernaut.fn.appendElement = function() {
- this.element = $('<div id=juggernaut>');
- $("body").append(this.element);
- }
View
97 engine_plugins/juggernaut/media/json.js
@@ -1,97 +0,0 @@
-(function ($) {
- var m = {
- '\b': '\\b',
- '\t': '\\t',
- '\n': '\\n',
- '\f': '\\f',
- '\r': '\\r',
- '"' : '\\"',
- '\\': '\\\\'
- },
- s = {
- 'array': function (x) {
- var a = ['['], b, f, i, l = x.length, v;
- for (i = 0; i < l; i += 1) {
- v = x[i];
- f = s[typeof v];
- if (f) {
- v = f(v);
- if (typeof v == 'string') {
- if (b) {
- a[a.length] = ',';
- }
- a[a.length] = v;
- b = true;
- }
- }
- }
- a[a.length] = ']';
- return a.join('');
- },
- 'boolean': function (x) {
- return String(x);
- },
- 'null': function (x) {
- return "null";
- },
- 'number': function (x) {
- return isFinite(x) ? String(x) : 'null';
- },
- 'object': function (x) {
- if (x) {
- if (x instanceof Array) {
- return s.array(x);
- }
- var a = ['{'], b, f, i, v;
- for (i in x) {
- v = x[i];
- f = s[typeof v];
- if (f) {
- v = f(v);
- if (typeof v == 'string') {
- if (b) {
- a[a.length] = ',';
- }
- a.push(s.string(i), ':', v);
- b = true;
- }
- }
- }
- a[a.length] = '}';
- return a.join('');
- }
- return 'null';
- },
- 'string': function (x) {
- if (/["\\\x00-\x1f]/.test(x)) {
- x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
- var c = m[b];
- if (c) {
- return c;
- }
- c = b.charCodeAt();
- return '\\u00' +
- Math.floor(c / 16).toString(16) +
- (c % 16).toString(16);
- });
- }
- return '"' + x + '"';
- }
- };
-
- $.toJSON = function(v) {
- var f = isNaN(v) ? s[typeof v] : s['number'];
- if (f) return f(v);
- };
-
- $.parseJSON = function(v, safe) {
- if (safe === undefined) safe = $.parseJSON.safe;
- if (safe && !/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(v))
- return undefined;
- return eval('('+v+')');
- };
-
- $.parseJSON.safe = false;
-
-})(jQuery);
-
View
79 engine_plugins/juggernaut/media/juggernaut.as
@@ -1,79 +0,0 @@
-/*
-Copyright (c) 2007 Alexander MacCaw
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-/*
- Compile using MTACS (http://www.mtasc.org/)
- mtasc -version 8 -header 1:1:1 -main -swf juggernaut.swf juggernaut.as
-*/
-
-import flash.external.ExternalInterface;
-
-class SocketServer {
-
- static var socket : XMLSocket;
-
- static function connect(host:String, port:Number) {
- // The following line was causing crashes on Leopard
- // System.security.loadPolicyFile('xmlsocket://' + host + ':' + port);
-
- socket = new XMLSocket();
- socket.onData = onData;
- socket.onConnect = onConnect;
- socket.onClose = onDisconnect;
- socket.connect(host, port);
- }
-
- static function disconnect(){
- socket.close();
- }
-
- static function onConnect(success:Boolean) {
- if(success){
- ExternalInterface.call("juggernaut.connected");
- } else {
- ExternalInterface.call("juggernaut.errorConnecting");
- }
- }
-
- static function sendData(data:String){
- socket.send(unescape(data));
- }
-
- static function onDisconnect() {
- ExternalInterface.call("juggernaut.disconnected");
- }
-
- static function onData(data:String) {
- ExternalInterface.call("juggernaut.receiveData", escape(data));
- }
-
- static function main() {
- ExternalInterface.addCallback("connect", null, connect);
- ExternalInterface.addCallback("sendData", null, sendData);
- ExternalInterface.addCallback("disconnect", null, disconnect);
-
- ExternalInterface.call("juggernaut.initialized");
- }
-
-}
-
View
205 engine_plugins/juggernaut/media/juggernaut.js
@@ -1,205 +0,0 @@
-/*
-Copyright (c) 2008 Alexander MacCaw
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-function Juggernaut(options) {
- this.is_connected = false,
- this.attempting_to_reconnect = false
- this.ever_been_connected = false
- this.hasFirebug = "console" in window && "firebug" in window.console
- this.options = options
- this.bindToWindow();
- }
-
-Juggernaut.fn = Juggernaut.prototype
-
-Juggernaut.fn.logger = function(msg) {
- if (this.options.debug) {
- msg = "Juggernaut: " + msg + " on " + this.options.host + ':' + this.options.port;
- this.hasFirebug ? console.log(msg) : alert(msg);
- }
- }
-
-Juggernaut.fn.initialized = function(){
- this.fire_event('initialized');
- this.connect();
- }
-
-Juggernaut.fn.broadcast = function(body, type, client_ids, channels){
- var msg = {command: 'broadcast', body: body, type: (type||'to_channels')}
- if(channels) msg['channels'] = channels;
- if(client_ids) msg['client_ids'] = client_ids;
- this.sendData(Juggernaut.toJSON(msg));
- }
-
-Juggernaut.fn.sendData = function(data){
- this.swf().sendData(escape(data));
- }
-
-Juggernaut.fn.connect = function(){
- if(!this.is_connected){
- this.fire_event('connect');
- this.swf().connect(this.options.host, this.options.port);
- }
- }
-
-Juggernaut.fn.disconnect = function(){
- if(this.is_connected) {
- this.swf().disconnect();
- this.is_connected = false;
- }
- }
-
-Juggernaut.fn.handshake = function() {
- var handshake = {};
- handshake['command'] = 'subscribe';
- if(this.options.session_id) handshake['session_id'] = this.options.session_id;
- if(this.options.client_id) handshake['client_id'] = this.options.client_id;
- if(this.options.channels) handshake['channels'] = this.options.channels;
- if(this.currentMsgId) {
- handshake['last_msg_id'] = this.currentMsgId;
- handshake['signature'] = this.currentSignature;
- }
-
- return handshake;
- }
-
-Juggernaut.fn.connected = function(e) {
- var json = Juggernaut.toJSON(this.handshake())
- this.sendData(json);
- this.ever_been_connected = true;
- this.is_connected = true;
- setTimeout(function(){
- if(this.is_connected) this.attempting_to_reconnect = false;
- }.bind(this), 1 * 1000);
- this.logger('Connected');
- this.fire_event('connected');
- }
-
-// OVERRIDE FOR CHAT STYLE APPS - POSSIBLE MALICIOUS CONTENT CAN BE EVALED
-Juggernaut.fn.receiveData = function(e) {
- var msg = Juggernaut.parseJSON(unescape(e.toString()));
- this.currentMsgId = msg.id;
- this.currentSignature = msg.signature;
- this.logger("Received data:\n" + msg.body + "\n");
- eval(msg.body);
- }
-
-var juggernaut;
-
-/*** START PROTOTYPE SPECIFIC - OVERRIDE FOR OTHER FRAMEWORKS ***/
-Juggernaut.fn.fire_event = function(fx_name) {
- $(document).fire("juggernaut:" + fx_name);
- }
-
-Juggernaut.fn.bindToWindow = function() {
-
- Event.observe(window, 'load', function() {
- juggernaut = this;
- this.appendFlashObject()
- }.bind(this));
-
- }
-
-Juggernaut.toJSON = function(hash) {
- return Object.toJSON(hash);
- }
-
-Juggernaut.parseJSON = function(string) {
- return string.evalJSON();
- }
-
-Juggernaut.fn.swf = function(){
- return $(this.options.swf_name);
- }
-
-Juggernaut.fn.appendElement = function() {
- this.element = new Element('div', { id: 'juggernaut' });
- $(document.body).insert({ bottom: this.element });
- }
-
-/*** END PROTOTYPE SPECIFIC ***/
-
-Juggernaut.fn.appendFlashObject = function(){
- if(this.swf()) {
- throw("Juggernaut error. 'swf_name' must be unique per juggernaut instance.");
- }
- Juggernaut.fn.appendElement();
- swfobject.embedSWF(
- this.options.swf_address,
- 'juggernaut',
- this.options.width,
- this.options.height,
- String(this.options.flash_version),
- this.options.ei_swf_address,
- {'bridgeName': this.options.bridge_name},
- {},
- {'id': this.options.swf_name, 'name': this.options.swf_name}
- );
- }
-
-
-Juggernaut.fn.refreshFlashObject = function(){
- this.swf().remove();
- this.appendFlashObject();
- }
-
-Juggernaut.fn.errorConnecting = function(e) {
- this.is_connected = false;
- if(!this.attempting_to_reconnect) {
- this.logger('There has been an error connecting');
- this.fire_event('errorConnecting');
- this.reconnect();
- }
- }
-
-Juggernaut.fn.disconnected = function(e) {
- this.is_connected = false;
- if(!this.attempting_to_reconnect) {
- this.logger('Connection has been lost');
- this.fire_event('disconnected');
- this.reconnect();
- }
- }
-
-Juggernaut.fn.reconnect = function(){
- if(this.options.reconnect_attempts){
- this.attempting_to_reconnect = true;
- this.fire_event('reconnect');
- this.logger('Will attempt to reconnect ' + this.options.reconnect_attempts + ' times,\
-the first in ' + (this.options.reconnect_intervals || 3) + ' seconds');
- for(var i=0; i < this.options.reconnect_attempts; i++){
- setTimeout(function(){
- if(!this.is_connected){
- this.logger('Attempting reconnect');
- if(!this.ever_been_connected){
- this.refreshFlashObject();
- } else {
- this.connect();
- }
- }
- }.bind(this), (this.options.reconnect_intervals || 3) * 1000 * (i + 1))
- }
- }
- }
-
-
View
BIN engine_plugins/juggernaut/media/juggernaut.swf
Binary file not shown.
View
93 engine_plugins/juggernaut/media/juggernaut.yml
@@ -1,93 +0,0 @@
- # ======================
- # Juggernaut Options
- # ======================
-
- # === Subscription authentication ===
- # Leave all subscription options uncommented to allow anyone to subscribe.
-
- # If specified, subscription_url is called everytime a client subscribes.
- # Parameters passed are: session_id, client_id and an array of channels.
- #
- # The server should check that the session_id matches up to the client_id
- # and that the client is allowed to access the specified channels.
- #
- # If a status code other than 200 is encountered, the subscription_request fails
- # and the client is disconnected.
- #
- # :subscription_url: http://localhost:3000/sessions/juggernaut_subscription
-
- # === Broadcast and query authentication ===
- # Leave all broadcast/query options uncommented to allow anyone to broadcast/query.
- #
- # Broadcast authentication in a production environment is very importantant since broadcasters
- # can execute JavaScript on subscribed clients, leaving you vulnerable to cross site scripting
- # attacks if broadcasters aren't authenticated.
-
- # 1) Via IP address
- #
- # If specified, if a client has an ip that is specified in allowed_ips, than it is automatically
- # authenticated, even if a secret_key isn't provided.
- #
- # This is the recommended method for broadcast authentication.
- #
- :allowed_ips:
- - 127.0.0.1
- # - 192.168.0.1
-
- # 2) Via HTTP request
- #
- # If specified, if a client attempts a broadcast/query, without a secret_key or using an IP
- # no included in allowed_ips, then broadcast_query_login_url will be called.
- # Parameters passed, if given, are: session_id, client_id, channels and type.
- #
- # The server should check that the session_id matches up to the client id, and the client
- # is allowed to perform that particular type of broadcast/query.
- #
- # If a status code other than 200 is encountered, the broadcast_query_login_url fails
- # and the client is disconnected.
- #
- # :broadcast_query_login_url: http://localhost:3000/sessions/juggernaut_broadcast
-
- # 3) Via shared secret key
- #
- # This secret key must be sent with any query/broadcast commands.
- # It must be the same as the one in the Rails config file.
- #
- # You shouldn't authenticate broadcasts from subscribed clients using this method
- # since the secret_key will be easily visible in the page (and not so secret any more)!
- #
- # :secret_key: 8a01f4941eac46fcb36354c62487ef04d113cdbe
-
- # == Subscription Logout ==
-
- # If specified, logout_connection_url is called everytime a specific connection from a subscribed client disconnects.
- # Parameters passed are session_id, client_id and an array of channels specific to that connection.
- #
- # :logout_connection_url: http://localhost:3000/sessions/juggernaut_connection_logout
-
- # Logout url is called when all connections from a subscribed client are closed.
- # Parameters passed are session_id and client_id.
- #
- # :logout_url: http://localhost:3000/sessions/juggernaut_logout
-
- # === Miscellaneous ===
-
- # timeout defaults to 10. A timeout is the time between when a client closes a connection
- # and a logout_request or logout_connection_request is made. The reason for this is that a client
- # may only temporarily be disconnected, and may attempt a reconnect very soon.
- #
- # :timeout: 10
-
- # store_messages defaults to false. If this option is true, messages send to connections will be stored.
- # This is useful since a client can then receive broadcasted message that it has missed (perhaps it was disconnected).
- #
- # :store_messages: false
-
- # === Server ===
-
- # Host defaults to "0.0.0.0". You shouldn't need to change this.
- # :host: 0.0.0.0
-
- # Port is mandatory
- :port: 5001
-
View
18 engine_plugins/juggernaut/media/juggernaut_hosts.yml
@@ -1,18 +0,0 @@
-# You should list any juggernaut hosts here.
-# You need only specify the secret key if you're using that type of authentication (see juggernaut.yml)
-#
-# Name: Mapping:
-# :port internal push server's port
-# :host internal push server's host/ip
-# :public_host public push server's host/ip (accessible from external clients)
-# :public_port public push server's port
-# :secret_key (optional) shared secret (should map to the key specified in the push server's config)
-# :environment (optional) limit host to a particular RAILS_ENV
-
-:hosts:
- - :port: 5001
- :host: 127.0.0.1
- :public_host: 127.0.0.1
- :public_port: 5001
- # :secret_key: your_secret_key
- # :environment: :development
View
0 engine_plugins/juggernaut/media/log/juggernaut.log
No changes.
View
5 engine_plugins/juggernaut/media/swfobject.js
@@ -1,5 +0,0 @@
-/* SWFObject v2.0 <http://code.google.com/p/swfobject/>
- Copyright (c) 2007 Geoff Stearns, Michael Williams, and Bobby van der Sluis
- This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
-*/
-var swfobject=function(){var Z="undefined",P="object",B="Shockwave Flash",h="ShockwaveFlash.ShockwaveFlash",W="application/x-shockwave-flash",K="SWFObjectExprInst",G=window,g=document,N=navigator,f=[],H=[],Q=null,L=null,T=null,S=false,C=false;var a=function(){var l=typeof g.getElementById!=Z&&typeof g.getElementsByTagName!=Z&&typeof g.createElement!=Z&&typeof g.appendChild!=Z&&typeof g.replaceChild!=Z&&typeof g.removeChild!=Z&&typeof g.cloneNode!=Z,t=[0,0,0],n=null;if(typeof N.plugins!=Z&&typeof N.plugins[B]==P){n=N.plugins[B].description;if(n){n=n.replace(/^.*\s+(\S+\s+\S+$)/,"$1");t[0]=parseInt(n.replace(/^(.*)\..*$/,"$1"),10);t[1]=parseInt(n.replace(/^.*\.(.*)\s.*$/,"$1"),10);t[2]=/r/.test(n)?parseInt(n.replace(/^.*r(.*)$/,"$1"),10):0}}else{if(typeof G.ActiveXObject!=Z){var o=null,s=false;try{o=new ActiveXObject(h+".7")}catch(k){try{o=new ActiveXObject(h+".6");t=[6,0,21];o.AllowScriptAccess="always"}catch(k){if(t[0]==6){s=true}}if(!s){try{o=new ActiveXObject(h)}catch(k){}}}if(!s&&o){try{n=o.GetVariable("$version");if(n){n=n.split(" ")[1].split(",");t=[parseInt(n[0],10),parseInt(n[1],10),parseInt(n[2],10)]}}catch(k){}}}}var v=N.userAgent.toLowerCase(),j=N.platform.toLowerCase(),r=/webkit/.test(v)?parseFloat(v.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,i=false,q=j?/win/.test(j):/win/.test(v),m=j?/mac/.test(j):/mac/.test(v);/*@cc_on i=true;@if(@_win32)q=true;@elif(@_mac)m=true;@end@*/return{w3cdom:l,pv:t,webkit:r,ie:i,win:q,mac:m}}();var e=function(){if(!a.w3cdom){return }J(I);if(a.ie&&a.win){try{g.write("<script id=__ie_ondomload defer=true src=//:><\/script>");var i=c("__ie_ondomload");if(i){i.onreadystatechange=function(){if(this.readyState=="complete"){this.parentNode.removeChild(this);V()}}}}catch(j){}}if(a.webkit&&typeof g.readyState!=Z){Q=setInterval(function(){if(/loaded|complete/.test(g.readyState)){V()}},10)}if(typeof g.addEventListener!=Z){g.addEventListener("DOMContentLoaded",V,null)}M(V)}();function V(){if(S){return }if(a.ie&&a.win){var m=Y("span");try{var l=g.getElementsByTagName("body")[0].appendChild(m);l.parentNode.removeChild(l)}catch(n){return }}S=true;if(Q){clearInterval(Q);Q=null}var j=f.length;for(var k=0;k<j;k++){f[k]()}}function J(i){if(S){i()}else{f[f.length]=i}}function M(j){if(typeof G.addEventListener!=Z){G.addEventListener("load",j,false)}else{if(typeof g.addEventListener!=Z){g.addEventListener("load",j,false)}else{if(typeof G.attachEvent!=Z){G.attachEvent("onload",j)}else{if(typeof G.onload=="function"){var i=G.onload;G.onload=function(){i();j()}}else{G.onload=j}}}}}function I(){var l=H.length;for(var j=0;j<l;j++){var m=H[j].id;if(a.pv[0]>0){var k=c(m);if(k){H[j].width=k.getAttribute("width")?k.getAttribute("width"):"0";H[j].height=k.getAttribute("height")?k.getAttribute("height"):"0";if(O(H[j].swfVersion)){if(a.webkit&&a.webkit<312){U(k)}X(m,true)}else{if(H[j].expressInstall&&!C&&O("6.0.65")&&(a.win||a.mac)){D(H[j])}else{d(k)}}}}else{X(m,true)}}}function U(m){var k=m.getElementsByTagName(P)[0];if(k){var p=Y("embed"),r=k.attributes;if(r){var o=r.length;for(var n=0;n<o;n++){if(r[n].nodeName.toLowerCase()=="data"){p.setAttribute("src",r[n].nodeValue)}else{p.setAttribute(r[n].nodeName,r[n].nodeValue)}}}var q=k.childNodes;if(q){var s=q.length;for(var l=0;l<s;l++){if(q[l].nodeType==1&&q[l].nodeName.toLowerCase()=="param"){p.setAttribute(q[l].getAttribute("name"),q[l].getAttribute("value"))}}}m.parentNode.replaceChild(p,m)}}function F(i){if(a.ie&&a.win&&O("8.0.0")){G.attachEvent("onunload",function(){var k=c(i);if(k){for(var j in k){if(typeof k[j]=="function"){k[j]=function(){}}}k.parentNode.removeChild(k)}})}}function D(j){C=true;var o=c(j.id);if(o){if(j.altContentId){var l=c(j.altContentId);if(l){L=l;T=j.altContentId}}else{L=b(o)}if(!(/%$/.test(j.width))&&parseInt(j.width,10)<310){j.width="310"}if(!(/%$/.test(j.height))&&parseInt(j.height,10)<137){j.height="137"}g.title=g.title.slice(0,47)+" - Flash Player Installation";var n=a.ie&&a.win?"ActiveX":"PlugIn",k=g.title,m="MMredirectURL="+G.location+"&MMplayerType="+n+"&MMdoctitle="+k,p=j.id;if(a.ie&&a.win&&o.readyState!=4){var i=Y("div");p+="SWFObjectNew";i.setAttribute("id",p);o.parentNode.insertBefore(i,o);o.style.display="none";G.attachEvent("onload",function(){o.parentNode.removeChild(o)})}R({data:j.expressInstall,id:K,width:j.width,height:j.height},{flashvars:m},p)}}function d(j){if(a.ie&&a.win&&j.readyState!=4){var i=Y("div");j.parentNode.insertBefore(i,j);i.parentNode.replaceChild(b(j),i);j.style.display="none";G.attachEvent("onload",function(){j.parentNode.removeChild(j)})}else{j.parentNode.replaceChild(b(j),j)}}function b(n){var m=Y("div");if(a.win&&a.ie){m.innerHTML=n.innerHTML}else{var k=n.getElementsByTagName(P)[0];if(k){var o=k.childNodes;if(o){var j=o.length;for(var l=0;l<j;l++){if(!(o[l].nodeType==1&&o[l].nodeName.toLowerCase()=="param")&&!(o[l].nodeType==8)){m.appendChild(o[l].cloneNode(true))}}}}}return m}function R(AE,AC,q){var p,t=c(q);if(typeof AE.id==Z){AE.id=q}if(a.ie&&a.win){var AD="";for(var z in AE){if(AE[z]!=Object.prototype[z]){if(z=="data"){AC.movie=AE[z]}else{if(z.toLowerCase()=="styleclass"){AD+=' class="'+AE[z]+'"'}else{if(z!="classid"){AD+=" "+z+'="'+AE[z]+'"'}}}}}var AB="";for(var y in AC){if(AC[y]!=Object.prototype[y]){AB+='<param name="'+y+'" value="'+AC[y]+'" />'}}t.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+AD+">"+AB+"</object>";F(AE.id);p=c(AE.id)}else{if(a.webkit&&a.webkit<312){var AA=Y("embed");AA.setAttribute("type",W);for(var x in AE){if(AE[x]!=Object.prototype[x]){if(x=="data"){AA.setAttribute("src",AE[x])}else{if(x.toLowerCase()=="styleclass"){AA.setAttribute("class",AE[x])}else{if(x!="classid"){AA.setAttribute(x,AE[x])}}}}}for(var w in AC){if(AC[w]!=Object.prototype[w]){if(w!="movie"){AA.setAttribute(w,AC[w])}}}t.parentNode.replaceChild(AA,t);p=AA}else{var s=Y(P);s.setAttribute("type",W);for(var v in AE){if(AE[v]!=Object.prototype[v]){if(v.toLowerCase()=="styleclass"){s.setAttribute("class",AE[v])}else{if(v!="classid"){s.setAttribute(v,AE[v])}}}}for(var u in AC){if(AC[u]!=Object.prototype[u]&&u!="movie"){E(s,u,AC[u])}}t.parentNode.replaceChild(s,t);p=s}}return p}function E(k,i,j){var l=Y("param");l.setAttribute("name",i);l.setAttribute("value",j);k.appendChild(l)}function c(i){return g.getElementById(i)}function Y(i){return g.createElement(i)}function O(k){var j=a.pv,i=k.split(".");i[0]=parseInt(i[0],10);i[1]=parseInt(i[1],10);i[2]=parseInt(i[2],10);return(j[0]>i[0]||(j[0]==i[0]&&j[1]>i[1])||(j[0]==i[0]&&j[1]==i[1]&&j[2]>=i[2]))?true:false}function A(m,j){if(a.ie&&a.mac){return }var l=g.getElementsByTagName("head")[0],k=Y("style");k.setAttribute("type","text/css");k.setAttribute("media","screen");if(!(a.ie&&a.win)&&typeof g.createTextNode!=Z){k.appendChild(g.createTextNode(m+" {"+j+"}"))}l.appendChild(k);if(a.ie&&a.win&&typeof g.styleSheets!=Z&&g.styleSheets.length>0){var i=g.styleSheets[g.styleSheets.length-1];if(typeof i.addRule==P){i.addRule(m,j)}}}function X(k,i){var j=i?"visible":"hidden";if(S){c(k).style.visibility=j}else{A("#"+k,"visibility:"+j)}}return{registerObject:function(l,i,k){if(!a.w3cdom||!l||!i){return }var j={};j.id=l;j.swfVersion=i;j.expressInstall=k?k:false;H[H.length]=j;X(l,false)},getObjectById:function(l){var i=null;if(a.w3cdom&&S){var j=c(l);if(j){var k=j.getElementsByTagName(P)[0];if(!k||(k&&typeof j.SetVariable!=Z)){i=j}else{if(typeof k.SetVariable!=Z){i=k}}}}return i},embedSWF:function(n,u,r,t,j,m,k,p,s){if(!a.w3cdom||!n||!u||!r||!t||!j){return }r+="";t+="";if(O(j)){X(u,false);var q=(typeof s==P)?s:{};q.data=n;q.width=r;q.height=t;var o=(typeof p==P)?p:{};if(typeof k==P){for(var l in k){if(k[l]!=Object.prototype[l]){if(typeof o.flashvars!=Z){o.flashvars+="&"+l+"="+k[l]}else{o.flashvars=l+"="+k[l]}}}}J(function(){R(q,o,u);if(q.id==u){X(u,true)}})}else{if(m&&!C&&O("6.0.65")&&(a.win||a.mac)){X(u,false);J(function(){var i={};i.id=i.altContentId=u;i.width=r;i.height=t;i.expressInstall=m;D(i)})}}},getFlashPlayerVersion:function(){return{major:a.pv[0],minor:a.pv[1],release:a.pv[2]}},hasFlashPlayerVersion:O,createSWF:function(k,j,i){if(a.w3cdom&&S){return R(k,j,i)}else{return undefined}},createCSS:function(j,i){if(a.w3cdom){A(j,i)}},addDomLoadEvent:J,addLoadEvent:M,getQueryParamValue:function(m){var l=g.location.search||g.location.hash;if(m==null){return l}if(l){var k=l.substring(1).split("&");for(var j=0;j<k.length;j++){if(k[j].substring(0,k[j].indexOf("="))==m){return k[j].substring((k[j].indexOf("=")+1))}}}return""},expressInstallCallback:function(){if(C&&L){var i=c(K);if(i){i.parentNode.replaceChild(L,i);if(T){X(T,true);if(a.ie&&a.win){L.style.display="block"}}L=null;T=null;C=false}}}}}();
View
13 engine_plugins/juggernaut/tasks/juggernaut.rake
@@ -1,13 +0,0 @@
-namespace :juggernaut do
- desc "Reinstall the Juggernaut js and swf files"
- task :reinstall do
- load "#{File.dirname(__FILE__)}/../install.rb"
- end
-end
-
-namespace :juggernaut do
- desc 'Compile the juggernaut flash file'
- task :compile_flash do
- `mtasc -header 1:1:1 -main -swf media/juggernaut.swf media/juggernaut.as`
- end
-end
View
6 init.rb
@@ -1,13 +1,13 @@
require 'redmine'
-Redmine::Plugin.register :redmine_dev_chat do
+Redmine::Plugin.register :redmine_chat_plugin do
name 'Redmine Developers Chat plugin'
author 'John Brien'
description 'Enables a Juggernaut Powered Chat Room for Developers and Teams Alike'
version '0.0.1'
- permission :chat, {:chat_messages => [:index, :new]}, :public => true
- menu :top_menu, :chat_messages, { :controller => 'chat_messages', :action => 'index' }, :caption => 'Chat', :after => :projects
+ permission :chat, {:chat_messages => [:index, :new], :chat_rooms => [:index, :show]}, :public => :loggedin
+ menu :top_menu, :chat_messages, { :controller => 'chat_rooms', :action => 'index' }, :caption => 'Chat', :after => :projects
project_module :chats do
permission :participate, :chat_messages => [:index, :new]
end

0 comments on commit ab8283b

Please sign in to comment.