Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2a6e1eeb7 | ||
|
|
2f9c2e6bd3 | ||
|
|
2df7c0ff3a | ||
|
|
f5d5077d2b | ||
|
|
94a1eb21a4 | ||
|
|
1f80a4b0d9 | ||
|
|
55220950d2 | ||
|
|
daea57a37c | ||
|
|
fe61739108 | ||
|
|
a4cd96e8b0 | ||
|
|
804302ce61 | ||
|
|
89ecbe9cdc | ||
|
|
aac3e1e51c | ||
|
|
595fef0d68 | ||
|
|
65a6e3985e | ||
|
|
f27a0eca5b | ||
|
|
2d34ab9235 | ||
|
|
03bff3308f | ||
|
|
006a1b4fd7 | ||
|
|
9095874a07 | ||
|
|
8ecfd1dcf8 | ||
|
|
35584bc53a | ||
|
|
21a16e0958 | ||
|
|
76d24e44bf | ||
|
|
efbdef9357 | ||
|
|
5eab4af70d | ||
|
|
96b2e00015 | ||
|
|
9939fbeef6 | ||
|
|
b369f82d15 | ||
|
|
0ad5dfaba0 | ||
|
|
d7d18689b7 |
@@ -238,7 +238,7 @@ class AccountController < ApplicationController
|
|||||||
def onthefly_creation_failed(user, auth_source_options = { })
|
def onthefly_creation_failed(user, auth_source_options = { })
|
||||||
@user = user
|
@user = user
|
||||||
session[:auth_source_registration] = auth_source_options unless auth_source_options.empty?
|
session[:auth_source_registration] = auth_source_options unless auth_source_options.empty?
|
||||||
render register_path
|
render :action => 'register'
|
||||||
end
|
end
|
||||||
|
|
||||||
def invalid_credentials
|
def invalid_credentials
|
||||||
|
|||||||
@@ -398,7 +398,7 @@ private
|
|||||||
end
|
end
|
||||||
|
|
||||||
@issue.project = @project
|
@issue.project = @project
|
||||||
@issue.author = User.current
|
@issue.author ||= User.current
|
||||||
# Tracker must be set before custom field values
|
# Tracker must be set before custom field values
|
||||||
@issue.tracker ||= @project.trackers.find((params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id] || :first)
|
@issue.tracker ||= @project.trackers.find((params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id] || :first)
|
||||||
if @issue.tracker.nil?
|
if @issue.tracker.nil?
|
||||||
|
|||||||
@@ -1029,6 +1029,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']
|
||||||
@@ -1095,8 +1100,14 @@ module ApplicationHelper
|
|||||||
unless @calendar_headers_tags_included
|
unless @calendar_headers_tags_included
|
||||||
@calendar_headers_tags_included = true
|
@calendar_headers_tags_included = true
|
||||||
content_for :header_tags do
|
content_for :header_tags do
|
||||||
|
start_of_week = Setting.start_of_week
|
||||||
|
start_of_week = l(:general_first_day_of_week, :default => '1') if start_of_week.blank?
|
||||||
|
# Redmine uses 1..7 (monday..sunday) in settings and locales
|
||||||
|
# JQuery uses 0..6 (sunday..saturday), 7 needs to be changed to 0
|
||||||
|
start_of_week = start_of_week.to_i % 7
|
||||||
|
|
||||||
tags = javascript_tag(
|
tags = javascript_tag(
|
||||||
"var datepickerOptions={dateFormat: 'yy-mm-dd', " +
|
"var datepickerOptions={dateFormat: 'yy-mm-dd', firstDay: #{start_of_week}, " +
|
||||||
"showOn: 'button', buttonImageOnly: true, buttonImage: '" +
|
"showOn: 'button', buttonImageOnly: true, buttonImage: '" +
|
||||||
path_to_image('/images/calendar.png') +
|
path_to_image('/images/calendar.png') +
|
||||||
"', showButtonPanel: true};")
|
"', showButtonPanel: true};")
|
||||||
|
|||||||
+26
-18
@@ -84,17 +84,21 @@ class Issue < ActiveRecord::Base
|
|||||||
# Returns a SQL conditions string used to find all issues visible by the specified user
|
# Returns a SQL conditions string used to find all issues visible by the specified user
|
||||||
def self.visible_condition(user, options={})
|
def self.visible_condition(user, options={})
|
||||||
Project.allowed_to_condition(user, :view_issues, options) do |role, user|
|
Project.allowed_to_condition(user, :view_issues, options) do |role, user|
|
||||||
case role.issues_visibility
|
if user.logged?
|
||||||
when 'all'
|
case role.issues_visibility
|
||||||
nil
|
when 'all'
|
||||||
when 'default'
|
nil
|
||||||
user_ids = [user.id] + user.groups.map(&:id)
|
when 'default'
|
||||||
"(#{table_name}.is_private = #{connection.quoted_false} OR #{table_name}.author_id = #{user.id} OR #{table_name}.assigned_to_id IN (#{user_ids.join(',')}))"
|
user_ids = [user.id] + user.groups.map(&:id)
|
||||||
when 'own'
|
"(#{table_name}.is_private = #{connection.quoted_false} OR #{table_name}.author_id = #{user.id} OR #{table_name}.assigned_to_id IN (#{user_ids.join(',')}))"
|
||||||
user_ids = [user.id] + user.groups.map(&:id)
|
when 'own'
|
||||||
"(#{table_name}.author_id = #{user.id} OR #{table_name}.assigned_to_id IN (#{user_ids.join(',')}))"
|
user_ids = [user.id] + user.groups.map(&:id)
|
||||||
|
"(#{table_name}.author_id = #{user.id} OR #{table_name}.assigned_to_id IN (#{user_ids.join(',')}))"
|
||||||
|
else
|
||||||
|
'1=0'
|
||||||
|
end
|
||||||
else
|
else
|
||||||
'1=0'
|
"(#{table_name}.is_private = #{connection.quoted_false})"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -102,15 +106,19 @@ class Issue < ActiveRecord::Base
|
|||||||
# Returns true if usr or current user is allowed to view the issue
|
# Returns true if usr or current user is allowed to view the issue
|
||||||
def visible?(usr=nil)
|
def visible?(usr=nil)
|
||||||
(usr || User.current).allowed_to?(:view_issues, self.project) do |role, user|
|
(usr || User.current).allowed_to?(:view_issues, self.project) do |role, user|
|
||||||
case role.issues_visibility
|
if user.logged?
|
||||||
when 'all'
|
case role.issues_visibility
|
||||||
true
|
when 'all'
|
||||||
when 'default'
|
true
|
||||||
!self.is_private? || self.author == user || user.is_or_belongs_to?(assigned_to)
|
when 'default'
|
||||||
when 'own'
|
!self.is_private? || (self.author == user || user.is_or_belongs_to?(assigned_to))
|
||||||
self.author == user || user.is_or_belongs_to?(assigned_to)
|
when 'own'
|
||||||
|
self.author == user || user.is_or_belongs_to?(assigned_to)
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
else
|
else
|
||||||
false
|
!self.is_private?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -133,6 +133,11 @@ class Role < ActiveRecord::Base
|
|||||||
self.builtin != 0
|
self.builtin != 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Return true if the role is the anonymous role
|
||||||
|
def anonymous?
|
||||||
|
builtin == 2
|
||||||
|
end
|
||||||
|
|
||||||
# Return true if the role is a project member role
|
# Return true if the role is a project member role
|
||||||
def member?
|
def member?
|
||||||
!self.builtin?
|
!self.builtin?
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class UserPreference < ActiveRecord::Base
|
|||||||
if attribute_present? attr_name
|
if attribute_present? attr_name
|
||||||
super
|
super
|
||||||
else
|
else
|
||||||
h = read_attribute(:others).dup || {}
|
h = (read_attribute(:others) || {}).dup
|
||||||
h.update(attr_name => value)
|
h.update(attr_name => value)
|
||||||
write_attribute(:others, h)
|
write_attribute(:others, h)
|
||||||
value
|
value
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<%= l(:field_delay) %>: <%= f.text_field :delay, :size => 3 %> <%= l(:label_day_plural) %>
|
<%= l(:field_delay) %>: <%= f.text_field :delay, :size => 3 %> <%= l(:label_day_plural) %>
|
||||||
</span>
|
</span>
|
||||||
<%= submit_tag l(:button_add) %>
|
<%= submit_tag l(:button_add) %>
|
||||||
<%= toggle_link l(:button_cancel), 'new-relation-form'%>
|
<%= link_to_function l(:button_cancel), '$("#new-relation-form").hide();'%>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<%= javascript_tag "observeAutocompleteField('relation_issue_to_id', '#{escape_javascript auto_complete_issues_path(:project_id => @project, :scope => (Setting.cross_project_issue_relations? ? 'all' : nil))}')" %>
|
<%= javascript_tag "observeAutocompleteField('relation_issue_to_id', '#{escape_javascript auto_complete_issues_path(:project_id => @project, :scope => (Setting.cross_project_issue_relations? ? 'all' : nil))}')" %>
|
||||||
|
|||||||
@@ -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,6 +1,4 @@
|
|||||||
<%= javascript_include_tag 'raphael.js' %>
|
<%= javascript_tag do %>
|
||||||
<%= javascript_include_tag 'revision_graph.js' %>
|
|
||||||
<script type="text/javascript" charset="utf-8">
|
|
||||||
function revisionGraphHandler(){
|
function revisionGraphHandler(){
|
||||||
drawRevisionGraph(
|
drawRevisionGraph(
|
||||||
document.getElementById('holder'),
|
document.getElementById('holder'),
|
||||||
@@ -10,5 +8,11 @@ function revisionGraphHandler(){
|
|||||||
}
|
}
|
||||||
$(document).ready(revisionGraphHandler);
|
$(document).ready(revisionGraphHandler);
|
||||||
$(window).resize(revisionGraphHandler);
|
$(window).resize(revisionGraphHandler);
|
||||||
</script>
|
<% end %>
|
||||||
|
|
||||||
<div id="holder" class="revision-graph"></div>
|
<div id="holder" class="revision-graph"></div>
|
||||||
|
|
||||||
|
<% content_for :header_tags do %>
|
||||||
|
<%= javascript_include_tag 'raphael' %>
|
||||||
|
<%= javascript_include_tag 'revision_graph' %>
|
||||||
|
<% end %>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<h2><%= l(:label_revision) %> <%= @diff_format_revisions %> <%=h @path %></h2>
|
<h2><%= l(:label_revision) %> <%= @diff_format_revisions %> <%=h @path %></h2>
|
||||||
|
|
||||||
<!-- Choose view type -->
|
<!-- Choose view type -->
|
||||||
<%= form_tag({:path => to_path_param(@path)}, :method => 'get') do %>
|
<%= form_tag({:action => 'diff', :id => @project,
|
||||||
<%= hidden_field_tag('rev', params[:rev]) if params[:rev] %>
|
:repository_id => @repository.identifier_param,
|
||||||
|
:path => to_path_param(@path), :rev=> @rev}, :method => 'get') do %>
|
||||||
<%= hidden_field_tag('rev_to', params[:rev_to]) if params[:rev_to] %>
|
<%= hidden_field_tag('rev_to', params[:rev_to]) if params[:rev_to] %>
|
||||||
<p>
|
<p>
|
||||||
<label><%= l(:label_view_diff) %></label>
|
<label><%= l(:label_view_diff) %></label>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<%= error_messages_for 'role' %>
|
<%= error_messages_for 'role' %>
|
||||||
|
|
||||||
|
<% unless @role.anonymous? %>
|
||||||
<div class="box tabular">
|
<div class="box tabular">
|
||||||
<% unless @role.builtin? %>
|
<% unless @role.builtin? %>
|
||||||
<p><%= f.text_field :name, :required => true %></p>
|
<p><%= f.text_field :name, :required => true %></p>
|
||||||
@@ -11,6 +12,7 @@
|
|||||||
<%= select_tag(:copy_workflow_from, content_tag("option") + options_from_collection_for_select(@roles, :id, :name, params[:copy_workflow_from] || @copy_from.try(:id))) %></p>
|
<%= select_tag(:copy_workflow_from, content_tag("option") + options_from_collection_for_select(@roles, :id, :name, params[:copy_workflow_from] || @copy_from.try(:id))) %></p>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<h3><%= l(:label_permissions) %></h3>
|
<h3><%= l(:label_permissions) %></h3>
|
||||||
<div class="box tabular" id="permissions">
|
<div class="box tabular" id="permissions">
|
||||||
|
|||||||
@@ -80,9 +80,8 @@ bs:
|
|||||||
format:
|
format:
|
||||||
unit: 'KM'
|
unit: 'KM'
|
||||||
format: '%u %n'
|
format: '%u %n'
|
||||||
separator:
|
negative_format: '%u -%n'
|
||||||
delimiter:
|
delimiter: ''
|
||||||
precision:
|
|
||||||
percentage:
|
percentage:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
|
|||||||
@@ -84,9 +84,7 @@ de:
|
|||||||
format:
|
format:
|
||||||
unit: '€'
|
unit: '€'
|
||||||
format: '%n %u'
|
format: '%n %u'
|
||||||
separator:
|
delimiter: ''
|
||||||
delimiter:
|
|
||||||
precision:
|
|
||||||
percentage:
|
percentage:
|
||||||
format:
|
format:
|
||||||
delimiter: ""
|
delimiter: ""
|
||||||
|
|||||||
@@ -1087,9 +1087,9 @@ ja:
|
|||||||
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: 子チケットをコピー
|
||||||
|
|||||||
@@ -939,6 +939,7 @@
|
|||||||
label_child_revision: 子項
|
label_child_revision: 子項
|
||||||
label_export_options: "%{export_format} 匯出選項"
|
label_export_options: "%{export_format} 匯出選項"
|
||||||
label_copy_attachments: 複製附件
|
label_copy_attachments: 複製附件
|
||||||
|
label_copy_subtasks: 複製子任務
|
||||||
label_item_position: "%{position} / %{count}"
|
label_item_position: "%{position} / %{count}"
|
||||||
label_completed_versions: 已完成版本
|
label_completed_versions: 已完成版本
|
||||||
label_search_for_watchers: 搜尋可供加入的監看者
|
label_search_for_watchers: 搜尋可供加入的監看者
|
||||||
@@ -1143,4 +1144,3 @@
|
|||||||
description_date_from: 輸入起始日期
|
description_date_from: 輸入起始日期
|
||||||
description_date_to: 輸入結束日期
|
description_date_to: 輸入結束日期
|
||||||
text_repository_identifier_info: '僅允許使用小寫英文字母 (a-z), 阿拉伯數字, 虛線與底線。<br />一旦儲存之後, 代碼便無法再次被更改。'
|
text_repository_identifier_info: '僅允許使用小寫英文字母 (a-z), 阿拉伯數字, 虛線與底線。<br />一旦儲存之後, 代碼便無法再次被更改。'
|
||||||
label_copy_subtasks: Copy subtasks
|
|
||||||
|
|||||||
+119
@@ -4,6 +4,125 @@ 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-30 v2.1.2
|
||||||
|
|
||||||
|
* Defect #11929: XSS vulnerability in Redmine 2.1.x
|
||||||
|
|
||||||
|
== 2012-09-30 v2.1.1
|
||||||
|
|
||||||
|
* Defect #11290: ParseDate missing in Ruby 1.9x
|
||||||
|
* Defect #11844: "load_default_data" rake task fails to print the error message if one occurs
|
||||||
|
* Defect #11850: Can't create a user from ldap by on-the-fly on the redmine server using URI prefix
|
||||||
|
* Defect #11872: Private issue visible to anonymous users after its author is deleted
|
||||||
|
* Defect #11885: Filter misses Selectionfield on IE8
|
||||||
|
* Defect #11893: New relation form Cancel link is broken with Chrome 21
|
||||||
|
* Defect #11905: Potential "can't dup NilClass" error in UserPreference
|
||||||
|
* Defect #11909: Autocomplete results not reset after clearing search field
|
||||||
|
* Defect #11922: bs.yml and de.yml lead to error by number_to_currency()
|
||||||
|
* Defect #11945: rake task prints "can't convert Errno::EACCES into String" in case of no permission of public/plugin_assets
|
||||||
|
* Defect #11975: Undefined status transitions allowed in workflow (author of issue changes when selecting a new status)
|
||||||
|
* Defect #11982: SCM diff view generates extra parameter for switching mode
|
||||||
|
* Patch #11897: Traditional Chinese language file (to r10433)
|
||||||
|
|
||||||
|
== 2012-09-16 v2.1.0
|
||||||
|
|
||||||
|
* Defect #2071: Reordering priority-enumerations breaks alternate-theme's issue-colouring
|
||||||
|
* Defect #2190: Month names not translated to german
|
||||||
|
* Defect #8978: LDAP timeout if an LDAP auth provider is unreachable
|
||||||
|
* Defect #9839: Gantt abbr of weekday should not be necessarily the first letter of the long day name
|
||||||
|
* Defect #10928: Documentation about generating a plugin is not up-to-date
|
||||||
|
* Defect #11034: TLS configuration documentation for Rails 3
|
||||||
|
* Defect #11073: UserCustomField order_statement returns wrong output
|
||||||
|
* Defect #11153: Default sorting for target version is DESC instead of ASC
|
||||||
|
* Defect #11207: Issues associated with a locked version are not copied when copying a project
|
||||||
|
* Defect #11304: Issue-class: status-1, status-2 etc. refer to status position instead of status id
|
||||||
|
* Defect #11331: Openid registration form should not require user to enter password
|
||||||
|
* Defect #11345: Context menu should show shared versions when editing issues from different projects
|
||||||
|
* Defect #11355: Plain text notification emails content is HTML escaped
|
||||||
|
* Defect #11388: Updating a version through rest API returns invalid JSON
|
||||||
|
* Defect #11389: Warning in awesome_nested_set.rb
|
||||||
|
* Defect #11503: Accessing /projects/:project/wiki/something.png fails with error 500
|
||||||
|
* Defect #11506: Versions that are not shared should not be assignable when selecting another project
|
||||||
|
* Defect #11508: Projects not ordered alphabetically after renaming project
|
||||||
|
* Defect #11540: Roadmap anchor links can be ambigous
|
||||||
|
* Defect #11545: Overwriting existing method Issue.open
|
||||||
|
* Defect #11552: MailHandler does not match assignee name with spaces
|
||||||
|
* Defect #11571: Custom fields of type version not proper handled in receiving e-mails
|
||||||
|
* Defect #11577: Can't use non-latin anchor in wiki
|
||||||
|
* Defect #11612: Revision graph sometimes broken due to raphael.js error
|
||||||
|
* Defect #11621: Redmine MIME Detection Of Javascript Files Non-Standard
|
||||||
|
* Defect #11633: Macro arguments should not be parsed by text formatters
|
||||||
|
* Defect #11662: Invalid query returned from Issues.visible scope after accessing User#projects_by_role with a role that is not present
|
||||||
|
* Defect #11691: 404 response when deleting a user from the edit page
|
||||||
|
* Defect #11723: redmine:send_reminders notification misses if assignee is a group
|
||||||
|
* Defect #11738: Batch update of issues clears project path
|
||||||
|
* Defect #11749: Redmine.pm: HEAD is not considered as a read-only method
|
||||||
|
* Defect #11814: Date picker does not respect week start setting
|
||||||
|
* Feature #703: Configurable required fields per tracker/status/role
|
||||||
|
* Feature #1006: Display thumbnails of attached images
|
||||||
|
* Feature #1091: Disabling default ticket fields per tracker
|
||||||
|
* Feature #1360: Permission for adding an issue to a version.
|
||||||
|
* Feature #3061: Let macros optionally match over multiple lines and ignore single curly braces
|
||||||
|
* Feature #3510: Inserting image thumbnails inside the wiki
|
||||||
|
* Feature #3521: Permissions for roles to change fields per tracker/status
|
||||||
|
* Feature #3640: Freeze / Close Projects
|
||||||
|
* Feature #3831: Support for subforums
|
||||||
|
* Feature #6597: Configurable session lifetime and timeout
|
||||||
|
* Feature #6965: Option to Copy Subtasks when copying an issue
|
||||||
|
* Feature #8161: Ability to filter issues on project custom fields
|
||||||
|
* Feature #8577: "Private" column and filter on the issue list
|
||||||
|
* Feature #8981: REST Api for Groups
|
||||||
|
* Feature #9258: Create role by copy
|
||||||
|
* Feature #9419: Group/sort the issue list by user/version-format custom fields
|
||||||
|
* Feature #10362: Show images in repositories inline when clicking the 'View' link
|
||||||
|
* Feature #10419: Upgrade raphael.js (2.1.0)
|
||||||
|
* Feature #11068: Ability to set default column order in issue list
|
||||||
|
* Feature #11102: Add autocomplete to "Related issue" field on revision
|
||||||
|
* Feature #11109: Repository Identifier should be frozen
|
||||||
|
* Feature #11181: Additional "Log time" link on project overview
|
||||||
|
* Feature #11205: Reversed order of priorities on the issue summary page
|
||||||
|
* Feature #11445: Switch from Prototype to JQuery
|
||||||
|
* Feature #11469: JSONP support
|
||||||
|
* Feature #11475: Redmine.pm: Allow fallback to other Apache auth providers
|
||||||
|
* Feature #11494: Don't turn #nnn with leading zeros into links
|
||||||
|
* Feature #11539: Display a projects tree instead of a flat list in notification preferences
|
||||||
|
* Feature #11578: Option to pass whole arguments to a macro without splitting them
|
||||||
|
* Feature #11595: Missing mime type for svg files
|
||||||
|
* Feature #11758: Upgrade to Rails 3.2.8
|
||||||
|
* Patch #4905: Redmine.pm: add support for Git's smart HTTP protocol
|
||||||
|
* Patch #10988: New Korean translation patch
|
||||||
|
* Patch #11201: Korean translation special update
|
||||||
|
* Patch #11401: Fix Japanese mistranslation for "button_submit"
|
||||||
|
* Patch #11402: Japanese translation added for default role names
|
||||||
|
* Patch #11411: Fix disordered use of long sound in Japanese "user" translation
|
||||||
|
* Patch #11412: Unnatural Japanese message when users failed to login
|
||||||
|
* Patch #11419: Fix wrong Japanese "label_attachment" translation
|
||||||
|
* Patch #11496: Make labels clickable in Adminstration/Settings
|
||||||
|
* Patch #11704: Avoid the use of tag("...", "...", true) in layout
|
||||||
|
* Patch #11818: Redmine.pm fails when permissions are NULL
|
||||||
|
|
||||||
|
== 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
|
== 2012-06-18 v2.0.3
|
||||||
|
|
||||||
* Defect #10688: PDF export from Wiki - Problems with tables
|
* Defect #10688: PDF export from Wiki - Problems with tables
|
||||||
|
|||||||
+5
-2
@@ -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 8.4)
|
* PostgreSQL (tested with PostgreSQL 9.1)
|
||||||
* SQLite3 (tested with SQLite 3.6)
|
* SQLite3 (tested with SQLite 3.6)
|
||||||
|
|
||||||
Optional:
|
Optional:
|
||||||
@@ -38,7 +38,10 @@ 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)
|
for the "production" environment (default database is MySQL and ruby1.8)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|||||||
@@ -249,7 +249,8 @@ sub RedmineDSN {
|
|||||||
roles.id IN (SELECT member_roles.role_id FROM members, member_roles WHERE members.user_id = users.id AND members.project_id = projects.id AND members.id = member_roles.member_id)
|
roles.id IN (SELECT member_roles.role_id FROM members, member_roles WHERE members.user_id = users.id AND members.project_id = projects.id AND members.id = member_roles.member_id)
|
||||||
OR
|
OR
|
||||||
(roles.builtin=1 AND cast(projects.is_public as CHAR) IN ('t', '1'))
|
(roles.builtin=1 AND cast(projects.is_public as CHAR) IN ('t', '1'))
|
||||||
) ";
|
)
|
||||||
|
AND roles.permissions IS NOT NULL";
|
||||||
$self->{RedmineQuery} = trim($query);
|
$self->{RedmineQuery} = trim($query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
require 'SVG/Graph/Plot'
|
require 'SVG/Graph/Plot'
|
||||||
require 'parsedate'
|
|
||||||
|
|
||||||
module SVG
|
module SVG
|
||||||
module Graph
|
module Graph
|
||||||
@@ -157,8 +156,7 @@ module SVG
|
|||||||
y = []
|
y = []
|
||||||
data[:data].each_index {|i|
|
data[:data].each_index {|i|
|
||||||
if i%2 == 0
|
if i%2 == 0
|
||||||
arr = ParseDate.parsedate( data[:data][i] )
|
t = DateTime.parse( data[:data][i] ).to_time
|
||||||
t = Time.local( *arr[0,6].compact )
|
|
||||||
x << t.to_i
|
x << t.to_i
|
||||||
else
|
else
|
||||||
y << data[:data][i]
|
y << data[:data][i]
|
||||||
@@ -173,8 +171,7 @@ module SVG
|
|||||||
protected
|
protected
|
||||||
|
|
||||||
def min_x_value=(value)
|
def min_x_value=(value)
|
||||||
arr = ParseDate.parsedate( value )
|
@min_x_value = DateTime.parse( data[:data][i] ).to_time
|
||||||
@min_x_value = Time.local( *arr[0,6].compact ).to_i
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -336,7 +336,11 @@ module Redmine #:nodoc:
|
|||||||
|
|
||||||
unless source_files.empty?
|
unless source_files.empty?
|
||||||
base_target_dir = File.join(destination, File.dirname(source_files.first).gsub(source, ''))
|
base_target_dir = File.join(destination, File.dirname(source_files.first).gsub(source, ''))
|
||||||
FileUtils.mkdir_p(base_target_dir)
|
begin
|
||||||
|
FileUtils.mkdir_p(base_target_dir)
|
||||||
|
rescue Exception => e
|
||||||
|
raise "Could not create directory #{base_target_dir}: " + e.message
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
source_dirs.each do |dir|
|
source_dirs.each do |dir|
|
||||||
@@ -346,7 +350,7 @@ module Redmine #:nodoc:
|
|||||||
begin
|
begin
|
||||||
FileUtils.mkdir_p(target_dir)
|
FileUtils.mkdir_p(target_dir)
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
raise "Could not create directory #{target_dir}: \n" + e
|
raise "Could not create directory #{target_dir}: " + e.message
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -357,7 +361,7 @@ module Redmine #:nodoc:
|
|||||||
FileUtils.cp(file, target)
|
FileUtils.cp(file, target)
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
raise "Could not copy #{file} to #{target}: \n" + e
|
raise "Could not copy #{file} to #{target}: " + e.message
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ module Redmine
|
|||||||
module VERSION #:nodoc:
|
module VERSION #:nodoc:
|
||||||
MAJOR = 2
|
MAJOR = 2
|
||||||
MINOR = 1
|
MINOR = 1
|
||||||
TINY = 0
|
TINY = 2
|
||||||
|
|
||||||
# Branch values:
|
# Branch values:
|
||||||
# * official release: nil
|
# * official release: nil
|
||||||
# * stable branch: stable
|
# * stable branch: stable
|
||||||
# * trunk: devel
|
# * trunk: devel
|
||||||
BRANCH = 'devel'
|
BRANCH = 'stable'
|
||||||
|
|
||||||
def self.revision
|
def self.revision
|
||||||
revision = nil
|
revision = nil
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ namespace :redmine do
|
|||||||
Redmine::DefaultData::Loader.load(current_language)
|
Redmine::DefaultData::Loader.load(current_language)
|
||||||
puts "Default configuration data loaded."
|
puts "Default configuration data loaded."
|
||||||
rescue Redmine::DefaultData::DataAlreadyLoaded => error
|
rescue Redmine::DefaultData::DataAlreadyLoaded => error
|
||||||
puts error
|
puts error.message
|
||||||
rescue => error
|
rescue => error
|
||||||
puts "Error: " + error
|
puts "Error: " + error.message
|
||||||
puts "Default configuration data was not loaded."
|
puts "Default configuration data was not loaded."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -152,10 +152,10 @@ function buildFilterRow(field, operator, values) {
|
|||||||
var option = $('<option>');
|
var option = $('<option>');
|
||||||
if ($.isArray(filterValue)) {
|
if ($.isArray(filterValue)) {
|
||||||
option.val(filterValue[1]).text(filterValue[0]);
|
option.val(filterValue[1]).text(filterValue[0]);
|
||||||
if (values.indexOf(filterValue[1]) > -1) {option.attr('selected', true)};
|
if ($.inArray(filterValue[1], values) > -1) {option.attr('selected', true);}
|
||||||
} else {
|
} else {
|
||||||
option.val(filterValue).text(filterValue);
|
option.val(filterValue).text(filterValue);
|
||||||
if (values.indexOf(filterValue) > -1) {option.attr('selected', true)};
|
if ($.inArray(filterValue, values) > -1) {option.attr('selected', true);}
|
||||||
}
|
}
|
||||||
select.append(option);
|
select.append(option);
|
||||||
}
|
}
|
||||||
@@ -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]);
|
||||||
@@ -204,7 +204,7 @@ function toggleFilter(field) {
|
|||||||
function enableValues(field, indexes) {
|
function enableValues(field, indexes) {
|
||||||
var fieldId = field.replace('.', '_');
|
var fieldId = field.replace('.', '_');
|
||||||
$('#tr_'+fieldId+' td.values .value').each(function(index) {
|
$('#tr_'+fieldId+' td.values .value').each(function(index) {
|
||||||
if (indexes.indexOf(index) >= 0) {
|
if ($.inArray(index, indexes) >= 0) {
|
||||||
$(this).removeAttr('disabled');
|
$(this).removeAttr('disabled');
|
||||||
$(this).parents('span').first().show();
|
$(this).parents('span').first().show();
|
||||||
} else {
|
} else {
|
||||||
@@ -478,16 +478,14 @@ function observeSearchfield(fieldId, targetId, url) {
|
|||||||
var val = $this.val();
|
var val = $this.val();
|
||||||
if ($this.attr('data-value-was') != val){
|
if ($this.attr('data-value-was') != val){
|
||||||
$this.attr('data-value-was', val);
|
$this.attr('data-value-was', val);
|
||||||
if (val != '') {
|
$.ajax({
|
||||||
$.ajax({
|
url: url,
|
||||||
url: url,
|
type: 'get',
|
||||||
type: 'get',
|
data: {q: $this.val()},
|
||||||
data: {q: $this.val()},
|
success: function(data){ $('#'+targetId).html(data); },
|
||||||
success: function(data){ $('#'+targetId).html(data); },
|
beforeSend: function(){ $this.addClass('ajax-loading'); },
|
||||||
beforeSend: function(){ $this.addClass('ajax-loading'); },
|
complete: function(){ $this.removeClass('ajax-loading'); }
|
||||||
complete: function(){ $this.removeClass('ajax-loading'); }
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var reset = function() {
|
var reset = function() {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -35,6 +35,9 @@ function drawRevisionGraph(holder, commits_hash, graph_space) {
|
|||||||
var path, title;
|
var path, title;
|
||||||
var revision_dot_overlay;
|
var revision_dot_overlay;
|
||||||
$.each(commits, function(index, commit) {
|
$.each(commits, function(index, commit) {
|
||||||
|
if (!commit.hasOwnProperty("space"))
|
||||||
|
commit.space = 0;
|
||||||
|
|
||||||
y = commit_table_rows.eq(max_rdmid - commit.rdmid).position().top - graph_y_offset + CIRCLE_INROW_OFFSET;
|
y = commit_table_rows.eq(max_rdmid - commit.rdmid).position().top - graph_y_offset + CIRCLE_INROW_OFFSET;
|
||||||
x = graph_x_offset + XSTEP / 2 + XSTEP * commit.space;
|
x = graph_x_offset + XSTEP / 2 + XSTEP * commit.space;
|
||||||
revisionGraph.circle(x, y, 3)
|
revisionGraph.circle(x, y, 3)
|
||||||
@@ -46,6 +49,9 @@ function drawRevisionGraph(holder, commits_hash, graph_space) {
|
|||||||
$.each(commit.parent_scmids, function(index, parent_scmid) {
|
$.each(commit.parent_scmids, function(index, parent_scmid) {
|
||||||
parent_commit = commits_by_scmid[parent_scmid];
|
parent_commit = commits_by_scmid[parent_scmid];
|
||||||
if (parent_commit) {
|
if (parent_commit) {
|
||||||
|
if (!parent_commit.hasOwnProperty("space"))
|
||||||
|
parent_commit.space = 0;
|
||||||
|
|
||||||
parent_y = commit_table_rows.eq(max_rdmid - parent_commit.rdmid).position().top - graph_y_offset + CIRCLE_INROW_OFFSET;
|
parent_y = commit_table_rows.eq(max_rdmid - parent_commit.rdmid).position().top - graph_y_offset + CIRCLE_INROW_OFFSET;
|
||||||
parent_x = graph_x_offset + XSTEP / 2 + XSTEP * parent_commit.space;
|
parent_x = graph_x_offset + XSTEP / 2 + XSTEP * parent_commit.space;
|
||||||
if (parent_commit.space == commit.space) {
|
if (parent_commit.space == commit.space) {
|
||||||
|
|||||||
@@ -96,8 +96,13 @@ class AttachmentsControllerTest < ActionController::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_save_diff_type
|
def test_save_diff_type
|
||||||
@request.session[:user_id] = 1 # admin
|
user1 = User.find(1)
|
||||||
|
user1.pref[:diff_type] = nil
|
||||||
|
user1.preference.save
|
||||||
user = User.find(1)
|
user = User.find(1)
|
||||||
|
assert_nil user.pref[:diff_type]
|
||||||
|
|
||||||
|
@request.session[:user_id] = 1 # admin
|
||||||
get :show, :id => 5
|
get :show, :id => 5
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template 'diff'
|
assert_template 'diff'
|
||||||
|
|||||||
@@ -2521,6 +2521,18 @@ class IssuesControllerTest < ActionController::TestCase
|
|||||||
assert_equal 'This is the test_new issue', issue.subject
|
assert_equal 'This is the test_new issue', issue.subject
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_update_edit_form_should_keep_issue_author
|
||||||
|
@request.session[:user_id] = 3
|
||||||
|
xhr :put, :new, :project_id => 1, :id => 1, :issue => {:subject => 'Changed'}
|
||||||
|
assert_response :success
|
||||||
|
assert_equal 'text/javascript', response.content_type
|
||||||
|
|
||||||
|
issue = assigns(:issue)
|
||||||
|
assert_equal User.find(2), issue.author
|
||||||
|
assert_equal 2, issue.author_id
|
||||||
|
assert_not_equal User.current, issue.author
|
||||||
|
end
|
||||||
|
|
||||||
def test_update_edit_form_should_propose_transitions_based_on_initial_status
|
def test_update_edit_form_should_propose_transitions_based_on_initial_status
|
||||||
@request.session[:user_id] = 2
|
@request.session[:user_id] = 2
|
||||||
WorkflowTransition.delete_all
|
WorkflowTransition.delete_all
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -53,8 +53,6 @@ class RepositoriesGitControllerTest < ActionController::TestCase
|
|||||||
if @char_1.respond_to?(:force_encoding)
|
if @char_1.respond_to?(:force_encoding)
|
||||||
@char_1.force_encoding('UTF-8')
|
@char_1.force_encoding('UTF-8')
|
||||||
end
|
end
|
||||||
|
|
||||||
Setting.default_language = 'en'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_create_and_update
|
def test_create_and_update
|
||||||
@@ -263,6 +261,8 @@ class RepositoriesGitControllerTest < ActionController::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_diff
|
def test_diff
|
||||||
|
assert_equal true, @repository.is_default
|
||||||
|
assert_nil @repository.identifier
|
||||||
assert_equal 0, @repository.changesets.count
|
assert_equal 0, @repository.changesets.count
|
||||||
@repository.fetch_changesets
|
@repository.fetch_changesets
|
||||||
@project.reload
|
@project.reload
|
||||||
@@ -320,10 +320,12 @@ class RepositoriesGitControllerTest < ActionController::TestCase
|
|||||||
with_settings :diff_max_lines_displayed => 5 do
|
with_settings :diff_max_lines_displayed => 5 do
|
||||||
# Truncated diff of changeset 2f9c0091
|
# Truncated diff of changeset 2f9c0091
|
||||||
with_cache do
|
with_cache do
|
||||||
get :diff, :id => PRJ_ID, :type => 'inline',
|
with_settings :default_language => 'en' do
|
||||||
:rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
|
get :diff, :id => PRJ_ID, :type => 'inline',
|
||||||
assert_response :success
|
:rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
|
||||||
assert @response.body.include?("... This diff was truncated")
|
assert_response :success
|
||||||
|
assert @response.body.include?("... This diff was truncated")
|
||||||
|
end
|
||||||
with_settings :default_language => 'fr' do
|
with_settings :default_language => 'fr' do
|
||||||
get :diff, :id => PRJ_ID, :type => 'inline',
|
get :diff, :id => PRJ_ID, :type => 'inline',
|
||||||
:rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
|
:rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
|
||||||
@@ -351,9 +353,55 @@ class RepositoriesGitControllerTest < ActionController::TestCase
|
|||||||
diff = assigns(:diff)
|
diff = assigns(:diff)
|
||||||
assert_not_nil diff
|
assert_not_nil diff
|
||||||
assert_tag :tag => 'h2', :content => /2f9c0091:61b685fb/
|
assert_tag :tag => 'h2', :content => /2f9c0091:61b685fb/
|
||||||
|
assert_tag :tag => "form",
|
||||||
|
:attributes => {
|
||||||
|
:action => "/projects/subproject1/repository/revisions/" +
|
||||||
|
"61b685fbe55ab05b5ac68402d5720c1a6ac973d1/diff"
|
||||||
|
}
|
||||||
|
assert_tag :tag => 'input',
|
||||||
|
:attributes => {
|
||||||
|
:id => "rev_to",
|
||||||
|
:name => "rev_to",
|
||||||
|
:type => "hidden",
|
||||||
|
:value => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_diff_path_in_subrepo
|
||||||
|
repo = Repository::Git.create(
|
||||||
|
:project => @project,
|
||||||
|
:url => REPOSITORY_PATH,
|
||||||
|
:identifier => 'test-diff-path',
|
||||||
|
:path_encoding => 'ISO-8859-1'
|
||||||
|
);
|
||||||
|
assert repo
|
||||||
|
assert_equal false, repo.is_default
|
||||||
|
assert_equal 'test-diff-path', repo.identifier
|
||||||
|
get :diff,
|
||||||
|
:id => PRJ_ID,
|
||||||
|
:repository_id => 'test-diff-path',
|
||||||
|
:rev => '61b685fbe55ab05b',
|
||||||
|
:rev_to => '2f9c0091c754a91a',
|
||||||
|
:type => 'inline'
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'diff'
|
||||||
|
diff = assigns(:diff)
|
||||||
|
assert_not_nil diff
|
||||||
|
assert_tag :tag => "form",
|
||||||
|
:attributes => {
|
||||||
|
:action => "/projects/subproject1/repository/test-diff-path/" +
|
||||||
|
"revisions/61b685fbe55ab05b/diff"
|
||||||
|
}
|
||||||
|
assert_tag :tag => 'input',
|
||||||
|
:attributes => {
|
||||||
|
:id => "rev_to",
|
||||||
|
:name => "rev_to",
|
||||||
|
:type => "hidden",
|
||||||
|
:value => '2f9c0091c754a91a'
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
def test_diff_latin_1
|
def test_diff_latin_1
|
||||||
if @ruby19_non_utf8_pass
|
if @ruby19_non_utf8_pass
|
||||||
puts_ruby19_non_utf8_pass()
|
puts_ruby19_non_utf8_pass()
|
||||||
@@ -385,8 +433,13 @@ class RepositoriesGitControllerTest < ActionController::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_save_diff_type
|
def test_save_diff_type
|
||||||
@request.session[:user_id] = 1 # admin
|
user1 = User.find(1)
|
||||||
|
user1.pref[:diff_type] = nil
|
||||||
|
user1.preference.save
|
||||||
user = User.find(1)
|
user = User.find(1)
|
||||||
|
assert_nil user.pref[:diff_type]
|
||||||
|
|
||||||
|
@request.session[:user_id] = 1 # admin
|
||||||
get :diff,
|
get :diff,
|
||||||
:id => PRJ_ID,
|
:id => PRJ_ID,
|
||||||
:rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
|
:rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
|
||||||
|
|||||||
@@ -110,6 +110,14 @@ class RolesControllerTest < ActionController::TestCase
|
|||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template 'edit'
|
assert_template 'edit'
|
||||||
assert_equal Role.find(1), assigns(:role)
|
assert_equal Role.find(1), assigns(:role)
|
||||||
|
assert_select 'select[name=?]', 'role[issues_visibility]'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_edit_anonymous
|
||||||
|
get :edit, :id => Role.anonymous.id
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'edit'
|
||||||
|
assert_select 'select[name=?]', 'role[issues_visibility]', 0
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_edit_invalid_should_respond_with_404
|
def test_edit_invalid_should_respond_with_404
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ require File.expand_path('../../test_helper', __FILE__)
|
|||||||
class BoardTest < ActiveSupport::TestCase
|
class BoardTest < ActiveSupport::TestCase
|
||||||
fixtures :projects, :boards, :messages, :attachments, :watchers
|
fixtures :projects, :boards, :messages, :attachments, :watchers
|
||||||
|
|
||||||
|
include Redmine::I18n
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
@project = Project.find(1)
|
@project = Project.find(1)
|
||||||
end
|
end
|
||||||
@@ -41,6 +43,7 @@ class BoardTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_parent_should_be_in_same_project
|
def test_parent_should_be_in_same_project
|
||||||
|
set_language_if_valid 'en'
|
||||||
board = Board.new(:project_id => 3, :name => 'Test', :description => 'Test', :parent_id => 1)
|
board = Board.new(:project_id => 3, :name => 'Test', :description => 'Test', :parent_id => 1)
|
||||||
assert !board.save
|
assert !board.save
|
||||||
assert_include "Parent forum is invalid", board.errors.full_messages
|
assert_include "Parent forum is invalid", board.errors.full_messages
|
||||||
|
|||||||
@@ -179,7 +179,8 @@ class ChangesetTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_commit_closing_a_subproject_issue
|
def test_commit_closing_a_subproject_issue
|
||||||
with_settings :commit_fix_status_id => 5, :commit_fix_keywords => 'closes' do
|
with_settings :commit_fix_status_id => 5, :commit_fix_keywords => 'closes',
|
||||||
|
:default_language => 'en' do
|
||||||
issue = Issue.find(5)
|
issue = Issue.find(5)
|
||||||
assert !issue.closed?
|
assert !issue.closed?
|
||||||
assert_difference 'Journal.count' do
|
assert_difference 'Journal.count' do
|
||||||
|
|||||||
+15
-13
@@ -25,7 +25,7 @@ class IssueTest < ActiveSupport::TestCase
|
|||||||
:versions,
|
:versions,
|
||||||
:issue_statuses, :issue_categories, :issue_relations, :workflows,
|
:issue_statuses, :issue_categories, :issue_relations, :workflows,
|
||||||
:enumerations,
|
:enumerations,
|
||||||
:issues,
|
:issues, :journals, :journal_details,
|
||||||
:custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
|
:custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
|
||||||
:time_entries
|
:time_entries
|
||||||
|
|
||||||
@@ -105,18 +105,6 @@ class IssueTest < ActiveSupport::TestCase
|
|||||||
assert_visibility_match User.anonymous, issues
|
assert_visibility_match User.anonymous, issues
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_visible_scope_for_anonymous_with_own_issues_visibility
|
|
||||||
Role.anonymous.update_attribute :issues_visibility, 'own'
|
|
||||||
Issue.create!(:project_id => 1, :tracker_id => 1,
|
|
||||||
:author_id => User.anonymous.id,
|
|
||||||
:subject => 'Issue by anonymous')
|
|
||||||
|
|
||||||
issues = Issue.visible(User.anonymous).all
|
|
||||||
assert issues.any?
|
|
||||||
assert_nil issues.detect {|issue| issue.author != User.anonymous}
|
|
||||||
assert_visibility_match User.anonymous, issues
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_visible_scope_for_anonymous_without_view_issues_permissions
|
def test_visible_scope_for_anonymous_without_view_issues_permissions
|
||||||
# Anonymous user should not see issues without permission
|
# Anonymous user should not see issues without permission
|
||||||
Role.anonymous.remove_permission!(:view_issues)
|
Role.anonymous.remove_permission!(:view_issues)
|
||||||
@@ -125,6 +113,20 @@ class IssueTest < ActiveSupport::TestCase
|
|||||||
assert_visibility_match User.anonymous, issues
|
assert_visibility_match User.anonymous, issues
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_default
|
||||||
|
assert Role.anonymous.update_attribute(:issues_visibility, 'default')
|
||||||
|
issue = Issue.generate_for_project!(Project.find(1), :author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
|
||||||
|
assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
|
||||||
|
assert !issue.visible?(User.anonymous)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_own
|
||||||
|
assert Role.anonymous.update_attribute(:issues_visibility, 'own')
|
||||||
|
issue = Issue.generate_for_project!(Project.find(1), :author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
|
||||||
|
assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
|
||||||
|
assert !issue.visible?(User.anonymous)
|
||||||
|
end
|
||||||
|
|
||||||
def test_visible_scope_for_non_member
|
def test_visible_scope_for_non_member
|
||||||
user = User.find(9)
|
user = User.find(9)
|
||||||
assert user.projects.empty?
|
assert user.projects.empty?
|
||||||
|
|||||||
@@ -171,6 +171,24 @@ class Redmine::I18nTest < ActiveSupport::TestCase
|
|||||||
assert_equal 'j', day_letter(4)
|
assert_equal 'j', day_letter(4)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_number_to_currency_for_each_language
|
||||||
|
valid_languages.each do |lang|
|
||||||
|
set_language_if_valid lang
|
||||||
|
assert_nothing_raised "#{lang} failure" do
|
||||||
|
number_to_currency(-1000.2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_number_to_currency_default
|
||||||
|
set_language_if_valid 'bs'
|
||||||
|
assert_equal "KM -1000,20", number_to_currency(-1000.2)
|
||||||
|
set_language_if_valid 'de'
|
||||||
|
euro_sign = "\xe2\x82\xac"
|
||||||
|
euro_sign.force_encoding('UTF-8') if euro_sign.respond_to?(:force_encoding)
|
||||||
|
assert_equal "-1000,20 #{euro_sign}", number_to_currency(-1000.2)
|
||||||
|
end
|
||||||
|
|
||||||
def test_valid_languages
|
def test_valid_languages
|
||||||
assert valid_languages.is_a?(Array)
|
assert valid_languages.is_a?(Array)
|
||||||
assert valid_languages.first.is_a?(Symbol)
|
assert valid_languages.first.is_a?(Symbol)
|
||||||
|
|||||||
@@ -54,4 +54,19 @@ class UserPreferenceTest < ActiveSupport::TestCase
|
|||||||
assert up.save
|
assert up.save
|
||||||
assert_kind_of Hash, up.others
|
assert_kind_of Hash, up.others
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_reading_value_from_nil_others_hash
|
||||||
|
up = UserPreference.new(:user => User.new)
|
||||||
|
up.others = nil
|
||||||
|
assert_nil up.others
|
||||||
|
assert_nil up[:foo]
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_writing_value_to_nil_others_hash
|
||||||
|
up = UserPreference.new(:user => User.new)
|
||||||
|
up.others = nil
|
||||||
|
assert_nil up.others
|
||||||
|
up[:foo] = 'bar'
|
||||||
|
assert_equal 'bar', up[:foo]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user