Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72c2aaf5c7 | ||
|
|
0e241bb857 | ||
|
|
9dcde53dab | ||
|
|
a44521527a | ||
|
|
f12590fa5c | ||
|
|
a1c6f710aa | ||
|
|
3ad82e4665 | ||
|
|
eef3b5b5ca | ||
|
|
ab69845ea2 | ||
|
|
af51a68b34 | ||
|
|
d5c08680f6 | ||
|
|
9b82b948e3 | ||
|
|
1c8510bc80 | ||
|
|
23861c7cc1 | ||
|
|
6550343cb9 | ||
|
|
a70cf2f833 | ||
|
|
0f219b973a | ||
|
|
d02e5e54a8 | ||
|
|
c050028102 | ||
|
|
012ffdf9e8 | ||
|
|
9e3aeeef88 | ||
|
|
21b162a624 | ||
|
|
b7e999d1aa | ||
|
|
284d03e1f8 | ||
|
|
3b4126e14f | ||
|
|
46a76ecb6e | ||
|
|
5a74edef89 | ||
|
|
2f9c2e6bd3 | ||
|
|
2df7c0ff3a |
@@ -19,6 +19,7 @@
|
|||||||
/public/plugin_assets
|
/public/plugin_assets
|
||||||
/tmp/*
|
/tmp/*
|
||||||
/tmp/cache/*
|
/tmp/cache/*
|
||||||
|
/tmp/pdf/*
|
||||||
/tmp/sessions/*
|
/tmp/sessions/*
|
||||||
/tmp/sockets/*
|
/tmp/sockets/*
|
||||||
/tmp/test/*
|
/tmp/test/*
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ public/dispatch.*
|
|||||||
public/plugin_assets
|
public/plugin_assets
|
||||||
tmp/*
|
tmp/*
|
||||||
tmp/cache/*
|
tmp/cache/*
|
||||||
|
tmp/pdf/*
|
||||||
tmp/sessions/*
|
tmp/sessions/*
|
||||||
tmp/sockets/*
|
tmp/sockets/*
|
||||||
tmp/test/*
|
tmp/test/*
|
||||||
|
|||||||
@@ -795,11 +795,10 @@ module ApplicationHelper
|
|||||||
if repository && User.current.allowed_to?(:browse_repository, project)
|
if repository && User.current.allowed_to?(:browse_repository, project)
|
||||||
name =~ %r{^[/\\]*(.*?)(@([0-9a-f]+))?(#(L\d+))?$}
|
name =~ %r{^[/\\]*(.*?)(@([0-9a-f]+))?(#(L\d+))?$}
|
||||||
path, rev, anchor = $1, $3, $5
|
path, rev, anchor = $1, $3, $5
|
||||||
link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:controller => 'repositories', :action => 'entry', :id => project, :repository_id => repository.identifier_param,
|
link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param,
|
||||||
:path => to_path_param(path),
|
:path => to_path_param(path),
|
||||||
:rev => rev,
|
:rev => rev,
|
||||||
:anchor => anchor,
|
:anchor => anchor},
|
||||||
:format => (prefix == 'export' ? 'raw' : nil)},
|
|
||||||
:class => (prefix == 'export' ? 'source download' : 'source')
|
:class => (prefix == 'export' ? 'source download' : 'source')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1029,6 +1028,11 @@ module ApplicationHelper
|
|||||||
content_tag(:a, name, {:href => '#', :onclick => "#{function}; return false;"}.merge(html_options))
|
content_tag(:a, name, {:href => '#', :onclick => "#{function}; return false;"}.merge(html_options))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Helper to render JSON in views
|
||||||
|
def raw_json(arg)
|
||||||
|
arg.to_json.to_s.gsub('/', '\/').html_safe
|
||||||
|
end
|
||||||
|
|
||||||
def back_url
|
def back_url
|
||||||
url = params[:back_url]
|
url = params[:back_url]
|
||||||
if url.nil? && referer = request.env['HTTP_REFERER']
|
if url.nil? && referer = request.env['HTTP_REFERER']
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ module ContextMenusHelper
|
|||||||
end
|
end
|
||||||
if options.delete(:disabled)
|
if options.delete(:disabled)
|
||||||
options.delete(:method)
|
options.delete(:method)
|
||||||
options.delete(:confirm)
|
options.delete(:data)
|
||||||
options.delete(:onclick)
|
options[:onclick] = 'return false;'
|
||||||
options[:class] << ' disabled'
|
options[:class] << ' disabled'
|
||||||
url = '#'
|
url = '#'
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -373,7 +373,8 @@ class MailHandler < ActionMailer::Base
|
|||||||
# try to reencode to utf8 manually with ruby1.8
|
# try to reencode to utf8 manually with ruby1.8
|
||||||
begin
|
begin
|
||||||
if h = email.header[:subject]
|
if h = email.header[:subject]
|
||||||
if m = h.value.match(/^=\?([^\?]+)\?/)
|
# http://tools.ietf.org/html/rfc2047#section-4
|
||||||
|
if m = h.value.match(/=\?([^\?]+)\?[BbQq]\?/)
|
||||||
subject = Redmine::CodesetUtil.to_utf8(subject, m[1])
|
subject = Redmine::CodesetUtil.to_utf8(subject, m[1])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -30,13 +30,13 @@ class Principal < ActiveRecord::Base
|
|||||||
if q.blank?
|
if q.blank?
|
||||||
{}
|
{}
|
||||||
else
|
else
|
||||||
q = q.to_s.downcase
|
q = q.to_s
|
||||||
pattern = "%#{q}%"
|
pattern = "%#{q}%"
|
||||||
sql = "LOWER(login) LIKE :p OR LOWER(firstname) LIKE :p OR LOWER(lastname) LIKE :p OR LOWER(mail) LIKE :p"
|
sql = "LOWER(login) LIKE LOWER(:p) OR LOWER(firstname) LIKE LOWER(:p) OR LOWER(lastname) LIKE LOWER(:p) OR LOWER(mail) LIKE LOWER(:p)"
|
||||||
params = {:p => pattern}
|
params = {:p => pattern}
|
||||||
if q =~ /^(.+)\s+(.+)$/
|
if q =~ /^(.+)\s+(.+)$/
|
||||||
a, b = "#{$1}%", "#{$2}%"
|
a, b = "#{$1}%", "#{$2}%"
|
||||||
sql << " OR (LOWER(firstname) LIKE :a AND LOWER(lastname) LIKE :b) OR (LOWER(firstname) LIKE :b AND LOWER(lastname) LIKE :a)"
|
sql << " OR (LOWER(firstname) LIKE LOWER(:a) AND LOWER(lastname) LIKE LOWER(:b)) OR (LOWER(firstname) LIKE LOWER(:b) AND LOWER(lastname) LIKE LOWER(:a))"
|
||||||
params.merge!(:a => a, :b => b)
|
params.merge!(:a => a, :b => b)
|
||||||
end
|
end
|
||||||
{:conditions => [sql, params]}
|
{:conditions => [sql, params]}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class Version < ActiveRecord::Base
|
|||||||
validates_format_of :effective_date, :with => /^\d{4}-\d{2}-\d{2}$/, :message => :not_a_date, :allow_nil => true
|
validates_format_of :effective_date, :with => /^\d{4}-\d{2}-\d{2}$/, :message => :not_a_date, :allow_nil => true
|
||||||
validates_inclusion_of :status, :in => VERSION_STATUSES
|
validates_inclusion_of :status, :in => VERSION_STATUSES
|
||||||
validates_inclusion_of :sharing, :in => VERSION_SHARINGS
|
validates_inclusion_of :sharing, :in => VERSION_SHARINGS
|
||||||
|
validate :validate_version
|
||||||
|
|
||||||
scope :named, lambda {|arg| { :conditions => ["LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip]}}
|
scope :named, lambda {|arg| { :conditions => ["LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip]}}
|
||||||
scope :open, :conditions => {:status => 'open'}
|
scope :open, :conditions => {:status => 'open'}
|
||||||
@@ -275,4 +276,10 @@ class Version < ActiveRecord::Base
|
|||||||
progress
|
progress
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def validate_version
|
||||||
|
if effective_date.nil? && @attributes['effective_date'].present?
|
||||||
|
errors.add :effective_date, :not_a_date
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
<% if @message.present? %>
|
<% if @message.present? %>
|
||||||
<p id="errorExplanation"><%=h @message %></p>
|
<p id="errorExplanation"><%=h @message %></p>
|
||||||
<% end %>
|
<% end %>
|
||||||
<p><a href="javascript:history.back()">Back</a></p>
|
<p><a href="javascript:history.back()"><%= l(:button_back) %></a></p>
|
||||||
|
|
||||||
<% html_title @status %>
|
<% html_title @status %>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
<tr class="group open">
|
<tr class="group open">
|
||||||
<td colspan="<%= query.columns.size + 2 %>">
|
<td colspan="<%= query.columns.size + 2 %>">
|
||||||
<span class="expander" onclick="toggleRowGroup(this);"> </span>
|
<span class="expander" onclick="toggleRowGroup(this);"> </span>
|
||||||
<%= group.blank? ? 'None' : column_content(@query.group_by_column, issue) %> <span class="count">(<%= @issue_count_by_group[group] %>)</span>
|
<%= group.blank? ? l(:label_none) : column_content(@query.group_by_column, issue) %> <span class="count">(<%= @issue_count_by_group[group] %>)</span>
|
||||||
<%= link_to_function("#{l(:button_collapse_all)}/#{l(:button_expand_all)}", "toggleAllRowGroups(this)", :class => 'toggle-all') %>
|
<%= link_to_function("#{l(:button_collapse_all)}/#{l(:button_expand_all)}", "toggleAllRowGroups(this)", :class => 'toggle-all') %>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<%= javascript_tag do %>
|
<%= javascript_tag do %>
|
||||||
var operatorLabels = <%= raw Query.operators_labels.to_json %>;
|
var operatorLabels = <%= raw_json Query.operators_labels %>;
|
||||||
var operatorByType = <%= raw Query.operators_by_filter_type.to_json %>;
|
var operatorByType = <%= raw_json Query.operators_by_filter_type %>;
|
||||||
var availableFilters = <%= raw query.available_filters_as_json.to_json %>;
|
var availableFilters = <%= raw_json query.available_filters_as_json %>;
|
||||||
var labelDayPlural = "<%= raw escape_javascript(l(:label_day_plural)) %>";
|
var labelDayPlural = <%= raw_json l(:label_day_plural) %>;
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
initFilters();
|
initFilters();
|
||||||
<% query.filters.each do |field, options| %>
|
<% query.filters.each do |field, options| %>
|
||||||
addFilter("<%= field %>", <%= raw query.operator_for(field).to_json %>, <%= raw query.values_for(field).to_json %>);
|
addFilter("<%= field %>", <%= raw_json query.operator_for(field) %>, <%= raw_json query.values_for(field) %>);
|
||||||
<% end %>
|
<% end %>
|
||||||
});
|
});
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<div class="contextual">
|
<div class="contextual">
|
||||||
<%= form_tag(
|
<%= form_tag(
|
||||||
{:controller => 'repositories', :action => 'revision', :id => @project,
|
{:controller => 'repositories', :action => 'revision', :id => @project,
|
||||||
:repository_id => @repository.identifier_param}
|
:repository_id => @repository.identifier_param},
|
||||||
|
:method => :get
|
||||||
) do %>
|
) do %>
|
||||||
<%= l(:label_revision) %>: <%= text_field_tag 'rev', @rev, :size => 8 %>
|
<%= l(:label_revision) %>: <%= text_field_tag 'rev', @rev, :size => 8 %>
|
||||||
<%= submit_tag 'OK' %>
|
<%= submit_tag 'OK' %>
|
||||||
|
|||||||
+11
-11
@@ -844,7 +844,7 @@ de:
|
|||||||
button_show: Anzeigen
|
button_show: Anzeigen
|
||||||
|
|
||||||
status_active: aktiv
|
status_active: aktiv
|
||||||
status_registered: angemeldet
|
status_registered: nicht aktivierte
|
||||||
status_locked: gesperrt
|
status_locked: gesperrt
|
||||||
|
|
||||||
version_status_open: offen
|
version_status_open: offen
|
||||||
@@ -1017,8 +1017,8 @@ de:
|
|||||||
description_date_from: Startdatum eintragen
|
description_date_from: Startdatum eintragen
|
||||||
description_date_to: Enddatum eintragen
|
description_date_to: Enddatum eintragen
|
||||||
|
|
||||||
label_parent_revision: Parent
|
label_parent_revision: Vorgänger
|
||||||
label_child_revision: Child
|
label_child_revision: Nachfolger
|
||||||
error_scm_annotate_big_text_file: Der Eintrag kann nicht umgesetzt werden, da er die maximale Textlänge überschreitet.
|
error_scm_annotate_big_text_file: Der Eintrag kann nicht umgesetzt werden, da er die maximale Textlänge überschreitet.
|
||||||
setting_default_issue_start_date_to_creation_date: Aktuelles Datum als Beginn für neue Tickets verwenden
|
setting_default_issue_start_date_to_creation_date: Aktuelles Datum als Beginn für neue Tickets verwenden
|
||||||
button_edit_section: Diesen Bereich bearbeiten
|
button_edit_section: Diesen Bereich bearbeiten
|
||||||
@@ -1068,14 +1068,14 @@ de:
|
|||||||
field_timeout: Auszeit (in Sekunden)
|
field_timeout: Auszeit (in Sekunden)
|
||||||
setting_thumbnails_enabled: Vorschaubilder von Dateianhängen anzeigen
|
setting_thumbnails_enabled: Vorschaubilder von Dateianhängen anzeigen
|
||||||
setting_thumbnails_size: Größe der Vorschaubilder (in Pixel)
|
setting_thumbnails_size: Größe der Vorschaubilder (in Pixel)
|
||||||
label_status_transitions: Status transitions
|
label_status_transitions: Statusänderungen
|
||||||
label_fields_permissions: Fields permissions
|
label_fields_permissions: Feldberechtigungen
|
||||||
label_readonly: Nur-Lese-Zugriff
|
label_readonly: Nur-Lese-Zugriff
|
||||||
label_required: Erforderlich
|
label_required: Erforderlich
|
||||||
text_repository_identifier_info: 'Kleinbuchstaben (a-z), Ziffern, Binde- und Unterstriche erlaubt.<br />Einmal gespeichert, kann die Kennung nicht mehr geändert werden.'
|
text_repository_identifier_info: 'Kleinbuchstaben (a-z), Ziffern, Binde- und Unterstriche erlaubt.<br />Einmal gespeichert, kann die Kennung nicht mehr geändert werden.'
|
||||||
field_board_parent: Parent forum
|
field_board_parent: Übergeordnetes Forum
|
||||||
label_attribute_of_project: Project's %{name}
|
label_attribute_of_project: "%{name} des Projekts"
|
||||||
label_attribute_of_author: Author's %{name}
|
label_attribute_of_author: "%{name} des Autors"
|
||||||
label_attribute_of_assigned_to: Assignee's %{name}
|
label_attribute_of_assigned_to: "%{name} des Bearbeiters"
|
||||||
label_attribute_of_fixed_version: Target version's %{name}
|
label_attribute_of_fixed_version: "%{name} der Zielversion"
|
||||||
label_copy_subtasks: Copy subtasks
|
label_copy_subtasks: Unteraufgaben kopieren
|
||||||
|
|||||||
+17
-17
@@ -1152,27 +1152,27 @@ ru:
|
|||||||
setting_session_lifetime: Session maximum lifetime
|
setting_session_lifetime: Session maximum lifetime
|
||||||
setting_session_timeout: Session inactivity timeout
|
setting_session_timeout: Session inactivity timeout
|
||||||
label_session_expiration: Session expiration
|
label_session_expiration: Session expiration
|
||||||
permission_close_project: Close / reopen the project
|
permission_close_project: Закрывать / открывать проекты
|
||||||
label_show_closed_projects: View closed projects
|
label_show_closed_projects: Просматривать закрытые проекты
|
||||||
button_close: Close
|
button_close: Сделать закрытым
|
||||||
button_reopen: Reopen
|
button_reopen: Сделать открытым
|
||||||
project_status_active: active
|
project_status_active: открытые
|
||||||
project_status_closed: closed
|
project_status_closed: закрытые
|
||||||
project_status_archived: archived
|
project_status_archived: архивированные
|
||||||
text_project_closed: This project is closed and read-only.
|
text_project_closed: Проект закрыт и находиться в режиме только для чтения.
|
||||||
notice_user_successful_create: User %{id} created.
|
notice_user_successful_create: Пользователь %{id} создан.
|
||||||
field_core_fields: Standard fields
|
field_core_fields: Стандартные поля
|
||||||
field_timeout: Timeout (in seconds)
|
field_timeout: Timeout (in seconds)
|
||||||
setting_thumbnails_enabled: Display attachment thumbnails
|
setting_thumbnails_enabled: Display attachment thumbnails
|
||||||
setting_thumbnails_size: Thumbnails size (in pixels)
|
setting_thumbnails_size: Thumbnails size (in pixels)
|
||||||
label_status_transitions: Status transitions
|
label_status_transitions: Статус-переходы
|
||||||
label_fields_permissions: Fields permissions
|
label_fields_permissions: Права на изменения полей
|
||||||
label_readonly: Read-only
|
label_readonly: Не изменяется
|
||||||
label_required: Required
|
label_required: Обязательное
|
||||||
text_repository_identifier_info: Допускаются только строчные латинские буквы (a-z), цифры, тире и подчеркивания.<br />После сохранения идентификатор изменить нельзя.
|
text_repository_identifier_info: Допускаются только строчные латинские буквы (a-z), цифры, тире и подчеркивания.<br />После сохранения идентификатор изменить нельзя.
|
||||||
field_board_parent: Parent forum
|
field_board_parent: Родительский форум
|
||||||
label_attribute_of_project: Project's %{name}
|
label_attribute_of_project: Project's %{name}
|
||||||
label_attribute_of_author: Author's %{name}
|
label_attribute_of_author: Имя автора %{name}
|
||||||
label_attribute_of_assigned_to: Assignee's %{name}
|
label_attribute_of_assigned_to: Assignee's %{name}
|
||||||
label_attribute_of_fixed_version: Target version's %{name}
|
label_attribute_of_fixed_version: Target version's %{name}
|
||||||
label_copy_subtasks: Copy subtasks
|
label_copy_subtasks: Копировать подзадачи
|
||||||
|
|||||||
@@ -1061,9 +1061,9 @@ zh:
|
|||||||
label_readonly: 只读
|
label_readonly: 只读
|
||||||
label_required: 必填
|
label_required: 必填
|
||||||
text_repository_identifier_info: 仅小写字母(a-z)、数字、破折号(-)和下划线(_)可以使用。<br />一旦保存,标识无法修改。
|
text_repository_identifier_info: 仅小写字母(a-z)、数字、破折号(-)和下划线(_)可以使用。<br />一旦保存,标识无法修改。
|
||||||
field_board_parent: Parent forum
|
field_board_parent: 父论坛
|
||||||
label_attribute_of_project: Project's %{name}
|
label_attribute_of_project: 项目 %{name}
|
||||||
label_attribute_of_author: Author's %{name}
|
label_attribute_of_author: 作者 %{name}
|
||||||
label_attribute_of_assigned_to: Assignee's %{name}
|
label_attribute_of_assigned_to: 分配给 %{name}
|
||||||
label_attribute_of_fixed_version: Target version's %{name}
|
label_attribute_of_fixed_version: 目标版本 %{name}
|
||||||
label_copy_subtasks: Copy subtasks
|
label_copy_subtasks: 复制子任务
|
||||||
|
|||||||
@@ -4,6 +4,29 @@ 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-11-17 v2.1.3
|
||||||
|
|
||||||
|
* Defect #12050: :export links to repository files lead to a 404 error
|
||||||
|
* Defect #12189: Missing tmp/pdf directory
|
||||||
|
* Defect #12195: Javascript error with IE7 / IE8 on new issue form
|
||||||
|
* Defect #12196: "Page not found" on OK button in SCM "View all revisions" page
|
||||||
|
* Defect #12199: Confirmation message displayed when clicking a disabled delete link in the context menu
|
||||||
|
* Defect #12231: Hardcoded "Back" in Repository
|
||||||
|
* Defect #12294: Incorrect german translation for "registered" users filter
|
||||||
|
* Defect #12349: Watchers auto-complete search on non-latin chars
|
||||||
|
* Defect #12358: 'None' grouped issue list section should be translated
|
||||||
|
* Defect #12359: Version date field regex validation accepts invalid date
|
||||||
|
* Defect #12375: Receiving mail subject encoding broken (MOJIBAKE) in some cases on Ruby 1.8
|
||||||
|
* Patch #9732: German translations
|
||||||
|
* Patch #12021: Russian locale translations
|
||||||
|
* Patch #12188: Simplified Chinese translation with zh.yml file based on Rev:10681
|
||||||
|
* Patch #12235: German translation for 2.1-stable
|
||||||
|
* Patch #12237: Added German Translation
|
||||||
|
|
||||||
|
== 2012-09-30 v2.1.2
|
||||||
|
|
||||||
|
* Defect #11929: XSS vulnerability in Redmine 2.1.x
|
||||||
|
|
||||||
== 2012-09-30 v2.1.1
|
== 2012-09-30 v2.1.1
|
||||||
|
|
||||||
* Defect #11290: ParseDate missing in Ruby 1.9x
|
* Defect #11290: ParseDate missing in Ruby 1.9x
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ module Redmine
|
|||||||
attachable_options[:delete_permission] = options.delete(:delete_permission) || "edit_#{self.name.pluralize.underscore}".to_sym
|
attachable_options[:delete_permission] = options.delete(:delete_permission) || "edit_#{self.name.pluralize.underscore}".to_sym
|
||||||
|
|
||||||
has_many :attachments, options.merge(:as => :container,
|
has_many :attachments, options.merge(:as => :container,
|
||||||
:order => "#{Attachment.table_name}.created_on",
|
:order => "#{Attachment.table_name}.created_on ASC, #{Attachment.table_name}.id ASC",
|
||||||
:dependent => :destroy)
|
:dependent => :destroy)
|
||||||
send :include, Redmine::Acts::Attachable::InstanceMethods
|
send :include, Redmine::Acts::Attachable::InstanceMethods
|
||||||
before_save :attach_saved_attachments
|
before_save :attach_saved_attachments
|
||||||
@@ -62,7 +62,19 @@ module Redmine
|
|||||||
|
|
||||||
def save_attachments(attachments, author=User.current)
|
def save_attachments(attachments, author=User.current)
|
||||||
if attachments.is_a?(Hash)
|
if attachments.is_a?(Hash)
|
||||||
attachments = attachments.values
|
attachments = attachments.stringify_keys
|
||||||
|
attachments = attachments.to_a.sort {|a, b|
|
||||||
|
if a.first.to_i > 0 && b.first.to_i > 0
|
||||||
|
a.first.to_i <=> b.first.to_i
|
||||||
|
elsif a.first.to_i > 0
|
||||||
|
1
|
||||||
|
elsif b.first.to_i > 0
|
||||||
|
-1
|
||||||
|
else
|
||||||
|
a.first <=> b.first
|
||||||
|
end
|
||||||
|
}
|
||||||
|
attachments = attachments.map(&:last)
|
||||||
end
|
end
|
||||||
if attachments.is_a?(Array)
|
if attachments.is_a?(Array)
|
||||||
attachments.each do |attachment|
|
attachments.each do |attachment|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ module Redmine
|
|||||||
module VERSION #:nodoc:
|
module VERSION #:nodoc:
|
||||||
MAJOR = 2
|
MAJOR = 2
|
||||||
MINOR = 1
|
MINOR = 1
|
||||||
TINY = 1
|
TINY = 3
|
||||||
|
|
||||||
# Branch values:
|
# Branch values:
|
||||||
# * official release: nil
|
# * official release: nil
|
||||||
|
|||||||
@@ -163,9 +163,9 @@ function buildFilterRow(field, operator, values) {
|
|||||||
case "date":
|
case "date":
|
||||||
case "date_past":
|
case "date_past":
|
||||||
tr.find('td.values').append(
|
tr.find('td.values').append(
|
||||||
'<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="10" class="value date_value" value="'+values[0]+'" /></span>' +
|
'<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="10" class="value date_value" /></span>' +
|
||||||
' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="10" class="value date_value" value="'+values[1]+'" /></span>' +
|
' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="10" class="value date_value" /></span>' +
|
||||||
' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="3" class="value" value="'+values[0]+'" /> '+labelDayPlural+'</span>'
|
' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="3" class="value" /> '+labelDayPlural+'</span>'
|
||||||
);
|
);
|
||||||
$('#values_'+fieldId+'_1').val(values[0]).datepicker(datepickerOptions);
|
$('#values_'+fieldId+'_1').val(values[0]).datepicker(datepickerOptions);
|
||||||
$('#values_'+fieldId+'_2').val(values[1]).datepicker(datepickerOptions);
|
$('#values_'+fieldId+'_2').val(values[1]).datepicker(datepickerOptions);
|
||||||
@@ -174,15 +174,15 @@ function buildFilterRow(field, operator, values) {
|
|||||||
case "string":
|
case "string":
|
||||||
case "text":
|
case "text":
|
||||||
tr.find('td.values').append(
|
tr.find('td.values').append(
|
||||||
'<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="30" class="value" value="'+values[0]+'" /></span>'
|
'<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="30" class="value" /></span>'
|
||||||
);
|
);
|
||||||
$('#values_'+fieldId).val(values[0]);
|
$('#values_'+fieldId).val(values[0]);
|
||||||
break;
|
break;
|
||||||
case "integer":
|
case "integer":
|
||||||
case "float":
|
case "float":
|
||||||
tr.find('td.values').append(
|
tr.find('td.values').append(
|
||||||
'<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="6" class="value" value="'+values[0]+'" /></span>' +
|
'<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="6" class="value" /></span>' +
|
||||||
' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="6" class="value" value="'+values[1]+'" /></span>'
|
' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="6" class="value" /></span>'
|
||||||
);
|
);
|
||||||
$('#values_'+fieldId+'_1').val(values[0]);
|
$('#values_'+fieldId+'_1').val(values[0]);
|
||||||
$('#values_'+fieldId+'_2').val(values[1]);
|
$('#values_'+fieldId+'_2').val(values[1]);
|
||||||
@@ -464,9 +464,11 @@ function updateBulkEditFrom(url) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function observeAutocompleteField(fieldId, url) {
|
function observeAutocompleteField(fieldId, url) {
|
||||||
$('#'+fieldId).autocomplete({
|
$(document).ready(function() {
|
||||||
source: url,
|
$('#'+fieldId).autocomplete({
|
||||||
minLength: 2,
|
source: url,
|
||||||
|
minLength: 2
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
From: John Smith <JSmith@somenet.foo>
|
||||||
|
To: "redmine@somenet.foo" <redmine@somenet.foo>
|
||||||
|
Subject: =?iso-2022-jp?b?GyRCJUYlOSVIGyhCCg=?=
|
||||||
|
Date: Fri, 1 Jun 2012 14:39:38 +0200
|
||||||
|
Message-ID: <87C31D42249DD0489D1A1444E3232DD7019D6183@foo.bar>
|
||||||
|
|
||||||
|
Fixture
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
From: John Smith <JSmith@somenet.foo>
|
||||||
|
To: "redmine@somenet.foo" <redmine@somenet.foo>
|
||||||
|
Subject: Re: =?iso-2022-jp?b?GyRCJUYlOSVIGyhCCg=?=
|
||||||
|
Date: Fri, 1 Jun 2012 14:39:38 +0200
|
||||||
|
Message-ID: <87C31D42249DD0489D1A1444E3232DD7019D6183@foo.bar>
|
||||||
|
|
||||||
|
Fixture
|
||||||
@@ -273,4 +273,12 @@ class QueriesControllerTest < ActionController::TestCase
|
|||||||
assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :set_filter => 1, :query_id => nil
|
assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :set_filter => 1, :query_id => nil
|
||||||
assert_nil Query.find_by_id(1)
|
assert_nil Query.find_by_id(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_backslash_should_be_escaped_in_filters
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
get :new, :subject => 'foo/bar'
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'new'
|
||||||
|
assert_include 'addFilter("subject", "=", ["foo\/bar"]);', response.body
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -532,6 +532,21 @@ class RepositoriesGitControllerTest < ActionController::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_revisions
|
||||||
|
assert_equal 0, @repository.changesets.count
|
||||||
|
@repository.fetch_changesets
|
||||||
|
@project.reload
|
||||||
|
assert_equal NUM_REV, @repository.changesets.count
|
||||||
|
get :revisions, :id => PRJ_ID
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'revisions'
|
||||||
|
assert_tag :tag => 'form',
|
||||||
|
:attributes => {
|
||||||
|
:method => 'get',
|
||||||
|
:action => '/projects/subproject1/repository/revision'
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
def test_revision
|
def test_revision
|
||||||
assert_equal 0, @repository.changesets.count
|
assert_equal 0, @repository.changesets.count
|
||||||
@repository.fetch_changesets
|
@repository.fetch_changesets
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ class ApiTest::IssuesTest < ActionController::IntegrationTest
|
|||||||
:member_roles,
|
:member_roles,
|
||||||
:issues,
|
:issues,
|
||||||
:issue_statuses,
|
:issue_statuses,
|
||||||
|
:issue_relations,
|
||||||
:versions,
|
:versions,
|
||||||
:trackers,
|
:trackers,
|
||||||
:projects_trackers,
|
:projects_trackers,
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ module ObjectHelpers
|
|||||||
|
|
||||||
def Issue.generate!(attributes={})
|
def Issue.generate!(attributes={})
|
||||||
issue = Issue.new(attributes)
|
issue = Issue.new(attributes)
|
||||||
|
issue.project ||= Project.find(1)
|
||||||
|
issue.tracker ||= issue.project.trackers.first
|
||||||
issue.subject = 'Generated' if issue.subject.blank?
|
issue.subject = 'Generated' if issue.subject.blank?
|
||||||
issue.author ||= User.find(2)
|
issue.author ||= User.find(2)
|
||||||
yield issue if block_given?
|
yield issue if block_given?
|
||||||
|
|||||||
@@ -253,8 +253,15 @@ RAW
|
|||||||
|
|
||||||
project_url = {:controller => 'projects', :action => 'show', :id => 'subproject1'}
|
project_url = {:controller => 'projects', :action => 'show', :id => 'subproject1'}
|
||||||
|
|
||||||
source_url = {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}
|
source_url = '/projects/ecookbook/repository/entry/some/file'
|
||||||
source_url_with_ext = {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file.ext']}
|
source_url_with_rev = '/projects/ecookbook/repository/revisions/52/entry/some/file'
|
||||||
|
source_url_with_ext = '/projects/ecookbook/repository/entry/some/file.ext'
|
||||||
|
source_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/entry/some/file.ext'
|
||||||
|
|
||||||
|
export_url = '/projects/ecookbook/repository/raw/some/file'
|
||||||
|
export_url_with_rev = '/projects/ecookbook/repository/revisions/52/raw/some/file'
|
||||||
|
export_url_with_ext = '/projects/ecookbook/repository/raw/some/file.ext'
|
||||||
|
export_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/raw/some/file.ext'
|
||||||
|
|
||||||
to_test = {
|
to_test = {
|
||||||
# tickets
|
# tickets
|
||||||
@@ -284,12 +291,16 @@ RAW
|
|||||||
'source:/some/file. ' => link_to('source:/some/file', source_url, :class => 'source') + ".",
|
'source:/some/file. ' => link_to('source:/some/file', source_url, :class => 'source') + ".",
|
||||||
'source:/some/file.ext. ' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
|
'source:/some/file.ext. ' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
|
||||||
'source:/some/file, ' => link_to('source:/some/file', source_url, :class => 'source') + ",",
|
'source:/some/file, ' => link_to('source:/some/file', source_url, :class => 'source') + ",",
|
||||||
'source:/some/file@52' => link_to('source:/some/file@52', source_url.merge(:rev => 52), :class => 'source'),
|
'source:/some/file@52' => link_to('source:/some/file@52', source_url_with_rev, :class => 'source'),
|
||||||
'source:/some/file.ext@52' => link_to('source:/some/file.ext@52', source_url_with_ext.merge(:rev => 52), :class => 'source'),
|
'source:/some/file.ext@52' => link_to('source:/some/file.ext@52', source_url_with_rev_and_ext, :class => 'source'),
|
||||||
'source:/some/file#L110' => link_to('source:/some/file#L110', source_url.merge(:anchor => 'L110'), :class => 'source'),
|
'source:/some/file#L110' => link_to('source:/some/file#L110', source_url + "#L110", :class => 'source'),
|
||||||
'source:/some/file.ext#L110' => link_to('source:/some/file.ext#L110', source_url_with_ext.merge(:anchor => 'L110'), :class => 'source'),
|
'source:/some/file.ext#L110' => link_to('source:/some/file.ext#L110', source_url_with_ext + "#L110", :class => 'source'),
|
||||||
'source:/some/file@52#L110' => link_to('source:/some/file@52#L110', source_url.merge(:rev => 52, :anchor => 'L110'), :class => 'source'),
|
'source:/some/file@52#L110' => link_to('source:/some/file@52#L110', source_url_with_rev + "#L110", :class => 'source'),
|
||||||
'export:/some/file' => link_to('export:/some/file', source_url.merge(:format => 'raw'), :class => 'source download'),
|
# export
|
||||||
|
'export:/some/file' => link_to('export:/some/file', export_url, :class => 'source download'),
|
||||||
|
'export:/some/file.ext' => link_to('export:/some/file.ext', export_url_with_ext, :class => 'source download'),
|
||||||
|
'export:/some/file@52' => link_to('export:/some/file@52', export_url_with_rev, :class => 'source download'),
|
||||||
|
'export:/some/file.ext@52' => link_to('export:/some/file.ext@52', export_url_with_rev_and_ext, :class => 'source download'),
|
||||||
# forum
|
# forum
|
||||||
'forum#2' => link_to('Discussion', board_url, :class => 'board'),
|
'forum#2' => link_to('Discussion', board_url, :class => 'board'),
|
||||||
'forum:Discussion' => link_to('Discussion', board_url, :class => 'board'),
|
'forum:Discussion' => link_to('Discussion', board_url, :class => 'board'),
|
||||||
|
|||||||
@@ -109,51 +109,55 @@ class IssuesHelperTest < ActionView::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_with_a_start_date_attribute_should_format_the_current_date
|
context "with a start_date attribute" do
|
||||||
@detail = JournalDetail.new(
|
should "format the current date" do
|
||||||
|
@detail = JournalDetail.new(
|
||||||
:property => 'attr',
|
:property => 'attr',
|
||||||
:old_value => '2010-01-01',
|
:old_value => '2010-01-01',
|
||||||
:value => '2010-01-31',
|
:value => '2010-01-31',
|
||||||
:prop_key => 'start_date'
|
:prop_key => 'start_date'
|
||||||
)
|
)
|
||||||
with_settings :date_format => '%m/%d/%Y' do
|
with_settings :date_format => '%m/%d/%Y' do
|
||||||
assert_match "01/31/2010", show_detail(@detail, true)
|
assert_match "01/31/2010", show_detail(@detail, true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def test_with_a_start_date_attribute_should_format_the_old_date
|
should "format the old date" do
|
||||||
@detail = JournalDetail.new(
|
@detail = JournalDetail.new(
|
||||||
:property => 'attr',
|
:property => 'attr',
|
||||||
:old_value => '2010-01-01',
|
:old_value => '2010-01-01',
|
||||||
:value => '2010-01-31',
|
:value => '2010-01-31',
|
||||||
:prop_key => 'start_date'
|
:prop_key => 'start_date'
|
||||||
)
|
)
|
||||||
with_settings :date_format => '%m/%d/%Y' do
|
with_settings :date_format => '%m/%d/%Y' do
|
||||||
assert_match "01/01/2010", show_detail(@detail, true)
|
assert_match "01/01/2010", show_detail(@detail, true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_with_a_due_date_attribute_should_with_a_due_date_attribute
|
context "with a due_date attribute" do
|
||||||
@detail = JournalDetail.new(
|
should "format the current date" do
|
||||||
|
@detail = JournalDetail.new(
|
||||||
:property => 'attr',
|
:property => 'attr',
|
||||||
:old_value => '2010-01-01',
|
:old_value => '2010-01-01',
|
||||||
:value => '2010-01-31',
|
:value => '2010-01-31',
|
||||||
:prop_key => 'due_date'
|
:prop_key => 'due_date'
|
||||||
)
|
)
|
||||||
with_settings :date_format => '%m/%d/%Y' do
|
with_settings :date_format => '%m/%d/%Y' do
|
||||||
assert_match "01/31/2010", show_detail(@detail, true)
|
assert_match "01/31/2010", show_detail(@detail, true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def test_with_a_due_date_attribute_should_format_the_old_date
|
should "format the old date" do
|
||||||
@detail = JournalDetail.new(
|
@detail = JournalDetail.new(
|
||||||
:property => 'attr',
|
:property => 'attr',
|
||||||
:old_value => '2010-01-01',
|
:old_value => '2010-01-01',
|
||||||
:value => '2010-01-31',
|
:value => '2010-01-31',
|
||||||
:prop_key => 'due_date'
|
:prop_key => 'due_date'
|
||||||
)
|
)
|
||||||
with_settings :date_format => '%m/%d/%Y' do
|
with_settings :date_format => '%m/%d/%Y' do
|
||||||
assert_match "01/01/2010", show_detail(@detail, true)
|
assert_match "01/01/2010", show_detail(@detail, true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,17 @@
|
|||||||
require File.expand_path('../../test_helper', __FILE__)
|
require File.expand_path('../../test_helper', __FILE__)
|
||||||
|
|
||||||
class IssueRelationTest < ActiveSupport::TestCase
|
class IssueRelationTest < ActiveSupport::TestCase
|
||||||
fixtures :issue_relations, :issues
|
fixtures :projects,
|
||||||
|
:users,
|
||||||
|
:roles,
|
||||||
|
:members,
|
||||||
|
:member_roles,
|
||||||
|
:issues,
|
||||||
|
:issue_statuses,
|
||||||
|
:issue_relations,
|
||||||
|
:enabled_modules,
|
||||||
|
:enumerations,
|
||||||
|
:trackers
|
||||||
|
|
||||||
def test_create
|
def test_create
|
||||||
from = Issue.find(1)
|
from = Issue.find(1)
|
||||||
|
|||||||
@@ -1576,4 +1576,18 @@ class IssueTest < ActiveSupport::TestCase
|
|||||||
def test_journals_after_with_blank_arg_should_return_all_journals
|
def test_journals_after_with_blank_arg_should_return_all_journals
|
||||||
assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
|
assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_save_attachments_with_hash_should_save_attachments_in_keys_order
|
||||||
|
set_tmp_attachments_directory
|
||||||
|
issue = Issue.generate!
|
||||||
|
issue.save_attachments({
|
||||||
|
'p0' => {'file' => mock_file_with_options(:original_filename => 'upload')},
|
||||||
|
'3' => {'file' => mock_file_with_options(:original_filename => 'bar')},
|
||||||
|
'1' => {'file' => mock_file_with_options(:original_filename => 'foo')}
|
||||||
|
})
|
||||||
|
issue.attach_saved_attachments
|
||||||
|
|
||||||
|
assert_equal 3, issue.reload.attachments.count
|
||||||
|
assert_equal %w(upload foo bar), issue.attachments.map(&:filename)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -382,6 +382,28 @@ class MailHandlerTest < ActiveSupport::TestCase
|
|||||||
assert_equal 'Testmail from Webmail: ä ö ü...', issue.subject
|
assert_equal 'Testmail from Webmail: ä ö ü...', issue.subject
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_add_issue_with_japanese_subject
|
||||||
|
issue = submit_email(
|
||||||
|
'subject_japanese_1.eml',
|
||||||
|
:issue => {:project => 'ecookbook'}
|
||||||
|
)
|
||||||
|
assert_kind_of Issue, issue
|
||||||
|
ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88"
|
||||||
|
ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
|
||||||
|
assert_equal ja, issue.subject
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_add_issue_with_mixed_japanese_subject
|
||||||
|
issue = submit_email(
|
||||||
|
'subject_japanese_2.eml',
|
||||||
|
:issue => {:project => 'ecookbook'}
|
||||||
|
)
|
||||||
|
assert_kind_of Issue, issue
|
||||||
|
ja = "Re: \xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88"
|
||||||
|
ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
|
||||||
|
assert_equal ja, issue.subject
|
||||||
|
end
|
||||||
|
|
||||||
def test_should_ignore_emails_from_locked_users
|
def test_should_ignore_emails_from_locked_users
|
||||||
User.find(2).lock!
|
User.find(2).lock!
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# encoding: utf-8
|
||||||
|
#
|
||||||
# Redmine - project management software
|
# Redmine - project management software
|
||||||
# Copyright (C) 2006-2012 Jean-Philippe Lang
|
# Copyright (C) 2006-2012 Jean-Philippe Lang
|
||||||
#
|
#
|
||||||
@@ -106,4 +108,11 @@ class PrincipalTest < ActiveSupport::TestCase
|
|||||||
assert_equal @palmer, results.first
|
assert_equal @palmer, results.first
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_like_scope_with_cyrillic_name
|
||||||
|
user = User.generate!(:firstname => 'Соболев', :lastname => 'Денис')
|
||||||
|
results = Principal.like('Собо')
|
||||||
|
assert_equal 1, results.count
|
||||||
|
assert_equal user, results.first
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -32,7 +32,13 @@ class VersionTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
def test_invalid_effective_date_validation
|
def test_invalid_effective_date_validation
|
||||||
v = Version.new(:project => Project.find(1), :name => '1.1', :effective_date => '99999-01-01')
|
v = Version.new(:project => Project.find(1), :name => '1.1', :effective_date => '99999-01-01')
|
||||||
assert !v.save
|
assert !v.valid?
|
||||||
|
v.effective_date = '2012-11-33'
|
||||||
|
assert !v.valid?
|
||||||
|
v.effective_date = '2012-31-11'
|
||||||
|
assert !v.valid?
|
||||||
|
v.effective_date = 'ABC'
|
||||||
|
assert !v.valid?
|
||||||
assert_include I18n.translate('activerecord.errors.messages.not_a_date'),
|
assert_include I18n.translate('activerecord.errors.messages.not_a_date'),
|
||||||
v.errors[:effective_date]
|
v.errors[:effective_date]
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user