Compare commits

..
1 Commits
Author SHA1 Message Date
Jean-Philippe Lang 72c2aaf5c7 tagged version 2.1.3
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/tags/2.1.3@10833 e93f8b46-1217-0410-a6f0-8f06a7374b81
2012-11-17 12:50:11 +00:00
30 changed files with 130 additions and 472 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
source 'http://rubygems.org' source 'http://rubygems.org'
gem 'rails', '3.2.11' gem 'rails', '3.2.8'
gem "jquery-rails", "~> 2.0.2" gem "jquery-rails", "~> 2.0.2"
gem "i18n", "~> 0.6.0" gem "i18n", "~> 0.6.0"
gem "coderay", "~> 1.0.6" gem "coderay", "~> 1.0.6"
@@ -41,7 +41,7 @@ end
platforms :mri_18, :mingw_18 do platforms :mri_18, :mingw_18 do
group :mysql do group :mysql do
gem "mysql", "~> 2.8.1" gem "mysql"
end end
end end
+1 -2
View File
@@ -26,8 +26,7 @@ class PreviewsController < ApplicationController
if @description && @description.gsub(/(\r?\n|\n\r?)/, "\n") == @issue.description.to_s.gsub(/(\r?\n|\n\r?)/, "\n") if @description && @description.gsub(/(\r?\n|\n\r?)/, "\n") == @issue.description.to_s.gsub(/(\r?\n|\n\r?)/, "\n")
@description = nil @description = nil
end end
# params[:notes] is useful for preview of notes in issue history @notes = params[:notes]
@notes = params[:notes] || (params[:issue] ? params[:issue][:notes] : nil)
else else
@description = (params[:issue] ? params[:issue][:description] : nil) @description = (params[:issue] ? params[:issue][:description] : nil)
end end
+12 -3
View File
@@ -129,6 +129,15 @@ class WikiController < ApplicationController
# don't keep previous comment # don't keep previous comment
@content.comments = nil @content.comments = nil
if !@page.new_record? && params[:content].present? && @content.text == params[:content][:text]
attachments = Attachment.attach_files(@page, params[:attachments])
render_attachment_warning_if_needed(@page)
# don't save content if text wasn't changed
@page.save
redirect_to :action => 'show', :project_id => @project, :id => @page.title
return
end
@content.comments = params[:content][:comments] @content.comments = params[:content][:comments]
@text = params[:content][:text] @text = params[:content][:text]
if params[:section].present? && Redmine::WikiFormatting.supports_section_edit? if params[:section].present? && Redmine::WikiFormatting.supports_section_edit?
@@ -140,8 +149,8 @@ class WikiController < ApplicationController
@content.text = @text @content.text = @text
end end
@content.author = User.current @content.author = User.current
@page.content = @content
if @page.save_with_content if @page.save
attachments = Attachment.attach_files(@page, params[:attachments]) attachments = Attachment.attach_files(@page, params[:attachments])
render_attachment_warning_if_needed(@page) render_attachment_warning_if_needed(@page)
call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page}) call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page})
@@ -230,7 +239,7 @@ class WikiController < ApplicationController
# Export wiki to a single pdf or html file # Export wiki to a single pdf or html file
def export def export
@pages = @wiki.pages.all(:order => 'title', :include => [:content, :attachments]) @pages = @wiki.pages.all(:order => 'title', :include => [:content, :attachments], :limit => 75)
respond_to do |format| respond_to do |format|
format.html { format.html {
export = render_to_string :action => 'export_multiple', :layout => false export = render_to_string :action => 'export_multiple', :layout => false
+1 -7
View File
@@ -130,13 +130,7 @@ class CustomField < ActiveRecord::Base
possible_values_options = possible_values_options(customized) possible_values_options = possible_values_options(customized)
if possible_values_options.present? if possible_values_options.present?
keyword = keyword.to_s.downcase keyword = keyword.to_s.downcase
if v = possible_values_options.detect {|text, id| text.downcase == keyword} possible_values_options.detect {|text, id| text.downcase == keyword}.try(:last)
if v.is_a?(Array)
v.last
else
v
end
end
else else
keyword keyword
end end
+3 -21
View File
@@ -124,7 +124,6 @@ class MailHandler < ActionMailer::Base
def dispatch def dispatch
headers = [email.in_reply_to, email.references].flatten.compact headers = [email.in_reply_to, email.references].flatten.compact
subject = email.subject.to_s
if headers.detect {|h| h.to_s =~ MESSAGE_ID_RE} if headers.detect {|h| h.to_s =~ MESSAGE_ID_RE}
klass, object_id = $1, $2.to_i klass, object_id = $1, $2.to_i
method_name = "receive_#{klass}_reply" method_name = "receive_#{klass}_reply"
@@ -133,9 +132,9 @@ class MailHandler < ActionMailer::Base
else else
# ignoring it # ignoring it
end end
elsif m = subject.match(ISSUE_REPLY_SUBJECT_RE) elsif m = email.subject.match(ISSUE_REPLY_SUBJECT_RE)
receive_issue_reply(m[1].to_i) receive_issue_reply(m[1].to_i)
elsif m = subject.match(MESSAGE_REPLY_SUBJECT_RE) elsif m = email.subject.match(MESSAGE_REPLY_SUBJECT_RE)
receive_message_reply(m[1].to_i) receive_message_reply(m[1].to_i)
else else
dispatch_to_default dispatch_to_default
@@ -245,26 +244,9 @@ class MailHandler < ActionMailer::Base
def add_attachments(obj) def add_attachments(obj)
if email.attachments && email.attachments.any? if email.attachments && email.attachments.any?
email.attachments.each do |attachment| email.attachments.each do |attachment|
filename = attachment.filename
unless filename.respond_to?(:encoding)
# try to reencode to utf8 manually with ruby1.8
h = attachment.header['Content-Disposition']
unless h.nil?
begin
if m = h.value.match(/filename\*[0-9\*]*=([^=']+)'/)
filename = Redmine::CodesetUtil.to_utf8(filename, m[1])
elsif m = h.value.match(/filename=.*=\?([^\?]+)\?[BbQq]\?/)
# http://tools.ietf.org/html/rfc2047#section-4
filename = Redmine::CodesetUtil.to_utf8(filename, m[1])
end
rescue
# nop
end
end
end
obj.attachments << Attachment.create(:container => obj, obj.attachments << Attachment.create(:container => obj,
:file => attachment.decoded, :file => attachment.decoded,
:filename => filename, :filename => attachment.filename,
:author => user, :author => user,
:content_type => attachment.mime_type) :content_type => attachment.mime_type)
end end
-4
View File
@@ -427,9 +427,5 @@ class Repository < ActiveRecord::Base
connection.delete("DELETE FROM #{ci} WHERE #{ci}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})") connection.delete("DELETE FROM #{ci} WHERE #{ci}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
connection.delete("DELETE FROM #{cp} WHERE #{cp}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})") connection.delete("DELETE FROM #{cp} WHERE #{cp}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
connection.delete("DELETE FROM #{cs} WHERE #{cs}.repository_id = #{id}") connection.delete("DELETE FROM #{cs} WHERE #{cs}.repository_id = #{id}")
clear_extra_info_of_changesets
end
def clear_extra_info_of_changesets
end end
end end
-11
View File
@@ -255,15 +255,4 @@ class Repository::Git < Repository
:order => 'committed_on DESC' :order => 'committed_on DESC'
) )
end end
def clear_extra_info_of_changesets
return if extra_info.nil?
v = extra_info["extra_report_last_commit"]
write_attribute(:extra_info, nil)
h = {}
h["extra_report_last_commit"] = v
merge_extra_info(h)
self.save
end
private :clear_extra_info_of_changesets
end end
-15
View File
@@ -172,21 +172,6 @@ class WikiPage < ActiveRecord::Base
self.parent = parent_page self.parent = parent_page
end end
# Saves the page and its content if text was changed
def save_with_content
ret = nil
transaction do
if new_record?
# Rails automatically saves associated content
ret = save
else
ret = save && (content.text_changed? ? content.save : true)
end
raise ActiveRecord::Rollback unless ret
end
ret
end
protected protected
def validate_parent_title def validate_parent_title
+1 -7
View File
@@ -1,8 +1,2 @@
$("#journal-<%= @journal.id %>-notes").hide(); $("#journal-<%= @journal.id %>-notes").hide();
$("#journal-<%= @journal.id %>-notes").after('<%= escape_javascript(render :partial => 'notes_form') %>');
if ($("form#journal-<%= @journal.id %>-form").length > 0) {
// journal edit form already loaded
$("#journal-<%= @journal.id %>-form").show();
} else {
$("#journal-<%= @journal.id %>-notes").after('<%= escape_javascript(render :partial => 'notes_form') %>');
}
@@ -14,7 +14,7 @@
<tr class="<%= cycle 'odd', 'even' %>"> <tr class="<%= cycle 'odd', 'even' %>">
<td> <td>
<%= link_to repository.identifier, <%= link_to repository.identifier,
{:controller => 'repositories', :action => 'show',:id => @project, :repository_id => repository.identifier_param} if repository.identifier.present? %> {:controller => 'repositories', :action => 'show',:id => @project, :repository_id => repository.identifier_param} if repository.identifier_param.present? %>
</td> </td>
<td align="center"><%= checked_image repository.is_default? %></td> <td align="center"><%= checked_image repository.is_default? %></td>
<td><%=h repository.scm_name %></td> <td><%=h repository.scm_name %></td>
+50 -50
View File
@@ -49,7 +49,7 @@ nl:
one: "ongeveer 1 uur" one: "ongeveer 1 uur"
other: "ongeveer %{count} uren" other: "ongeveer %{count} uren"
x_hours: x_hours:
one: "1 uur" one: "1 hour"
other: "%{count} hours" other: "%{count} hours"
x_days: x_days:
one: "1 dag" one: "1 dag"
@@ -990,58 +990,58 @@ nl:
description_all_columns: Alle kolommen description_all_columns: Alle kolommen
button_export: Exporteren button_export: Exporteren
label_export_options: "%{export_format} export opties" label_export_options: "%{export_format} export opties"
error_attachment_too_big: Dit bestand kan niet worden geupload omdat het de maximaal toegestane grootte overschrijd (%{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: "Opslaan gefaald voor %{count} tijdsnotatie(s) van %{total} geselecteerde: %{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 incidenten zero: 0 issue
one: 1 incidenten one: 1 issue
other: "%{count} incidenten" other: "%{count} issues"
label_repository_new: Nieuw repository label_repository_new: New repository
field_repository_is_default: Hoofd repository field_repository_is_default: Main repository
label_copy_attachments: Copieer bijlage(n) label_copy_attachments: Copy attachments
label_item_position: "%{position}/%{count}" label_item_position: "%{position}/%{count}"
label_completed_versions: Versies compleet label_completed_versions: Completed versions
field_multiple: Meerdere waardes field_multiple: Multiple values
setting_commit_cross_project_ref: Sta toe om incidenten van alle projecten te refereren en oplossen setting_commit_cross_project_ref: Allow issues of all the other projects to be referenced and fixed
text_issue_conflict_resolution_add_notes: Voeg mijn notities toe en annuleer andere wijzigingen text_issue_conflict_resolution_add_notes: Add my notes and discard my other changes
text_issue_conflict_resolution_overwrite: Voeg mijn wijzigingen alsnog toe (voorgaande notities worden bewaard, maar sommige kunnen overschreden worden) text_issue_conflict_resolution_overwrite: Apply my changes anyway (previous notes will be kept but some changes may be overwritten)
notice_issue_update_conflict: Dit incident is reeds geupdate door een andere gebruiker terwijl jij bezig was notice_issue_update_conflict: The issue has been updated by an other user while you were editing it.
text_issue_conflict_resolution_cancel: Annuleer mijn wijzigingen en geef pagina opnieuw weer %{link} text_issue_conflict_resolution_cancel: Discard all my changes and redisplay %{link}
permission_manage_related_issues: Beheer gerelateerde incidenten permission_manage_related_issues: Manage related issues
field_auth_source_ldap_filter: LDAP filter field_auth_source_ldap_filter: LDAP filter
label_search_for_watchers: Zoek om monitoorders toe te voegen label_search_for_watchers: Search for watchers to add
notice_account_deleted: Uw account is permanent verwijderd notice_account_deleted: Your account has been permanently deleted.
setting_unsubscribe: Sta gebruikers toe hun eigen account te verwijderen setting_unsubscribe: Allow users to delete their own account
button_delete_my_account: Verwijder mijn account button_delete_my_account: Delete my account
text_account_destroy_confirmation: |- text_account_destroy_confirmation: |-
Weet u zeker dat u door wilt gaan? Are you sure you want to proceed?
Uw account wordt permanent verwijderd zonder mogelijkheid deze te heractiveren. Your account will be permanently deleted, with no way to reactivate it.
error_session_expired: Uw sessie is verlopen. U dient opnieuw in te loggen. error_session_expired: Your session has expired. Please login again.
text_session_expiration_settings: "Waarschuwing: door deze instelling te wijzigen kan sessies laten verlopen inclusief de uwe" text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
setting_session_lifetime: Maximale sessieduur setting_session_lifetime: Session maximum lifetime
setting_session_timeout: Sessie inactiviteit timeout setting_session_timeout: Session inactivity timeout
label_session_expiration: Sessie verlopen label_session_expiration: Session expiration
permission_close_project: Sluit / heropen project permission_close_project: Close / reopen the project
label_show_closed_projects: Gesloten projecten weergeven label_show_closed_projects: View closed projects
button_close: Sluiten button_close: Close
button_reopen: Heropen button_reopen: Reopen
project_status_active: actief project_status_active: active
project_status_closed: gesloten project_status_closed: closed
project_status_archived: gearchiveerd project_status_archived: archived
text_project_closed: Dit project is gesloten en op alleen-lezen text_project_closed: This project is closed and read-only.
notice_user_successful_create: Gebruiker %{id} aangemaakt. notice_user_successful_create: User %{id} created.
field_core_fields: Standaard verleden field_core_fields: Standard fields
field_timeout: Timeout (in seconds) field_timeout: Timeout (in seconds)
setting_thumbnails_enabled: Geef bijlage miniaturen weer setting_thumbnails_enabled: Display attachment thumbnails
setting_thumbnails_size: Grootte miniaturen (in pixels) setting_thumbnails_size: Thumbnails size (in pixels)
label_status_transitions: Status transitie label_status_transitions: Status transitions
label_fields_permissions: Permissie velden label_fields_permissions: Fields permissions
label_readonly: Alleen-lezen label_readonly: Read-only
label_required: Verplicht label_required: Required
text_repository_identifier_info: 'Alleen kleine letter (a-z), cijfers, streepjes en liggende streepjes zijn toegestaan.<br />Eenmaal opgeslagen kan de identifier niet worden gewijzigd.' text_repository_identifier_info: 'Alleen kleine letter (a-z), cijfers, streepjes en liggende streepjes zijn toegestaan.<br />Eenmaal opgeslagen kan de identifier niet worden gewijzigd.'
field_board_parent: Hoofd forum field_board_parent: Parent forum
label_attribute_of_project: Project %{name} label_attribute_of_project: Project's %{name}
label_attribute_of_author: Auteur(s) %{name} label_attribute_of_author: Author's %{name}
label_attribute_of_assigned_to: Toegewezen %{name} label_attribute_of_assigned_to: Assignee's %{name}
label_attribute_of_fixed_version: Target versions %{name} label_attribute_of_fixed_version: Target version's %{name}
label_copy_subtasks: Kopieer subtaken label_copy_subtasks: Copy subtasks
+35 -35
View File
@@ -971,64 +971,64 @@
setting_issue_group_assignment: Tillat tildeling av saker til grupper setting_issue_group_assignment: Tillat tildeling av saker til grupper
label_diff: diff label_diff: diff
description_query_sort_criteria_direction: Sorteringsretning description_query_sort_criteria_direction: Sort direction
description_project_scope: Search scope description_project_scope: Search scope
description_filter: Filter description_filter: Filter
description_user_mail_notification: Mail notification settings description_user_mail_notification: Mail notification settings
description_date_from: Oppgi startdato description_date_from: Enter start date
description_message_content: Meldingsinnhold description_message_content: Message content
description_available_columns: Tilgjengelige kolonner description_available_columns: Available Columns
description_date_range_interval: Velg datointervall ved å spesifisere start- og sluttdato 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: Søkefelt description_search: Searchfield
description_notes: Notes description_notes: Notes
description_date_range_list: Choose range from list description_date_range_list: Choose range from list
description_choose_project: Prosjekter description_choose_project: Projects
description_date_to: Oppgi sluttdato description_date_to: Enter end date
description_query_sort_criteria_attribute: Sort attribute description_query_sort_criteria_attribute: Sort attribute
description_wiki_subpages_reassign: Velg ny overordnet side description_wiki_subpages_reassign: Choose new parent page
description_selected_columns: Valgte kolonner description_selected_columns: Selected Columns
label_parent_revision: Overordnet label_parent_revision: Parent
label_child_revision: Underordnet label_child_revision: Child
error_scm_annotate_big_text_file: The entry cannot be annotated, as it exceeds the maximum text file size. 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: Bruk dagens dato som startdato for nye saker setting_default_issue_start_date_to_creation_date: Use current date as start date for new issues
button_edit_section: Rediger denne seksjonen button_edit_section: Edit this section
setting_repositories_encodings: Attachments and repositories encodings setting_repositories_encodings: Attachments and repositories encodings
description_all_columns: Alle kolonnene description_all_columns: All Columns
button_export: Eksporter button_export: Export
label_export_options: "%{export_format} eksportvalg" label_export_options: "%{export_format} export options"
error_attachment_too_big: Filen overstiger maksimum filstørrelse (%{max_size}) og kan derfor ikke lastes opp 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 sak zero: 0 sak
one: 1 sak one: 1 sak
other: "%{count} saker" other: "%{count} saker"
label_repository_new: Nytt depot label_repository_new: New repository
field_repository_is_default: Hoveddepot field_repository_is_default: Main repository
label_copy_attachments: Kopier vedlegg label_copy_attachments: Copy attachments
label_item_position: "%{position}/%{count}" label_item_position: "%{position}/%{count}"
label_completed_versions: Completed versions label_completed_versions: Completed versions
text_project_identifier_info: Kun små bokstaver (a-z), tall, bindestrek (-) og "underscore" (_) er tillatt.<br />Etter lagring er det ikke mulig å gjøre endringer. 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: Flere verdier field_multiple: Multiple values
setting_commit_cross_project_ref: Allow issues of all the other projects to be referenced and fixed setting_commit_cross_project_ref: Allow issues of all the other projects to be referenced and fixed
text_issue_conflict_resolution_add_notes: Add my notes and discard my other changes text_issue_conflict_resolution_add_notes: Add my notes and discard my other changes
text_issue_conflict_resolution_overwrite: Apply my changes anyway (previous notes will be kept but some changes may be overwritten) text_issue_conflict_resolution_overwrite: Apply my changes anyway (previous notes will be kept but some changes may be overwritten)
notice_issue_update_conflict: Saken ble oppdatert av en annen bruker mens du redigerte den. notice_issue_update_conflict: The issue has been updated by an other user while you were editing it.
text_issue_conflict_resolution_cancel: Forkast alle endringen mine og vis %{link} på nytt text_issue_conflict_resolution_cancel: Discard all my changes and redisplay %{link}
permission_manage_related_issues: Manage related issues permission_manage_related_issues: Manage related issues
field_auth_source_ldap_filter: LDAP filter field_auth_source_ldap_filter: LDAP filter
label_search_for_watchers: Search for watchers to add label_search_for_watchers: Search for watchers to add
notice_account_deleted: Din konto er ugjenkallelig slettet. notice_account_deleted: Your account has been permanently deleted.
setting_unsubscribe: Tillat brukere å slette sin egen konto setting_unsubscribe: Allow users to delete their own account
button_delete_my_account: Slett kontoen min button_delete_my_account: Delete my account
text_account_destroy_confirmation: |- text_account_destroy_confirmation: |-
Er du sikker på at du ønsker å fortsette? Are you sure you want to proceed?
Kontoen din vil bli ugjenkallelig slettet uten mulighet for å reaktiveres igjen. Your account will be permanently deleted, with no way to reactivate it.
error_session_expired: Økten har gått ut på tid. Vennligst logg på igjen. error_session_expired: Your session has expired. Please login again.
text_session_expiration_settings: "Advarsel: ved å endre disse innstillingene kan aktive økter gå ut på tid, inkludert din egen." text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
setting_session_lifetime: Øktenes makslengde setting_session_lifetime: Session maximum lifetime
setting_session_timeout: Økten er avsluttet på grunn av inaktivitet setting_session_timeout: Session inactivity timeout
label_session_expiration: Økten er avsluttet label_session_expiration: Session expiration
permission_close_project: Close / reopen the project permission_close_project: Close / reopen the project
label_show_closed_projects: View closed projects label_show_closed_projects: View closed projects
button_close: Close button_close: Close
+11 -11
View File
@@ -1121,7 +1121,7 @@ ru:
button_export: Экспорт button_export: Экспорт
label_export_options: "%{export_format} параметры экспорта" label_export_options: "%{export_format} параметры экспорта"
error_attachment_too_big: Этот файл нельзя загрузить из-за превышения максимального размера файла (%{max_size}) error_attachment_too_big: Этот файл нельзя загрузить из-за превышения максимального размера файла (%{max_size})
notice_failed_to_save_time_entries: "Невозможно сохранить %{count} затраченное время для %{total} выбранных: %{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 Задач
one: 1 Задача one: 1 Задача
@@ -1147,11 +1147,11 @@ ru:
setting_unsubscribe: "Разрешить пользователям удалять свои учетные записи" setting_unsubscribe: "Разрешить пользователям удалять свои учетные записи"
button_delete_my_account: "Удалить мою учетную запись" button_delete_my_account: "Удалить мою учетную запись"
text_account_destroy_confirmation: "Ваша учетная запись будет полностью удалена без возможности восстановления.\nВы уверены, что хотите продолжить?" text_account_destroy_confirmation: "Ваша учетная запись будет полностью удалена без возможности восстановления.\nВы уверены, что хотите продолжить?"
error_session_expired: Срок вашей сессии истек. Пожалуйста войдите еще раз error_session_expired: Your session has expired. Please login again.
text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours." text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
setting_session_lifetime: Максимальная продолжительность сессии setting_session_lifetime: Session maximum lifetime
setting_session_timeout: Таймут сессии setting_session_timeout: Session inactivity timeout
label_session_expiration: Срок истечения сессии label_session_expiration: Session expiration
permission_close_project: Закрывать / открывать проекты permission_close_project: Закрывать / открывать проекты
label_show_closed_projects: Просматривать закрытые проекты label_show_closed_projects: Просматривать закрытые проекты
button_close: Сделать закрытым button_close: Сделать закрытым
@@ -1162,17 +1162,17 @@ ru:
text_project_closed: Проект закрыт и находиться в режиме только для чтения. text_project_closed: Проект закрыт и находиться в режиме только для чтения.
notice_user_successful_create: Пользователь %{id} создан. notice_user_successful_create: Пользователь %{id} создан.
field_core_fields: Стандартные поля field_core_fields: Стандартные поля
field_timeout: Таймаут (в секундах) field_timeout: Timeout (in seconds)
setting_thumbnails_enabled: Отображать превью для приложений setting_thumbnails_enabled: Display attachment thumbnails
setting_thumbnails_size: Размер первью (в пикселях) setting_thumbnails_size: Thumbnails size (in pixels)
label_status_transitions: Статус-переходы label_status_transitions: Статус-переходы
label_fields_permissions: Права на изменения полей label_fields_permissions: Права на изменения полей
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: Родительский форум field_board_parent: Родительский форум
label_attribute_of_project: Проект %{name} label_attribute_of_project: Project's %{name}
label_attribute_of_author: Имя автора %{name} label_attribute_of_author: Имя автора %{name}
label_attribute_of_assigned_to: Назначена %{name} label_attribute_of_assigned_to: Assignee's %{name}
label_attribute_of_fixed_version: Версия %{name} label_attribute_of_fixed_version: Target version's %{name}
label_copy_subtasks: Копировать подзадачи label_copy_subtasks: Копировать подзадачи
-25
View File
@@ -4,31 +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/
== 2013-01-09 v2.1.6
* Upgrade to Rails 3.2.11
== 2012-12-18 v2.1.5
* Defect #12400: Validation fails when receiving an email with list custom fields
* Defect #12451: Macros.rb extract_macro_options should use lazy search
* Defect #12513: Grouping of issues by custom fields not correct in PDF export
* Defect #12566: Issue history notes previews are broken
* Defect #12568: Clicking "edit" on a journal multiple times shows multiple forms
* Patch #12605: Norwegian translation for 1.4-stable update
* Patch #12614: Dutch translation
* Patch #12615: Russian translation
== 2012-11-24 v2.1.4
* Defect #12274: Wiki export from Index by title is truncated
* Defect #12298: Right-click context menu unable to batch/bulk update (IE8)
* Defect #12332: Repository identifier does not display on Project/Settings/Repositories
* Defect #12396: Error when receiving an email without subject header
* Defect #12399: Non ASCII attachment filename encoding broken (MOJIBAKE) in receiving mail on Ruby 1.8
* Defect #12409: Git: changesets aren't read after clear_changesets call
* Defect #12431: Project.rebuild! sorts root projects by id instead of name
== 2012-11-17 v2.1.3 == 2012-11-17 v2.1.3
* Defect #12050: :export links to repository files lead to a 404 error * Defect #12050: :export links to repository files lead to a 404 error
@@ -186,7 +186,7 @@ module CollectiveIdea #:nodoc:
end end
# Find root node(s) # Find root node(s)
root_nodes = where("#{quoted_parent_column_name} IS NULL").order(acts_as_nested_set_options[:order]).each do |root_node| root_nodes = where("#{quoted_parent_column_name} IS NULL").order("#{quoted_left_column_name}, #{quoted_right_column_name}, id").each do |root_node|
# setup index for this scope # setup index for this scope
indices[scope.call(root_node)] ||= 0 indices[scope.call(root_node)] ||= 0
set_left_and_rights.call(root_node) set_left_and_rights.call(root_node)
+1 -1
View File
@@ -422,7 +422,7 @@ module Redmine
if query.grouped? && if query.grouped? &&
(group = query.group_by_column.value(issue)) != previous_group (group = query.group_by_column.value(issue)) != previous_group
pdf.SetFontStyle('B',10) pdf.SetFontStyle('B',10)
group_label = group.blank? ? 'None' : group.to_s.dup group_label = group.blank? ? 'None' : group.to_s
group_label << " (#{query.issue_count_by_group[group]})" group_label << " (#{query.issue_count_by_group[group]})"
pdf.Bookmark group_label, 0, -1 pdf.Bookmark group_label, 0, -1
pdf.RDMCell(table_width + col_id_width, row_height * 2, group_label, 1, 1, 'L') pdf.RDMCell(table_width + col_id_width, row_height * 2, group_label, 1, 1, 'L')
+1 -1
View File
@@ -4,7 +4,7 @@ module Redmine
module VERSION #:nodoc: module VERSION #:nodoc:
MAJOR = 2 MAJOR = 2
MINOR = 1 MINOR = 1
TINY = 6 TINY = 3
# Branch values: # Branch values:
# * official release: nil # * official release: nil
+1 -1
View File
@@ -48,7 +48,7 @@ module Redmine
def extract_macro_options(args, *keys) def extract_macro_options(args, *keys)
options = {} options = {}
while args.last.to_s.strip =~ %r{^(.+?)\=(.+)$} && keys.include?($1.downcase.to_sym) while args.last.to_s.strip =~ %r{^(.+)\=(.+)$} && keys.include?($1.downcase.to_sym)
options[$1.downcase.to_sym] = $2 options[$1.downcase.to_sym] = $2
args.pop args.pop
end end
+1 -1
View File
@@ -25,7 +25,7 @@ function contextMenuClick(event) {
} }
contextMenuHide(); contextMenuHide();
if (target.is('a') || target.is('img')) { return; } if (target.is('a') || target.is('img')) { return; }
if (event.which == 1 || (navigator.appVersion.match(/\bMSIE\b/))) { if (event.which == 1 /*TODO || (navigator.appVersion.match(/\bMSIE\b/))*/) {
var tr = target.parents('tr').first(); var tr = target.parents('tr').first();
if (tr.length && tr.hasClass('hascontextmenu')) { if (tr.length && tr.hasClass('hascontextmenu')) {
// a row was clicked, check if the click was on checkbox // a row was clicked, check if the click was on checkbox
@@ -1,26 +0,0 @@
Date: Tue, 20 Nov 2012 23:08:25 +0900
Message-ID: <CANBr5-UZM=Odz4U3Q6vHd_9cd2tCT-_P9xDd=hRJ0aoMNTWXbw@mail.gmail.com>
Subject: test
From: John Smith <JSmith@somenet.foo>
To: redmine@somenet.foo
Content-Type: multipart/mixed; boundary=14dae93a13bf76ca5d04ceedc458
--14dae93a13bf76ca5d04ceedc458
Content-Type: text/plain; charset=ISO-8859-1
test
--14dae93a13bf76ca5d04ceedc458
Content-Type: text/plain; charset=US-ASCII;
name="=?ISO-8859-1?B?xOTW9tz8xOTW9tz8xOTW9tz8xOTW9tz8xOTW9tw=?=
=?ISO-8859-1?B?/MTk1vbc/MTk1vbc/MTk1vbc/MTk1vbc/MTk1vbc?=
=?ISO-8859-1?B?/MTk1vbc/C50eHQ=?="
Content-Disposition: attachment;
filename="=?ISO-8859-1?B?xOTW9tz8xOTW9tz8xOTW9tz8xOTW9tz8xOTW9tw=?=
=?ISO-8859-1?B?/MTk1vbc/MTk1vbc/MTk1vbc/MTk1vbc/MTk1vbc?=
=?ISO-8859-1?B?/MTk1vbc/C50eHQ=?="
Content-Transfer-Encoding: base64
X-Attachment-Id: f_h9r3mcjz0
dGVzdAo=
--14dae93a13bf76ca5d04ceedc458--
-20
View File
@@ -1,20 +0,0 @@
Date: Mon, 19 Nov 2012 10:17:45 +0900
Message-ID: <CANBr5-U6cXMfLek5QiB2ZrBPR3vTThn9_Upvdkf3Dkod664+Xw@mail.gmail.com>
Subject: test
From: John Smith <JSmith@somenet.foo>
To: redmine@somenet.foo
Content-Type: multipart/mixed; boundary=bcaec54ee4ea84f77904cecee22e
--bcaec54ee4ea84f77904cecee22e
Content-Type: text/plain; charset=ISO-8859-1
test
--bcaec54ee4ea84f77904cecee22e
Content-Type: text/plain; charset=US-ASCII; name="=?ISO-2022-JP?B?GyRCJUYlOSVIGyhCLnR4dA==?="
Content-Disposition: attachment; filename="=?ISO-2022-JP?B?GyRCJUYlOSVIGyhCLnR4dA==?="
Content-Transfer-Encoding: base64
X-Attachment-Id: f_h9owndpv0
dGVzdAo=
--bcaec54ee4ea84f77904cecee22e--
-10
View File
@@ -1,10 +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>
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
@@ -1,34 +0,0 @@
Message-ID: <50AB9546.7020800@gmail.com>
Date: Tue, 20 Nov 2012 23:35:50 +0900
From: John Smith <JSmith@somenet.foo>
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.17) Gecko/20110428 Fedora/3.1.10-1.fc13 Thunderbird/3.1.10
MIME-Version: 1.0
To: redmine@somenet.foo
Subject: test
Content-Type: multipart/mixed;
boundary="------------050902080306030406090208"
This is a multi-part message in MIME format.
--------------050902080306030406090208
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
test
--------------050902080306030406090208
Content-Type: image/png;
name="=?ISO-8859-1?Q?=C4=E4=D6=F6=DC=FC=C4=E4=D6=F6=DC=FC=C4=E4=D6=F6=DC=FC=C4=E4?=
=?ISO-8859-1?Q?=D6=F6=DC=FC=C4=E4=D6=F6=DC=FC=C4=E4=D6=F6=DC=FC=C4=E4=D6?=
=?ISO-8859-1?Q?=F6=DC=FC=C4=E4=D6=F6=DC=FC=C4=E4=D6=F6=DC=FC=C4=E4=D6=F6?=
=?ISO-8859-1?Q?=DC=FC=C4=E4=D6=F6=DC=FC=2Epng?="
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename*0*=ISO-8859-1''%C4%E4%D6%F6%DC%FC%C4%E4%D6%F6%DC%FC%C4%E4%D6%F6;
filename*1*=%DC%FC%C4%E4%D6%F6%DC%FC%C4%E4%D6%F6%DC%FC%C4%E4%D6%F6%DC%FC;
filename*2*=%C4%E4%D6%F6%DC%FC%C4%E4%D6%F6%DC%FC%C4%E4%D6%F6%DC%FC%C4%E4;
filename*3*=%D6%F6%DC%FC%C4%E4%D6%F6%DC%FC%2E%70%6E%67
iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAAXNSR0IArs4c6QAAAAlwSFlz
AAALEwAACxMBAJqcGAAAAAd0SU1FB9wLFA4fJhRKIUQAAAAUSURBVAjXY/z//z8DEmBiQAWk
8gHq9gMHP8uZWAAAAABJRU5ErkJggg==
--------------050902080306030406090208--
@@ -1,26 +0,0 @@
Message-ID: <50AA00C6.4070108@gmail.com>
Date: Mon, 19 Nov 2012 18:49:58 +0900
From: John Smith <JSmith@somenet.foo>
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.15) Gecko/20101027 Fedora/3.0.10-1.fc12 Lightning/1.0b1 Thunderbird/3.0.10
MIME-Version: 1.0
To: redmine@somenet.foo
Subject: test
Content-Type: multipart/mixed;
boundary="------------030104060902010800050907"
This is a multi-part message in MIME format.
--------------030104060902010800050907
Content-Type: text/plain; charset=ISO-2022-JP
Content-Transfer-Encoding: 7bit
test
--------------030104060902010800050907
Content-Type: text/plain;
name="=?ISO-2022-JP?B?GyRCJUYlOSVIGyhCLnR4dA==?="
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename*=ISO-2022-JP''%1B%24%42%25%46%25%39%25%48%1B%28%42%2E%74%78%74
dGVzdAo=
--------------030104060902010800050907--
@@ -39,4 +39,3 @@ pulvinar dui, a gravida orci mi eget odio. Nunc a lacus.
category: Stock management category: Stock management
searchable field: Value for a custom field searchable field: Value for a custom field
Database: postgresql
-5
View File
@@ -212,9 +212,4 @@ class CustomFieldTest < ActiveSupport::TestCase
assert_nil CustomField.new(:field_format => 'text').value_class assert_nil CustomField.new(:field_format => 'text').value_class
assert_nil CustomField.new.value_class assert_nil CustomField.new.value_class
end end
def test_value_from_keyword_for_list_custom_field
field = CustomField.find(1)
assert_equal 'PostgreSQL', field.value_from_keyword('postgresql', Issue.find(1))
end
end end
@@ -100,25 +100,6 @@ class Redmine::WikiFormatting::MacrosTest < ActionView::TestCase
assert_equal '<p>Hello world! Object: Issue, Called with no argument and no block of text.</p>', textilizable(text, :object => Issue.find(1)) assert_equal '<p>Hello world! Object: Issue, Called with no argument and no block of text.</p>', textilizable(text, :object => Issue.find(1))
end end
def test_extract_macro_options_should_with_args
options = extract_macro_options(["arg1", "arg2"], :foo, :size)
assert_equal([["arg1", "arg2"], {}], options)
end
def test_extract_macro_options_should_with_options
options = extract_macro_options(["foo=bar", "size=2"], :foo, :size)
assert_equal([[], {:foo => "bar", :size => "2"}], options)
end
def test_extract_macro_options_should_with_args_and_options
options = extract_macro_options(["arg1", "arg2", "foo=bar", "size=2"], :foo, :size)
assert_equal([["arg1", "arg2"], {:foo => "bar", :size => "2"}], options)
end
def test_extract_macro_options_should_parse_options_lazily
options = extract_macro_options(["params=x=1&y=2"], :params)
assert_equal([[], {:params => "x=1&y=2"}], options)
end
def test_macro_exception_should_be_displayed def test_macro_exception_should_be_displayed
Redmine::WikiFormatting::Macros.macro :exception do |obj, args| Redmine::WikiFormatting::Macros.macro :exception do |obj, args|
+2 -85
View File
@@ -177,8 +177,8 @@ class MailHandlerTest < ActiveSupport::TestCase
assert !issue.new_record? assert !issue.new_record?
issue.reload issue.reload
assert_equal 'New ticket with custom field values', issue.subject assert_equal 'New ticket with custom field values', issue.subject
assert_equal 'PostgreSQL', issue.custom_field_value(1) assert_equal 'Value for a custom field',
assert_equal 'Value for a custom field', issue.custom_field_value(2) issue.custom_value_for(CustomField.find_by_name('Searchable field')).value
assert !issue.description.match(/^searchable field:/i) assert !issue.description.match(/^searchable field:/i)
end end
@@ -373,80 +373,6 @@ class MailHandlerTest < ActiveSupport::TestCase
assert_equal 'caaf384198bcbc9563ab5c058acd73cd', attachment.digest assert_equal 'caaf384198bcbc9563ab5c058acd73cd', attachment.digest
end end
def test_thunderbird_with_attachment_ja
issue = submit_email(
'thunderbird_with_attachment_ja.eml',
:issue => {:project => 'ecookbook'}
)
assert_kind_of Issue, issue
assert_equal 1, issue.attachments.size
ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt"
ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
attachment = issue.attachments.first
assert_equal ja, attachment.filename
assert_equal 5, attachment.filesize
assert File.exist?(attachment.diskfile)
assert_equal 5, File.size(attachment.diskfile)
assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest
end
def test_gmail_with_attachment_ja
issue = submit_email(
'gmail_with_attachment_ja.eml',
:issue => {:project => 'ecookbook'}
)
assert_kind_of Issue, issue
assert_equal 1, issue.attachments.size
ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt"
ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
attachment = issue.attachments.first
assert_equal ja, attachment.filename
assert_equal 5, attachment.filesize
assert File.exist?(attachment.diskfile)
assert_equal 5, File.size(attachment.diskfile)
assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest
end
def test_thunderbird_with_attachment_latin1
issue = submit_email(
'thunderbird_with_attachment_iso-8859-1.eml',
:issue => {:project => 'ecookbook'}
)
assert_kind_of Issue, issue
assert_equal 1, issue.attachments.size
u = ""
u.force_encoding('UTF-8') if u.respond_to?(:force_encoding)
u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc"
u1.force_encoding('UTF-8') if u1.respond_to?(:force_encoding)
11.times { u << u1 }
attachment = issue.attachments.first
assert_equal "#{u}.png", attachment.filename
assert_equal 130, attachment.filesize
assert File.exist?(attachment.diskfile)
assert_equal 130, File.size(attachment.diskfile)
assert_equal '4d80e667ac37dddfe05502530f152abb', attachment.digest
end
def test_gmail_with_attachment_latin1
issue = submit_email(
'gmail_with_attachment_iso-8859-1.eml',
:issue => {:project => 'ecookbook'}
)
assert_kind_of Issue, issue
assert_equal 1, issue.attachments.size
u = ""
u.force_encoding('UTF-8') if u.respond_to?(:force_encoding)
u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc"
u1.force_encoding('UTF-8') if u1.respond_to?(:force_encoding)
11.times { u << u1 }
attachment = issue.attachments.first
assert_equal "#{u}.txt", attachment.filename
assert_equal 5, attachment.filesize
assert File.exist?(attachment.diskfile)
assert_equal 5, File.size(attachment.diskfile)
assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest
end
def test_add_issue_with_iso_8859_1_subject def test_add_issue_with_iso_8859_1_subject
issue = submit_email( issue = submit_email(
'subject_as_iso-8859-1.eml', 'subject_as_iso-8859-1.eml',
@@ -467,15 +393,6 @@ class MailHandlerTest < ActiveSupport::TestCase
assert_equal ja, issue.subject assert_equal ja, issue.subject
end end
def test_add_issue_with_no_subject_header
issue = submit_email(
'no_subject_header.eml',
:issue => {:project => 'ecookbook'}
)
assert_kind_of Issue, issue
assert_equal '(no subject)', issue.subject
end
def test_add_issue_with_mixed_japanese_subject def test_add_issue_with_mixed_japanese_subject
issue = submit_email( issue = submit_email(
'subject_japanese_2.eml', 'subject_japanese_2.eml',
+6 -13
View File
@@ -28,17 +28,17 @@ class ProjectNestedSetTest < ActiveSupport::TestCase
@a2 = Project.create!(:name => 'A2', :identifier => 'projecta2') @a2 = Project.create!(:name => 'A2', :identifier => 'projecta2')
@a2.set_parent!(@a) @a2.set_parent!(@a)
@c = Project.create!(:name => 'C', :identifier => 'projectc')
@c1 = Project.create!(:name => 'C1', :identifier => 'projectc1')
@c1.set_parent!(@c)
@b = Project.create!(:name => 'B', :identifier => 'projectb') @b = Project.create!(:name => 'B', :identifier => 'projectb')
@b2 = Project.create!(:name => 'B2', :identifier => 'projectb2')
@b2.set_parent!(@b)
@b1 = Project.create!(:name => 'B1', :identifier => 'projectb1') @b1 = Project.create!(:name => 'B1', :identifier => 'projectb1')
@b1.set_parent!(@b) @b1.set_parent!(@b)
@b11 = Project.create!(:name => 'B11', :identifier => 'projectb11') @b11 = Project.create!(:name => 'B11', :identifier => 'projectb11')
@b11.set_parent!(@b1) @b11.set_parent!(@b1)
@b2 = Project.create!(:name => 'B2', :identifier => 'projectb2')
@b2.set_parent!(@b)
@c = Project.create!(:name => 'C', :identifier => 'projectc')
@c1 = Project.create!(:name => 'C1', :identifier => 'projectc1')
@c1.set_parent!(@c)
@a, @a1, @a2, @b, @b1, @b11, @b2, @c, @c1 = *(Project.all.sort_by(&:name)) @a, @a1, @a2, @b, @b1, @b11, @b2, @c, @c1 = *(Project.all.sort_by(&:name))
end end
@@ -47,13 +47,6 @@ class ProjectNestedSetTest < ActiveSupport::TestCase
assert_valid_nested_set assert_valid_nested_set
end end
def test_rebuild_should_build_valid_tree
Project.update_all "lft = NULL, rgt = NULL"
Project.rebuild!
assert_valid_nested_set
end
def test_moving_a_child_to_a_different_parent_should_keep_valid_tree def test_moving_a_child_to_a_different_parent_should_keep_valid_tree
assert_no_difference 'Project.count' do assert_no_difference 'Project.count' do
Project.find_by_name('B1').set_parent!(Project.find_by_name('A2')) Project.find_by_name('B1').set_parent!(Project.find_by_name('A2'))
-34
View File
@@ -217,40 +217,6 @@ class RepositoryGitTest < ActiveSupport::TestCase
assert_equal h1, h2 assert_equal h1, h2
end end
def test_keep_extra_report_last_commit_in_clear_changesets
assert_nil @repository.extra_info
h = {}
h["extra_report_last_commit"] = "1"
@repository.merge_extra_info(h)
@repository.save
@project.reload
assert_equal 0, @repository.changesets.count
@repository.fetch_changesets
@project.reload
assert_equal NUM_REV, @repository.changesets.count
@repository.send(:clear_changesets)
assert_equal 1, @repository.extra_info.size
assert_equal "1", @repository.extra_info["extra_report_last_commit"]
end
def test_refetch_after_clear_changesets
assert_nil @repository.extra_info
assert_equal 0, @repository.changesets.count
@repository.fetch_changesets
@project.reload
assert_equal NUM_REV, @repository.changesets.count
@repository.send(:clear_changesets)
@project.reload
assert_equal 0, @repository.changesets.count
@repository.fetch_changesets
@project.reload
assert_equal NUM_REV, @repository.changesets.count
end
def test_parents def test_parents
assert_equal 0, @repository.changesets.count assert_equal 0, @repository.changesets.count
@repository.fetch_changesets @repository.fetch_changesets