Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial commit...

  • Loading branch information...
commit ac44c3771c5db29eb3a1982ae1ed4534a5dcb409 0 parents
@peelman authored
47 app/controllers/cc_addresses_controller.rb
@@ -0,0 +1,47 @@
+class CcAddressesController < ApplicationController
+ before_filter :find_project, :authorize
+
+ def create
+ @cc_address = CcAddress.new(params[:new_address])
+ respond_to do |format|
+ if @cc_address.save
+ format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
+ format.js do
+ render :update do |page|
+ if @cc_address.errors.empty?
+ @cc_address = nil
+ end
+ page.replace_html "cc-addresses", :partial => 'issues/cc_addresses', :locals => { :issue => @issue, :project => @project }
+ end
+ end
+ else
+ format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
+ format.js do
+ render :update do |page|
+ page.replace_html "cc-addresses", :partial => 'issues/cc_addresses', :locals => { :issue => @issue, :project => @project }
+ end
+ end
+ end
+ end
+ end
+
+ def destroy
+ cc_address = CcAddress.find(params[:id])
+ if request.post? && @issue.cc_addresses.include?(cc_address)
+ cc_address.destroy
+ @issue.reload
+ end
+ respond_to do |format|
+ format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
+ format.js { render(:update) { |page| page.replace_html "cc-addresses", :partial => 'issues/cc_addresses', :locals => { :issue => @issue, :project => @project } } }
+ end
+ end
+
+private
+ def find_project
+ @issue = Issue.find(params[:issue_id])
+ @project = @issue.project
+ rescue ActiveRecord::RecordNotFound
+ render_404
+ end
+end
6 app/models/cc_address.rb
@@ -0,0 +1,6 @@
+class CcAddress < ActiveRecord::Base
+ belongs_to :issue
+ validates_presence_of :issue_id, :mail
+ validates_uniqueness_of :mail, :scope => :issue_id
+ validates_format_of :mail, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
+end
19 app/views/issues/_cc_addresses.html.erb
@@ -0,0 +1,19 @@
+<div id="cc-addresses">
+ <hr />
+
+ <div class="contextual">
+ <% if authorize_for('cc_addresses', 'create') %>
+ <%= toggle_link l(:button_add), 'new-cc-address-form' %>
+ <% end %>
+ </div>
+
+ <p><strong><%= l(:field_cc_addresses) %></strong></p>
+ <%= render :partial => 'issues/cc_addresses/list', :locals => {:issue => @issue} %>
+
+ <% remote_form_for(:new_address, @cc_address,
+ :url => {:controller => :cc_addresses, :action => :create, :issue_id => @issue },
+ :method => :post,
+ :html => {:id => 'new-cc-address-form', :style => (@cc_address ? '' : 'display: none;')}) do |f| %>
+ <%= render :partial => 'issues/cc_addresses/form', :locals => { :f => f, :issue_id => @issue }%>
+ <% end %>
+</div>
13 app/views/issues/cc_addresses/_form.rhtml
@@ -0,0 +1,13 @@
+<%= error_messages_for :cc_address %>
+<table>
+ <tr>
+ <td><%= l(:label_cc_address) %>:</td>
+ <td><%= f.text_field :mail, :size => 50 %><%= f.hidden_field :issue_id, :value => @issue.id %></td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <%= submit_tag l(:button_add) %>
+ <%= toggle_link l(:button_cancel), 'new-cc-address-form'%>
+ </td>
+ </tr>
+</table>
37 app/views/issues/cc_addresses/_list.html.erb
@@ -0,0 +1,37 @@
+<% if issue.cc_addresses.any? %>
+ <div class="wiki">
+ <ul>
+ <table style="width: 100%; border: 0; margin-bottom: 0;">
+ <% issue.cc_addresses.each do |cc_address| %>
+ <tr>
+ <td style="border: 0; padding: 0;">
+ <li>
+ <%= cc_address.mail %>
+ </li>
+ </td>
+ <% if authorize_for('cc_addresses', 'destroy') %>
+ <td style="border: 0; padding: 0;">
+ <%= link_to_remote(image_tag('delete.png'), {
+ :url => {
+ :controller => 'cc_addresses',
+ :action => 'destroy',
+ :issue_id => issue,
+ :id => cc_address,
+ :only_path => true
+ },
+ :method => :post})
+ %>
+ </td>
+ <% end %>
+ </tr>
+ <% end %>
+ </table>
+ </ul>
+ </div>
+<% else %>
+<div class="wiki">
+ <ul>
+ <li><em><%= l(:label_none) %></em></li>
+ </ul>
+</div>
+<% end %>
3  config/locales/en.yml
@@ -0,0 +1,3 @@
+en:
+ field_cc_addresses: Carbon Copy Addresses
+ label_cc_address: Address
12 db/migrate/001_create_cc_addresses.rb
@@ -0,0 +1,12 @@
+class CreateCcAddresses < ActiveRecord::Migration
+ def self.up
+ create_table :cc_addresses do |t|
+ t.string :mail
+ t.integer :issue_id
+ end
+ end
+
+ def self.down
+ drop_table :cc_addresses
+ end
+end
28 init.rb
@@ -0,0 +1,28 @@
+require 'redmine'
+
+# Patches to the Redmine core.
+require 'dispatcher'
+
+Dispatcher.to_prepare :redmine_cc_addresses do
+ require_dependency 'issue'
+ # Guards against including the module multiple time (like in tests)
+ # and registering multiple callbacks
+ unless Issue.included_modules.include? RedmineCcAddresses::IssuePatch
+ Issue.send(:include, RedmineCcAddresses::IssuePatch)
+ end
+end
+
+require_dependency 'cc_addresses_issue_show_hook'
+
+Redmine::Plugin.register :redmine_cc_addresses do
+ name 'Issue CC Addresses'
+ author 'Nick Peelman'
+ description 'Allows CC Addresses to be attached to an issue'
+ version '0.0.1'
+
+ project_module :cc_addresses do |map|
+ map.permission :view_cc_addresses, { }
+ map.permission :add_cc_addresses, { :cc_addresses => :create }
+ map.permission :delete_cc_addresses, { :cc_addresses => :destroy }
+ end
+end
39 lib/cc_addresses_issue_show_hook.rb
@@ -0,0 +1,39 @@
+# Extension to ViewListener to allow an :if parameter to render_on.
+# See <http://www.redmine.org/boards/3/topics/show/4316>
+module Redmine
+ module Hook
+ class ViewListener
+ def self.render_on(hook, options={})
+ define_method hook do |context|
+ if !options.include?(:if) || evaluate_if_option(options[:if], context)
+ context[:controller].send(:render_to_string, {:locals => context}.merge(options))
+ end
+ end
+ end
+
+ private
+
+ def evaluate_if_option(if_option, context)
+ case if_option
+ when Symbol
+ send(if_option, context)
+ when Method, Proc
+ if_option.call(context)
+ end
+ end
+ end
+ end
+end
+
+class ShowCcAddressesHook < Redmine::Hook::ViewListener
+ render_on :view_issues_show_description_bottom, :partial => "issues/cc_addresses", :if => :has_permission?
+
+private
+ def protect_against_forgery?
+ false
+ end
+
+ def has_permission?(context)
+ context[:project].module_enabled?('cc_addresses') and User.current.allowed_to?(:view_cc_addresses, context[:project])
+ end
+end
13 lib/redmine_cc_addresses/issue_patch.rb
@@ -0,0 +1,13 @@
+module RedmineCcAddresses
+ # Patches Redmine's Issues Model dynamically. Adds a relationship
+ # Issue +has_many+ to IssueResource
+ module IssuePatch
+ def self.included(base) # :nodoc:
+ # Same as typing in the class
+ base.class_eval do
+ belongs_to :deliverable
+ has_many :cc_addresses, :class_name => 'CcAddress', :foreign_key => 'issue_id', :dependent => :delete_all
+ end
+ end
+ end
+end
1  routes.rb
@@ -0,0 +1 @@
+map.connect 'issues/:issue_id/cc_addresses/:action/:id', :controller => 'cc_addresses'
Please sign in to comment.
Something went wrong with that request. Please try again.