summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Philippe Lang <jp_lang@yahoo.fr>2008-05-18 16:53:23 +0000
committerJean-Philippe Lang <jp_lang@yahoo.fr>2008-05-18 16:53:23 +0000
commit729d1176ea855b71334d7e593bb8b1a5b2c31f72 (patch)
tree0fd928dbd81e6d50fd43630fc2861c2eea5c2a61
parentc0db7007fa11e6e870f9b15883c2912d352c4c69 (diff)
downloadredmine-729d1176ea855b71334d7e593bb8b1a5b2c31f72.tar.gz
redmine-729d1176ea855b71334d7e593bb8b1a5b2c31f72.zip
Merged r1385 and r1426 to r1434 from trunk.
git-svn-id: http://redmine.rubyforge.org/svn/branches/0.7-stable@1437 e93f8b46-1217-0410-a6f0-8f06a7374b81
-rw-r--r--app/models/attachment.rb15
-rw-r--r--app/models/project.rb7
-rw-r--r--app/models/query.rb17
-rw-r--r--app/views/issues/_edit.rhtml2
-rw-r--r--app/views/roles/_form.rhtml4
-rw-r--r--app/views/settings/_notifications.rhtml4
-rw-r--r--lib/redcloth.rb4
-rw-r--r--lib/redmine/scm/adapters/git_adapter.rb4
-rw-r--r--lib/redmine/wiki_formatting.rb2
-rw-r--r--public/javascripts/application.js8
-rw-r--r--public/stylesheets/application.css4
-rw-r--r--test/fixtures/issues.yml18
-rw-r--r--test/functional/issues_controller_test.rb31
-rw-r--r--test/functional/projects_controller_test.rb25
-rw-r--r--test/unit/attachment_test.rb32
-rw-r--r--test/unit/helpers/application_helper_test.rb12
16 files changed, 158 insertions, 31 deletions
diff --git a/app/models/attachment.rb b/app/models/attachment.rb
index 08f440816..f44fe8b4d 100644
--- a/app/models/attachment.rb
+++ b/app/models/attachment.rb
@@ -40,7 +40,7 @@ class Attachment < ActiveRecord::Base
@temp_file = incoming_file
if @temp_file.size > 0
self.filename = sanitize_filename(@temp_file.original_filename)
- self.disk_filename = DateTime.now.strftime("%y%m%d%H%M%S") + "_" + self.filename
+ self.disk_filename = Attachment.disk_filename(filename)
self.content_type = @temp_file.content_type.to_s.chomp
self.filesize = @temp_file.size
end
@@ -100,4 +100,17 @@ private
# Finally, replace all non alphanumeric, hyphens or periods with underscore
@filename = just_filename.gsub(/[^\w\.\-]/,'_')
end
+
+ # Returns an ASCII or hashed filename
+ def self.disk_filename(filename)
+ df = DateTime.now.strftime("%y%m%d%H%M%S") + "_"
+ if filename =~ %r{^[a-zA-Z0-9_\.\-]*$}
+ df << filename
+ else
+ df << Digest::MD5.hexdigest(filename)
+ # keep the extension if any
+ df << $1 if filename =~ %r{(\.[a-zA-Z0-9]+)$}
+ end
+ df
+ end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 964469649..8c32c8562 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -73,9 +73,9 @@ class Project < ActiveRecord::Base
def issues_with_subprojects(include_subprojects=false)
conditions = nil
- if include_subprojects && !active_children.empty?
- ids = [id] + active_children.collect {|c| c.id}
- conditions = ["#{Project.table_name}.id IN (#{ids.join(',')})"]
+ if include_subprojects
+ ids = [id] + child_ids
+ conditions = ["#{Project.table_name}.id IN (#{ids.join(',')}) AND #{Project.visible_by}"]
end
conditions ||= ["#{Project.table_name}.id = ?", id]
# Quick and dirty fix for Rails 2 compatibility
@@ -93,6 +93,7 @@ class Project < ActiveRecord::Base
end
def self.visible_by(user=nil)
+ user ||= User.current
if user && user.admin?
return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"
elsif user && user.memberships.any?
diff --git a/app/models/query.rb b/app/models/query.rb
index d9a720812..f25b5c401 100644
--- a/app/models/query.rb
+++ b/app/models/query.rb
@@ -265,7 +265,7 @@ class Query < ActiveRecord::Base
def statement
# project/subprojects clause
- clause = ''
+ project_clauses = []
if project && !@project.active_children.empty?
ids = [project.id]
if has_filter?("subproject_id")
@@ -277,17 +277,16 @@ class Query < ActiveRecord::Base
# main project only
else
# all subprojects
- ids += project.active_children.collect{|p| p.id}
+ ids += project.child_ids
end
elsif Setting.display_subprojects_issues?
- ids += project.active_children.collect{|p| p.id}
+ ids += project.child_ids
end
- clause << "#{Issue.table_name}.project_id IN (%s)" % ids.join(',')
+ project_clauses << "#{Issue.table_name}.project_id IN (%s)" % ids.join(',')
elsif project
- clause << "#{Issue.table_name}.project_id = %d" % project.id
- else
- clause << Project.visible_by(User.current)
+ project_clauses << "#{Issue.table_name}.project_id = %d" % project.id
end
+ project_clauses << Project.visible_by(User.current)
# filters clauses
filters_clauses = []
@@ -365,8 +364,6 @@ class Query < ActiveRecord::Base
filters_clauses << sql
end if filters and valid?
- clause << ' AND ' unless clause.empty?
- clause << filters_clauses.join(' AND ') unless filters_clauses.empty?
- clause
+ (project_clauses + filters_clauses).join(' AND ')
end
end
diff --git a/app/views/issues/_edit.rhtml b/app/views/issues/_edit.rhtml
index 2e00ab520..49f198a63 100644
--- a/app/views/issues/_edit.rhtml
+++ b/app/views/issues/_edit.rhtml
@@ -21,9 +21,9 @@
<p><%= time_entry.text_field :hours, :size => 6, :label => :label_spent_time %> <%= l(:field_hours) %></p>
</div>
<div class="splitcontentright">
- <p><%= time_entry.text_field :comments, :size => 40 %></p>
<p><%= time_entry.select :activity_id, (@activities.collect {|p| [p.name, p.id]}) %></p>
</div>
+ <p><%= time_entry.text_field :comments, :size => 60 %></p>
<% end %>
</fieldset>
<% end %>
diff --git a/app/views/roles/_form.rhtml b/app/views/roles/_form.rhtml
index 58dc2af41..4aad45471 100644
--- a/app/views/roles/_form.rhtml
+++ b/app/views/roles/_form.rhtml
@@ -12,7 +12,7 @@
<% end %>
<h3><%= l(:label_permissions) %></h3>
-<div class="box">
+<div class="box" id="permissions">
<% perms_by_module = @permissions.group_by {|p| p.project_module.to_s} %>
<% perms_by_module.keys.sort.each do |mod| %>
<fieldset><legend><%= mod.blank? ? l(:label_project) : mod.humanize %></legend>
@@ -24,6 +24,6 @@
<% end %>
</fieldset>
<% end %>
-<br /><%= check_all_links 'role_form' %>
+<br /><%= check_all_links 'permissions' %>
<%= hidden_field_tag 'role[permissions][]', '' %>
</div>
diff --git a/app/views/settings/_notifications.rhtml b/app/views/settings/_notifications.rhtml
index ac3213853..1a472d606 100644
--- a/app/views/settings/_notifications.rhtml
+++ b/app/views/settings/_notifications.rhtml
@@ -9,13 +9,13 @@
<%= hidden_field_tag 'settings[bcc_recipients]', 0 %></p>
</div>
-<fieldset class="box"><legend><%=l(:text_select_mail_notifications)%></legend>
+<fieldset class="box" id="notified_events"><legend><%=l(:text_select_mail_notifications)%></legend>
<% @notifiables.each do |notifiable| %>
<label><%= check_box_tag 'settings[notified_events][]', notifiable, Setting.notified_events.include?(notifiable) %>
<%= l_or_humanize(notifiable) %></label><br />
<% end %>
<%= hidden_field_tag 'settings[notified_events][]', '' %>
-<p><%= check_all_links('mail-options-form') %></p>
+<p><%= check_all_links('notified_events') %></p>
</fieldset>
<fieldset class="box"><legend><%= l(:setting_emails_footer) %></legend>
diff --git a/lib/redcloth.rb b/lib/redcloth.rb
index 7729ced46..f94c95738 100644
--- a/lib/redcloth.rb
+++ b/lib/redcloth.rb
@@ -376,13 +376,13 @@ class RedCloth < String
re =
case rtype
when :limit
- /(^|[>\s])
+ /(^|[>\s\(])
(#{rcq})
(#{C})
(?::(\S+?))?
([^\s\-].*?[^\s\-]|\w)
#{rcq}
- (?=[[:punct:]]|\s|$)/x
+ (?=[[:punct:]]|\s|\)|$)/x
else
/(#{rcq})
(#{C})
diff --git a/lib/redmine/scm/adapters/git_adapter.rb b/lib/redmine/scm/adapters/git_adapter.rb
index 77604f283..a9ab505a8 100644
--- a/lib/redmine/scm/adapters/git_adapter.rb
+++ b/lib/redmine/scm/adapters/git_adapter.rb
@@ -27,8 +27,8 @@ module Redmine
# Get the revision of a particuliar file
def get_rev (rev,path)
- cmd="git --git-dir #{target('')} show #{shell_quote rev} -- #{shell_quote path}" if rev!='latest' and (! rev.nil?)
- cmd="git --git-dir #{target('')} log -1 master -- #{shell_quote path}" if
+ cmd="#{GIT_BIN} --git-dir #{target('')} show #{shell_quote rev} -- #{shell_quote path}" if rev!='latest' and (! rev.nil?)
+ cmd="#{GIT_BIN} --git-dir #{target('')} log -1 master -- #{shell_quote path}" if
rev=='latest' or rev.nil?
rev=[]
i=0
diff --git a/lib/redmine/wiki_formatting.rb b/lib/redmine/wiki_formatting.rb
index 9b341e02d..8866e8cde 100644
--- a/lib/redmine/wiki_formatting.rb
+++ b/lib/redmine/wiki_formatting.rb
@@ -26,7 +26,7 @@ module Redmine
class TextileFormatter < RedCloth
# auto_link rule after textile rules so that it doesn't break !image_url! tags
- RULES = [:textile, :inline_auto_link, :inline_auto_mailto, :inline_toc, :inline_macros]
+ RULES = [:textile, :block_markdown_rule, :inline_auto_link, :inline_auto_mailto, :inline_toc, :inline_macros]
def initialize(*args)
super
diff --git a/public/javascripts/application.js b/public/javascripts/application.js
index 4e8849842..f3d771a10 100644
--- a/public/javascripts/application.js
+++ b/public/javascripts/application.js
@@ -2,10 +2,10 @@
Copyright (C) 2006-2008 Jean-Philippe Lang */
function checkAll (id, checked) {
- var el = document.getElementById(id);
- for (var i = 0; i < el.elements.length; i++) {
- if (el.elements[i].disabled==false) {
- el.elements[i].checked = checked;
+ var els = Element.descendants(id);
+ for (var i = 0; i < els.length; i++) {
+ if (els[i].disabled==false) {
+ els[i].checked = checked;
}
}
}
diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css
index 26f66f0b8..8e4bf995c 100644
--- a/public/stylesheets/application.css
+++ b/public/stylesheets/application.css
@@ -223,6 +223,8 @@ height: 1%;
clear:left;
}
+html>body .tabular p {overflow:auto;}
+
.tabular label{
font-weight: bold;
float: left;
@@ -239,6 +241,8 @@ text-align: left;
width: 200px;
}
+input#time_entry_comments { width: 90%;}
+
#preview fieldset {margin-top: 1em; background: url(../images/draft.png)}
.tabular.settings p{ padding-left: 300px; }
diff --git a/test/fixtures/issues.yml b/test/fixtures/issues.yml
index 4f42d93c4..48195a7b7 100644
--- a/test/fixtures/issues.yml
+++ b/test/fixtures/issues.yml
@@ -71,4 +71,20 @@ issues_005:
assigned_to_id:
author_id: 2
status_id: 1
-
+issues_006:
+ created_on: <%= 1.minute.ago.to_date.to_s(:db) %>
+ project_id: 5
+ updated_on: <%= 1.minute.ago.to_date.to_s(:db) %>
+ priority_id: 4
+ subject: Issue of a private subproject
+ id: 6
+ fixed_version_id:
+ category_id:
+ description: This is an issue of a private subproject of cookbook
+ tracker_id: 1
+ assigned_to_id:
+ author_id: 2
+ status_id: 1
+ start_date: <%= Date.today.to_s(:db) %>
+ due_date: <%= 1.days.from_now.to_date.to_s(:db) %>
+ \ No newline at end of file
diff --git a/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb
index a6d2ca6e3..c4389fedd 100644
--- a/test/functional/issues_controller_test.rb
+++ b/test/functional/issues_controller_test.rb
@@ -53,13 +53,44 @@ class IssuesControllerTest < Test::Unit::TestCase
assert_template 'index.rhtml'
assert_not_nil assigns(:issues)
assert_nil assigns(:project)
+ assert_tag :tag => 'a', :content => /Can't print recipes/
+ assert_tag :tag => 'a', :content => /Subproject issue/
+ # private projects hidden
+ assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
+ assert_no_tag :tag => 'a', :content => /Issue on project 2/
end
def test_index_with_project
+ Setting.display_subprojects_issues = 0
get :index, :project_id => 1
assert_response :success
assert_template 'index.rhtml'
assert_not_nil assigns(:issues)
+ assert_tag :tag => 'a', :content => /Can't print recipes/
+ assert_no_tag :tag => 'a', :content => /Subproject issue/
+ end
+
+ def test_index_with_project_and_subprojects
+ Setting.display_subprojects_issues = 1
+ get :index, :project_id => 1
+ assert_response :success
+ assert_template 'index.rhtml'
+ assert_not_nil assigns(:issues)
+ assert_tag :tag => 'a', :content => /Can't print recipes/
+ assert_tag :tag => 'a', :content => /Subproject issue/
+ assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
+ end
+
+ def test_index_with_project_and_subprojects_should_show_private_subprojects
+ @request.session[:user_id] = 2
+ Setting.display_subprojects_issues = 1
+ get :index, :project_id => 1
+ assert_response :success
+ assert_template 'index.rhtml'
+ assert_not_nil assigns(:issues)
+ assert_tag :tag => 'a', :content => /Can't print recipes/
+ assert_tag :tag => 'a', :content => /Subproject issue/
+ assert_tag :tag => 'a', :content => /Issue of a private subproject/
end
def test_index_with_project_and_filter
diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb
index 5af7b5572..bebe96f29 100644
--- a/test/functional/projects_controller_test.rb
+++ b/test/functional/projects_controller_test.rb
@@ -29,6 +29,7 @@ class ProjectsControllerTest < Test::Unit::TestCase
@controller = ProjectsController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
+ @request.session[:user_id] = nil
end
def test_index
@@ -237,11 +238,21 @@ class ProjectsControllerTest < Test::Unit::TestCase
assert_not_nil assigns(:calendar)
end
- def test_calendar_with_subprojects
+ def test_calendar_with_subprojects_should_not_show_private_subprojects
get :calendar, :id => 1, :with_subprojects => 1, :tracker_ids => [1, 2]
assert_response :success
assert_template 'calendar'
assert_not_nil assigns(:calendar)
+ assert_no_tag :tag => 'a', :content => /#6/
+ end
+
+ def test_calendar_with_subprojects_should_show_private_subprojects
+ @request.session[:user_id] = 2
+ get :calendar, :id => 1, :with_subprojects => 1, :tracker_ids => [1, 2]
+ assert_response :success
+ assert_template 'calendar'
+ assert_not_nil assigns(:calendar)
+ assert_tag :tag => 'a', :content => /#6/
end
def test_gantt
@@ -251,13 +262,23 @@ class ProjectsControllerTest < Test::Unit::TestCase
assert_not_nil assigns(:events)
end
- def test_gantt_with_subprojects
+ def test_gantt_with_subprojects_should_not_show_private_subprojects
get :gantt, :id => 1, :with_subprojects => 1, :tracker_ids => [1, 2]
assert_response :success
assert_template 'gantt.rhtml'
assert_not_nil assigns(:events)
+ assert_no_tag :tag => 'a', :content => /#6/
end
+ def test_gantt_with_subprojects_should_show_private_subprojects
+ @request.session[:user_id] = 2
+ get :gantt, :id => 1, :with_subprojects => 1, :tracker_ids => [1, 2]
+ assert_response :success
+ assert_template 'gantt.rhtml'
+ assert_not_nil assigns(:events)
+ assert_tag :tag => 'a', :content => /#6/
+ end
+
def test_gantt_export_to_pdf
get :gantt, :id => 1, :format => 'pdf'
assert_response :success
diff --git a/test/unit/attachment_test.rb b/test/unit/attachment_test.rb
new file mode 100644
index 000000000..99f7c29f9
--- /dev/null
+++ b/test/unit/attachment_test.rb
@@ -0,0 +1,32 @@
+# redMine - project management software
+# Copyright (C) 2006-2007 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+require File.dirname(__FILE__) + '/../test_helper'
+
+class AttachmentTest < Test::Unit::TestCase
+
+ def setup
+ end
+
+ def test_diskfilename
+ assert Attachment.disk_filename("test_file.txt") =~ /^\d{12}_test_file.txt$/
+ assert_equal 'test_file.txt', Attachment.disk_filename("test_file.txt")[13..-1]
+ assert_equal '770c509475505f37c2b8fb6030434d6b.txt', Attachment.disk_filename("test_accentué.txt")[13..-1]
+ assert_equal 'f8139524ebb8f32e51976982cd20a85d', Attachment.disk_filename("test_accentué")[13..-1]
+ assert_equal 'cbb5b0f30978ba03731d61f9f6d10011', Attachment.disk_filename("test_accentué.ça")[13..-1]
+ end
+end
diff --git a/test/unit/helpers/application_helper_test.rb b/test/unit/helpers/application_helper_test.rb
index 3ab06d2a2..8bd745124 100644
--- a/test/unit/helpers/application_helper_test.rb
+++ b/test/unit/helpers/application_helper_test.rb
@@ -162,6 +162,18 @@ class ApplicationHelperTest < HelperTestCase
to_test.each { |text, result| assert_equal "<table>#{result}</table>", textilizable(text).gsub(/[\t\n]/, '') }
end
+ def test_text_formatting
+ to_test = {'*_+bold, italic and underline+_*' => '<strong><em><ins>bold, italic and underline</ins></em></strong>',
+ '(_text within parentheses_)' => '(<em>text within parentheses</em>)'
+ }
+ to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
+ end
+
+ def test_wiki_horizontal_rule
+ assert_equal '<hr />', textilizable('---')
+ assert_equal '<p>Dashes: ---</p>', textilizable('Dashes: ---')
+ end
+
def test_macro_hello_world
text = "{{hello_world}}"
assert textilizable(text).match(/Hello world!/)