Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Version 0.6.0: Compatibility with Redmine 2.1

* Added stylesheet for stealth mode
* Use 'redmine_stealth' as plugin name (per Robbedoes33 in issue #19)
  • Loading branch information...
commit 3297b53d95bc03839201f34767aca2616ad5e6d8 1 parent eeaa4ea
Riley Martinez-Lynch authored
6 README.textile
View
@@ -4,7 +4,9 @@ This is a plugin for the "Redmine project management application":http://www.red
h2. Installation
-# Install the redmine-stealth-plugin into your redmine application directory. For Redmine 2, git clone http://github.com/teleological/redmine-stealth-plugin.git plugins/redmine-stealth-plugin or for Redmine 1: ./script/plugin install http://github.com/teleological/redmine-stealth-plugin.git
+# Install the redmine_stealth plugin into your redmine plugins directory:
+# git clone http://github.com/teleological/redmine_stealth.git
+# plugins/redmine_stealth (or vendor/plugins/redmine_stealth for Redmine 1.)
# Restart any running Redmine application servers or touch tmp/restart.txt for Passenger
# Configure the per-role permissions for "Toggle stealth mode" as desired
@@ -16,6 +18,7 @@ h2. Usage
h2. Compatibility
+* Version 0.6.0 was written for Redmine 2.1.2 and tested for backwards-compatibility with Redmine 2.0.3 and Redmine 1.4.3.
* Version 0.5.0 was written for Redmine 2.0.3 and tested for backwards-compatibility with Redmine 1.4.3.
* Version 0.4.0 was written for Redmine 1.4.3 and added support for Ruby 1.9.
* Previous versions were written for Redmine 0.9.1.stable and reported to work with Redmine 1.1.2 and 1.3-stable.
@@ -24,4 +27,3 @@ h2. Compatibility
h2. License
This software is licensed under the GNU GPL v2. See COPYRIGHT and COPYING for details.
-
19 app/controllers/stealth_controller.rb
View
@@ -1,15 +1,24 @@
class StealthController < ApplicationController
+
unloadable
before_filter :authorize_global, :only => :toggle
def toggle
- ::RedmineStealth.toggle_stealth_mode!
- next_toggle_label = ::RedmineStealth.toggle_stealth_label
- toggle_domid = ::RedmineStealth::DOMID_STEALTH_TOGGLE
- render :update do |page|
- page[toggle_domid].replace_html(next_toggle_label)
+ is_cloaked = toggle_for_params
+ render :js => RedmineStealth.javascript_toggle_statement(is_cloaked)
+ end
+
+ private
+
+ def toggle_for_params
+ if params[:toggle] == 'true'
+ RedmineStealth.cloak!
+ elsif params[:toggle] == 'false'
+ RedmineStealth.decloak!
+ else
+ RedmineStealth.toggle_stealth_mode!
end
end
25 assets/javascripts/prototype-stealth.js
View
@@ -0,0 +1,25 @@
+(function(root) {
+
+ root.RedmineStealth = {
+
+ cloak: function(label) {
+ $('stealth_toggle').update(label).
+ writeAttribute('data-params-toggle', "false");
+ $$('body')[0].removeClassName('stealth_off').
+ addClassName('stealth_on');
+ },
+
+ decloak: function(label) {
+ $('stealth_toggle').update(label).
+ writeAttribute('data-params-toggle', "true");
+ $$('body')[0].removeClassName('stealth_on').
+ addClassName('stealth_off');
+ },
+
+ notifyFailure: function() {
+ alert($('stealth_toggle').readAttribute('data-failure-message'));
+ }
+
+ };
+
+}).call({}, this);
40 assets/javascripts/stealth.js
View
@@ -1,11 +1,29 @@
-function toggleStealthClassesOnBody() {
- el = $$('body')[0]
-
- if (el.hasClassName('stealth_on')) {
- el.removeClassName('stealth_on');
- el.addClassName('stealth_off');
- } else {
- el.removeClassName('stealth_off');
- el.addClassName('stealth_on');
- }
-}
+
+jQuery(function($) {
+
+ window.RedmineStealth = {
+
+ cloak: function(label) {
+ $('#stealth_toggle').text(label).
+ data({ params : { toggle : 'false' } });
+ $('body').removeClass('stealth_off').
+ addClass('stealth_on');
+ },
+
+ decloak: function(label) {
+ $('#stealth_toggle').text(label).
+ data({ params : { toggle : 'true' } });
+ $('body').removeClass('stealth_on').
+ addClass('stealth_off');
+ },
+
+ notifyFailure: function() {
+ alert($('#stealth_toggle').data('failure-message'));
+ }
+
+ };
+
+ $('#stealth_toggle').bind('ajax:error', RedmineStealth.notifyFailure);
+
+});
+
4 assets/stylesheets/stealth.css
View
@@ -0,0 +1,4 @@
+
+body.stealth_on #top-menu { background: #000; }
+body.stealth_on #header { background: #2C4056; }
+
5 config/routes.rb
View
@@ -2,14 +2,15 @@
if Rails::VERSION::MAJOR >= 3
RedmineApp::Application.routes.draw do
- match '/stealth/toggle', :to => 'stealth#toggle'
+ post '/stealth/toggle', :to => 'stealth#toggle'
end
else
ActionController::Routing::Routes.draw do |map|
map.connect '/stealth/toggle',
- :controller => 'stealth', :action => 'toggle'
+ :controller => 'stealth', :action => 'toggle',
+ :conditions => { :method => :post }
end
end
92 init.rb
View
@@ -3,25 +3,42 @@
require 'redmine/i18n'
require 'redmine_stealth'
-require 'redmine_menu_manager_extensions'
+
+unless RedmineStealth::USE_UJS
+ require 'redmine_ext/menu_manager_extensions'
+end
if Rails::VERSION::MAJOR >= 3
- require 'stealth_mail_interceptor'
+ require 'redmine_stealth/mail_interceptor'
else
- require 'action_mailer_base_extensions'
+ require 'action_mailer_ext/base_extensions'
end
-require 'stealth_hooks'
+require 'redmine_stealth/hooks'
Redmine::Plugin.register :redmine_stealth do
extend Redmine::I18n
+ plugin_locale_glob = respond_to?(:directory) ?
+ File.join(directory, 'config', 'locales', '*.yml') :
+ File.join(Rails.root, 'vendor', 'plugins',
+ 'redmine_stealth', 'config', 'locales', '*.yml')
+
+ ::I18n.load_path += Dir.glob(plugin_locale_glob)
+
+ menu_options = {
+ :html => {
+ 'id' => 'stealth_toggle',
+ 'data-failure-message' => l(RedmineStealth::MESSAGE_TOGGLE_FAILED)
+ }
+ }
+
name 'Redmine Stealth plugin'
author 'Riley Lynch'
description 'Enables users to disable Redmine email notifications ' +
'for their actions'
- version '0.5.1'
+ version '0.6.0'
if respond_to?(:url)
url 'http://teleological.github.com/redmine-stealth-plugin'
@@ -32,47 +49,40 @@
permission :toggle_stealth_mode, :stealth => :toggle
- decide_toggle_display =
- lambda do |*_|
- show_toggle = false
- if my_user = ::User.current
- toggle_action = {:controller => 'stealth', :action => 'toggle'}
- if my_user.allowed_to?(toggle_action,nil,:global => true)
- show_toggle = true
- end
- end
- show_toggle
+ toggle_url = { :controller => 'stealth', :action => 'toggle' }
+
+ decide_toggle_display = lambda do |*_|
+ can_toggle = false
+ if user = ::User.current
+ can_toggle = user.allowed_to?(toggle_url, nil, :global => true)
end
+ can_toggle
+ end
- stealth_menuitem_captioner =
- lambda { |project| ::RedmineStealth.toggle_stealth_label }
+ stealth_menuitem_captioner = lambda do |project|
+ is_cloaked = RedmineStealth.cloaked?
+ RedmineStealth.status_label(is_cloaked)
+ end
- menu :account_menu, :stealth,
- { :controller => 'stealth', :action => 'toggle' },
- :first => true,
- :if => decide_toggle_display,
- :caption => stealth_menuitem_captioner,
- :html => {
- :id => ::RedmineStealth::DOMID_STEALTH_TOGGLE,
- },
- :remote => {
- :failure => "alert('#{l(::RedmineStealth::MESSAGE_TOGGLE_FAILED)}')",
+ if RedmineStealth::USE_UJS
+ menu_options[:html].update('remote' => true, 'method' => :post)
+ else
+ menu_options[:remote] = {
+ :method => :post,
+ :failure => 'RedmineStealth.notifyFailure();',
+ :with => %q{(function() {
+ var $toggle = $('stealth_toggle');
+ var params = $toggle.readAttribute('data-params-toggle');
+ return params ? ('toggle=' + params) : '';
+ })()}
}
-end
-
-require 'application_helper'
-require 'stealth_css_helper'
-
-stealth_css_helper_mixin = lambda do |*_|
- unless ApplicationHelper.included_modules.include?(StealthCssHelper)
- ApplicationHelper.send(:include, StealthCssHelper)
end
-end
-if Rails::VERSION::MAJOR >= 3
- ActionDispatch::Callbacks.to_prepare(&stealth_css_helper_mixin)
-else
- require 'dispatcher'
- Dispatcher.to_prepare(&stealth_css_helper_mixin)
+ menu :account_menu, :stealth, toggle_url, {
+ :first => true,
+ :if => decide_toggle_display,
+ :caption => stealth_menuitem_captioner
+ }.merge(menu_options)
+
end
23 lib/action_mailer_base_extensions.rb
View
@@ -1,23 +0,0 @@
-
-# Rails < 3
-
-module ActionMailerBaseExtensions
- def deliver_with_stealth!(mail=nil)
- mail ||= instance_variable_get(:@mail)
- if ::RedmineStealth.cloaked?
- if logger && mail
- logger.info("Squelching notification: #{mail.subject}")
- end
- else
- deliver_without_stealth!(mail)
- end
- end
-end
-
-module ActionMailer
- class Base
- include ActionMailerBaseExtensions
- alias_method_chain :deliver!, :stealth
- end
-end
-
25 lib/action_mailer_ext/base_extensions.rb
View
@@ -0,0 +1,25 @@
+
+# Rails < 3
+
+module ActionMailerExt
+ module BaseExtensions
+ def deliver_with_stealth!(mail=nil)
+ mail ||= instance_variable_get(:@mail)
+ if RedmineStealth.cloaked?
+ if logger && mail
+ logger.info("Squelching notification: #{mail.subject}")
+ end
+ else
+ deliver_without_stealth!(mail)
+ end
+ end
+ end
+end
+
+module ActionMailer
+ class Base
+ include ActionMailerExt::BaseExtensions
+ alias_method_chain :deliver!, :stealth
+ end
+end
+
40 lib/redmine_ext/menu_manager_extensions.rb
View
@@ -0,0 +1,40 @@
+
+require 'redmine/menu_manager'
+
+module Redmine
+ module MenuManager
+
+ class MenuItem
+
+ attr_reader :remote_options
+
+ def initialize_with_remote(name, url, options)
+ @remote_options = options.delete(:remote)
+ initialize_without_remote(name, url, options)
+ end
+
+ alias_method_chain :initialize, :remote
+
+ end
+
+ module MenuHelper
+
+ def render_single_menu_node_with_remote(item, caption, url, is_sel)
+ if remote_options = item.remote_options
+ non_html_options = remote_options.kind_of?(Hash) ?
+ remote_options.reverse_merge(:url => url) : { :url => url }
+ link_to_remote(h(caption),
+ non_html_options,
+ item.html_options(:selected => is_sel))
+ else
+ render_single_menu_node_without_remote(item, caption, url, is_sel)
+ end
+ end
+
+ alias_method_chain :render_single_menu_node, :remote
+
+ end
+
+ end
+end
+
42 lib/redmine_menu_manager_extensions.rb
View
@@ -1,42 +0,0 @@
-
-module RedmineMenuManagerExtensions
-end
-
-require 'redmine/menu_manager'
-
-module Redmine
- module MenuManager
- class MenuItem
- attr_reader :remote
- def initialize_with_remote_option(name,url,options)
- if remote_options = options.delete(:remote)
- remote_options = {} unless remote_options.kind_of?(::Hash)
- @remote = remote_options
- initialize_without_remote_option(name,url,options)
- else
- @remote = nil
- initialize_without_remote_option(name,url,options)
- end
- end
- alias_method_chain :initialize, :remote_option
- end
- module MenuHelper
- def render_single_menu_node_with_remote_option(item,caption,url,selected)
- if user_remote_options = item.remote
- remote_options = {
- :url => url,
- :success => "toggleStealthClassesOnBody();"
- }
- remote_options.update(user_remote_options)
- link_to_remote(h(caption), remote_options,
- item.html_options(:selected => selected))
- else
- render_single_menu_node_without_remote_option(item,
- caption,url,selected)
- end
- end
- alias_method_chain :render_single_menu_node, :remote_option
- end
- end
-end
-
52 lib/redmine_stealth.rb
View
@@ -1,33 +1,30 @@
-module RedmineStealth
- include Redmine::I18n
- LABEL_ACTION_CLOAK = 'enable_stealth_mode'
- LABEL_ACTION_DECLOAK = 'disable_stealth_mode'
+module RedmineStealth
- MESSAGE_TOGGLE_FAILED = 'failed_to_toggle_stealth_mode'
+ include Redmine::I18n
- DOMID_STEALTH_TOGGLE = 'stealth_toggle'
+ USE_UJS = defined?(::Jquery)
PREF_STEALTH_ENABLED = :stealth_mode
+ MESSAGE_ACTION_CLOAK = 'enable_stealth_mode'
+ MESSAGE_ACTION_DECLOAK = 'disable_stealth_mode'
+ MESSAGE_TOGGLE_FAILED = 'failed_to_toggle_stealth_mode'
+
module_function
def cloaked?
- is_cloaked = false
- if my_user = ::User.current
- is_cloaked = true if my_user.pref[PREF_STEALTH_ENABLED]
- end
- is_cloaked
+ current_user = ::User.current
+ !! (current_user && current_user.pref[PREF_STEALTH_ENABLED])
end
- def set_stealth_mode(is_active)
- if my_user = ::User.current
- user_prefs = my_user.pref
- user_prefs[PREF_STEALTH_ENABLED] = is_active
- user_prefs.save! if user_prefs.changed?
- else
- logger.warn("No user to set stealth mode") if logger
- end
+ def status_label(is_cloaked)
+ is_cloaked ? l(MESSAGE_ACTION_DECLOAK) : l(MESSAGE_ACTION_CLOAK)
+ end
+
+ def toggle_stealth_mode!
+ is_cloaked = cloaked?
+ is_cloaked ? decloak! : cloak!
end
def cloak!
@@ -38,12 +35,21 @@ def decloak!
set_stealth_mode(false)
end
- def toggle_stealth_mode!
- cloaked? ? decloak! : cloak!
+ def set_stealth_mode(is_cloaked)
+ if current_user = ::User.current
+ user_prefs = current_user.pref
+ user_prefs[PREF_STEALTH_ENABLED] = is_cloaked
+ user_prefs.save! if user_prefs.changed?
+ is_cloaked
+ else
+ logger.warn("No user to set stealth mode") if logger
+ end
end
- def toggle_stealth_label
- cloaked? ? l(LABEL_ACTION_DECLOAK) : l(LABEL_ACTION_CLOAK)
+ def javascript_toggle_statement(is_cloaked)
+ label = status_label(is_cloaked)
+ method = "RedmineStealth.#{ is_cloaked ? 'cloak' : 'decloak' }"
+ "#{method}('#{label}');"
end
end
32 lib/redmine_stealth/hooks.rb
View
@@ -0,0 +1,32 @@
+
+module RedmineStealth
+ class Hooks < Redmine::Hook::ViewListener
+
+ def controller_account_success_authentication_after(context={})
+ ::RedmineStealth.decloak!
+ end
+
+ def view_layouts_base_html_head(context={})
+ stylesheet_link_tag('stealth', :plugin => 'redmine_stealth')
+ end
+
+ def view_layouts_base_body_bottom(context={})
+ is_cloaked = RedmineStealth.cloaked?
+ init_state = RedmineStealth.javascript_toggle_statement(is_cloaked)
+
+ if RedmineStealth::USE_UJS
+ js_lib = 'stealth'
+ javascript_include_tag(js_lib, :plugin => 'redmine_stealth') +
+ javascript_tag("jQuery(function($) { #{init_state} });")
+ else
+ js_lib = 'prototype-stealth'
+ javascript_include_tag(js_lib, :plugin => 'redmine_stealth') +
+ javascript_tag(%Q{
+ document.observe("dom:loaded", function() { #{init_state} });
+ })
+ end
+ end
+
+ end
+end
+
18 lib/redmine_stealth/mail_interceptor.rb
View
@@ -0,0 +1,18 @@
+
+# Rails >= 3
+
+module RedmineStealth
+ class MailInterceptor
+ def self.delivering_email(msg)
+ if RedmineStealth.cloaked?
+ msg.perform_deliveries = false
+ if logger = ActionMailer::Base.logger
+ logger.info("Squelching notification: #{msg.subject}")
+ end
+ end
+ end
+ end
+end
+
+ActionMailer::Base.register_interceptor(RedmineStealth::MailInterceptor)
+
23 lib/stealth_css_helper.rb
View
@@ -1,23 +0,0 @@
-
-module StealthCssHelper
- def self.included(base) # :nodoc:
- base.send(:include, InstanceMethods)
-
- base.class_eval do
- unloadable
- alias_method_chain :body_css_classes, :stealth
- end
- end
-
- module InstanceMethods
- def body_css_classes_with_stealth
- css = body_css_classes_without_stealth || ''
- if ::RedmineStealth.cloaked?
- css += ' stealth_on'
- else
- css += ' stealth_off'
- end
- end
- end
-end
-
13 lib/stealth_hooks.rb
View
@@ -1,13 +0,0 @@
-module RedmineStealth
- class Hooks < Redmine::Hook::ViewListener
- def controller_account_success_authentication_after(context={})
- # on login decloak
- ::RedmineStealth.decloak!
- end
-
- def view_layouts_base_html_head(context={})
- javascript_include_tag 'stealth.js',
- :plugin => 'redmine-stealth-plugin'
- end
- end
-end
16 lib/stealth_mail_interceptor.rb
View
@@ -1,16 +0,0 @@
-
-# Rails >= 3
-
-class StealthMailInterceptor
- def self.delivering_email(msg)
- if ::RedmineStealth.cloaked?
- msg.perform_deliveries = false
- if logger = ActionMailer::Base.logger
- logger.info("Squelching notification: #{msg.subject}")
- end
- end
- end
-end
-
-ActionMailer::Base.register_interceptor(StealthMailInterceptor)
-
Please sign in to comment.
Something went wrong with that request. Please try again.