Compare commits

..
1 Commits
Author SHA1 Message Date
Jean-Philippe Lang 924cf77a61 tagged version 2.0.1
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/tags/2.0.1@9733 e93f8b46-1217-0410-a6f0-8f06a7374b81
2012-05-28 07:25:08 +00:00
143 changed files with 325 additions and 990 deletions
+3 -5
View File
@@ -1,11 +1,11 @@
source 'http://rubygems.org' source 'http://rubygems.org'
gem 'rails', '3.2.6' gem 'rails', '3.2.3'
gem 'prototype-rails', '3.2.1' gem 'prototype-rails', '3.2.1'
gem "i18n", "~> 0.6.0" gem "i18n", "~> 0.6.0"
gem "coderay", "~> 1.0.6" gem "coderay", "~> 1.0.6"
gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby] gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby]
gem "builder", "3.0.0" gem "builder"
# Optional gem for LDAP authentication # Optional gem for LDAP authentication
group :ldap do group :ldap do
@@ -74,9 +74,7 @@ end
group :test do group :test do
gem "shoulda", "~> 2.11" gem "shoulda", "~> 2.11"
# Shoulda does not work nice on Ruby 1.9.3 and seems to need test-unit explicitely. gem "mocha"
gem "test-unit", :platforms => [:mri_19]
gem "mocha", "0.12.3"
end end
local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local") local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local")
+2 -2
View File
@@ -445,9 +445,9 @@ class ApplicationController < ActionController::Base
# Returns the API key present in the request # Returns the API key present in the request
def api_key_from_request def api_key_from_request
if params[:key].present? if params[:key].present?
params[:key].to_s params[:key]
elsif request.headers["X-Redmine-API-Key"].present? elsif request.headers["X-Redmine-API-Key"].present?
request.headers["X-Redmine-API-Key"].to_s request.headers["X-Redmine-API-Key"]
end end
end end
+2 -2
View File
@@ -43,10 +43,10 @@ class BoardsController < ApplicationController
@topic_count = @board.topics.count @topic_count = @board.topics.count
@topic_pages = Paginator.new self, @topic_count, per_page_option, params['page'] @topic_pages = Paginator.new self, @topic_count, per_page_option, params['page']
@topics = @board.topics.reorder("#{Message.table_name}.sticky DESC").order(sort_clause).all( @topics = @board.topics.find :all, :order => ["#{Message.table_name}.sticky DESC", sort_clause].compact.join(', '),
:include => [:author, {:last_reply => :author}], :include => [:author, {:last_reply => :author}],
:limit => @topic_pages.items_per_page, :limit => @topic_pages.items_per_page,
:offset => @topic_pages.current.offset) :offset => @topic_pages.current.offset
@message = Message.new(:board => @board) @message = Message.new(:board => @board)
render :action => 'show', :layout => !request.xhr? render :action => 'show', :layout => !request.xhr?
} }
+9 -17
View File
@@ -18,13 +18,12 @@
class TimelogController < ApplicationController class TimelogController < ApplicationController
menu_item :issues menu_item :issues
before_filter :find_project_for_new_time_entry, :only => [:create] before_filter :find_project, :only => [:create]
before_filter :find_time_entry, :only => [:show, :edit, :update] before_filter :find_time_entry, :only => [:show, :edit, :update]
before_filter :find_time_entries, :only => [:bulk_edit, :bulk_update, :destroy] before_filter :find_time_entries, :only => [:bulk_edit, :bulk_update, :destroy]
before_filter :authorize, :except => [:new, :index, :report] before_filter :authorize, :except => [:new, :index, :report]
before_filter :find_optional_project, :only => [:index, :report] before_filter :find_optional_project, :only => [:new, :index, :report]
before_filter :find_optional_project_for_new_time_entry, :only => [:new]
before_filter :authorize_global, :only => [:new, :index, :report] before_filter :authorize_global, :only => [:new, :index, :report]
accept_rss_auth :index accept_rss_auth :index
@@ -39,7 +38,7 @@ class TimelogController < ApplicationController
def index def index
sort_init 'spent_on', 'desc' sort_init 'spent_on', 'desc'
sort_update 'spent_on' => ['spent_on', "#{TimeEntry.table_name}.created_on"], sort_update 'spent_on' => 'spent_on',
'user' => 'user_id', 'user' => 'user_id',
'activity' => 'activity_id', 'activity' => 'activity_id',
'project' => "#{Project.table_name}.name", 'project' => "#{Project.table_name}.name",
@@ -134,13 +133,9 @@ class TimelogController < ApplicationController
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
if params[:continue] if params[:continue]
if params[:project_id] if params[:project_id]
redirect_to :action => 'new', :project_id => @time_entry.project, :issue_id => @time_entry.issue, redirect_to :action => 'new', :project_id => @time_entry.project, :issue_id => @time_entry.issue, :back_url => params[:back_url]
:time_entry => {:issue_id => @time_entry.issue_id, :activity_id => @time_entry.activity_id},
:back_url => params[:back_url]
else else
redirect_to :action => 'new', redirect_to :action => 'new', :back_url => params[:back_url]
:time_entry => {:project_id => @time_entry.project_id, :issue_id => @time_entry.issue_id, :activity_id => @time_entry.activity_id},
:back_url => params[:back_url]
end end
else else
redirect_back_or_default :action => 'index', :project_id => @time_entry.project redirect_back_or_default :action => 'index', :project_id => @time_entry.project
@@ -263,7 +258,7 @@ private
end end
end end
def find_optional_project_for_new_time_entry def find_project
if (project_id = (params[:project_id] || params[:time_entry] && params[:time_entry][:project_id])).present? if (project_id = (params[:project_id] || params[:time_entry] && params[:time_entry][:project_id])).present?
@project = Project.find(project_id) @project = Project.find(project_id)
end end
@@ -271,15 +266,12 @@ private
@issue = Issue.find(issue_id) @issue = Issue.find(issue_id)
@project ||= @issue.project @project ||= @issue.project
end end
rescue ActiveRecord::RecordNotFound
render_404
end
def find_project_for_new_time_entry
find_optional_project_for_new_time_entry
if @project.nil? if @project.nil?
render_404 render_404
return false
end end
rescue ActiveRecord::RecordNotFound
render_404
end end
def find_optional_project def find_optional_project
+2 -4
View File
@@ -253,7 +253,7 @@ module ApplicationHelper
def project_tree_options_for_select(projects, options = {}) def project_tree_options_for_select(projects, options = {})
s = '' s = ''
project_tree(projects) do |project, level| project_tree(projects) do |project, level|
name_prefix = (level > 0 ? ('&nbsp;' * 2 * level + '&#187; ') : '').html_safe name_prefix = (level > 0 ? ('&nbsp;' * 2 * level + '&#187; ').html_safe : '')
tag_options = {:value => project.id} tag_options = {:value => project.id}
if project == options[:selected] || (options[:selected].respond_to?(:include?) && options[:selected].include?(project)) if project == options[:selected] || (options[:selected].respond_to?(:include?) && options[:selected].include?(project))
tag_options[:selected] = 'selected' tag_options[:selected] = 'selected'
@@ -812,7 +812,7 @@ module ApplicationHelper
end end
end end
HEADING_RE = /(<h(\d)( [^>]+)?>(.+?)<\/h(\d)>)/i unless const_defined?(:HEADING_RE) HEADING_RE = /(<h(1|2|3|4)( [^>]+)?>(.+?)<\/h(1|2|3|4)>)/i unless const_defined?(:HEADING_RE)
def parse_sections(text, project, obj, attr, only_path, options) def parse_sections(text, project, obj, attr, only_path, options)
return unless options[:edit_section_links] return unless options[:edit_section_links]
@@ -883,8 +883,6 @@ module ApplicationHelper
# Renders the TOC with given headings # Renders the TOC with given headings
def replace_toc(text, headings) def replace_toc(text, headings)
text.gsub!(TOC_RE) do text.gsub!(TOC_RE) do
# Keep only the 4 first levels
headings = headings.select{|level, anchor, item| level <= 4}
if headings.empty? if headings.empty?
'' ''
else else
+3 -3
View File
@@ -46,17 +46,17 @@ module RepositoriesHelper
end end
def render_changeset_changes def render_changeset_changes
changes = @changeset.filechanges.find(:all, :limit => 1000, :order => 'path').collect do |change| changes = @changeset.changes.find(:all, :limit => 1000, :order => 'path').collect do |change|
case change.action case change.action
when 'A' when 'A'
# Detects moved/copied files # Detects moved/copied files
if !change.from_path.blank? if !change.from_path.blank?
change.action = change.action =
@changeset.filechanges.detect {|c| c.action == 'D' && c.path == change.from_path} ? 'R' : 'C' @changeset.changes.detect {|c| c.action == 'D' && c.path == change.from_path} ? 'R' : 'C'
end end
change change
when 'D' when 'D'
@changeset.filechanges.detect {|c| c.from_path == change.path} ? nil : change @changeset.changes.detect {|c| c.from_path == change.path} ? nil : change
else else
change change
end end
-1
View File
@@ -24,7 +24,6 @@ class Attachment < ActiveRecord::Base
validates_presence_of :filename, :author validates_presence_of :filename, :author
validates_length_of :filename, :maximum => 255 validates_length_of :filename, :maximum => 255
validates_length_of :disk_filename, :maximum => 255 validates_length_of :disk_filename, :maximum => 255
validates_length_of :description, :maximum => 255
validate :validate_max_file_size validate :validate_max_file_size
acts_as_event :title => :filename, acts_as_event :title => :filename,
+1 -1
View File
@@ -20,7 +20,7 @@ require 'iconv'
class Changeset < ActiveRecord::Base class Changeset < ActiveRecord::Base
belongs_to :repository belongs_to :repository
belongs_to :user belongs_to :user
has_many :filechanges, :class_name => 'Change', :dependent => :delete_all has_many :changes, :dependent => :delete_all
has_and_belongs_to_many :issues has_and_belongs_to_many :issues
has_and_belongs_to_many :parents, has_and_belongs_to_many :parents,
:class_name => "Changeset", :class_name => "Changeset",
-22
View File
@@ -124,28 +124,6 @@ class Issue < ActiveRecord::Base
end end
end end
# AR#Persistence#destroy would raise and RecordNotFound exception
# if the issue was already deleted or updated (non matching lock_version).
# This is a problem when bulk deleting issues or deleting a project
# (because an issue may already be deleted if its parent was deleted
# first).
# The issue is reloaded by the nested_set before being deleted so
# the lock_version condition should not be an issue but we handle it.
def destroy
super
rescue ActiveRecord::RecordNotFound
# Stale or already deleted
begin
reload
rescue ActiveRecord::RecordNotFound
# The issue was actually already deleted
@destroyed = true
return freeze
end
# The issue was stale, retry to destroy
super
end
# Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields # Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields
def available_custom_fields def available_custom_fields
(project && tracker) ? (project.all_issue_custom_fields & tracker.custom_fields.all) : [] (project && tracker) ? (project.all_issue_custom_fields & tracker.custom_fields.all) : []
+8 -28
View File
@@ -50,8 +50,8 @@ class MailHandler < ActionMailer::Base
cattr_accessor :ignored_emails_headers cattr_accessor :ignored_emails_headers
@@ignored_emails_headers = { @@ignored_emails_headers = {
'X-Auto-Response-Suppress' => 'oof', 'X-Auto-Response-Suppress' => 'OOF',
'Auto-Submitted' => /^auto-/ 'Auto-Submitted' => 'auto-replied'
} }
# Processes incoming emails # Processes incoming emails
@@ -69,14 +69,11 @@ class MailHandler < ActionMailer::Base
# Ignore auto generated emails # Ignore auto generated emails
self.class.ignored_emails_headers.each do |key, ignored_value| self.class.ignored_emails_headers.each do |key, ignored_value|
value = email.header[key] value = email.header[key]
if value if value && value.to_s.downcase == ignored_value.downcase
value = value.to_s.downcase if logger && logger.info
if (ignored_value.is_a?(Regexp) && value.match(ignored_value)) || value == ignored_value logger.info "MailHandler: ignoring email with #{key}:#{value} header"
if logger && logger.info
logger.info "MailHandler: ignoring email with #{key}:#{value} header"
end
return false
end end
return false
end end
end end
@user = User.find_by_mail(sender_email) if sender_email.present? @user = User.find_by_mail(sender_email) if sender_email.present?
@@ -166,7 +163,7 @@ class MailHandler < ActionMailer::Base
issue = Issue.new(:author => user, :project => project) issue = Issue.new(:author => user, :project => project)
issue.safe_attributes = issue_attributes_from_keywords(issue) issue.safe_attributes = issue_attributes_from_keywords(issue)
issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)} issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
issue.subject = cleaned_up_subject issue.subject = email.subject.to_s.chomp[0,255]
if issue.subject.blank? if issue.subject.blank?
issue.subject = '(no subject)' issue.subject = '(no subject)'
end end
@@ -226,7 +223,7 @@ class MailHandler < ActionMailer::Base
end end
if !message.locked? if !message.locked?
reply = Message.new(:subject => cleaned_up_subject.gsub(%r{^.*msg\d+\]}, '').strip, reply = Message.new(:subject => email.subject.gsub(%r{^.*msg\d+\]}, '').strip,
:content => cleaned_up_text_body) :content => cleaned_up_text_body)
reply.author = user reply.author = user
reply.board = message.board reply.board = message.board
@@ -367,23 +364,6 @@ class MailHandler < ActionMailer::Base
cleanup_body(plain_text_body) cleanup_body(plain_text_body)
end end
def cleaned_up_subject
subject = email.subject.to_s
unless subject.respond_to?(:encoding)
# try to reencode to utf8 manually with ruby1.8
begin
if h = email.header[:subject]
if m = h.value.match(/^=\?([^\?]+)\?/)
subject = Redmine::CodesetUtil.to_utf8(subject, m[1])
end
end
rescue
# nop
end
end
subject.strip[0,255]
end
def self.full_sanitizer def self.full_sanitizer
@full_sanitizer ||= HTML::FullSanitizer.new @full_sanitizer ||= HTML::FullSanitizer.new
end end
+1 -3
View File
@@ -361,9 +361,7 @@ class Mailer < ActionMailer::Base
def self.with_synched_deliveries(&block) def self.with_synched_deliveries(&block)
saved_method = ActionMailer::Base.delivery_method saved_method = ActionMailer::Base.delivery_method
if m = saved_method.to_s.match(%r{^async_(.+)$}) if m = saved_method.to_s.match(%r{^async_(.+)$})
synched_method = m[1] ActionMailer::Base.delivery_method = m[1].to_sym
ActionMailer::Base.delivery_method = synched_method.to_sym
ActionMailer::Base.send "#{synched_method}_settings=", ActionMailer::Base.send("async_#{synched_method}_settings")
end end
yield yield
ensure ensure
+2 -2
View File
@@ -174,9 +174,9 @@ class Query < ActiveRecord::Base
if values_for(field) if values_for(field)
case type_for(field) case type_for(field)
when :integer when :integer
add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && !v.match(/^[+-]?\d+$/) } add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && !v.match(/^\d+$/) }
when :float when :float
add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && !v.match(/^[+-]?\d+(\.\d*)?$/) } add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && !v.match(/^\d+(\.\d*)?$/) }
when :date, :date_past when :date, :date_past
case operator_for(field) case operator_for(field)
when "=", ">=", "<=", "><" when "=", ">=", "<=", "><"
+4 -4
View File
@@ -22,7 +22,7 @@ class Repository < ActiveRecord::Base
belongs_to :project belongs_to :project
has_many :changesets, :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC" has_many :changesets, :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC"
has_many :filechanges, :class_name => 'Change', :through => :changesets has_many :changes, :through => :changesets
serialize :extra_info serialize :extra_info
@@ -37,8 +37,8 @@ class Repository < ActiveRecord::Base
validates_presence_of :identifier, :unless => Proc.new { |r| r.is_default? || r.set_as_default? } validates_presence_of :identifier, :unless => Proc.new { |r| r.is_default? || r.set_as_default? }
validates_uniqueness_of :identifier, :scope => :project_id, :allow_blank => true validates_uniqueness_of :identifier, :scope => :project_id, :allow_blank => true
validates_exclusion_of :identifier, :in => %w(show entry raw changes annotate diff show stats graph) validates_exclusion_of :identifier, :in => %w(show entry raw changes annotate diff show stats graph)
# donwcase letters, digits, dashes, underscores but not digits only # donwcase letters, digits, dashes but not digits only
validates_format_of :identifier, :with => /^(?!\d+$)[a-z0-9\-_]*$/, :allow_blank => true validates_format_of :identifier, :with => /^(?!\d+$)[a-z0-9\-]*$/, :allow_blank => true
# Checks if the SCM is enabled when creating a repository # Checks if the SCM is enabled when creating a repository
validate :repo_create_validation, :on => :create validate :repo_create_validation, :on => :create
@@ -228,7 +228,7 @@ class Repository < ActiveRecord::Base
:order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC", :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC",
:limit => limit) :limit => limit)
else else
filechanges.find( changes.find(
:all, :all,
:include => {:changeset => :user}, :include => {:changeset => :user},
:conditions => ["path = ?", path.with_leading_slash], :conditions => ["path = ?", path.with_leading_slash],
+4 -4
View File
@@ -54,7 +54,7 @@ class Repository::Cvs < Repository
if entries if entries
entries.each() do |entry| entries.each() do |entry|
if ( ! entry.lastrev.nil? ) && ( ! entry.lastrev.revision.nil? ) if ( ! entry.lastrev.nil? ) && ( ! entry.lastrev.revision.nil? )
change = filechanges.find_by_revision_and_path( change=changes.find_by_revision_and_path(
entry.lastrev.revision, entry.lastrev.revision,
scm.with_leading_slash(entry.path) ) scm.with_leading_slash(entry.path) )
if change if change
@@ -94,7 +94,7 @@ class Repository::Cvs < Repository
if rev_to.to_i > 0 if rev_to.to_i > 0
changeset_to = changesets.find_by_revision(rev_to) changeset_to = changesets.find_by_revision(rev_to)
end end
changeset_from.filechanges.each() do |change_from| changeset_from.changes.each() do |change_from|
revision_from = nil revision_from = nil
revision_to = nil revision_to = nil
if path.nil? || (change_from.path.starts_with? scm.with_leading_slash(path)) if path.nil? || (change_from.path.starts_with? scm.with_leading_slash(path))
@@ -102,7 +102,7 @@ class Repository::Cvs < Repository
end end
if revision_from if revision_from
if changeset_to if changeset_to
changeset_to.filechanges.each() do |change_to| changeset_to.changes.each() do |change_to|
revision_to = change_to.revision if change_to.path == change_from.path revision_to = change_to.revision if change_to.path == change_from.path
end end
end end
@@ -133,7 +133,7 @@ class Repository::Cvs < Repository
# only add the change to the database, if it doen't exists. the cvs log # only add the change to the database, if it doen't exists. the cvs log
# is not exclusive at all. # is not exclusive at all.
tmp_time = revision.time.clone tmp_time = revision.time.clone
unless filechanges.find_by_path_and_revision( unless changes.find_by_path_and_revision(
scm.with_leading_slash(revision.paths[0][:path]), scm.with_leading_slash(revision.paths[0][:path]),
revision.paths[0][:revision] revision.paths[0][:revision]
) )
+1 -1
View File
@@ -79,7 +79,7 @@ class Repository::Darcs < Repository
return nil if patch_from.nil? return nil if patch_from.nil?
patch_to = changesets.find_by_revision(rev_to) if rev_to patch_to = changesets.find_by_revision(rev_to) if rev_to
if path.blank? if path.blank?
path = patch_from.filechanges.collect{|change| change.path}.join(' ') path = patch_from.changes.collect{|change| change.path}.join(' ')
end end
patch_from ? scm.diff(path, patch_from.scmid, patch_to ? patch_to.scmid : nil) : nil patch_from ? scm.diff(path, patch_from.scmid, patch_to ? patch_to.scmid : nil) : nil
end end
+1 -1
View File
@@ -66,7 +66,7 @@ class TimeEntry < ActiveRecord::Base
end end
} }
safe_attributes 'hours', 'comments', 'issue_id', 'activity_id', 'spent_on', 'custom_field_values', 'custom_fields' safe_attributes 'hours', 'comments', 'issue_id', 'activity_id', 'spent_on', 'custom_field_values'
def initialize(attributes=nil, *args) def initialize(attributes=nil, *args)
super super
+4 -7
View File
@@ -130,11 +130,8 @@ class User < Principal
# Returns the user that matches provided login and password, or nil # Returns the user that matches provided login and password, or nil
def self.try_to_login(login, password) def self.try_to_login(login, password)
login = login.to_s
password = password.to_s
# Make sure no one can sign in with an empty password # Make sure no one can sign in with an empty password
return nil if password.empty? return nil if password.to_s.empty?
user = find_by_login(login) user = find_by_login(login)
if user if user
# user is already in local database # user is already in local database
@@ -167,7 +164,7 @@ class User < Principal
# Returns the user who matches the given autologin +key+ or nil # Returns the user who matches the given autologin +key+ or nil
def self.try_to_autologin(key) def self.try_to_autologin(key)
tokens = Token.find_all_by_action_and_value('autologin', key.to_s) tokens = Token.find_all_by_action_and_value('autologin', key)
# Make sure there's only 1 token that matches the key # Make sure there's only 1 token that matches the key
if tokens.size == 1 if tokens.size == 1
token = tokens.first token = tokens.first
@@ -341,12 +338,12 @@ class User < Principal
end end
def self.find_by_rss_key(key) def self.find_by_rss_key(key)
token = Token.find_by_action_and_value('feeds', key.to_s) token = Token.find_by_value(key)
token && token.user.active? ? token.user : nil token && token.user.active? ? token.user : nil
end end
def self.find_by_api_key(key) def self.find_by_api_key(key)
token = Token.find_by_action_and_value('api', key.to_s) token = Token.find_by_action_and_value('api', key)
token && token.user.active? ? token.user : nil token && token.user.active? ? token.user : nil
end end
+1 -1
View File
@@ -1,4 +1,4 @@
<h2><%= @author.nil? ? l(:label_activity) : l(:label_user_activity, link_to_user(@author)).html_safe %></h2> <h2><%= @author.nil? ? l(:label_activity) : l(:label_user_activity, link_to_user(@author)) %></h2>
<p class="subtitle"><%= l(:label_date_from_to, :start => format_date(@date_to - @days), :end => format_date(@date_to-1)) %></p> <p class="subtitle"><%= l(:label_date_from_to, :start => format_date(@date_to - @days), :end => format_date(@date_to-1)) %></p>
<div id="activity"> <div id="activity">
+1 -1
View File
@@ -10,7 +10,7 @@
<span> <span>
<%= file_field_tag 'attachments[1][file]', :size => 30, :id => nil, :class => 'file', <%= file_field_tag 'attachments[1][file]', :size => 30, :id => nil, :class => 'file',
:onchange => "checkFileSize(this, #{Setting.attachment_max_size.to_i.kilobytes}, '#{escape_javascript(l(:error_attachment_too_big, :max_size => number_to_human_size(Setting.attachment_max_size.to_i.kilobytes)))}');" -%> :onchange => "checkFileSize(this, #{Setting.attachment_max_size.to_i.kilobytes}, '#{escape_javascript(l(:error_attachment_too_big, :max_size => number_to_human_size(Setting.attachment_max_size.to_i.kilobytes)))}');" -%>
<%= text_field_tag 'attachments[1][description]', '', :id => nil, :class => 'description', :maxlength => 255, :placeholder => l(:label_optional_description) %> <%= text_field_tag 'attachments[1][description]', '', :id => nil, :class => 'description', :placeholder => l(:label_optional_description) %>
<%= link_to_function(image_tag('delete.png'), 'removeFileField(this)', :title => (l(:button_delete))) %> <%= link_to_function(image_tag('delete.png'), 'removeFileField(this)', :title => (l(:button_delete))) %>
</span> </span>
</span> </span>
+1 -1
View File
@@ -21,6 +21,6 @@
<% if @notes.present? %> <% if @notes.present? %>
<label><%= radio_button_tag 'conflict_resolution', 'add_notes' %> <%= l(:text_issue_conflict_resolution_add_notes) %></label><br /> <label><%= radio_button_tag 'conflict_resolution', 'add_notes' %> <%= l(:text_issue_conflict_resolution_add_notes) %></label><br />
<% end %> <% end %>
<label><%= radio_button_tag 'conflict_resolution', 'cancel' %> <%= l(:text_issue_conflict_resolution_cancel, :link => link_to_issue(@issue, :subject => false)).html_safe %></label> <label><%= radio_button_tag 'conflict_resolution', 'cancel' %> <%= l(:text_issue_conflict_resolution_cancel, :link => link_to_issue(@issue, :subject => false)) %></label>
</p> </p>
<p><%= submit_tag l(:button_submit) %></p> <p><%= submit_tag l(:button_submit) %></p>
+2 -2
View File
@@ -7,14 +7,14 @@
<div class="next-prev-links contextual"> <div class="next-prev-links contextual">
<%= link_to_if @prev_issue_id, <%= link_to_if @prev_issue_id,
"\xc2\xab #{l(:label_previous)}", "\xc2\xab #{l(:label_previous)}",
(@prev_issue_id ? issue_path(@prev_issue_id) : nil), issue_path(@prev_issue_id),
:title => "##{@prev_issue_id}" %> | :title => "##{@prev_issue_id}" %> |
<% if @issue_position && @issue_count %> <% if @issue_position && @issue_count %>
<span class="position"><%= l(:label_item_position, :position => @issue_position, :count => @issue_count) %></span> | <span class="position"><%= l(:label_item_position, :position => @issue_position, :count => @issue_count) %></span> |
<% end %> <% end %>
<%= link_to_if @next_issue_id, <%= link_to_if @next_issue_id,
"#{l(:label_next)} \xc2\xbb", "#{l(:label_next)} \xc2\xbb",
(@next_issue_id ? issue_path(@next_issue_id) : nil), issue_path(@next_issue_id),
:title => "##{@next_issue_id}" %> :title => "##{@next_issue_id}" %>
</div> </div>
<% end %> <% end %>
+1 -1
View File
@@ -1,3 +1,3 @@
<p><%= l(:mail_body_wiki_content_added, :id => link_to(h(@wiki_content.page.pretty_title), @wiki_content_url), <p><%= l(:mail_body_wiki_content_added, :id => link_to(h(@wiki_content.page.pretty_title), @wiki_content_url),
:author => h(@wiki_content.author)).html_safe %><br /> :author => h(@wiki_content.author)) %><br />
<em><%=h @wiki_content.comments %></em></p> <em><%=h @wiki_content.comments %></em></p>
@@ -1,5 +1,5 @@
<p><%= l(:mail_body_wiki_content_updated, :id => link_to(h(@wiki_content.page.pretty_title), @wiki_content_url), <p><%= l(:mail_body_wiki_content_updated, :id => link_to(h(@wiki_content.page.pretty_title), @wiki_content_url),
:author => h(@wiki_content.author)).html_safe %><br /> :author => h(@wiki_content.author)) %><br />
<em><%=h @wiki_content.comments %></em></p> <em><%=h @wiki_content.comments %></em></p>
<p><%= l(:label_view_diff) %>:<br /> <p><%= l(:label_view_diff) %>:<br />
+1 -2
View File
@@ -4,8 +4,7 @@
<%=l(:text_project_destroy_confirmation)%> <%=l(:text_project_destroy_confirmation)%>
<% if @project_to_destroy.descendants.any? %> <% if @project_to_destroy.descendants.any? %>
<br /><%= l(:text_subprojects_destroy_warning, <br /><%= l(:text_subprojects_destroy_warning, content_tag('strong', h(@project_to_destroy.descendants.collect{|p| p.to_s}.join(', ')))) %>
content_tag('strong', h(@project_to_destroy.descendants.collect{|p| p.to_s}.join(', ')))).html_safe %>
<% end %> <% end %>
</p> </p>
<p> <p>
+1 -1
View File
@@ -1,6 +1,6 @@
<%= labelled_remote_form_for @wiki, <%= labelled_remote_form_for @wiki,
:as => :wiki, :as => :wiki,
:url => { :controller => 'wikis', :action => 'edit', :id => @project }, :method => 'post' do |f| %> :url => { :controller => 'wikis', :action => 'edit', :id => @project } do |f| %>
<%= error_messages_for 'wiki' %> <%= error_messages_for 'wiki' %>
+1 -1
View File
@@ -1,5 +1,5 @@
<h2><%= l(:label_repository) %></h2> <h2><%= l(:label_repository) %></h2>
<%= labelled_form_for :repository, @repository, :url => repository_path(@repository), :html => {:method => :put} do |f| %> <%= labelled_form_for :repository, @repository, :url => repository_path(@path), :html => {:method => :put} do |f| %>
<%= render :partial => 'form', :locals => {:f => f} %> <%= render :partial => 'form', :locals => {:f => f} %>
<% end %> <% end %>
+1 -1
View File
@@ -83,7 +83,7 @@
:id => @project, :id => @project,
:repository_id => @repository.identifier_param, :repository_id => @repository.identifier_param,
:path => "", :path => "",
:rev => @changeset.identifier) if @changeset.filechanges.any? %></p> :rev => @changeset.identifier) if @changeset.changes.any? %></p>
<div class="changeset-changes"> <div class="changeset-changes">
<%= render_changeset_changes %> <%= render_changeset_changes %>
-1
View File
@@ -1,7 +1,6 @@
<h2><%= l(:label_spent_time) %></h2> <h2><%= l(:label_spent_time) %></h2>
<%= labelled_form_for @time_entry, :url => time_entries_path do |f| %> <%= labelled_form_for @time_entry, :url => time_entries_path do |f| %>
<%= hidden_field_tag 'project_id', params[:project_id] if params[:project_id] %>
<%= render :partial => 'form', :locals => {:f => f} %> <%= render :partial => 'form', :locals => {:f => f} %>
<%= submit_tag l(:button_create) %> <%= submit_tag l(:button_create) %>
<%= submit_tag l(:button_create_and_continue), :name => 'continue' %> <%= submit_tag l(:button_create_and_continue), :name => 'continue' %>
+1 -1
View File
@@ -3,7 +3,7 @@
<%= select_tag 'user[mail_notification]', options_for_select(user_mail_notification_options(@user), @user.mail_notification), <%= select_tag 'user[mail_notification]', options_for_select(user_mail_notification_options(@user), @user.mail_notification),
:onchange => 'if (this.value == "selected") {Element.show("notified-projects")} else {Element.hide("notified-projects")}' %> :onchange => 'if (this.value == "selected") {Element.show("notified-projects")} else {Element.hide("notified-projects")}' %>
</p> </p>
<%= content_tag 'div', :id => 'notified-projects', :style => (@user.mail_notification == 'selected' ? '' : 'display:none;') do %> <% content_tag 'div', :id => 'notified-projects', :style => (@user.mail_notification == 'selected' ? '' : 'display:none;') do %>
<p><% @user.projects.each do |project| %> <p><% @user.projects.each do |project| %>
<label><%= check_box_tag 'notified_project_ids[]', project.id, @user.notified_projects_ids.include?(project.id) %> <%=h project.name %></label><br /> <label><%= check_box_tag 'notified_project_ids[]', project.id, @user.notified_projects_ids.include?(project.id) %> <%=h project.name %></label><br />
<% end %></p> <% end %></p>
+2 -2
View File
@@ -76,14 +76,14 @@ ar:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
byte: byte:
one: "Byte" one: "Byte"
other: "Bytes" other: "Bytes"
kb: "KB" kb: "kB"
mb: "MB" mb: "MB"
gb: "GB" gb: "GB"
tb: "TB" tb: "TB"
+1 -1
View File
@@ -78,7 +78,7 @@ bg:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+1 -1
View File
@@ -89,7 +89,7 @@ bs:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+1 -1
View File
@@ -80,7 +80,7 @@ ca:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+2 -2
View File
@@ -81,14 +81,14 @@ cs:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
byte: byte:
one: "Bajt" one: "Bajt"
other: "Bajtů" other: "Bajtů"
kb: "KB" kb: "kB"
mb: "MB" mb: "MB"
gb: "GB" gb: "GB"
tb: "TB" tb: "TB"
+1 -1
View File
@@ -91,7 +91,7 @@ da:
format: format:
# separator: # separator:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+2 -2
View File
@@ -93,7 +93,7 @@ de:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
@@ -1036,7 +1036,7 @@ de:
label_copy_attachments: Anhänge Kopieren label_copy_attachments: Anhänge Kopieren
label_item_position: "%{position}/%{count}" label_item_position: "%{position}/%{count}"
label_completed_versions: Abgeschlossene Versionen label_completed_versions: Abgeschlossene Versionen
field_multiple: Mehrere Werte field_multiple: Mehrer Werte
setting_commit_cross_project_ref: Erlauben auf Tickets aller anderen Projekte zu referenzieren setting_commit_cross_project_ref: Erlauben auf Tickets aller anderen Projekte zu referenzieren
text_issue_conflict_resolution_add_notes: Meine Änderungen übernehmen und alle anderen Änderungen verwerfen text_issue_conflict_resolution_add_notes: Meine Änderungen übernehmen und alle anderen Änderungen verwerfen
text_issue_conflict_resolution_overwrite: Meine Änderungen trotzdem übernehmen (vorherige Notizen bleiben erhalten aber manche können überschrieben werden) text_issue_conflict_resolution_overwrite: Meine Änderungen trotzdem übernehmen (vorherige Notizen bleiben erhalten aber manche können überschrieben werden)
+1 -1
View File
@@ -77,7 +77,7 @@ el:
precision: 3 precision: 3
human: human:
format: format:
precision: 3 precision: 1
delimiter: "" delimiter: ""
storage_units: storage_units:
format: "%n %u" format: "%n %u"
+2 -2
View File
@@ -81,14 +81,14 @@ en-GB:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
byte: byte:
one: "Byte" one: "Byte"
other: "Bytes" other: "Bytes"
kb: "KB" kb: "kB"
mb: "MB" mb: "MB"
gb: "GB" gb: "GB"
tb: "TB" tb: "TB"
+2 -2
View File
@@ -77,14 +77,14 @@ en:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
byte: byte:
one: "Byte" one: "Byte"
other: "Bytes" other: "Bytes"
kb: "KB" kb: "kB"
mb: "MB" mb: "MB"
gb: "GB" gb: "GB"
tb: "TB" tb: "TB"
+1 -1
View File
@@ -48,7 +48,7 @@ es:
# These three are to override number.format and are optional # These three are to override number.format and are optional
# separator: # separator:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+1 -1
View File
@@ -94,7 +94,7 @@ et:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+1 -1
View File
@@ -79,7 +79,7 @@ eu:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+1 -1
View File
@@ -77,7 +77,7 @@ fa:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+1 -1
View File
@@ -64,7 +64,7 @@ fi:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+1 -1
View File
@@ -91,7 +91,7 @@ fr:
format: '%n %u' format: '%n %u'
human: human:
format: format:
precision: 3 precision: 2
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+1 -1
View File
@@ -32,7 +32,7 @@ gl:
format: format:
# separator: # separator:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+1 -1
View File
@@ -72,7 +72,7 @@ hr:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+1 -1
View File
@@ -97,7 +97,7 @@
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+1 -1
View File
@@ -78,7 +78,7 @@ id:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+2 -2
View File
@@ -96,7 +96,7 @@ ja:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
@@ -758,7 +758,7 @@ ja:
label_week: 週 label_week: 週
label_date_from: "日付指定: " label_date_from: "日付指定: "
label_date_to: から label_date_to: から
label_language_based: ユーザの言語の設定に従う label_language_based: 既定の言語の設定に従う
label_sort_by: "並び替え %{value}" label_sort_by: "並び替え %{value}"
label_send_test_email: テストメールを送信 label_send_test_email: テストメールを送信
label_feeds_access_key: RSSアクセスキー label_feeds_access_key: RSSアクセスキー
+1 -1
View File
@@ -119,7 +119,7 @@ ko:
# These three are to override number.format and are optional # These three are to override number.format and are optional
# separator: # separator:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+1 -1
View File
@@ -109,7 +109,7 @@ lt:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
# Storage units output formatting. # Storage units output formatting.
# %u is the storage unit, %n is the number (default: 2 MB) # %u is the storage unit, %n is the number (default: 2 MB)
+1 -1
View File
@@ -72,7 +72,7 @@ lv:
human: human:
format: format:
delimiter: " " delimiter: " "
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+1 -1
View File
@@ -77,7 +77,7 @@ mk:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+1 -1
View File
@@ -75,7 +75,7 @@ mn:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+1 -1
View File
@@ -74,7 +74,7 @@ nl:
precision: 3 precision: 3
human: human:
format: format:
precision: 3 precision: 1
delimiter: "" delimiter: ""
storage_units: storage_units:
format: "%n %u" format: "%n %u"
+1 -1
View File
@@ -63,7 +63,7 @@
other: "nesten %{count} år" other: "nesten %{count} år"
number: number:
format: format:
precision: 3 precision: 2
separator: "." separator: "."
delimiter: "," delimiter: ","
currency: currency:
+1 -1
View File
@@ -21,7 +21,7 @@ pl:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+5 -5
View File
@@ -18,10 +18,10 @@ pt-BR:
time: time:
formats: formats:
default: "%A, %d de %B de %Y, %H:%M h" default: "%A, %d de %B de %Y, %H:%M hs"
time: "%H:%M h" time: "%H:%M hs"
short: "%d/%m, %H:%M h" short: "%d/%m, %H:%M hs"
long: "%A, %d de %B de %Y, %H:%M h" long: "%A, %d de %B de %Y, %H:%M hs"
only_second: "%S" only_second: "%S"
datetime: datetime:
formats: formats:
@@ -97,7 +97,7 @@ pt-BR:
delimiter: '.' delimiter: '.'
human: human:
format: format:
precision: 3 precision: 1
delimiter: '.' delimiter: '.'
storage_units: storage_units:
format: "%n %u" format: "%n %u"
+1 -1
View File
@@ -89,7 +89,7 @@ pt:
delimiter: '' delimiter: ''
human: human:
format: format:
precision: 3 precision: 1
delimiter: '' delimiter: ''
storage_units: storage_units:
format: "%n %u" format: "%n %u"
+1 -1
View File
@@ -73,7 +73,7 @@ ro:
human: human:
format: format:
precision: 3 precision: 1
delimiter: "" delimiter: ""
storage_units: storage_units:
format: "%n %u" format: "%n %u"
+35 -35
View File
@@ -68,7 +68,7 @@ ru:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 2
# Rails 2.2 # Rails 2.2
# storage_units: [байт, КБ, МБ, ГБ, ТБ] # storage_units: [байт, КБ, МБ, ГБ, ТБ]
@@ -1089,11 +1089,11 @@ ru:
notice_issue_successful_create: Задача %{id} создана. notice_issue_successful_create: Задача %{id} создана.
label_between: между label_between: между
setting_issue_group_assignment: Разрешить назначение задач группам пользователей setting_issue_group_assignment: Разрешить назначение задач группам пользователей
label_diff: Разница(diff) label_diff: diff
text_git_repository_note: Repository is bare and local (e.g. /gitrepo, c:\gitrepo) text_git_repository_note: Repository is bare and local (e.g. /gitrepo, c:\gitrepo)
description_query_sort_criteria_direction: Порядок сортировки description_query_sort_criteria_direction: Sort direction
description_project_scope: Search scope description_project_scope: Search scope
description_filter: Фильтр description_filter: Filter
description_user_mail_notification: Mail notification settings description_user_mail_notification: Mail notification settings
description_date_from: Enter start date description_date_from: Enter start date
description_message_content: Message content description_message_content: Message content
@@ -1101,23 +1101,23 @@ ru:
description_date_range_interval: Choose range by selecting start and end date description_date_range_interval: Choose range by selecting start and end date
description_issue_category_reassign: Choose issue category description_issue_category_reassign: Choose issue category
description_search: Searchfield description_search: Searchfield
description_notes: Примечания description_notes: Notes
description_date_range_list: Выберите диапазон из списка description_date_range_list: Choose range from list
description_choose_project: Проекты description_choose_project: Projects
description_date_to: Введите дату выполнения description_date_to: Enter end date
description_query_sort_criteria_attribute: Критерий сортировки description_query_sort_criteria_attribute: Sort attribute
description_wiki_subpages_reassign: Выбрать новую родительскую страницу description_wiki_subpages_reassign: Choose new parent page
description_selected_columns: Выбранные столбцы description_selected_columns: Selected Columns
label_parent_revision: Родительский label_parent_revision: Parent
label_child_revision: Дочерний label_child_revision: Child
error_scm_annotate_big_text_file: Комментарий невозможен из-за превышения максимального размера текстового файла. error_scm_annotate_big_text_file: The entry cannot be annotated, as it exceeds the maximum text file size.
setting_default_issue_start_date_to_creation_date: Использовать текущую дату в качестве даты начала для новых задач setting_default_issue_start_date_to_creation_date: Use current date as start date for new issues
button_edit_section: Редактировать эту секцию button_edit_section: Edit this section
setting_repositories_encodings: Кодировка вложений и хранилищ setting_repositories_encodings: Attachments and repositories encodings
description_all_columns: Все столбцы description_all_columns: All Columns
button_export: Экспорт button_export: Export
label_export_options: "%{export_format} параметры экспорта" label_export_options: "%{export_format} export options"
error_attachment_too_big: Этот файл нельзя загрузить из-за превышения максимального размера файла (%{max_size}) error_attachment_too_big: This file cannot be uploaded because it exceeds the maximum allowed file size (%{max_size})
notice_failed_to_save_time_entries: "Failed to save %{count} time entrie(s) on %{total} selected: %{ids}." notice_failed_to_save_time_entries: "Failed to save %{count} time entrie(s) on %{total} selected: %{ids}."
label_x_issues: label_x_issues:
zero: 0 Задач zero: 0 Задач
@@ -1125,21 +1125,21 @@ ru:
few: "%{count} Задач" few: "%{count} Задач"
many: "%{count} Задач" many: "%{count} Задач"
other: "%{count} Задач" other: "%{count} Задач"
label_repository_new: Новое хранилище label_repository_new: New repository
field_repository_is_default: Хранилище по умолчанию field_repository_is_default: Main repository
label_copy_attachments: Копировать вложения label_copy_attachments: Copy attachments
label_item_position: "%{position}/%{count}" label_item_position: "%{position}/%{count}"
label_completed_versions: Завершенные версии label_completed_versions: Completed versions
text_project_identifier_info: Допускаются только строчные латинские буквы (a-z), цифры, тире и подчеркивания.<br />После сохранения идентификатор изменить нельзя. text_project_identifier_info: Only lower case letters (a-z), numbers, dashes and underscores are allowed.<br />Once saved, the identifier cannot be changed.
field_multiple: Множественные значения field_multiple: Multiple values
setting_commit_cross_project_ref: Разрешить ссылаться и исправлять задачи во всех остальных проектах setting_commit_cross_project_ref: Allow issues of all the other projects to be referenced and fixed
text_issue_conflict_resolution_add_notes: Добавить мои примечания и отказаться от моих изменений text_issue_conflict_resolution_add_notes: Add my notes and discard my other changes
text_issue_conflict_resolution_overwrite: Применить мои изменения (все предыдущие замечания будут сохранены, но некоторые изменения могут быть перезаписаны) text_issue_conflict_resolution_overwrite: Apply my changes anyway (previous notes will be kept but some changes may be overwritten)
notice_issue_update_conflict: Кто-то изменил задачу, пока вы ее редактировали. notice_issue_update_conflict: The issue has been updated by an other user while you were editing it.
text_issue_conflict_resolution_cancel: Отменить мои изменения и показать задачу заново %{link} text_issue_conflict_resolution_cancel: Discard all my changes and redisplay %{link}
permission_manage_related_issues: Управление связанными задачами permission_manage_related_issues: Manage related issues
field_ldap_filter: Фильтр LDAP field_ldap_filter: LDAP filter
label_search_for_watchers: Найти наблюдателей label_search_for_watchers: Search for watchers to add
notice_account_deleted: "Ваша учетная запись полностью удалена" notice_account_deleted: "Ваша учетная запись полностью удалена"
setting_unsubscribe: "Разрешить пользователям удалять свои учетные записи" setting_unsubscribe: "Разрешить пользователям удалять свои учетные записи"
button_delete_my_account: "Удалить мою учетную запись" button_delete_my_account: "Удалить мою учетную запись"
+1 -1
View File
@@ -75,7 +75,7 @@ sk:
human: human:
format: format:
precision: 3 precision: 1
delimiter: "" delimiter: ""
storage_units: storage_units:
format: "%n %u" format: "%n %u"
+1 -1
View File
@@ -75,7 +75,7 @@ sl:
precision: 3 precision: 3
human: human:
format: format:
precision: 3 precision: 1
delimiter: "" delimiter: ""
storage_units: storage_units:
format: "%n %u" format: "%n %u"
+2 -2
View File
@@ -77,14 +77,14 @@ sq:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
byte: byte:
one: "Byte" one: "Byte"
other: "Bytes" other: "Bytes"
kb: "KB" kb: "kB"
mb: "MB" mb: "MB"
gb: "GB" gb: "GB"
tb: "TB" tb: "TB"
+1 -1
View File
@@ -77,7 +77,7 @@ sr-YU:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+1 -1
View File
@@ -77,7 +77,7 @@ sr:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+2 -2
View File
@@ -47,14 +47,14 @@ sv:
# These three are to override number.format and are optional # These three are to override number.format and are optional
# separator: # separator:
delimiter: "" delimiter: ""
precision: 3 # precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
byte: byte:
one: "Byte" one: "Byte"
other: "Bytes" other: "Bytes"
kb: "KB" kb: "kB"
mb: "MB" mb: "MB"
gb: "GB" gb: "GB"
tb: "TB" tb: "TB"
+1 -1
View File
@@ -74,7 +74,7 @@ th:
precision: 3 precision: 3
human: human:
format: format:
precision: 3 precision: 1
delimiter: "" delimiter: ""
storage_units: storage_units:
format: "%n %u" format: "%n %u"
+1 -1
View File
@@ -99,7 +99,7 @@ tr:
format: format:
delimiter: '.' delimiter: '.'
separator: ',' separator: ','
precision: 3 precision: 2
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+1 -1
View File
@@ -74,7 +74,7 @@ uk:
precision: 3 precision: 3
human: human:
format: format:
precision: 3 precision: 1
delimiter: "" delimiter: ""
storage_units: storage_units:
format: "%n %u" format: "%n %u"
+1 -1
View File
@@ -48,7 +48,7 @@ vi:
# These three are to override number.format and are optional # These three are to override number.format and are optional
# separator: # separator:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
+1 -1
View File
@@ -87,7 +87,7 @@
# 下列三個選項設定, 若有設定值將會取代 number.format 成為預設值 # 下列三個選項設定, 若有設定值將會取代 number.format 成為預設值
# separator: # separator:
delimiter: "" delimiter: ""
precision: 3 precision: 1
# 儲存單位輸出格式. # 儲存單位輸出格式.
# %u 是儲存單位, %n 是數值 (預設值: 2 MB) # %u 是儲存單位, %n 是數值 (預設值: 2 MB)
storage_units: storage_units:
+2 -2
View File
@@ -79,14 +79,14 @@ zh:
human: human:
format: format:
delimiter: "" delimiter: ""
precision: 3 precision: 1
storage_units: storage_units:
format: "%n %u" format: "%n %u"
units: units:
byte: byte:
one: "Byte" one: "Byte"
other: "Bytes" other: "Bytes"
kb: "KB" kb: "kB"
mb: "MB" mb: "MB"
gb: "GB" gb: "GB"
tb: "TB" tb: "TB"
-2
View File
@@ -224,7 +224,6 @@ RedmineApp::Application.routes.draw do
get 'projects/:id/repository/:repository_id/revisions', :to => 'repositories#revisions' get 'projects/:id/repository/:repository_id/revisions', :to => 'repositories#revisions'
get 'projects/:id/repository/:repository_id/revisions/:rev/:action(/*path(.:ext))', get 'projects/:id/repository/:repository_id/revisions/:rev/:action(/*path(.:ext))',
:controller => 'repositories', :controller => 'repositories',
:format => false,
:constraints => { :constraints => {
:action => /(browse|show|entry|raw|annotate|diff)/, :action => /(browse|show|entry|raw|annotate|diff)/,
:rev => /[a-z0-9\.\-_]+/ :rev => /[a-z0-9\.\-_]+/
@@ -243,7 +242,6 @@ RedmineApp::Application.routes.draw do
delete 'projects/:id/repository/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue' delete 'projects/:id/repository/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue'
get 'projects/:id/repository/revisions/:rev/:action(/*path(.:ext))', get 'projects/:id/repository/revisions/:rev/:action(/*path(.:ext))',
:controller => 'repositories', :controller => 'repositories',
:format => false,
:constraints => { :constraints => {
:action => /(browse|show|entry|raw|annotate|diff)/, :action => /(browse|show|entry|raw|annotate|diff)/,
:rev => /[a-z0-9\.\-_]+/ :rev => /[a-z0-9\.\-_]+/
-49
View File
@@ -4,55 +4,6 @@ Redmine - project management software
Copyright (C) 2006-2012 Jean-Philippe Lang Copyright (C) 2006-2012 Jean-Philippe Lang
http://www.redmine.org/ http://www.redmine.org/
== 2012-09-16 v2.0.4
* Defect #10818: Running rake in test environment causes exception
* Defect #11209: Wiki diff may generate broken HTML
* Defect #11217: Project names in drop-down are escaped twice
* Defect #11262: Link is escaped in wiki added/updated notification email
* Defect #11307: Can't filter for negative numeric custom fields
* Defect #11325: Unified diff link broken on specific file/revision diff view
* Defect #11341: Escaped link in conflict resolution form
* Defect #11365: Attachment description length is not validated
* Defect #11511: Confirmation page has broken HTML when a project folding sub project is deleted
* Defect #11533: rake redmine:plugins:test doesn't run tests in subdirectories
* Defect #11541: Version sharing is missing in the REST API
* Defect #11550: Issue reminder doesn't work when using asynchronous delivery
* Defect #11776: Can't override mailer views inside redmine plugin.
* Defect #11789: Edit section links broken with h5/h6 headings
* Feature #11338: Exclude emails with auto-submitted => auto-generated
* Patch #11299: redmine:plugins:migrate should update db/schema.rb
* Patch #11328: Fix Japanese mistranslation for 'label_language_based'
* Patch #11448: Russian translation for 1.4-stable and 2.0-stable
* Patch #11600: Fix plural form of the abbreviation for hours in Brazilian Portuguese
== 2012-06-18 v2.0.3
* Defect #10688: PDF export from Wiki - Problems with tables
* Defect #11061: Cannot choose commit versions to view differences in Git/Mercurial repository view
* Defect #11065: E-Mail submitted tickets: German umlauts in 'Subject' get malformed (ruby 1.8)
* Defect #11098: Default priorities have the same position and can't be reordered
* Defect #11105: <% content_for :header_tags do %> doesn't work inside hook
* Defect #11112: REST API - custom fields in POST/PUT ignored for time_entries
* Defect #11118: "Maximum file size" displayed on upload forms is incorrect
* Defect #11124: Link to user is escaped in activity title
* Defect #11133: Wiki-page section edit link can point to incorrect section
* Defect #11160: SQL Error on time report if a custom field has multiple values for an entry
* Defect #11170: Topics sort order is broken in Redmine 2.x
* Defect #11178: Spent time sorted by date-descending order lists same-date entries in physical order (not-reverse)
* Defect #11185: Redmine fails to delete a project with parent/child task
* Feature #11162: Upgrade to Rails 3.2.6
* Patch #11113: Small glitch in German localization
== 2012-06-05 v2.0.2
* Defect #11032: Project list is not shown when "For any event on the selected projects only..." is selected on user edit panel
* Defect #11038: "Create and continue" should preserve project, issue and activity when logging time
* Defect #11046: Redmine.pm does not support "bind as user" ldap authentication
* Defect #11051: reposman.rb fails in 1.4.2 because of missing require for rubygems
* Defect #11085: Wiki start page can't be changed
* Feature #11084: Update Rails to 3.2.5
== 2012-05-28 v2.0.1 == 2012-05-28 v2.0.1
* Defect #10923: After creating a new Version Redmine jumps back to "Information" * Defect #10923: After creating a new Version Redmine jumps back to "Information"
+2 -5
View File
@@ -13,7 +13,7 @@ http://www.redmine.org/
* A database: * A database:
* MySQL (tested with MySQL 5.1) * MySQL (tested with MySQL 5.1)
* PostgreSQL (tested with PostgreSQL 9.1) * PostgreSQL (tested with PostgreSQL 8.4)
* SQLite3 (tested with SQLite 3.6) * SQLite3 (tested with SQLite 3.6)
Optional: Optional:
@@ -38,10 +38,7 @@ Optional:
3. Create an empty utf8 encoded database: "redmine" for example 3. Create an empty utf8 encoded database: "redmine" for example
4. Configure the database parameters in config/database.yml 4. Configure the database parameters in config/database.yml
for the "production" environment (default database is MySQL and ruby1.8) for the "production" environment (default database is MySQL)
If you're running Redmine with MySQL and ruby1.9, replace the adapter name
with `mysql2`
5. Generate a session store secret 5. Generate a session store secret
+2 -9
View File
@@ -366,19 +366,12 @@ sub is_member {
); );
$sthldap->execute($auth_source_id); $sthldap->execute($auth_source_id);
while (my @rowldap = $sthldap->fetchrow_array) { while (my @rowldap = $sthldap->fetchrow_array) {
my $bind_as = $rowldap[3] ? $rowldap[3] : "";
my $bind_pw = $rowldap[4] ? $rowldap[4] : "";
if ($bind_as =~ m/\$login/) {
# replace $login with $redmine_user and use $redmine_pass
$bind_as =~ s/\$login/$redmine_user/g;
$bind_pw = $redmine_pass
}
my $ldap = Authen::Simple::LDAP->new( my $ldap = Authen::Simple::LDAP->new(
host => ($rowldap[2] eq "1" || $rowldap[2] eq "t") ? "ldaps://$rowldap[0]:$rowldap[1]" : $rowldap[0], host => ($rowldap[2] eq "1" || $rowldap[2] eq "t") ? "ldaps://$rowldap[0]:$rowldap[1]" : $rowldap[0],
port => $rowldap[1], port => $rowldap[1],
basedn => $rowldap[5], basedn => $rowldap[5],
binddn => $bind_as, binddn => $rowldap[3] ? $rowldap[3] : "",
bindpw => $bind_pw, bindpw => $rowldap[4] ? $rowldap[4] : "",
filter => "(".$rowldap[6]."=%s)" filter => "(".$rowldap[6]."=%s)"
); );
my $method = $r->method; my $method = $r->method;
-1
View File
@@ -3,7 +3,6 @@
require 'optparse' require 'optparse'
require 'find' require 'find'
require 'etc' require 'etc'
require 'rubygems'
Version = "1.4" Version = "1.4"
SUPPORTED_SCM = %w( Subversion Darcs Mercurial Bazaar Git Filesystem ) SUPPORTED_SCM = %w( Subversion Darcs Mercurial Bazaar Git Filesystem )
+1 -17
View File
@@ -2,23 +2,7 @@ Description:
The plugin generator creates stubs for a new Redmine plugin. The plugin generator creates stubs for a new Redmine plugin.
Example: Example:
./script/rails generate redmine_plugin meetings ./script/generate redmine_plugin meetings
create plugins/meetings/app
create plugins/meetings/app/controllers
create plugins/meetings/app/helpers
create plugins/meetings/app/models
create plugins/meetings/app/views
create plugins/meetings/db/migrate
create plugins/meetings/lib/tasks
create plugins/meetings/assets/images
create plugins/meetings/assets/javascripts
create plugins/meetings/assets/stylesheets
create plugins/meetings/config/locales
create plugins/meetings/test
create plugins/meetings/test/fixtures
create plugins/meetings/test/unit
create plugins/meetings/test/functional
create plugins/meetings/test/integration
create plugins/meetings/README.rdoc create plugins/meetings/README.rdoc
create plugins/meetings/init.rb create plugins/meetings/init.rb
create plugins/meetings/config/routes.rb create plugins/meetings/config/routes.rb
@@ -2,4 +2,4 @@ Description:
Generates a plugin controller. Generates a plugin controller.
Example: Example:
./script/rails generate redmine_plugin_controller meetings pools index show vote ./script/generate redmine_plugin_controller meetings pools index show vote
+1 -1
View File
@@ -2,4 +2,4 @@ Description:
Generates a plugin model. Generates a plugin model.
Examples: Examples:
./script/rails generate redmine_plugin_model meetings pool ./script/generate redmine_plugin_model meetings pool
@@ -131,15 +131,6 @@ module ActiveRecord
when 'lowest' when 'lowest'
move_to_bottom move_to_bottom
end end
reset_positions_in_list
end
def reset_positions_in_list
acts_as_list_class.where(scope_condition).reorder("#{position_column} ASC, id ASC").each_with_index do |item, i|
unless item.send(position_column) == (i + 1)
acts_as_list_class.update_all({position_column => (i + 1)}, {:id => item.id})
end
end
end end
# Removes the item from the list. # Removes the item from the list.
@@ -218,7 +209,7 @@ module ActiveRecord
def bottom_item(except = nil) def bottom_item(except = nil)
conditions = scope_condition conditions = scope_condition
conditions = "#{conditions} AND #{self.class.primary_key} != #{except.id}" if except conditions = "#{conditions} AND #{self.class.primary_key} != #{except.id}" if except
acts_as_list_class.where(conditions).reorder("#{position_column} DESC").first acts_as_list_class.find(:first, :conditions => conditions, :order => "#{position_column} DESC")
end end
# Forces item to assume the bottom position in the list. # Forces item to assume the bottom position in the list.
+21 -28
View File
@@ -283,7 +283,6 @@ class TCPDF
@state ||= 0 @state ||= 0
@tableborder ||= 0 @tableborder ||= 0
@tdbegin ||= false @tdbegin ||= false
@tdtext ||= ''
@tdwidth ||= 0 @tdwidth ||= 0
@tdheight ||= 0 @tdheight ||= 0
@tdalign ||= "L" @tdalign ||= "L"
@@ -3511,12 +3510,28 @@ class TCPDF
else else
#Text #Text
if (@tdbegin) if (@href)
element.gsub!(/[\t\r\n\f]/, "");
@tdtext << element.gsub(/&nbsp;/, " ");
elsif (@href)
element.gsub!(/[\t\r\n\f]/, ""); element.gsub!(/[\t\r\n\f]/, "");
addHtmlLink(@href, element, fill); addHtmlLink(@href, element, fill);
elsif (@tdbegin)
element.gsub!(/[\t\r\n\f]/, "");
element.gsub!(/&nbsp;/, " ");
base_page = @page;
base_x = @x;
base_y = @y;
MultiCell(@tdwidth, @tdheight, unhtmlentities(element.strip), @tableborder, @tdalign, @tdfill, 1);
tr_end = @t_cells[@table_id][@tr_id][@td_id]['j1'] + 1;
if @max_td_page[tr_end].nil? or (@max_td_page[tr_end] < @page)
@max_td_page[tr_end] = @page
@max_td_y[tr_end] = @y
elsif (@max_td_page[tr_end] == @page)
@max_td_y[tr_end] = @y if @max_td_y[tr_end].nil? or (@max_td_y[tr_end] < @y)
end
@page = base_page;
@x = base_x + @tdwidth;
@y = base_y;
elsif (@pre_state == true and element.length > 0) elsif (@pre_state == true and element.length > 0)
Write(@lasth, unhtmlentities(element), '', fill); Write(@lasth, unhtmlentities(element), '', fill);
elsif (element.strip.length > 0) elsif (element.strip.length > 0)
@@ -3810,7 +3825,6 @@ class TCPDF
@x += 5; @x += 5;
when 'table' when 'table'
Ln();
if @default_table_columns < @max_table_columns[@table_id] if @default_table_columns < @max_table_columns[@table_id]
@table_columns = @max_table_columns[@table_id]; @table_columns = @max_table_columns[@table_id];
else else
@@ -3907,11 +3921,6 @@ class TCPDF
when 'img' when 'img'
if (!attrs['src'].nil?) if (!attrs['src'].nil?)
# Don't generates image inside table tag
if (@tdbegin)
@tdtext << attrs['src'];
return
end
# Only generates image include a pdf if RMagick is avalaible # Only generates image include a pdf if RMagick is avalaible
unless Object.const_defined?(:Magick) unless Object.const_defined?(:Magick)
Write(@lasth, attrs['src'], '', fill); Write(@lasth, attrs['src'], '', fill);
@@ -4070,23 +4079,6 @@ class TCPDF
Ln(); Ln();
when 'td','th' when 'td','th'
base_page = @page;
base_x = @x;
base_y = @y;
MultiCell(@tdwidth, @tdheight, unhtmlentities(@tdtext.strip), @tableborder, @tdalign, @tdfill, 1);
tr_end = @t_cells[@table_id][@tr_id][@td_id]['j1'] + 1;
if @max_td_page[tr_end].nil? or (@max_td_page[tr_end] < @page)
@max_td_page[tr_end] = @page
@max_td_y[tr_end] = @y
elsif (@max_td_page[tr_end] == @page)
@max_td_y[tr_end] = @y if @max_td_y[tr_end].nil? or (@max_td_y[tr_end] < @y)
end
@page = base_page;
@x = base_x + @tdwidth;
@y = base_y;
@tdtext = '';
@tdbegin = false; @tdbegin = false;
@tdwidth = 0; @tdwidth = 0;
@tdheight = 0; @tdheight = 0;
@@ -4134,6 +4126,7 @@ class TCPDF
@l_margin -= 5; @l_margin -= 5;
@r_margin -= 5; @r_margin -= 5;
@tableborder=0; @tableborder=0;
Ln();
@table_id += 1; @table_id += 1;
when 'strong' when 'strong'
+4 -5
View File
@@ -50,17 +50,16 @@ module Redmine
words_add += 1 words_add += 1
else else
del_at = pos unless del_at del_at = pos unless del_at
deleted << ' ' unless deleted.empty? deleted << ' ' + h(change[2])
deleted << h(change[2])
words_del += 1 words_del += 1
end end
end end
if add_at if add_at
words[add_at] = '<span class="diff_in">'.html_safe + words[add_at] words[add_at] = '<span class="diff_in">' + words[add_at]
words[add_to] = words[add_to] + '</span>'.html_safe words[add_to] = words[add_to] + '</span>'
end end
if del_at if del_at
words.insert del_at - del_off + dels + words_add, '<span class="diff_out">'.html_safe + deleted + '</span>'.html_safe words.insert del_at - del_off + dels + words_add, '<span class="diff_out">' + deleted + '</span>'
dels += 1 dels += 1
del_off += words_del del_off += words_del
words_del = 0 words_del = 0
+3 -3
View File
@@ -138,21 +138,21 @@ module Redmine
# Add list and boolean custom fields as available criteria # Add list and boolean custom fields as available criteria
custom_fields = (@project.nil? ? IssueCustomField.for_all : @project.all_issue_custom_fields) custom_fields = (@project.nil? ? IssueCustomField.for_all : @project.all_issue_custom_fields)
custom_fields.select {|cf| %w(list bool).include? cf.field_format }.each do |cf| custom_fields.select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
@available_criteria["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Issue' AND c.customized_id = #{Issue.table_name}.id ORDER BY c.value LIMIT 1)", @available_criteria["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Issue' AND c.customized_id = #{Issue.table_name}.id)",
:format => cf.field_format, :format => cf.field_format,
:label => cf.name} :label => cf.name}
end if @project end if @project
# Add list and boolean time entry custom fields # Add list and boolean time entry custom fields
TimeEntryCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf| TimeEntryCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
@available_criteria["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'TimeEntry' AND c.customized_id = #{TimeEntry.table_name}.id ORDER BY c.value LIMIT 1)", @available_criteria["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'TimeEntry' AND c.customized_id = #{TimeEntry.table_name}.id)",
:format => cf.field_format, :format => cf.field_format,
:label => cf.name} :label => cf.name}
end end
# Add list and boolean time entry activity custom fields # Add list and boolean time entry activity custom fields
TimeEntryActivityCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf| TimeEntryActivityCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
@available_criteria["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Enumeration' AND c.customized_id = #{TimeEntry.table_name}.activity_id ORDER BY c.value LIMIT 1)", @available_criteria["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Enumeration' AND c.customized_id = #{TimeEntry.table_name}.activity_id)",
:format => cf.field_format, :format => cf.field_format,
:label => cf.name} :label => cf.name}
end end
+3 -10
View File
@@ -107,13 +107,7 @@ module Redmine
# #
def self.render_on(hook, options={}) def self.render_on(hook, options={})
define_method hook do |context| define_method hook do |context|
if context[:hook_caller].respond_to?(:render) context[:controller].send(:render_to_string, {:locals => context}.merge(options))
context[:hook_caller].send(:render, {:locals => context}.merge(options))
elsif context[:controller].is_a?(ActionController::Base)
context[:controller].send(:render_to_string, {:locals => context}.merge(options))
else
raise "Cannot render #{self.name} hook from #{context[:hook_caller].class.name}"
end
end end
end end
@@ -144,15 +138,14 @@ module Redmine
# * project => current project # * project => current project
# * request => Request instance # * request => Request instance
# * controller => current Controller instance # * controller => current Controller instance
# * hook_caller => object that called the hook
# #
module Helper module Helper
def call_hook(hook, context={}) def call_hook(hook, context={})
if is_a?(ActionController::Base) if is_a?(ActionController::Base)
default_context = {:controller => self, :project => @project, :request => request, :hook_caller => self} default_context = {:controller => self, :project => @project, :request => request}
Redmine::Hook.call_hook(hook, default_context.merge(context)) Redmine::Hook.call_hook(hook, default_context.merge(context))
else else
default_context = { :project => @project, :hook_caller => self } default_context = { :project => @project }
default_context[:controller] = controller if respond_to?(:controller) default_context[:controller] = controller if respond_to?(:controller)
default_context[:request] = request if respond_to?(:request) default_context[:request] = request if respond_to?(:request)
Redmine::Hook.call_hook(hook, default_context.merge(context)).join(' ').html_safe Redmine::Hook.call_hook(hook, default_context.merge(context)).join(' ').html_safe
-1
View File
@@ -82,7 +82,6 @@ module Redmine #:nodoc:
view_path = File.join(p.directory, 'app', 'views') view_path = File.join(p.directory, 'app', 'views')
if File.directory?(view_path) if File.directory?(view_path)
ActionController::Base.prepend_view_path(view_path) ActionController::Base.prepend_view_path(view_path)
ActionMailer::Base.prepend_view_path(view_path)
end end
# Adds the app/{controllers,helpers,models} directories of the plugin to the autoload path # Adds the app/{controllers,helpers,models} directories of the plugin to the autoload path
+1 -1
View File
@@ -4,7 +4,7 @@ module Redmine
module VERSION #:nodoc: module VERSION #:nodoc:
MAJOR = 2 MAJOR = 2
MINOR = 0 MINOR = 0
TINY = 4 TINY = 1
# Branch values: # Branch values:
# * official release: nil # * official release: nil
@@ -69,7 +69,7 @@ module Redmine
l = 1 l = 1
started = false started = false
ended = false ended = false
text.scan(/(((?:.*?)(\A|\r?\n\s*\r?\n))(h(\d+)(#{A}#{C})\.(?::(\S+))? (.*?)$)|.*)/m).each do |all, content, lf, heading, level| text.scan(/(((?:.*?)(\A|\r?\n\r?\n))(h(\d+)(#{A}#{C})\.(?::(\S+))? (.*?)$)|.*)/m).each do |all, content, lf, heading, level|
if heading.nil? if heading.nil?
if ended if ended
after << all after << all
+2 -2
View File
@@ -163,7 +163,7 @@ namespace :redmine do
set_inheritance_column :none set_inheritance_column :none
# ticket changes: only migrate status changes and comments # ticket changes: only migrate status changes and comments
has_many :ticket_changes, :class_name => "TracTicketChange", :foreign_key => :ticket has_many :changes, :class_name => "TracTicketChange", :foreign_key => :ticket
has_many :customs, :class_name => "TracTicketCustom", :foreign_key => :ticket has_many :customs, :class_name => "TracTicketCustom", :foreign_key => :ticket
def attachments def attachments
@@ -487,7 +487,7 @@ namespace :redmine do
end end
# Comments and status/resolution changes # Comments and status/resolution changes
ticket.ticket_changes.group_by(&:time).each do |time, changeset| ticket.changes.group_by(&:time).each do |time, changeset|
status_change = changeset.select {|change| change.field == 'status'}.first status_change = changeset.select {|change| change.field == 'status'}.first
resolution_change = changeset.select {|change| change.field == 'resolution'}.first resolution_change = changeset.select {|change| change.field == 'resolution'}.first
comment_change = changeset.select {|change| change.field == 'comment'}.first comment_change = changeset.select {|change| change.field == 'comment'}.first
-32
View File
@@ -70,8 +70,6 @@ namespace :redmine do
rescue Redmine::PluginNotFound rescue Redmine::PluginNotFound
abort "Plugin #{name} was not found." abort "Plugin #{name} was not found."
end end
Rake::Task["db:schema:dump"].invoke
end end
desc 'Copies plugins assets into the public directory.' desc 'Copies plugins assets into the public directory.'
@@ -84,36 +82,6 @@ namespace :redmine do
abort "Plugin #{name} was not found." abort "Plugin #{name} was not found."
end end
end end
desc 'Runs the plugins tests.'
task :test do
Rake::Task["redmine:plugins:test:units"].invoke
Rake::Task["redmine:plugins:test:functionals"].invoke
Rake::Task["redmine:plugins:test:integration"].invoke
end
namespace :test do
desc 'Runs the plugins unit tests.'
Rake::TestTask.new :units => "db:test:prepare" do |t|
t.libs << "test"
t.verbose = true
t.test_files = FileList["plugins/#{ENV['NAME'] || '*'}/test/unit/**/*_test.rb"]
end
desc 'Runs the plugins functional tests.'
Rake::TestTask.new :functionals => "db:test:prepare" do |t|
t.libs << "test"
t.verbose = true
t.test_files = FileList["plugins/#{ENV['NAME'] || '*'}/test/functional/**/*_test.rb"]
end
desc 'Runs the plugins integration tests.'
Rake::TestTask.new :integration => "db:test:prepare" do |t|
t.libs << "test"
t.verbose = true
t.test_files = FileList["plugins/#{ENV['NAME'] || '*'}/test/integration/**/*_test.rb"]
end
end
end end
end end
+1 -1
View File
@@ -4,7 +4,7 @@ table.revision-info td {
padding: 0px; padding: 0px;
} }
div.revision-graph { position: absolute; min-width: 1px; } div.revision-graph { position: absolute; }
div.changeset-changes ul { margin: 0; padding: 0; } div.changeset-changes ul { margin: 0; padding: 0; }
div.changeset-changes ul > ul { margin-left: 18px; padding: 0; } div.changeset-changes ul > ul { margin-left: 18px; padding: 0; }
-11
View File
@@ -1,11 +0,0 @@
Content-Type: application/ms-tnef; name="winmail.dat"
Content-Transfer-Encoding: binary
From: John Smith <JSmith@somenet.foo>
To: "redmine@somenet.foo" <redmine@somenet.foo>
Subject: =?iso-8859-1?Q?Testmail_from_Webmail:_=E4_=F6_=FC...?=
Date: Fri, 1 Jun 2012 14:39:38 +0200
Message-ID: <87C31D42249DD0489D1A1444E3232DD7019D6183@foo.bar>
Accept-Language: de-CH, en-US
Content-Language: de-CH
Fixture
+2 -11
View File
@@ -55,16 +55,13 @@ class ActivitiesControllerTest < ActionController::TestCase
end end
def test_global_index def test_global_index
@request.session[:user_id] = 1
get :index get :index
assert_response :success assert_response :success
assert_template 'index' assert_template 'index'
assert_not_nil assigns(:events_by_day) assert_not_nil assigns(:events_by_day)
i5 = Issue.find(5)
d5 = User.find(1).time_to_date(i5.created_on)
assert_tag :tag => "h3", assert_tag :tag => "h3",
:content => /#{d5.day}/, :content => /#{5.day.ago.to_date.day}/,
:sibling => { :tag => "dl", :sibling => { :tag => "dl",
:child => { :tag => "dt", :child => { :tag => "dt",
:attributes => { :class => /issue/ }, :attributes => { :class => /issue/ },
@@ -76,19 +73,13 @@ class ActivitiesControllerTest < ActionController::TestCase
end end
def test_user_index def test_user_index
@request.session[:user_id] = 1
get :index, :user_id => 2 get :index, :user_id => 2
assert_response :success assert_response :success
assert_template 'index' assert_template 'index'
assert_not_nil assigns(:events_by_day) assert_not_nil assigns(:events_by_day)
assert_select 'h2 a[href=/users/2]', :text => 'John Smith'
i1 = Issue.find(1)
d1 = User.find(1).time_to_date(i1.created_on)
assert_tag :tag => "h3", assert_tag :tag => "h3",
:content => /#{d1.day}/, :content => /#{3.day.ago.to_date.day}/,
:sibling => { :tag => "dl", :sibling => { :tag => "dl",
:child => { :tag => "dt", :child => { :tag => "dt",
:attributes => { :class => /issue/ }, :attributes => { :class => /issue/ },
-14
View File
@@ -55,20 +55,6 @@ class BoardsControllerTest < ActionController::TestCase
assert_not_nil assigns(:topics) assert_not_nil assigns(:topics)
end end
def test_show_should_display_sticky_messages_first
Message.update_all(:sticky => 0)
Message.update_all({:sticky => 1}, {:id => 1})
get :show, :project_id => 1, :id => 1
assert_response :success
topics = assigns(:topics)
assert_not_nil topics
assert topics.size > 1, "topics size was #{topics.size}"
assert topics.first.sticky?
assert topics.first.updated_on < topics.second.updated_on
end
def test_show_with_permission_should_display_the_new_message_form def test_show_with_permission_should_display_the_new_message_form
@request.session[:user_id] = 2 @request.session[:user_id] = 2
get :show, :project_id => 1, :id => 1 get :show, :project_id => 1, :id => 1
+4 -23
View File
@@ -18,9 +18,7 @@
require File.expand_path('../../test_helper', __FILE__) require File.expand_path('../../test_helper', __FILE__)
class DocumentsControllerTest < ActionController::TestCase class DocumentsControllerTest < ActionController::TestCase
fixtures :projects, :users, :roles, :members, :member_roles, fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, :documents, :enumerations
:enabled_modules, :documents, :enumerations,
:groups_users, :attachments
def setup def setup
User.current = nil User.current = nil
@@ -97,16 +95,16 @@ LOREM
def test_create_with_one_attachment def test_create_with_one_attachment
ActionMailer::Base.deliveries.clear ActionMailer::Base.deliveries.clear
Setting.notified_events << 'document_added'
@request.session[:user_id] = 2 @request.session[:user_id] = 2
set_tmp_attachments_directory set_tmp_attachments_directory
with_settings :notified_events => %w(document_added) do post :create, :project_id => 'ecookbook',
post :create, :project_id => 'ecookbook',
:document => { :title => 'DocumentsControllerTest#test_post_new', :document => { :title => 'DocumentsControllerTest#test_post_new',
:description => 'This is a new document', :description => 'This is a new document',
:category_id => 2}, :category_id => 2},
:attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}} :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
end
assert_redirected_to '/projects/ecookbook/documents' assert_redirected_to '/projects/ecookbook/documents'
document = Document.find_by_title('DocumentsControllerTest#test_post_new') document = Document.find_by_title('DocumentsControllerTest#test_post_new')
@@ -126,23 +124,6 @@ LOREM
assert_template 'new' assert_template 'new'
end end
def test_create_non_default_category
@request.session[:user_id] = 2
category2 = Enumeration.find_by_name('User documentation')
category2.update_attributes(:is_default => true)
category1 = Enumeration.find_by_name('Uncategorized')
post :create,
:project_id => 'ecookbook',
:document => { :title => 'no default',
:description => 'This is a new document',
:category_id => category1.id }
assert_redirected_to '/projects/ecookbook/documents'
doc = Document.find_by_title('no default')
assert_not_nil doc
assert_equal category1.id, doc.category_id
assert_equal category1, doc.category
end
def test_edit def test_edit
@request.session[:user_id] = 2 @request.session[:user_id] = 2
get :edit, :id => 1 get :edit, :id => 1
+6 -6
View File
@@ -58,14 +58,13 @@ class FilesControllerTest < ActionController::TestCase
def test_create_file def test_create_file
set_tmp_attachments_directory set_tmp_attachments_directory
@request.session[:user_id] = 2 @request.session[:user_id] = 2
Setting.notified_events = ['file_added']
ActionMailer::Base.deliveries.clear ActionMailer::Base.deliveries.clear
with_settings :notified_events => %w(file_added) do assert_difference 'Attachment.count' do
assert_difference 'Attachment.count' do post :create, :project_id => 1, :version_id => '',
post :create, :project_id => 1, :version_id => '', :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
:attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}} assert_response :redirect
assert_response :redirect
end
end end
assert_redirected_to '/projects/ecookbook/files' assert_redirected_to '/projects/ecookbook/files'
a = Attachment.find(:first, :order => 'created_on DESC') a = Attachment.find(:first, :order => 'created_on DESC')
@@ -81,6 +80,7 @@ class FilesControllerTest < ActionController::TestCase
def test_create_version_file def test_create_version_file
set_tmp_attachments_directory set_tmp_attachments_directory
@request.session[:user_id] = 2 @request.session[:user_id] = 2
Setting.notified_events = ['file_added']
assert_difference 'Attachment.count' do assert_difference 'Attachment.count' do
post :create, :project_id => 1, :version_id => '2', post :create, :project_id => 1, :version_id => '2',
@@ -1371,7 +1371,6 @@ class IssuesControllerTest < ActionController::TestCase
:tag => 'input', :tag => 'input',
:attributes => {:type => 'file', :name => 'attachments[1][file]'} :attributes => {:type => 'file', :name => 'attachments[1][file]'}
} }
assert_select 'input[name=?][maxlength=255]', 'attachments[1][description]'
end end
def test_get_new_should_prefill_the_form_from_params def test_get_new_should_prefill_the_form_from_params
@@ -71,14 +71,10 @@ class IssuesControllerTransactionTest < ActionController::TestCase
assert_response :success assert_response :success
assert_template 'edit' assert_template 'edit'
assert_tag 'div', :attributes => {:class => 'conflict'}
assert_select 'div.conflict' assert_tag 'input', :attributes => {:name => 'conflict_resolution', :value => 'overwrite'}
assert_select 'input[name=?][value=?]', 'conflict_resolution', 'overwrite' assert_tag 'input', :attributes => {:name => 'conflict_resolution', :value => 'add_notes'}
assert_select 'input[name=?][value=?]', 'conflict_resolution', 'add_notes' assert_tag 'input', :attributes => {:name => 'conflict_resolution', :value => 'cancel'}
assert_select 'label' do
assert_select 'input[name=?][value=?]', 'conflict_resolution', 'cancel'
assert_select 'a[href=/issues/2]'
end
end end
def test_update_stale_issue_should_save_attachments def test_update_stale_issue_should_save_attachments

Some files were not shown because too many files have changed in this diff Show More