Revision 9528
Added by Jean-Philippe Lang about 13 years ago
trunk/.gitignore | ||
---|---|---|
5 | 5 |
/config/database.yml |
6 | 6 |
/config/email.yml |
7 | 7 |
/config/initializers/session_store.rb |
8 |
/config/initializers/secret_token.rb |
|
8 | 9 |
/coverage |
9 | 10 |
/db/*.db |
10 | 11 |
/db/*.sqlite3 |
trunk/.hgignore | ||
---|---|---|
7 | 7 |
config/database.yml |
8 | 8 |
config/email.yml |
9 | 9 |
config/initializers/session_store.rb |
10 |
config/initializers/secret_token.rb |
|
10 | 11 |
coverage |
11 | 12 |
db/*.db |
12 | 13 |
db/*.sqlite3 |
trunk/Gemfile | ||
---|---|---|
1 |
source :rubygems
|
|
1 |
source 'http://rubygems.org'
|
|
2 | 2 |
|
3 |
gem "rails", "2.3.14" |
|
4 |
gem "i18n", "~> 0.4.2" |
|
3 |
gem 'rails', '3.2.3' |
|
4 |
gem 'prototype-rails', '3.2.1' |
|
5 |
gem "i18n", "~> 0.6.0" |
|
5 | 6 |
gem "coderay", "~> 1.0.6" |
6 | 7 |
gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby] |
7 | 8 |
gem "tzinfo", "~> 0.3.31" |
9 |
gem "builder" |
|
8 | 10 |
|
9 | 11 |
# Optional gem for LDAP authentication |
10 | 12 |
group :ldap do |
... | ... | |
14 | 16 |
# Optional gem for OpenID authentication |
15 | 17 |
group :openid do |
16 | 18 |
gem "ruby-openid", "~> 2.1.4", :require => "openid" |
19 |
gem "rack-openid" |
|
17 | 20 |
end |
18 | 21 |
|
19 | 22 |
# Optional gem for exporting the gantt to a PNG file, not supported with jruby |
... | ... | |
45 | 48 |
|
46 | 49 |
platforms :mri_19, :mingw_19 do |
47 | 50 |
group :mysql do |
48 |
gem "mysql2", "~> 0.2.7"
|
|
51 |
gem "mysql2", "~> 0.3.11"
|
|
49 | 52 |
end |
50 | 53 |
end |
51 | 54 |
|
... | ... | |
69 | 72 |
gem "rdoc", ">= 2.4.2" |
70 | 73 |
end |
71 | 74 |
|
75 |
|
|
72 | 76 |
group :test do |
73 |
gem "shoulda", "~> 2.10.3"
|
|
77 |
gem "shoulda" |
|
74 | 78 |
gem "mocha" |
75 | 79 |
end |
76 | 80 |
|
trunk/Rakefile | ||
---|---|---|
1 |
#!/usr/bin/env rake |
|
1 | 2 |
# Add your own tasks in files placed in lib/tasks ending in .rake, |
2 |
# for example lib/tasks/switchtower.rake, and they will automatically be available to Rake.
|
|
3 |
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
|
3 | 4 |
|
4 |
require(File.join(File.dirname(__FILE__), 'config', 'boot'))
|
|
5 |
require File.expand_path('../config/application', __FILE__)
|
|
5 | 6 |
|
6 |
require 'rake' |
|
7 |
require 'rake/testtask' |
|
8 |
|
|
9 |
begin |
|
10 |
require 'rdoc/task' |
|
11 |
rescue LoadError |
|
12 |
# RDoc is not available |
|
13 |
end |
|
14 |
|
|
15 |
require 'tasks/rails' |
|
7 |
RedmineApp::Application.load_tasks |
trunk/app/controllers/application_controller.rb | ||
---|---|---|
22 | 22 |
|
23 | 23 |
class ApplicationController < ActionController::Base |
24 | 24 |
include Redmine::I18n |
25 |
|
|
26 |
class_attribute :accept_api_auth_actions |
|
27 |
class_attribute :accept_rss_auth_actions |
|
28 |
class_attribute :model_object |
|
25 | 29 |
|
26 | 30 |
layout 'base' |
27 |
exempt_from_layout 'builder', 'rsb' |
|
28 | 31 |
|
29 | 32 |
protect_from_forgery |
30 | 33 |
def handle_unverified_request |
... | ... | |
68 | 71 |
end |
69 | 72 |
|
70 | 73 |
before_filter :user_setup, :check_if_login_required, :set_localization |
71 |
filter_parameter_logging :password |
|
72 | 74 |
|
73 | 75 |
rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token |
74 | 76 |
rescue_from ::Unauthorized, :with => :deny_access |
... | ... | |
77 | 79 |
include Redmine::MenuManager::MenuController |
78 | 80 |
helper Redmine::MenuManager::MenuHelper |
79 | 81 |
|
80 |
Redmine::Scm::Base.all.each do |scm| |
|
81 |
require_dependency "repository/#{scm.underscore}" |
|
82 |
end |
|
83 |
|
|
84 | 82 |
def user_setup |
85 | 83 |
# Check the settings cache for each request |
86 | 84 |
Setting.check_cache |
... | ... | |
242 | 240 |
end |
243 | 241 |
|
244 | 242 |
def find_model_object |
245 |
model = self.class.read_inheritable_attribute('model_object')
|
|
243 |
model = self.class.model_object
|
|
246 | 244 |
if model |
247 | 245 |
@object = model.find(params[:id]) |
248 | 246 |
self.instance_variable_set('@' + controller_name.singularize, @object) if @object |
... | ... | |
252 | 250 |
end |
253 | 251 |
|
254 | 252 |
def self.model_object(model) |
255 |
write_inheritable_attribute('model_object', model)
|
|
253 |
self.model_object = model
|
|
256 | 254 |
end |
257 | 255 |
|
258 | 256 |
# Filter for bulk issue operations |
... | ... | |
388 | 386 |
|
389 | 387 |
def self.accept_rss_auth(*actions) |
390 | 388 |
if actions.any? |
391 |
write_inheritable_attribute('accept_rss_auth_actions', actions)
|
|
389 |
self.accept_rss_auth_actions = actions
|
|
392 | 390 |
else |
393 |
read_inheritable_attribute('accept_rss_auth_actions') || []
|
|
391 |
self.accept_rss_auth_actions || []
|
|
394 | 392 |
end |
395 | 393 |
end |
396 | 394 |
|
... | ... | |
400 | 398 |
|
401 | 399 |
def self.accept_api_auth(*actions) |
402 | 400 |
if actions.any? |
403 |
write_inheritable_attribute('accept_api_auth_actions', actions)
|
|
401 |
self.accept_api_auth_actions = actions
|
|
404 | 402 |
else |
405 |
read_inheritable_attribute('accept_api_auth_actions') || []
|
|
403 |
self.accept_api_auth_actions || []
|
|
406 | 404 |
end |
407 | 405 |
end |
408 | 406 |
|
... | ... | |
523 | 521 |
else |
524 | 522 |
@error_messages = objects.errors.full_messages |
525 | 523 |
end |
526 |
render :template => 'common/error_messages.api', :status => :unprocessable_entity, :layout => false
|
|
524 |
render :template => 'common/error_messages.api', :status => :unprocessable_entity, :layout => nil
|
|
527 | 525 |
end |
528 | 526 |
|
529 |
# Overrides #default_template so that the api template |
|
530 |
# is used automatically if it exists |
|
531 |
def default_template(action_name = self.action_name) |
|
532 |
if api_request? |
|
533 |
begin |
|
534 |
return self.view_paths.find_template(default_template_name(action_name), 'api') |
|
535 |
rescue ::ActionView::MissingTemplate |
|
536 |
# the api template was not found |
|
537 |
# fallback to the default behaviour |
|
538 |
end |
|
539 |
end |
|
540 |
super |
|
541 |
end |
|
542 |
|
|
543 |
# Overrides #pick_layout so that #render with no arguments |
|
527 |
# Overrides #_include_layout? so that #render with no arguments |
|
544 | 528 |
# doesn't use the layout for api requests |
545 |
def pick_layout(*args)
|
|
546 |
api_request? ? nil : super
|
|
529 |
def _include_layout?(*args)
|
|
530 |
api_request? ? false : super
|
|
547 | 531 |
end |
548 | 532 |
end |
trunk/app/controllers/messages_controller.rb | ||
---|---|---|
95 | 95 |
# Delete a messages |
96 | 96 |
def destroy |
97 | 97 |
(render_403; return false) unless @message.destroyable_by?(User.current) |
98 |
r = @message.to_param |
|
98 | 99 |
@message.destroy |
99 | 100 |
redirect_to @message.parent.nil? ? |
100 | 101 |
{ :controller => 'boards', :action => 'show', :project_id => @project, :id => @board } : |
101 |
{ :action => 'show', :id => @message.parent, :r => @message }
|
|
102 |
{ :action => 'show', :id => @message.parent, :r => r }
|
|
102 | 103 |
end |
103 | 104 |
|
104 | 105 |
def quote |
trunk/app/controllers/repositories_controller.rb | ||
---|---|---|
18 | 18 |
require 'SVG/Graph/Bar' |
19 | 19 |
require 'SVG/Graph/BarHorizontal' |
20 | 20 |
require 'digest/sha1' |
21 |
require 'redmine/scm/adapters/abstract_adapter' |
|
21 | 22 |
|
22 | 23 |
class ChangesetNotFound < Exception; end |
23 | 24 |
class InvalidRevisionParam < Exception; end |
... | ... | |
307 | 308 |
@repository = @project.repository |
308 | 309 |
end |
309 | 310 |
(render_404; return false) unless @repository |
310 |
@path = params[:path].join('/') unless params[:path].nil? |
|
311 |
@path ||= '' |
|
311 |
@path = params[:path].is_a?(Array) ? params[:path].join('/') : params[:path].to_s |
|
312 | 312 |
@rev = params[:rev].blank? ? @repository.default_branch : params[:rev].to_s.strip |
313 | 313 |
@rev_to = params[:rev_to] |
314 | 314 |
|
... | ... | |
343 | 343 |
@date_to = Date.today |
344 | 344 |
@date_from = @date_to << 11 |
345 | 345 |
@date_from = Date.civil(@date_from.year, @date_from.month, 1) |
346 |
commits_by_day = repository.changesets.count(
|
|
346 |
commits_by_day = Changeset.count(
|
|
347 | 347 |
:all, :group => :commit_date, |
348 |
:conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
|
|
348 |
:conditions => ["repository_id = ? AND commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to])
|
|
349 | 349 |
commits_by_month = [0] * 12 |
350 | 350 |
commits_by_day.each {|c| commits_by_month[c.first.to_date.months_ago] += c.last } |
351 | 351 |
|
352 |
changes_by_day = repository.changes.count(
|
|
353 |
:all, :group => :commit_date, |
|
354 |
:conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
|
|
352 |
changes_by_day = Change.count(
|
|
353 |
:all, :group => :commit_date, :include => :changeset,
|
|
354 |
:conditions => ["#{Changeset.table_name}.repository_id = ? AND #{Changeset.table_name}.commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to])
|
|
355 | 355 |
changes_by_month = [0] * 12 |
356 | 356 |
changes_by_day.each {|c| changes_by_month[c.first.to_date.months_ago] += c.last } |
357 | 357 |
|
... | ... | |
384 | 384 |
end |
385 | 385 |
|
386 | 386 |
def graph_commits_per_author(repository) |
387 |
commits_by_author = repository.changesets.count(:all, :group => :committer)
|
|
387 |
commits_by_author = Changeset.count(:all, :group => :committer, :conditions => ["repository_id = ?", repository.id])
|
|
388 | 388 |
commits_by_author.to_a.sort! {|x, y| x.last <=> y.last} |
389 | 389 |
|
390 |
changes_by_author = repository.changes.count(:all, :group => :committer)
|
|
390 |
changes_by_author = Change.count(:all, :group => :committer, :include => :changeset, :conditions => ["#{Changeset.table_name}.repository_id = ?", repository.id])
|
|
391 | 391 |
h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o} |
392 | 392 |
|
393 | 393 |
fields = commits_by_author.collect {|r| r.first} |
trunk/app/controllers/watchers_controller.rb | ||
---|---|---|
109 | 109 |
@watched = klass.find(params[:object_id]) |
110 | 110 |
@project = @watched.project |
111 | 111 |
elsif params[:project_id] |
112 |
@project = Project.visible.find(params[:project_id]) |
|
112 |
@project = Project.visible.find_by_param(params[:project_id])
|
|
113 | 113 |
end |
114 | 114 |
rescue |
115 | 115 |
render_404 |
trunk/app/controllers/wiki_controller.rb | ||
---|---|---|
163 | 163 |
# Optimistic locking exception |
164 | 164 |
flash.now[:error] = l(:notice_locking_conflict) |
165 | 165 |
render :action => 'edit' |
166 |
rescue ActiveRecord::RecordNotSaved |
|
167 |
render :action => 'edit' |
|
166 | 168 |
end |
167 | 169 |
|
168 | 170 |
# rename a page |
trunk/app/helpers/application_helper.rb | ||
---|---|---|
930 | 930 |
def labelled_form_for(*args, &proc) |
931 | 931 |
args << {} unless args.last.is_a?(Hash) |
932 | 932 |
options = args.last |
933 |
if args.first.is_a?(Symbol) |
|
934 |
options.merge!(:as => args.shift) |
|
935 |
end |
|
933 | 936 |
options.merge!({:builder => Redmine::Views::LabelledFormBuilder}) |
934 | 937 |
form_for(*args, &proc) |
935 | 938 |
end |
... | ... | |
1060 | 1063 |
# +user+ can be a User or a string that will be scanned for an email address (eg. 'joe <[email protected]>') |
1061 | 1064 |
def avatar(user, options = { }) |
1062 | 1065 |
if Setting.gravatar_enabled? |
1063 |
options.merge!({:ssl => (defined?(request) && request.ssl?), :default => Setting.gravatar_default})
|
|
1066 |
options.merge!({:ssl => (request && request.ssl?), :default => Setting.gravatar_default})
|
|
1064 | 1067 |
email = nil |
1065 | 1068 |
if user.respond_to?(:mail) |
1066 | 1069 |
email = user.mail |
... | ... | |
1079 | 1082 |
|
1080 | 1083 |
# Returns the javascript tags that are included in the html layout head |
1081 | 1084 |
def javascript_heads |
1082 |
tags = javascript_include_tag(:defaults)
|
|
1085 |
tags = javascript_include_tag('prototype', 'effects', 'dragdrop', 'controls', 'rails', 'application')
|
|
1083 | 1086 |
unless User.current.pref.warn_on_leaving_unsaved == '0' |
1084 | 1087 |
tags << "\n".html_safe + javascript_tag("Event.observe(window, 'load', function(){ new WarnLeavingUnsaved('#{escape_javascript( l(:text_warn_on_leaving_unsaved) )}'); });") |
1085 | 1088 |
end |
trunk/app/helpers/wiki_helper.rb | ||
---|---|---|
21 | 21 |
|
22 | 22 |
def wiki_page_options_for_select(pages, selected = nil, parent = nil, level = 0) |
23 | 23 |
pages = pages.group_by(&:parent) unless pages.is_a?(Hash) |
24 |
s = '' |
|
24 |
s = ''.html_safe
|
|
25 | 25 |
if pages.has_key?(parent) |
26 | 26 |
pages[parent].each do |page| |
27 | 27 |
attrs = "value='#{page.id}'" |
28 | 28 |
attrs << " selected='selected'" if selected == page |
29 |
indent = (level > 0) ? (' ' * level * 2 + '» ') : nil
|
|
29 |
indent = (level > 0) ? (' ' * level * 2 + '» ') : ''
|
|
30 | 30 |
|
31 |
s << "<option #{attrs}>#{indent}#{h page.pretty_title}</option>\n" +
|
|
31 |
s << content_tag('option', (indent + h(page.pretty_title)).html_safe, :value => page.id.to_s, :selected => selected == page) +
|
|
32 | 32 |
wiki_page_options_for_select(pages, selected, page, level + 1) |
33 | 33 |
end |
34 | 34 |
end |
trunk/app/models/custom_field.rb | ||
---|---|---|
80 | 80 |
when 'bool' |
81 | 81 |
[[l(:general_text_Yes), '1'], [l(:general_text_No), '0']] |
82 | 82 |
else |
83 |
read_possible_values_utf8_encoded || []
|
|
83 |
possible_values || []
|
|
84 | 84 |
end |
85 | 85 |
end |
86 | 86 |
|
... | ... | |
91 | 91 |
when 'bool' |
92 | 92 |
['1', '0'] |
93 | 93 |
else |
94 |
read_possible_values_utf8_encoded |
|
94 |
values = super() |
|
95 |
if values.is_a?(Array) |
|
96 |
values.each do |value| |
|
97 |
value.force_encoding('UTF-8') if value.respond_to?(:force_encoding) |
|
98 |
end |
|
99 |
end |
|
100 |
values |
|
95 | 101 |
end |
96 | 102 |
end |
97 | 103 |
|
98 | 104 |
# Makes possible_values accept a multiline string |
99 | 105 |
def possible_values=(arg) |
100 | 106 |
if arg.is_a?(Array) |
101 |
write_attribute(:possible_values, arg.compact.collect(&:strip).select {|v| !v.blank?})
|
|
107 |
super(arg.compact.collect(&:strip).select {|v| !v.blank?})
|
|
102 | 108 |
else |
103 | 109 |
self.possible_values = arg.to_s.split(/[\n\r]+/) |
104 | 110 |
end |
... | ... | |
218 | 224 |
end |
219 | 225 |
errs |
220 | 226 |
end |
221 |
|
|
222 |
def read_possible_values_utf8_encoded |
|
223 |
values = read_attribute(:possible_values) |
|
224 |
if values.is_a?(Array) |
|
225 |
values.each do |value| |
|
226 |
value.force_encoding('UTF-8') if value.respond_to?(:force_encoding) |
|
227 |
end |
|
228 |
end |
|
229 |
values |
|
230 |
end |
|
231 | 227 |
end |
trunk/app/models/issue.rb | ||
---|---|---|
246 | 246 |
write_attribute(:description, arg) |
247 | 247 |
end |
248 | 248 |
|
249 |
# Overrides attributes= so that project and tracker get assigned first
|
|
250 |
def attributes_with_project_and_tracker_first=(new_attributes, *args)
|
|
249 |
# Overrides assign_attributes so that project and tracker get assigned first
|
|
250 |
def assign_attributes_with_project_and_tracker_first(new_attributes, *args)
|
|
251 | 251 |
return if new_attributes.nil? |
252 | 252 |
attrs = new_attributes.dup |
253 | 253 |
attrs.stringify_keys! |
... | ... | |
257 | 257 |
send "#{attr}=", attrs.delete(attr) |
258 | 258 |
end |
259 | 259 |
end |
260 |
send :attributes_without_project_and_tracker_first=, attrs, *args
|
|
260 |
send :assign_attributes_without_project_and_tracker_first, attrs, *args
|
|
261 | 261 |
end |
262 | 262 |
# Do not redefine alias chain on reload (see #4838) |
263 |
alias_method_chain(:attributes=, :project_and_tracker_first) unless method_defined?(:attributes_without_project_and_tracker_first=)
|
|
263 |
alias_method_chain(:assign_attributes, :project_and_tracker_first) unless method_defined?(:assign_attributes_without_project_and_tracker_first)
|
|
264 | 264 |
|
265 | 265 |
def estimated_hours=(h) |
266 | 266 |
write_attribute :estimated_hours, (h.is_a?(String) ? h.to_hours : h) |
... | ... | |
350 | 350 |
end |
351 | 351 |
|
352 | 352 |
# mass-assignment security bypass |
353 |
self.send :attributes=, attrs, false
|
|
353 |
assign_attributes attrs, :without_protection => true
|
|
354 | 354 |
end |
355 | 355 |
|
356 | 356 |
def done_ratio |
... | ... | |
921 | 921 |
p.estimated_hours = nil if p.estimated_hours == 0.0 |
922 | 922 |
|
923 | 923 |
# ancestors will be recursively updated |
924 |
p.save(false) |
|
924 |
p.save(:validate => false)
|
|
925 | 925 |
end |
926 | 926 |
end |
927 | 927 |
|
trunk/app/models/mail_handler.rb | ||
---|---|---|
15 | 15 |
# along with this program; if not, write to the Free Software |
16 | 16 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
17 | 17 |
|
18 |
class MailHandler < ActionMailer::Base |
|
18 |
require 'vendor/tmail' |
|
19 |
|
|
20 |
class MailHandler |
|
19 | 21 |
include ActionView::Helpers::SanitizeHelper |
20 | 22 |
include Redmine::I18n |
21 | 23 |
|
... | ... | |
39 | 41 |
@@handler_options[:allow_override] << 'status' unless @@handler_options[:issue].has_key?(:status) |
40 | 42 |
|
41 | 43 |
@@handler_options[:no_permission_check] = (@@handler_options[:no_permission_check].to_s == '1' ? true : false) |
42 |
super email |
|
44 |
|
|
45 |
mail = TMail::Mail.parse(email) |
|
46 |
mail.base64_decode |
|
47 |
new.receive(mail) |
|
43 | 48 |
end |
44 | 49 |
|
50 |
def logger |
|
51 |
Rails.logger |
|
52 |
end |
|
53 |
|
|
45 | 54 |
cattr_accessor :ignored_emails_headers |
46 | 55 |
@@ignored_emails_headers = { |
47 | 56 |
'X-Auto-Response-Suppress' => 'OOF', |
trunk/app/models/mailer.rb | ||
---|---|---|
21 | 21 |
helper :issues |
22 | 22 |
helper :custom_fields |
23 | 23 |
|
24 |
include ActionController::UrlWriter |
|
25 | 24 |
include Redmine::I18n |
26 | 25 |
|
27 | 26 |
def self.default_url_options |
28 |
h = Setting.host_name |
|
29 |
h = h.to_s.gsub(%r{\/.*$}, '') unless Redmine::Utils.relative_url_root.blank? |
|
30 |
{ :host => h, :protocol => Setting.protocol } |
|
27 |
{ :host => Setting.host_name, :protocol => Setting.protocol } |
|
31 | 28 |
end |
32 | 29 |
|
33 | 30 |
# Builds a tmail object used to email recipients of the added issue. |
... | ... | |
42 | 39 |
redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to |
43 | 40 |
message_id issue |
44 | 41 |
@author = issue.author |
45 |
recipients issue.recipients |
|
46 |
cc(issue.watcher_recipients - @recipients) |
|
47 |
subject "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}" |
|
48 |
body :issue => issue, |
|
49 |
:issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue) |
|
50 |
render_multipart('issue_add', body) |
|
42 |
@issue = issue |
|
43 |
@issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue) |
|
44 |
recipients = issue.recipients |
|
45 |
cc = issue.watcher_recipients - recipients |
|
46 |
mail :to => recipients, |
|
47 |
:cc => cc, |
|
48 |
:subject => "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}" |
|
51 | 49 |
end |
52 | 50 |
|
53 | 51 |
# Builds a tmail object used to email recipients of the edited issue. |
... | ... | |
64 | 62 |
message_id journal |
65 | 63 |
references issue |
66 | 64 |
@author = journal.user |
67 |
recipients issue.recipients |
|
65 |
recipients = issue.recipients
|
|
68 | 66 |
# Watchers in cc |
69 |
cc(issue.watcher_recipients - @recipients)
|
|
67 |
cc = issue.watcher_recipients - recipients
|
|
70 | 68 |
s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] " |
71 | 69 |
s << "(#{issue.status.name}) " if journal.new_value_for('status_id') |
72 | 70 |
s << issue.subject |
73 |
subject s
|
|
74 |
body :issue => issue,
|
|
75 |
:journal => journal,
|
|
76 |
:issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => "change-#{journal.id}")
|
|
77 |
|
|
78 |
render_multipart('issue_edit', body)
|
|
71 |
@issue = issue
|
|
72 |
@journal = journal
|
|
73 |
@issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => "change-#{journal.id}")
|
|
74 |
mail :to => recipients,
|
|
75 |
:cc => cc, |
|
76 |
:subject => s
|
|
79 | 77 |
end |
80 | 78 |
|
81 | 79 |
def reminder(user, issues, days) |
82 | 80 |
set_language_if_valid user.language |
83 |
recipients user.mail |
|
84 |
subject l(:mail_subject_reminder, :count => issues.size, :days => days) |
|
85 |
body :issues => issues, |
|
86 |
:days => days, |
|
87 |
:issues_url => url_for(:controller => 'issues', :action => 'index', |
|
81 |
@issues = issues |
|
82 |
@days = days |
|
83 |
@issues_url = url_for(:controller => 'issues', :action => 'index', |
|
88 | 84 |
:set_filter => 1, :assigned_to_id => user.id, |
89 | 85 |
:sort => 'due_date:asc') |
90 |
render_multipart('reminder', body) |
|
86 |
mail :to => user.mail, |
|
87 |
:subject => l(:mail_subject_reminder, :count => issues.size, :days => days) |
|
91 | 88 |
end |
92 | 89 |
|
93 | 90 |
# Builds a tmail object used to email users belonging to the added document's project. |
... | ... | |
97 | 94 |
# Mailer.deliver_document_added(document) => sends an email to the document's project recipients |
98 | 95 |
def document_added(document) |
99 | 96 |
redmine_headers 'Project' => document.project.identifier |
100 |
recipients document.recipients |
|
101 | 97 |
@author = User.current |
102 |
subject "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
|
|
103 |
body :document => document,
|
|
104 |
:document_url => url_for(:controller => 'documents', :action => 'show', :id => document)
|
|
105 |
render_multipart('document_added', body)
|
|
98 |
@document = document
|
|
99 |
@document_url = url_for(:controller => 'documents', :action => 'show', :id => document)
|
|
100 |
mail :to => document.recipients,
|
|
101 |
:subject => "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
|
|
106 | 102 |
end |
107 | 103 |
|
108 | 104 |
# Builds a tmail object used to email recipients of a project when an attachements are added. |
... | ... | |
119 | 115 |
when 'Project' |
120 | 116 |
added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container) |
121 | 117 |
added_to = "#{l(:label_project)}: #{container}" |
122 |
recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect {|u| u.mail} |
|
118 |
recipients = container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect {|u| u.mail}
|
|
123 | 119 |
when 'Version' |
124 | 120 |
added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container.project) |
125 | 121 |
added_to = "#{l(:label_version)}: #{container.name}" |
126 |
recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect {|u| u.mail} |
|
122 |
recipients = container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect {|u| u.mail}
|
|
127 | 123 |
when 'Document' |
128 | 124 |
added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id) |
129 | 125 |
added_to = "#{l(:label_document)}: #{container.title}" |
130 |
recipients container.recipients |
|
126 |
recipients = container.recipients
|
|
131 | 127 |
end |
132 | 128 |
redmine_headers 'Project' => container.project.identifier |
133 |
subject "[#{container.project.name}] #{l(:label_attachment_new)}"
|
|
134 |
body :attachments => attachments,
|
|
135 |
:added_to => added_to,
|
|
136 |
:added_to_url => added_to_url
|
|
137 |
render_multipart('attachments_added', body)
|
|
129 |
@attachments = attachments
|
|
130 |
@added_to = added_to
|
|
131 |
@added_to_url = added_to_url
|
|
132 |
mail :to => recipients,
|
|
133 |
:subject => "[#{container.project.name}] #{l(:label_attachment_new)}"
|
|
138 | 134 |
end |
139 | 135 |
|
140 | 136 |
# Builds a tmail object used to email recipients of a news' project when a news item is added. |
... | ... | |
146 | 142 |
redmine_headers 'Project' => news.project.identifier |
147 | 143 |
@author = news.author |
148 | 144 |
message_id news |
149 |
recipients news.recipients |
|
150 |
subject "[#{news.project.name}] #{l(:label_news)}: #{news.title}" |
|
151 |
body :news => news, |
|
152 |
:news_url => url_for(:controller => 'news', :action => 'show', :id => news) |
|
153 |
render_multipart('news_added', body) |
|
145 |
@news = news |
|
146 |
@news_url = url_for(:controller => 'news', :action => 'show', :id => news) |
|
147 |
mail :to => news.recipients, |
|
148 |
:subject => "[#{news.project.name}] #{l(:label_news)}: #{news.title}" |
|
154 | 149 |
end |
155 | 150 |
|
156 | 151 |
# Builds a tmail object used to email recipients of a news' project when a news comment is added. |
... | ... | |
163 | 158 |
redmine_headers 'Project' => news.project.identifier |
164 | 159 |
@author = comment.author |
165 | 160 |
message_id comment |
166 |
recipients news.recipients |
|
167 |
cc news.watcher_recipients |
|
168 |
subject "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}" |
|
169 |
body :news => news, |
|
170 |
:comment => comment, |
|
171 |
:news_url => url_for(:controller => 'news', :action => 'show', :id => news) |
|
172 |
render_multipart('news_comment_added', body) |
|
161 |
@news = news |
|
162 |
@comment = comment |
|
163 |
@news_url = url_for(:controller => 'news', :action => 'show', :id => news) |
|
164 |
mail :to => news.recipients, |
|
165 |
:cc => news.watcher_recipients, |
|
166 |
:subject => "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}" |
|
173 | 167 |
end |
174 | 168 |
|
175 | 169 |
# Builds a tmail object used to email the recipients of the specified message that was posted. |
... | ... | |
183 | 177 |
@author = message.author |
184 | 178 |
message_id message |
185 | 179 |
references message.parent unless message.parent.nil? |
186 |
recipients(message.recipients) |
|
187 |
cc((message.root.watcher_recipients + message.board.watcher_recipients).uniq - @recipients) |
|
188 |
subject "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}" |
|
189 |
body :message => message, |
|
190 |
:message_url => url_for(message.event_url) |
|
191 |
render_multipart('message_posted', body) |
|
180 |
recipients = message.recipients |
|
181 |
cc = ((message.root.watcher_recipients + message.board.watcher_recipients).uniq - recipients) |
|
182 |
@message = message |
|
183 |
@message_url = url_for(message.event_url) |
|
184 |
mail :to => recipients, |
|
185 |
:cc => cc, |
|
186 |
:subject => "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}" |
|
192 | 187 |
end |
193 | 188 |
|
194 | 189 |
# Builds a tmail object used to email the recipients of a project of the specified wiki content was added. |
... | ... | |
201 | 196 |
'Wiki-Page-Id' => wiki_content.page.id |
202 | 197 |
@author = wiki_content.author |
203 | 198 |
message_id wiki_content |
204 |
recipients wiki_content.recipients |
|
205 |
cc(wiki_content.page.wiki.watcher_recipients - recipients) |
|
206 |
subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :id => wiki_content.page.pretty_title)}" |
|
207 |
body :wiki_content => wiki_content, |
|
208 |
:wiki_content_url => url_for(:controller => 'wiki', :action => 'show', |
|
199 |
recipients = wiki_content.recipients |
|
200 |
cc = wiki_content.page.wiki.watcher_recipients - recipients |
|
201 |
@wiki_content = wiki_content |
|
202 |
@wiki_content_url = url_for(:controller => 'wiki', :action => 'show', |
|
209 | 203 |
:project_id => wiki_content.project, |
210 | 204 |
:id => wiki_content.page.title) |
211 |
render_multipart('wiki_content_added', body) |
|
205 |
mail :to => recipients, |
|
206 |
:cc => cc, |
|
207 |
:subject => "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :id => wiki_content.page.pretty_title)}" |
|
212 | 208 |
end |
213 | 209 |
|
214 | 210 |
# Builds a tmail object used to email the recipients of a project of the specified wiki content was updated. |
... | ... | |
221 | 217 |
'Wiki-Page-Id' => wiki_content.page.id |
222 | 218 |
@author = wiki_content.author |
223 | 219 |
message_id wiki_content |
224 |
recipients wiki_content.recipients |
|
225 |
cc(wiki_content.page.wiki.watcher_recipients + wiki_content.page.watcher_recipients - recipients) |
|
226 |
subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :id => wiki_content.page.pretty_title)}" |
|
227 |
body :wiki_content => wiki_content, |
|
228 |
:wiki_content_url => url_for(:controller => 'wiki', :action => 'show', |
|
220 |
recipients = wiki_content.recipients |
|
221 |
cc = wiki_content.page.wiki.watcher_recipients + wiki_content.page.watcher_recipients - recipients |
|
222 |
@wiki_content = wiki_content |
|
223 |
@wiki_content_url = url_for(:controller => 'wiki', :action => 'show', |
|
229 | 224 |
:project_id => wiki_content.project, |
230 |
:id => wiki_content.page.title),
|
|
231 |
:wiki_diff_url => url_for(:controller => 'wiki', :action => 'diff',
|
|
225 |
:id => wiki_content.page.title) |
|
226 |
@wiki_diff_url = url_for(:controller => 'wiki', :action => 'diff',
|
|
232 | 227 |
:project_id => wiki_content.project, :id => wiki_content.page.title, |
233 | 228 |
:version => wiki_content.version) |
234 |
render_multipart('wiki_content_updated', body) |
|
229 |
mail :to => recipients, |
|
230 |
:cc => cc, |
|
231 |
:subject => "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :id => wiki_content.page.pretty_title)}" |
|
235 | 232 |
end |
236 | 233 |
|
237 | 234 |
# Builds a tmail object used to email the specified user their account information. |
... | ... | |
241 | 238 |
# Mailer.deliver_account_information(user, password) => sends account information to the user |
242 | 239 |
def account_information(user, password) |
243 | 240 |
set_language_if_valid user.language |
244 |
recipients user.mail |
|
245 |
subject l(:mail_subject_register, Setting.app_title) |
|
246 |
body :user => user, |
|
247 |
:password => password, |
|
248 |
:login_url => url_for(:controller => 'account', :action => 'login') |
|
249 |
render_multipart('account_information', body) |
|
241 |
@user = user |
|
242 |
@password = password |
|
243 |
@login_url = url_for(:controller => 'account', :action => 'login') |
|
244 |
mail :to => user.mail, |
|
245 |
:subject => l(:mail_subject_register, Setting.app_title) |
|
250 | 246 |
end |
251 | 247 |
|
252 | 248 |
# Builds a tmail object used to email all active administrators of an account activation request. |
... | ... | |
256 | 252 |
# Mailer.deliver_account_activation_request(user)=> sends an email to all active administrators |
257 | 253 |
def account_activation_request(user) |
258 | 254 |
# Send the email to all active administrators |
259 |
recipients User.active.find(:all, :conditions => {:admin => true}).collect { |u| u.mail }.compact |
|
260 |
subject l(:mail_subject_account_activation_request, Setting.app_title) |
|
261 |
body :user => user, |
|
262 |
:url => url_for(:controller => 'users', :action => 'index', |
|
255 |
recipients = User.active.find(:all, :conditions => {:admin => true}).collect { |u| u.mail }.compact |
|
256 |
@user = user |
|
257 |
@url = url_for(:controller => 'users', :action => 'index', |
|
263 | 258 |
:status => User::STATUS_REGISTERED, |
264 | 259 |
:sort_key => 'created_on', :sort_order => 'desc') |
265 |
render_multipart('account_activation_request', body) |
|
260 |
mail :to => recipients, |
|
261 |
:subject => l(:mail_subject_account_activation_request, Setting.app_title) |
|
266 | 262 |
end |
267 | 263 |
|
268 | 264 |
# Builds a tmail object used to email the specified user that their account was activated by an administrator. |
... | ... | |
272 | 268 |
# Mailer.deliver_account_activated(user) => sends an email to the registered user |
273 | 269 |
def account_activated(user) |
274 | 270 |
set_language_if_valid user.language |
275 |
recipients user.mail |
|
276 |
subject l(:mail_subject_register, Setting.app_title) |
|
277 |
body :user => user, |
|
278 |
:login_url => url_for(:controller => 'account', :action => 'login') |
|
279 |
render_multipart('account_activated', body) |
|
271 |
@user = user |
|
272 |
@login_url = url_for(:controller => 'account', :action => 'login') |
|
273 |
mail :to => user.mail, |
|
274 |
:subject => l(:mail_subject_register, Setting.app_title) |
|
280 | 275 |
end |
281 | 276 |
|
282 | 277 |
def lost_password(token) |
283 | 278 |
set_language_if_valid(token.user.language) |
284 |
recipients token.user.mail |
|
285 |
subject l(:mail_subject_lost_password, Setting.app_title) |
|
286 |
body :token => token, |
|
287 |
:url => url_for(:controller => 'account', :action => 'lost_password', :token => token.value) |
|
288 |
render_multipart('lost_password', body) |
|
279 |
@token = token |
|
280 |
@url = url_for(:controller => 'account', :action => 'lost_password', :token => token.value) |
|
281 |
mail :to => token.user.mail, |
|
282 |
:subject => l(:mail_subject_lost_password, Setting.app_title) |
|
289 | 283 |
end |
290 | 284 |
|
291 | 285 |
def register(token) |
292 | 286 |
set_language_if_valid(token.user.language) |
293 |
recipients token.user.mail |
|
294 |
subject l(:mail_subject_register, Setting.app_title) |
|
295 |
body :token => token, |
|
296 |
:url => url_for(:controller => 'account', :action => 'activate', :token => token.value) |
|
297 |
render_multipart('register', body) |
|
287 |
@token = token |
|
288 |
@url = url_for(:controller => 'account', :action => 'activate', :token => token.value) |
|
289 |
mail :to => token.user.mail, |
|
290 |
:subject => l(:mail_subject_register, Setting.app_title) |
|
298 | 291 |
end |
299 | 292 |
|
300 | 293 |
def test_email(user) |
301 | 294 |
set_language_if_valid(user.language) |
302 |
recipients user.mail |
|
303 |
subject 'Redmine test' |
|
304 |
body :url => url_for(:controller => 'welcome') |
|
305 |
render_multipart('test_email', body) |
|
295 |
@url = url_for(:controller => 'welcome') |
|
296 |
mail :to => user.mail, |
|
297 |
:subject => 'Redmine test' |
|
306 | 298 |
end |
307 | 299 |
|
308 | 300 |
# Overrides default deliver! method to prevent from sending an email |
... | ... | |
313 | 305 |
(cc.nil? || cc.empty?) && |
314 | 306 |
(bcc.nil? || bcc.empty?) |
315 | 307 |
|
316 |
# Set Message-Id and References |
|
317 |
if @message_id_object |
|
318 |
mail.message_id = self.class.message_id_for(@message_id_object) |
|
319 |
end |
|
320 |
if @references_objects |
|
321 |
mail.references = @references_objects.collect {|o| self.class.message_id_for(o)} |
|
322 |
end |
|
323 | 308 |
|
324 | 309 |
# Log errors when raise_delivery_errors is set to false, Rails does not |
325 | 310 |
raise_errors = self.class.raise_delivery_errors |
... | ... | |
383 | 368 |
ActionMailer::Base.delivery_method = saved_method |
384 | 369 |
end |
385 | 370 |
|
386 |
private |
|
387 |
def initialize_defaults(method_name) |
|
388 |
super |
|
389 |
@initial_language = current_language |
|
390 |
set_language_if_valid Setting.default_language |
|
391 |
from Setting.mail_from |
|
392 |
|
|
393 |
# Common headers |
|
394 |
headers 'X-Mailer' => 'Redmine', |
|
371 |
def mail(headers={}) |
|
372 |
headers.merge! 'X-Mailer' => 'Redmine', |
|
395 | 373 |
'X-Redmine-Host' => Setting.host_name, |
396 | 374 |
'X-Redmine-Site' => Setting.app_title, |
397 | 375 |
'X-Auto-Response-Suppress' => 'OOF', |
398 |
'Auto-Submitted' => 'auto-generated' |
|
399 |
end
|
|
376 |
'Auto-Submitted' => 'auto-generated',
|
|
377 |
'From' => Setting.mail_from
|
|
400 | 378 |
|
401 |
# Appends a Redmine header field (name is prepended with 'X-Redmine-') |
|
402 |
def redmine_headers(h) |
|
403 |
h.each { |k,v| headers["X-Redmine-#{k}"] = v.to_s } |
|
404 |
end |
|
405 |
|
|
406 |
# Overrides the create_mail method |
|
407 |
def create_mail |
|
408 | 379 |
# Removes the author from the recipients and cc |
409 | 380 |
# if he doesn't want to receive notifications about what he does |
410 | 381 |
if @author && @author.logged? && @author.pref[:no_self_notified] |
411 |
if recipients |
|
412 |
recipients((recipients.is_a?(Array) ? recipients : [recipients]) - [@author.mail]) |
|
413 |
end |
|
414 |
if cc |
|
415 |
cc((cc.is_a?(Array) ? cc : [cc]) - [@author.mail]) |
|
416 |
end |
|
382 |
headers[:to].delete(@author.mail) if headers[:to].is_a?(Array) |
|
383 |
headers[:cc].delete(@author.mail) if headers[:cc].is_a?(Array) |
|
417 | 384 |
end |
418 | 385 |
|
419 | 386 |
if @author && @author.logged? |
420 | 387 |
redmine_headers 'Sender' => @author.login |
421 | 388 |
end |
422 | 389 |
|
423 |
notified_users = [recipients, cc].flatten.compact.uniq |
|
424 |
# Rails would log recipients only, not cc and bcc |
|
425 |
mylogger.info "Sending email notification to: #{notified_users.join(', ')}" if mylogger |
|
426 |
|
|
427 | 390 |
# Blind carbon copy recipients |
428 | 391 |
if Setting.bcc_recipients? |
429 |
bcc(notified_users)
|
|
430 |
recipients []
|
|
431 |
cc []
|
|
392 |
headers[:bcc] = [headers[:to], headers[:cc]].flatten.uniq.reject(&:blank?)
|
|
393 |
headers[:to] = nil
|
|
394 |
headers[:cc] = nil
|
|
432 | 395 |
end |
396 |
|
|
397 |
if @message_id_object |
|
398 |
headers[:message_id] = "<#{self.class.message_id_for(@message_id_object)}>" |
|
399 |
end |
|
400 |
if @references_objects |
|
401 |
headers[:references] = @references_objects.collect {|o| "<#{self.class.message_id_for(o)}>"}.join(' ') |
|
402 |
end |
|
403 |
|
|
404 |
super headers do |format| |
|
405 |
format.text |
|
406 |
format.html unless Setting.plain_text_mail? |
|
407 |
end |
|
408 |
|
|
409 |
set_language_if_valid @initial_language |
|
410 |
end |
|
411 |
|
|
412 |
def initialize(*args) |
|
413 |
@initial_language = current_language |
|
414 |
set_language_if_valid Setting.default_language |
|
433 | 415 |
super |
434 | 416 |
end |
417 |
|
|
418 |
def self.deliver_mail(mail) |
|
419 |
return false if mail.to.blank? && mail.cc.blank? && mail.bcc.blank? |
|
420 |
super |
|
421 |
end |
|
435 | 422 |
|
436 |
# Rails 2.3 has problems rendering implicit multipart messages with |
|
437 |
# layouts so this method will wrap an multipart messages with |
|
438 |
# explicit parts. |
|
439 |
# |
|
440 |
# https://rails.lighthouseapp.com/projects/8994/tickets/2338-actionmailer-mailer-views-and-content-type |
|
441 |
# https://rails.lighthouseapp.com/projects/8994/tickets/1799-actionmailer-doesnt-set-template_format-when-rendering-layouts |
|
442 |
|
|
443 |
def render_multipart(method_name, body) |
|
444 |
if Setting.plain_text_mail? |
|
445 |
content_type "text/plain" |
|
446 |
body render(:file => "#{method_name}.text.erb", |
|
447 |
:body => body, |
|
448 |
:layout => 'mailer.text.erb') |
|
423 |
def self.method_missing(method, *args, &block) |
|
424 |
if m = method.to_s.match(%r{^deliver_(.+)$}) |
|
425 |
send(m[1], *args).deliver |
|
449 | 426 |
else |
450 |
content_type "multipart/alternative" |
|
451 |
part :content_type => "text/plain", |
|
452 |
:body => render(:file => "#{method_name}.text.erb", |
|
453 |
:body => body, :layout => 'mailer.text.erb') |
|
454 |
part :content_type => "text/html", |
|
455 |
:body => render_message("#{method_name}.html.erb", body) |
|
427 |
super |
|
456 | 428 |
end |
457 | 429 |
end |
458 | 430 |
|
459 |
# Makes partial rendering work with Rails 1.2 (retro-compatibility) |
|
460 |
def self.controller_path |
|
461 |
'' |
|
462 |
end unless respond_to?('controller_path') |
|
431 |
private |
|
463 | 432 |
|
433 |
# Appends a Redmine header field (name is prepended with 'X-Redmine-') |
|
434 |
def redmine_headers(h) |
|
435 |
h.each { |k,v| headers["X-Redmine-#{k}"] = v.to_s } |
|
436 |
end |
|
437 |
|
|
464 | 438 |
# Returns a predictable Message-Id for the given object |
465 | 439 |
def self.message_id_for(object) |
466 | 440 |
# id + timestamp should reduce the odds of a collision |
... | ... | |
469 | 443 |
hash = "redmine.#{object.class.name.demodulize.underscore}-#{object.id}.#{timestamp.strftime("%Y%m%d%H%M%S")}" |
470 | 444 |
host = Setting.mail_from.to_s.gsub(%r{^.*@}, '') |
471 | 445 |
host = "#{::Socket.gethostname}.redmine" if host.empty? |
472 |
"<#{hash}@#{host}>"
|
|
446 |
"#{hash}@#{host}"
|
|
473 | 447 |
end |
474 | 448 |
|
475 |
private |
|
476 |
|
|
477 | 449 |
def message_id(object) |
478 | 450 |
@message_id_object = object |
479 | 451 |
end |
... | ... | |
487 | 459 |
Rails.logger |
488 | 460 |
end |
489 | 461 |
end |
490 |
|
|
491 |
# Patch TMail so that message_id is not overwritten |
|
492 |
module TMail |
|
493 |
class Mail |
|
494 |
def add_message_id( fqdn = nil ) |
|
495 |
self.message_id ||= ::TMail::new_message_id(fqdn) |
|
496 |
end |
|
497 |
end |
|
498 |
end |
trunk/app/models/project.rb | ||
---|---|---|
272 | 272 |
end |
273 | 273 |
end |
274 | 274 |
|
275 |
def self.find_by_param(*args) |
|
276 |
self.find(*args) |
|
277 |
end |
|
278 |
|
|
275 | 279 |
def reload(*args) |
276 | 280 |
@shared_versions = nil |
277 | 281 |
@rolled_up_versions = nil |
trunk/app/models/repository.rb | ||
---|---|---|
57 | 57 |
end |
58 | 58 |
|
59 | 59 |
alias :attributes_without_extra_info= :attributes= |
60 |
def attributes=(new_attributes, guard_protected_attributes = true)
|
|
60 |
def attributes=(new_attributes) |
|
61 | 61 |
return if new_attributes.nil? |
62 | 62 |
attributes = new_attributes.dup |
63 | 63 |
attributes.stringify_keys! |
... | ... | |
72 | 72 |
end |
73 | 73 |
end |
74 | 74 |
|
75 |
send :attributes_without_extra_info=, p, guard_protected_attributes
|
|
75 |
send :attributes_without_extra_info=, p |
|
76 | 76 |
if p_extra.keys.any? |
77 | 77 |
merge_extra_info(p_extra) |
78 | 78 |
end |
trunk/app/models/role.rb | ||
---|---|---|
36 | 36 |
before_destroy :check_deletable |
37 | 37 |
has_many :workflows, :dependent => :delete_all do |
38 | 38 |
def copy(source_role) |
39 |
Workflow.copy(nil, source_role, nil, proxy_owner) |
|
39 |
Workflow.copy(nil, source_role, nil, proxy_association.owner)
|
|
40 | 40 |
end |
41 | 41 |
end |
42 | 42 |
|
trunk/app/models/tracker.rb | ||
---|---|---|
20 | 20 |
has_many :issues |
21 | 21 |
has_many :workflows, :dependent => :delete_all do |
22 | 22 |
def copy(source_tracker) |
23 |
Workflow.copy(source_tracker, nil, proxy_owner, nil) |
|
23 |
Workflow.copy(source_tracker, nil, proxy_association.owner, nil)
|
|
24 | 24 |
end |
25 | 25 |
end |
26 | 26 |
|
trunk/app/views/account/login.html.erb | ||
---|---|---|
1 | 1 |
<%= call_hook :view_account_login_top %> |
2 | 2 |
<div id="login-form"> |
3 |
<% form_tag({:action=> "login"}) do %> |
|
3 |
<%= form_tag({:action=> "login"}) do %>
|
|
4 | 4 |
<%= back_url_hidden_field_tag %> |
5 | 5 |
<table> |
6 | 6 |
<tr> |
trunk/app/views/account/lost_password.html.erb | ||
---|---|---|
1 | 1 |
<h2><%=l(:label_password_lost)%></h2> |
2 | 2 |
|
3 | 3 |
<div class="box"> |
4 |
<% form_tag({:action=> "lost_password"}, :class => "tabular") do %> |
|
4 |
<%= form_tag({:action=> "lost_password"}, :class => "tabular") do %>
|
|
5 | 5 |
|
6 | 6 |
<p><label for="mail"><%=l(:field_mail)%> <span class="required">*</span></label> |
7 | 7 |
<%= text_field_tag 'mail', nil, :size => 40 %> |
trunk/app/views/account/password_recovery.html.erb | ||
---|---|---|
2 | 2 |
|
3 | 3 |
<%= error_messages_for 'user' %> |
4 | 4 |
|
5 |
<% form_tag({:token => @token.value}) do %> |
|
5 |
<%= form_tag({:token => @token.value}) do %>
|
|
6 | 6 |
<div class="box tabular"> |
7 | 7 |
<p><label for="new_password"><%=l(:field_new_password)%> <span class="required">*</span></label> |
8 | 8 |
<%= password_field_tag 'new_password', nil, :size => 25 %> |
trunk/app/views/account/register.html.erb | ||
---|---|---|
1 | 1 |
<h2><%=l(:label_register)%> <%=link_to l(:label_login_with_open_id_option), signin_url if Setting.openid? %></h2> |
2 | 2 |
|
3 |
<% labelled_form_for @user, :url => {:action => 'register'} do |f| %> |
|
3 |
<%= labelled_form_for @user, :url => {:action => 'register'} do |f| %>
|
|
4 | 4 |
<%= error_messages_for 'user' %> |
5 | 5 |
|
6 | 6 |
<div class="box tabular"> |
trunk/app/views/activities/index.html.erb | ||
---|---|---|
40 | 40 |
<% end %> |
41 | 41 |
|
42 | 42 |
<% content_for :sidebar do %> |
43 |
<% form_tag({}, :method => :get) do %> |
|
43 |
<%= form_tag({}, :method => :get) do %>
|
|
44 | 44 |
<h3><%= l(:label_activity) %></h3> |
45 | 45 |
<p><% @activity.event_types.each do |t| %> |
46 | 46 |
<%= check_box_tag "show_#{t}", 1, @activity.scope.include?(t) %> |
trunk/app/views/admin/_no_data.html.erb | ||
---|---|---|
1 | 1 |
<div class="nodata"> |
2 |
<% form_tag({:action => 'default_configuration'}) do %> |
|
2 |
<%= form_tag({:action => 'default_configuration'}) do %>
|
|
3 | 3 |
<%= simple_format(l(:text_no_configuration_data)) %> |
4 | 4 |
<p><%= l(:field_language) %>: |
5 | 5 |
<%= select_tag 'lang', options_for_select(lang_options_for_select(false), current_language.to_s) %> |
trunk/app/views/admin/projects.html.erb | ||
---|---|---|
4 | 4 |
|
5 | 5 |
<h2><%=l(:label_project_plural)%></h2> |
6 | 6 |
|
7 |
<% form_tag({}, :method => :get) do %> |
|
7 |
<%= form_tag({}, :method => :get) do %>
|
|
8 | 8 |
<fieldset><legend><%= l(:label_filter_plural) %></legend> |
9 | 9 |
<label for='status'><%= l(:field_status) %> :</label> |
10 | 10 |
<%= select_tag 'status', project_status_options_for_select(@status), :class => "small", :onchange => "this.form.submit(); return false;" %> |
trunk/app/views/attachments/diff.html.erb | ||
---|---|---|
7 | 7 |
<span class="size">(<%= number_to_human_size @attachment.filesize %>)</span></p> |
8 | 8 |
</div> |
9 | 9 |
<p> |
10 |
<% form_tag({}, :method => 'get') do %> |
|
10 |
<%= form_tag({}, :method => 'get') do %>
|
|
11 | 11 |
<label><%= l(:label_view_diff) %></label> |
12 | 12 |
<%= select_tag 'type', |
13 | 13 |
options_for_select( |
trunk/app/views/auth_sources/edit.html.erb | ||
---|---|---|
1 | 1 |
<h2><%=l(:label_auth_source)%> (<%= h(@auth_source.auth_method_name) %>)</h2> |
2 | 2 |
|
3 |
<% form_tag({:action => 'update', :id => @auth_source}, :method => :put, :class => "tabular") do %> |
|
3 |
<%= form_tag({:action => 'update', :id => @auth_source}, :method => :put, :class => "tabular") do %>
|
|
4 | 4 |
<%= render :partial => auth_source_partial_name(@auth_source) %> |
5 | 5 |
<%= submit_tag l(:button_save) %> |
6 | 6 |
<% end %> |
trunk/app/views/auth_sources/new.html.erb | ||
---|---|---|
1 | 1 |
<h2><%=l(:label_auth_source_new)%> (<%= h(@auth_source.auth_method_name) %>)</h2> |
2 | 2 |
|
3 |
<% form_tag({:action => 'create'}, :class => "tabular") do %> |
|
3 |
<%= form_tag({:action => 'create'}, :class => "tabular") do %>
|
|
4 | 4 |
<%= hidden_field_tag 'type', @auth_source.type %> |
5 | 5 |
<%= render :partial => auth_source_partial_name(@auth_source) %> |
6 | 6 |
<%= submit_tag l(:button_create) %> |
trunk/app/views/boards/edit.html.erb | ||
---|---|---|
1 | 1 |
<h2><%= l(:label_board) %></h2> |
2 | 2 |
|
3 |
<% labelled_form_for @board, :url => project_board_path(@project, @board) do |f| %> |
|
3 |
<%= labelled_form_for @board, :url => project_board_path(@project, @board) do |f| %>
|
|
4 | 4 |
<%= render :partial => 'form', :locals => {:f => f} %> |
5 | 5 |
<%= submit_tag l(:button_save) %> |
6 | 6 |
<% end %> |
trunk/app/views/boards/new.html.erb | ||
---|---|---|
1 | 1 |
<h2><%= l(:label_board_new) %></h2> |
2 | 2 |
|
3 |
<% labelled_form_for @board, :url => project_boards_path(@project) do |f| %> |
|
3 |
<%= labelled_form_for @board, :url => project_boards_path(@project) do |f| %>
|
|
4 | 4 |
<%= render :partial => 'form', :locals => {:f => f} %> |
5 | 5 |
<%= submit_tag l(:button_create) %> |
6 | 6 |
<% end %> |
trunk/app/views/boards/show.html.erb | ||
---|---|---|
11 | 11 |
<div id="add-message" style="display:none;"> |
12 | 12 |
<% if authorize_for('messages', 'new') %> |
13 | 13 |
<h2><%= link_to h(@board.name), :controller => 'boards', :action => 'show', :project_id => @project, :id => @board %> » <%= l(:label_message_new) %></h2> |
14 |
<% form_for :message, @message, :url => {:controller => 'messages', :action => 'new', :board_id => @board}, :html => {:multipart => true, :id => 'message-form'} do |f| %>
|
|
14 |
<%= form_for @message, :url => {:controller => 'messages', :action => 'new', :board_id => @board}, :html => {:multipart => true, :id => 'message-form'} do |f| %>
|
|
15 | 15 |
<%= render :partial => 'messages/form', :locals => {:f => f} %> |
16 | 16 |
<p><%= submit_tag l(:button_create) %> |
17 | 17 |
<%= link_to_remote l(:label_preview), |
trunk/app/views/calendars/show.html.erb | ||
---|---|---|
1 | 1 |
<h2><%= @query.new_record? ? l(:label_calendar) : h(@query.name) %></h2> |
2 | 2 |
|
3 |
<% form_tag({:controller => 'calendars', :action => 'show', :project_id => @project}, :method => :get, :id => 'query_form') do %> |
|
3 |
<%= form_tag({:controller => 'calendars', :action => 'show', :project_id => @project}, |
|
4 |
:method => :get, :id => 'query_form') do %> |
|
4 | 5 |
<%= hidden_field_tag 'set_filter', '1' %> |
5 | 6 |
<fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>"> |
6 | 7 |
<legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend> |
trunk/app/views/common/feed.atom.builder | ||
---|---|---|
1 | 1 |
xml.instruct! |
2 | 2 |
xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do |
3 | 3 |
xml.title truncate_single_line(@title, :length => 100) |
4 |
xml.link "rel" => "self", "href" => url_for(params.merge(:only_path => false, :escape => false))
|
|
5 |
xml.link "rel" => "alternate", "href" => url_for(params.merge(:only_path => false, :format => nil, :key => nil, :escape => false))
|
|
4 |
xml.link "rel" => "self", "href" => url_for(params.merge(:only_path => false)) |
|
5 |
xml.link "rel" => "alternate", "href" => url_for(params.merge(:only_path => false, :format => nil, :key => nil)) |
|
6 | 6 |
xml.id url_for(:controller => 'welcome', :only_path => false) |
7 | 7 |
xml.updated((@items.first ? @items.first.event_datetime : Time.now).xmlschema) |
8 | 8 |
xml.author { xml.name "#{Setting.app_title}" } |
trunk/app/views/custom_fields/edit.html.erb | ||
---|---|---|
2 | 2 |
» <%= link_to l(@custom_field.type_name), :controller => 'custom_fields', :action => 'index', :tab => @custom_field.class.name %> |
3 | 3 |
» <%=h @custom_field.name %></h2> |
4 | 4 |
|
5 |
<% labelled_form_for :custom_field, @custom_field, :url => custom_field_path(@custom_field), :html => {:method => :put} do |f| %> |
|
5 |
<%= labelled_form_for :custom_field, @custom_field, :url => custom_field_path(@custom_field), :html => {:method => :put} do |f| %>
|
|
6 | 6 |
<%= render :partial => 'form', :locals => { :f => f } %> |
7 | 7 |
<%= submit_tag l(:button_save) %> |
8 | 8 |
<% end %> |
trunk/app/views/custom_fields/new.html.erb | ||
---|---|---|
2 | 2 |
» <%= link_to l(@custom_field.type_name), :controller => 'custom_fields', :action => 'index', :tab => @custom_field.class.name %> |
3 | 3 |
» <%= l(:label_custom_field_new) %></h2> |
4 | 4 |
|
5 |
<% labelled_form_for :custom_field, @custom_field, :url => custom_fields_path do |f| %> |
|
5 |
<%= labelled_form_for :custom_field, @custom_field, :url => custom_fields_path do |f| %>
|
|
6 | 6 |
<%= render :partial => 'form', :locals => { :f => f } %> |
7 | 7 |
<%= hidden_field_tag 'type', @custom_field.type %> |
8 | 8 |
<%= submit_tag l(:button_save) %> |
trunk/app/views/documents/edit.html.erb | ||
---|---|---|
1 | 1 |
<h2><%=l(:label_document)%></h2> |
2 | 2 |
|
3 |
<% labelled_form_for @document do |f| %> |
|
3 |
<%= labelled_form_for @document do |f| %>
|
|
4 | 4 |
<%= render :partial => 'form', :locals => {:f => f} %> |
5 | 5 |
<p><%= submit_tag l(:button_save) %></p> |
6 | 6 |
<% end %> |
trunk/app/views/documents/index.html.erb | ||
---|---|---|
5 | 5 |
|
6 | 6 |
<div id="add-document" style="display:none;"> |
7 | 7 |
<h2><%=l(:label_document_new)%></h2> |
8 |
<% labelled_form_for @document, :url => project_documents_path(@project), :html => {:multipart => true} do |f| %> |
|
8 |
<%= labelled_form_for @document, :url => project_documents_path(@project), :html => {:multipart => true} do |f| %>
|
|
9 | 9 |
<%= render :partial => 'form', :locals => {:f => f} %> |
10 | 10 |
<p> |
11 | 11 |
<%= submit_tag l(:button_create) %> |
trunk/app/views/documents/new.html.erb | ||
---|---|---|
1 | 1 |
<h2><%=l(:label_document_new)%></h2> |
2 | 2 |
|
3 |
<% labelled_form_for @document, :url => project_documents_path(@project), :html => {:multipart => true} do |f| %> |
|
3 |
<%= labelled_form_for @document, :url => project_documents_path(@project), :html => {:multipart => true} do |f| %>
|
|
4 | 4 |
<%= render :partial => 'form', :locals => {:f => f} %> |
5 | 5 |
<p><%= submit_tag l(:button_create) %></p> |
6 | 6 |
<% end %> |
trunk/app/views/documents/show.html.erb | ||
---|---|---|
19 | 19 |
<% if authorize_for('documents', 'add_attachment') %> |
20 | 20 |
<p><%= link_to l(:label_attachment_new), {}, :onclick => "Element.show('add_attachment_form'); Element.hide(this); Element.scrollTo('add_attachment_form'); return false;", |
21 | 21 |
:id => 'attach_files_link' %></p> |
22 |
<% form_tag({ :controller => 'documents', :action => 'add_attachment', :id => @document }, :multipart => true, :id => "add_attachment_form", :style => "display:none;") do %> |
|
22 |
<%= form_tag({ :controller => 'documents', :action => 'add_attachment', :id => @document }, :multipart => true, :id => "add_attachment_form", :style => "display:none;") do %>
|
|
23 | 23 |
<div class="box"> |
24 | 24 |
<p><%= render :partial => 'attachments/form' %></p> |
25 | 25 |
</div> |
trunk/app/views/enumerations/destroy.html.erb | ||
---|---|---|
1 | 1 |
<h2><%= l(@enumeration.option_name) %>: <%=h @enumeration %></h2> |
2 | 2 |
|
3 |
<% form_tag({}, :method => :delete) do %> |
|
3 |
<%= form_tag({}, :method => :delete) do %>
|
|
4 | 4 |
<div class="box"> |
5 | 5 |
<p><strong><%= l(:text_enumeration_destroy_question, @enumeration.objects_count) %></strong></p> |
6 | 6 |
<p><label for='reassign_to_id'><%= l(:text_enumeration_category_reassign_to) %></label> |
trunk/app/views/enumerations/edit.html.erb | ||
---|---|---|
1 | 1 |
<h2><%= link_to l(@enumeration.option_name), enumerations_path %> » <%=h @enumeration %></h2> |
2 | 2 |
|
3 |
<% labelled_form_for :enumeration, @enumeration, :url => enumeration_path(@enumeration), :html => {:method => :put} do |f| %> |
|
3 |
<%= labelled_form_for :enumeration, @enumeration, :url => enumeration_path(@enumeration), :html => {:method => :put} do |f| %>
|
|
4 | 4 |
<%= render :partial => 'form', :locals => {:f => f} %> |
5 | 5 |
<%= submit_tag l(:button_save) %> |
6 | 6 |
<% end %> |
trunk/app/views/enumerations/new.html.erb | ||
---|---|---|
1 | 1 |
<h2><%= link_to l(@enumeration.option_name), enumerations_path %> » <%=l(:label_enumeration_new)%></h2> |
2 | 2 |
|
3 |
<% labelled_form_for :enumeration, @enumeration, :url => enumerations_path do |f| %> |
|
3 |
<%= labelled_form_for :enumeration, @enumeration, :url => enumerations_path do |f| %>
|
|
4 | 4 |
<%= f.hidden_field :type %> |
5 | 5 |
<%= render :partial => 'form', :locals => {:f => f} %> |
6 | 6 |
<%= submit_tag l(:button_create) %> |
trunk/app/views/files/new.html.erb | ||
---|---|---|
1 | 1 |
<h2><%=l(:label_attachment_new)%></h2> |
2 | 2 |
|
3 | 3 |
<%= error_messages_for 'attachment' %> |
4 |
<% form_tag(project_files_path(@project), :multipart => true, :class => "tabular") do %> |
|
4 |
<%= form_tag(project_files_path(@project), :multipart => true, :class => "tabular") do %>
|
|
5 | 5 |
<div class="box"> |
6 | 6 |
|
7 | 7 |
<% if @versions.any? %> |
trunk/app/views/gantts/show.html.erb | ||
---|---|---|
1 | 1 |
<% @gantt.view = self %> |
2 | 2 |
<h2><%= @query.new_record? ? l(:label_gantt) : h(@query.name) %></h2> |
3 | 3 |
|
4 |
<% form_tag({:controller => 'gantts', :action => 'show', :project_id => @project, :month => params[:month], :year => params[:year], :months => params[:months]}, :method => :get, :id => 'query_form') do %> |
|
4 |
<%= form_tag({:controller => 'gantts', :action => 'show', |
|
5 |
:project_id => @project, :month => params[:month], |
|
6 |
:year => params[:year], :months => params[:months]}, |
|
7 |
:method => :get, :id => 'query_form') do %> |
|
5 | 8 |
<%= hidden_field_tag 'set_filter', '1' %> |
6 | 9 |
<fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>"> |
7 | 10 |
<legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend> |
trunk/app/views/groups/_general.html.erb | ||
---|---|---|
1 |
<% labelled_form_for @group do |f| %> |
|
1 |
<%= labelled_form_for @group do |f| %>
|
|
2 | 2 |
<%= render :partial => 'form', :locals => { :f => f } %> |
3 | 3 |
<%= submit_tag l(:button_save) %> |
4 | 4 |
<% end %> |
trunk/app/views/groups/_memberships.html.erb | ||
---|---|---|
16 | 16 |
<td class="project"><%=h membership.project %></td> |
17 | 17 |
<td class="roles"> |
18 | 18 |
<span id="member-<%= membership.id %>-roles"><%=h membership.roles.sort.collect(&:to_s).join(', ') %></span> |
19 |
<% remote_form_for(:membership, :url => { :action => 'edit_membership', :id => @group, :membership_id => membership }, |
|
20 |
:html => { :id => "member-#{membership.id}-roles-form", :style => 'display:none;'}) do %> |
|
19 |
<%= form_for(:membership, :remote => true, |
|
20 |
:url => { :action => 'edit_membership', :id => @group, :membership_id => membership }, |
|
21 |
:html => { :id => "member-#{membership.id}-roles-form", :style => 'display:none;'}) do %> |
|
21 | 22 |
<p><% roles.each do |role| %> |
22 | 23 |
<label><%= check_box_tag 'membership[role_ids][]', role.id, membership.roles.include?(role) %> <%=h role %></label><br /> |
23 | 24 |
<% end %></p> |
... | ... | |
55 | 56 |
<div class="splitcontentright"> |
56 | 57 |
<% if projects.any? %> |
57 | 58 |
<fieldset><legend><%=l(:label_project_new)%></legend> |
58 |
<% remote_form_for(:membership, :url => { :action => 'edit_membership', :id => @group }) do %>
|
|
59 |
<%= form_for(:membership, :remote => true, :url => { :action => 'edit_membership', :id => @group }) do %>
|
|
59 | 60 |
<%= label_tag "membership_project_id", l(:description_choose_project), :class => "hidden-for-sighted" %> |
60 | 61 |
<%= select_tag 'membership[project_id]', options_for_membership_project_select(@group, projects) %> |
61 | 62 |
<p><%= l(:label_role_plural) %>: |
trunk/app/views/groups/_users.html.erb | ||
---|---|---|
29 | 29 |
<div class="splitcontentright"> |
30 | 30 |
<% users = User.active.not_in_group(@group).all(:limit => 100) %> |
31 | 31 |
<% if users.any? %> |
32 |
<% remote_form_for(@group, :url => group_users_path(@group), :html => {:method => :post}) do |f| %> |
|
32 |
<%= form_for(@group, :remote => true, :url => group_users_path(@group), |
|
33 |
:html => {:method => :post}) do |f| %> |
|
33 | 34 |
<fieldset><legend><%=l(:label_user_new)%></legend> |
34 | 35 |
|
35 | 36 |
<p><%= label_tag "user_search", l(:label_user_search) %><%= text_field_tag 'user_search', nil %></p> |
trunk/app/views/groups/new.html.erb | ||
---|---|---|
1 | 1 |
<h2><%= link_to l(:label_group_plural), groups_path %> » <%= l(:label_group_new) %></h2> |
2 | 2 |
|
3 |
<% labelled_form_for @group do |f| %> |
|
3 |
<%= labelled_form_for @group do |f| %>
|
|
4 | 4 |
<%= render :partial => 'form', :locals => { :f => f } %> |
5 | 5 |
<p> |
6 | 6 |
<%= f.submit l(:button_create) %> |
trunk/app/views/issue_categories/destroy.html.erb | ||
---|---|---|
1 | 1 |
<h2><%=l(:label_issue_category)%>: <%=h @category.name %></h2> |
2 | 2 |
|
3 |
<% form_tag(issue_category_path(@category), :method => :delete) do %> |
|
3 |
<%= form_tag(issue_category_path(@category), :method => :delete) do %>
|
|
4 | 4 |
<div class="box"> |
5 | 5 |
<p><strong><%= l(:text_issue_category_destroy_question, @issue_count) %></strong></p> |
6 | 6 |
<p><label><%= radio_button_tag 'todo', 'nullify', true %> <%= l(:text_issue_category_destroy_assignments) %></label><br /> |
trunk/app/views/issue_statuses/edit.html.erb | ||
---|---|---|
1 | 1 |
<h2><%= link_to l(:label_issue_status_plural), issue_statuses_path %> » <%=h @issue_status %></h2> |
2 | 2 |
|
3 |
<% labelled_form_for @issue_status do |f| %> |
|
3 |
<%= labelled_form_for @issue_status do |f| %>
|
|
4 | 4 |
<%= render :partial => 'form', :locals => {:f => f} %> |
5 | 5 |
<%= submit_tag l(:button_save) %> |
6 | 6 |
<% end %> |
trunk/app/views/issue_statuses/new.html.erb | ||
---|---|---|
1 | 1 |
<h2><%= link_to l(:label_issue_status_plural), issue_statuses_path %> » <%=l(:label_issue_status_new)%></h2> |
2 | 2 |
|
3 |
<% labelled_form_for @issue_status do |f| %> |
|
3 |
<%= labelled_form_for @issue_status do |f| %>
|
|
4 | 4 |
<%= render :partial => 'form', :locals => {:f => f} %> |
5 | 5 |
<%= submit_tag l(:button_create) %> |
6 | 6 |
<% end %> |
trunk/app/views/issues/_action_menu.html.erb | ||
---|---|---|
1 | 1 |
<div class="contextual"> |
2 | 2 |
<%= link_to_if_authorized(l(:button_update), {:controller => 'issues', :action => 'edit', :id => @issue }, :onclick => 'showAndScrollTo("update", "notes"); return false;', :class => 'icon icon-edit', :accesskey => accesskey(:edit)) %> |
3 |
<%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'new', :issue_id => @issue}, :class => 'icon icon-time-add' %>
|
|
3 |
<%= link_to l(:button_log_time), new_issue_time_entry_path(@issue), :class => 'icon icon-time-add' if User.current.allowed_to?(:log_time, @project) %>
|
|
4 | 4 |
<%= watcher_tag(@issue, User.current) %> |
5 | 5 |
<%= link_to_if_authorized l(:button_copy), {:controller => 'issues', :action => 'new', :project_id => @project, :copy_from => @issue}, :class => 'icon icon-copy' %> |
6 | 6 |
<%= link_to l(:button_delete), issue_path(@issue), :confirm => issues_destroy_confirmation_message(@issue), :method => :delete, :class => 'icon icon-del' if User.current.allowed_to?(:delete_issues, @project) %> |
trunk/app/views/issues/_attributes.html.erb | ||
---|---|---|
1 |
<% labelled_fields_for :issue, @issue do |f| %> |
|
1 |
<%= labelled_fields_for :issue, @issue do |f| %>
|
|
2 | 2 |
|
3 | 3 |
<div class="splitcontent"> |
4 | 4 |
<div class="splitcontentleft"> |
Also available in: Unified diff
Merged rails-3.2 branch.