diff --git a/.gitignore b/.gitignore
index 123812cc..f4461f60 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,8 @@
/db/*.sqlite3
/db/schema.rb
/files/*
+/lib/redmine/scm/adapters/mercurial/redminehelper.pyc
+/lib/redmine/scm/adapters/mercurial/redminehelper.pyo
/log/*.log*
/log/mongrel_debug
/public/dispatch.*
diff --git a/.hgignore b/.hgignore
index 733faf9f..e407dd69 100644
--- a/.hgignore
+++ b/.hgignore
@@ -12,6 +12,8 @@ db/*.db
db/*.sqlite3
db/schema.rb
files/*
+lib/redmine/scm/adapters/mercurial/redminehelper.pyc
+lib/redmine/scm/adapters/mercurial/redminehelper.pyo
log/*.log*
log/mongrel_debug
public/dispatch.*
@@ -23,3 +25,5 @@ tmp/sockets/*
tmp/test/*
vendor/rails
*.rbc
+.svn/
+.git/
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 29e4e4b0..db56eff9 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -132,7 +132,7 @@ class GroupsController < ApplicationController
def autocomplete_for_user
@group = Group.find(params[:id])
- @users = User.active.like(params[:q]).find(:all, :limit => 100) - @group.users
+ @users = User.active.not_in_group(@group).like(params[:q]).all(:limit => 100)
render :layout => false
end
diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb
index 051f8910..fdce296c 100644
--- a/app/controllers/issues_controller.rb
+++ b/app/controllers/issues_controller.rb
@@ -112,7 +112,7 @@ class IssuesController < ApplicationController
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@edit_allowed = User.current.allowed_to?(:edit_issues, @project)
@priorities = IssuePriority.all
- @time_entry = TimeEntry.new
+ @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
respond_to do |format|
format.html { render :template => 'issues/show.rhtml' }
format.api
@@ -236,7 +236,13 @@ class IssuesController < ApplicationController
return unless api_request?
end
end
- @issues.each(&:destroy)
+ @issues.each do |issue|
+ begin
+ issue.reload.destroy
+ rescue ::ActiveRecord::RecordNotFound # raised by #reload if issue no longer exists
+ # nothing to do, issue was already deleted (eg. by a parent)
+ end
+ end
respond_to do |format|
format.html { redirect_back_or_default(:action => 'index', :project_id => @project) }
format.api { head :ok }
@@ -265,7 +271,7 @@ private
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@priorities = IssuePriority.all
@edit_allowed = User.current.allowed_to?(:edit_issues, @project)
- @time_entry = TimeEntry.new
+ @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
@time_entry.attributes = params[:time_entry]
@notes = params[:notes] || (params[:issue].present? ? params[:issue][:notes] : nil)
diff --git a/app/controllers/journals_controller.rb b/app/controllers/journals_controller.rb
index 1f65dc82..ac3cbb67 100644
--- a/app/controllers/journals_controller.rb
+++ b/app/controllers/journals_controller.rb
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2008 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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
@@ -16,13 +16,15 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class JournalsController < ApplicationController
- before_filter :find_journal, :only => [:edit]
+ before_filter :find_journal, :only => [:edit, :diff]
before_filter :find_issue, :only => [:new]
before_filter :find_optional_project, :only => [:index]
- before_filter :authorize, :only => [:new, :edit]
+ before_filter :authorize, :only => [:new, :edit, :diff]
accept_key_auth :index
-
+ menu_item :issues
+
helper :issues
+ helper :custom_fields
helper :queries
include QueriesHelper
helper :sort
@@ -44,6 +46,17 @@ class JournalsController < ApplicationController
render_404
end
+ def diff
+ @issue = @journal.issue
+ if params[:detail_id].present?
+ @detail = @journal.details.find_by_id(params[:detail_id])
+ else
+ @detail = @journal.details.detect {|d| d.prop_key == 'description'}
+ end
+ (render_404; return false) unless @issue && @detail
+ @diff = Redmine::Helpers::Diff.new(@detail.value, @detail.old_value)
+ end
+
def new
journal = Journal.find(params[:journal_id]) if params[:journal_id]
if journal
@@ -68,6 +81,7 @@ class JournalsController < ApplicationController
end
def edit
+ (render_403; return false) unless @journal.editable_by?(User.current)
if request.post?
@journal.update_attributes(:notes => params[:notes]) if params[:notes]
@journal.destroy if @journal.details.empty? && @journal.notes.blank?
@@ -76,13 +90,21 @@ class JournalsController < ApplicationController
format.html { redirect_to :controller => 'issues', :action => 'show', :id => @journal.journalized_id }
format.js { render :action => 'update' }
end
+ else
+ respond_to do |format|
+ format.html {
+ # TODO: implement non-JS journal update
+ render :nothing => true
+ }
+ format.js
+ end
end
end
-private
+ private
+
def find_journal
@journal = Journal.find(params[:id])
- (render_403; return false) unless @journal.editable_by?(User.current)
@project = @journal.journalized.project
rescue ActiveRecord::RecordNotFound
render_404
diff --git a/app/controllers/news_controller.rb b/app/controllers/news_controller.rb
index e7c643e9..bc7eabb5 100644
--- a/app/controllers/news_controller.rb
+++ b/app/controllers/news_controller.rb
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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
@@ -25,6 +25,8 @@ class NewsController < ApplicationController
before_filter :find_optional_project, :only => :index
accept_key_auth :index
+ helper :watchers
+
def index
case params[:format]
when 'xml', 'json'
diff --git a/app/controllers/previews_controller.rb b/app/controllers/previews_controller.rb
index 612025cb..f1dbedf7 100644
--- a/app/controllers/previews_controller.rb
+++ b/app/controllers/previews_controller.rb
@@ -1,3 +1,20 @@
+# Redmine - project management software
+# Copyright (C) 2006-2011 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.
+
class PreviewsController < ApplicationController
before_filter :find_project
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 459b5478..ea2ddd13 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -1,5 +1,5 @@
# Redmine - project management software
-# Copyright (C) 2006-2009 Jean-Philippe Lang
+# Copyright (C) 2006-2011 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
@@ -143,7 +143,7 @@ class ProjectsController < ApplicationController
end
@users_by_role = @project.users_by_role
- @subprojects = @project.children.visible
+ @subprojects = @project.children.visible.all
@news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC")
@trackers = @project.rolled_up_trackers
@@ -156,11 +156,10 @@ class ProjectsController < ApplicationController
:include => [:project, :status, :tracker],
:conditions => cond)
- TimeEntry.visible_by(User.current) do
- @total_hours = TimeEntry.sum(:hours,
- :include => :project,
- :conditions => cond).to_f
+ if User.current.allowed_to?(:view_time_entries, @project)
+ @total_hours = TimeEntry.visible.sum(:hours, :include => :project, :conditions => cond).to_f
end
+
@key = User.current.rss_key
respond_to do |format|
diff --git a/app/controllers/queries_controller.rb b/app/controllers/queries_controller.rb
index 0b798636..60f3b445 100644
--- a/app/controllers/queries_controller.rb
+++ b/app/controllers/queries_controller.rb
@@ -25,10 +25,11 @@ class QueriesController < ApplicationController
@query.project = params[:query_is_for_all] ? nil : @project
@query.user = User.current
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
- @query.column_names = nil if params[:default_columns]
- @query.add_filters(params[:fields], params[:operators], params[:values]) if params[:fields]
+ @query.add_filters(params[:fields] || params[:f], params[:operators] || params[:op], params[:values] || params[:v]) if params[:fields] || params[:f]
@query.group_by ||= params[:group_by]
+ @query.column_names = params[:c] if params[:c]
+ @query.column_names = nil if params[:default_columns]
if request.post? && params[:confirm] && @query.save
flash[:notice] = l(:notice_successful_create)
@@ -41,10 +42,12 @@ class QueriesController < ApplicationController
def edit
if request.post?
@query.filters = {}
- @query.add_filters(params[:fields], params[:operators], params[:values]) if params[:fields]
+ @query.add_filters(params[:fields] || params[:f], params[:operators] || params[:op], params[:values] || params[:v]) if params[:fields] || params[:f]
@query.attributes = params[:query]
@query.project = nil if params[:query_is_for_all]
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
+ @query.group_by ||= params[:group_by]
+ @query.column_names = params[:c] if params[:c]
@query.column_names = nil if params[:default_columns]
if @query.save
diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb
index de44f1d0..47547250 100644
--- a/app/controllers/repositories_controller.rb
+++ b/app/controllers/repositories_controller.rb
@@ -77,6 +77,7 @@ class RepositoriesController < ApplicationController
@repository.fetch_changesets if Setting.autofetch_changesets? && @path.empty?
@entries = @repository.entries(@path, @rev)
+ @changeset = @repository.find_changeset_by_name(@rev)
if request.xhr?
@entries ? render(:partial => 'dir_list_content') : render(:nothing => true)
else
@@ -122,17 +123,35 @@ class RepositoriesController < ApplicationController
@content = @repository.cat(@path, @rev)
(show_error_not_found; return) unless @content
- if 'raw' == params[:format] || @content.is_binary_data? ||
- (@entry.size && @entry.size > Setting.file_max_size_displayed.to_i.kilobyte)
+ if 'raw' == params[:format] ||
+ (@content.size && @content.size > Setting.file_max_size_displayed.to_i.kilobyte) ||
+ ! is_entry_text_data?(@content, @path)
# Force the download
- send_data @content, :filename => filename_for_content_disposition(@path.split('/').last)
+ send_opt = { :filename => filename_for_content_disposition(@path.split('/').last) }
+ send_type = Redmine::MimeType.of(@path)
+ send_opt[:type] = send_type.to_s if send_type
+ send_data @content, send_opt
else
# Prevent empty lines when displaying a file with Windows style eol
+ # TODO: UTF-16
+ # Is this needs? AttachmentsController reads file simply.
@content.gsub!("\r\n", "\n")
@changeset = @repository.find_changeset_by_name(@rev)
- end
+ end
end
+ def is_entry_text_data?(ent, path)
+ # UTF-16 contains "\x00".
+ # It is very strict that file contains less than 30% of ascii symbols
+ # in non Western Europe.
+ return true if Redmine::MimeType.is_type?('text', path)
+ # Ruby 1.8.6 has a bug of integer divisions.
+ # http://apidock.com/ruby/v1_8_6_287/String/is_binary_data%3F
+ return false if ent.is_binary_data?
+ true
+ end
+ private :is_entry_text_data?
+
def annotate
@entry = @repository.entry(@path, @rev)
(show_error_not_found; return) unless @entry
@@ -218,7 +237,7 @@ class RepositoriesController < ApplicationController
@rev = params[:rev].blank? ? @repository.default_branch : params[:rev].strip
@rev_to = params[:rev_to]
- unless @rev.to_s.match(REV_PARAM_RE) && @rev.to_s.match(REV_PARAM_RE)
+ unless @rev.to_s.match(REV_PARAM_RE) && @rev_to.to_s.match(REV_PARAM_RE)
if @repository.branches.blank?
raise InvalidRevisionParam
end
diff --git a/app/controllers/timelog_controller.rb b/app/controllers/timelog_controller.rb
index f75d5833..604a8f24 100644
--- a/app/controllers/timelog_controller.rb
+++ b/app/controllers/timelog_controller.rb
@@ -40,60 +40,56 @@ class TimelogController < ApplicationController
'hours' => 'hours'
cond = ARCondition.new
- if @project.nil?
- cond << Project.allowed_to_condition(User.current, :view_time_entries)
- elsif @issue.nil?
- cond << @project.project_condition(Setting.display_subprojects_issues?)
- else
+ if @issue
cond << "#{Issue.table_name}.root_id = #{@issue.root_id} AND #{Issue.table_name}.lft >= #{@issue.lft} AND #{Issue.table_name}.rgt <= #{@issue.rgt}"
+ elsif @project
+ cond << @project.project_condition(Setting.display_subprojects_issues?)
end
retrieve_date_range
cond << ['spent_on BETWEEN ? AND ?', @from, @to]
- TimeEntry.visible_by(User.current) do
- respond_to do |format|
- format.html {
- # Paginate results
- @entry_count = TimeEntry.count(:include => [:project, :issue], :conditions => cond.conditions)
- @entry_pages = Paginator.new self, @entry_count, per_page_option, params['page']
- @entries = TimeEntry.find(:all,
- :include => [:project, :activity, :user, {:issue => :tracker}],
- :conditions => cond.conditions,
- :order => sort_clause,
- :limit => @entry_pages.items_per_page,
- :offset => @entry_pages.current.offset)
- @total_hours = TimeEntry.sum(:hours, :include => [:project, :issue], :conditions => cond.conditions).to_f
+ respond_to do |format|
+ format.html {
+ # Paginate results
+ @entry_count = TimeEntry.visible.count(:include => [:project, :issue], :conditions => cond.conditions)
+ @entry_pages = Paginator.new self, @entry_count, per_page_option, params['page']
+ @entries = TimeEntry.visible.find(:all,
+ :include => [:project, :activity, :user, {:issue => :tracker}],
+ :conditions => cond.conditions,
+ :order => sort_clause,
+ :limit => @entry_pages.items_per_page,
+ :offset => @entry_pages.current.offset)
+ @total_hours = TimeEntry.visible.sum(:hours, :include => [:project, :issue], :conditions => cond.conditions).to_f
- render :layout => !request.xhr?
- }
- format.api {
- @entry_count = TimeEntry.count(:include => [:project, :issue], :conditions => cond.conditions)
- @entry_pages = Paginator.new self, @entry_count, per_page_option, params['page']
- @entries = TimeEntry.find(:all,
- :include => [:project, :activity, :user, {:issue => :tracker}],
- :conditions => cond.conditions,
- :order => sort_clause,
- :limit => @entry_pages.items_per_page,
- :offset => @entry_pages.current.offset)
- }
- format.atom {
- entries = TimeEntry.find(:all,
- :include => [:project, :activity, :user, {:issue => :tracker}],
- :conditions => cond.conditions,
- :order => "#{TimeEntry.table_name}.created_on DESC",
- :limit => Setting.feeds_limit.to_i)
- render_feed(entries, :title => l(:label_spent_time))
- }
- format.csv {
- # Export all entries
- @entries = TimeEntry.find(:all,
- :include => [:project, :activity, :user, {:issue => [:tracker, :assigned_to, :priority]}],
- :conditions => cond.conditions,
- :order => sort_clause)
- send_data(entries_to_csv(@entries), :type => 'text/csv; header=present', :filename => 'timelog.csv')
- }
- end
+ render :layout => !request.xhr?
+ }
+ format.api {
+ @entry_count = TimeEntry.visible.count(:include => [:project, :issue], :conditions => cond.conditions)
+ @entry_pages = Paginator.new self, @entry_count, per_page_option, params['page']
+ @entries = TimeEntry.visible.find(:all,
+ :include => [:project, :activity, :user, {:issue => :tracker}],
+ :conditions => cond.conditions,
+ :order => sort_clause,
+ :limit => @entry_pages.items_per_page,
+ :offset => @entry_pages.current.offset)
+ }
+ format.atom {
+ entries = TimeEntry.visible.find(:all,
+ :include => [:project, :activity, :user, {:issue => :tracker}],
+ :conditions => cond.conditions,
+ :order => "#{TimeEntry.table_name}.created_on DESC",
+ :limit => Setting.feeds_limit.to_i)
+ render_feed(entries, :title => l(:label_spent_time))
+ }
+ format.csv {
+ # Export all entries
+ @entries = TimeEntry.visible.find(:all,
+ :include => [:project, :activity, :user, {:issue => [:tracker, :assigned_to, :priority]}],
+ :conditions => cond.conditions,
+ :order => sort_clause)
+ send_data(entries_to_csv(@entries), :type => 'text/csv; header=present', :filename => 'timelog.csv')
+ }
end
end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index c7dadf04..c0ab99a3 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -1,5 +1,5 @@
# Redmine - project management software
-# Copyright (C) 2006-2010 Jean-Philippe Lang
+# Copyright (C) 2006-2011 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
@@ -38,6 +38,9 @@ class UsersController < ApplicationController
@limit = per_page_option
end
+ scope = User
+ scope = scope.in_group(params[:group_id].to_i) if params[:group_id].present?
+
@status = params[:status] ? params[:status].to_i : 1
c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status])
@@ -46,19 +49,22 @@ class UsersController < ApplicationController
c << ["LOWER(login) LIKE ? OR LOWER(firstname) LIKE ? OR LOWER(lastname) LIKE ? OR LOWER(mail) LIKE ?", name, name, name, name]
end
- @user_count = User.count(:conditions => c.conditions)
+ @user_count = scope.count(:conditions => c.conditions)
@user_pages = Paginator.new self, @user_count, @limit, params['page']
@offset ||= @user_pages.current.offset
- @users = User.find :all,
+ @users = scope.find :all,
:order => sort_clause,
:conditions => c.conditions,
:limit => @limit,
:offset => @offset
- respond_to do |format|
- format.html { render :layout => !request.xhr? }
+ respond_to do |format|
+ format.html {
+ @groups = Group.all.sort
+ render :layout => !request.xhr?
+ }
format.api
- end
+ end
end
def show
diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb
index e7e38930..5b87f902 100644
--- a/app/controllers/wiki_controller.rb
+++ b/app/controllers/wiki_controller.rb
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2007 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 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
@@ -44,7 +44,14 @@ class WikiController < ApplicationController
# List of pages, sorted alphabetically and by parent (hierarchy)
def index
- load_pages_grouped_by_date_without_content
+ load_pages_for_index
+ @pages_by_parent_id = @pages.group_by(&:parent_id)
+ end
+
+ # List of page, by last update
+ def date_index
+ load_pages_for_index
+ @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
end
# display a page (in editing mode if it doesn't exist)
@@ -93,9 +100,6 @@ class WikiController < ApplicationController
# To prevent StaleObjectError exception when reverting to a previous version
@content.version = @page.content.version
- rescue ActiveRecord::StaleObjectError
- # Optimistic locking exception
- flash[:error] = l(:notice_locking_conflict)
end
verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
@@ -131,7 +135,8 @@ class WikiController < ApplicationController
rescue ActiveRecord::StaleObjectError
# Optimistic locking exception
- flash[:error] = l(:notice_locking_conflict)
+ flash.now[:error] = l(:notice_locking_conflict)
+ render :action => 'edit'
end
# rename a page
@@ -215,10 +220,6 @@ class WikiController < ApplicationController
redirect_to :action => 'show', :project_id => @project, :id => nil
end
end
-
- def date_index
- load_pages_grouped_by_date_without_content
- end
def preview
page = @wiki.find_page(params[:id])
@@ -266,14 +267,8 @@ private
extend helper unless self.instance_of?(helper)
helper.instance_method(:initial_page_content).bind(self).call(page)
end
-
- # eager load information about last updates, without loading text
- def load_pages_grouped_by_date_without_content
- @pages = @wiki.pages.find :all, :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on",
- :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id",
- :order => 'title'
- @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
- @pages_by_parent_id = @pages.group_by(&:parent_id)
- end
+ def load_pages_for_index
+ @pages = @wiki.pages.with_updated_on.all(:order => 'title', :include => {:wiki => :project})
+ end
end
diff --git a/app/controllers/workflows_controller.rb b/app/controllers/workflows_controller.rb
index ed464012..9ca1a98c 100644
--- a/app/controllers/workflows_controller.rb
+++ b/app/controllers/workflows_controller.rb
@@ -32,14 +32,17 @@ class WorkflowsController < ApplicationController
if request.post?
Workflow.destroy_all( ["role_id=? and tracker_id=?", @role.id, @tracker.id])
- (params[:issue_status] || []).each { |old, news|
- news.each { |new|
- @role.workflows.build(:tracker_id => @tracker.id, :old_status_id => old, :new_status_id => new)
+ (params[:issue_status] || []).each { |status_id, transitions|
+ transitions.each { |new_status_id, options|
+ author = options.is_a?(Array) && options.include?('author') && !options.include?('always')
+ assignee = options.is_a?(Array) && options.include?('assignee') && !options.include?('always')
+ @role.workflows.build(:tracker_id => @tracker.id, :old_status_id => status_id, :new_status_id => new_status_id, :author => author, :assignee => assignee)
}
}
if @role.save
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'edit', :role_id => @role, :tracker_id => @tracker
+ return
end
end
@@ -48,6 +51,14 @@ class WorkflowsController < ApplicationController
@statuses = @tracker.issue_statuses
end
@statuses ||= IssueStatus.find(:all, :order => 'position')
+
+ if @tracker && @role && @statuses.any?
+ workflows = Workflow.all(:conditions => {:role_id => @role.id, :tracker_id => @tracker.id})
+ @workflows = {}
+ @workflows['always'] = workflows.select {|w| !w.author && !w.assignee}
+ @workflows['author'] = workflows.select {|w| w.author}
+ @workflows['assignee'] = workflows.select {|w| w.assignee}
+ end
end
def copy
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 67509b22..69d55f34 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -1,5 +1,5 @@
# Redmine - project management software
-# Copyright (C) 2006-2010 Jean-Philippe Lang
+# Copyright (C) 2006-2011 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
@@ -187,15 +187,15 @@ module ApplicationHelper
end
end
- def render_page_hierarchy(pages, node=nil)
+ def render_page_hierarchy(pages, node=nil, options={})
content = ''
if pages[node]
content << "
\n"
pages[node].each do |page|
content << "- "
content << link_to(h(page.pretty_title), {:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title},
- :title => (page.respond_to?(:updated_on) ? l(:label_updated_time, distance_of_time_in_words(Time.now, page.updated_on)) : nil))
- content << "\n" + render_page_hierarchy(pages, page.id) if pages[page.id]
+ :title => (options[:timestamp] && page.updated_on ? l(:label_updated_time, distance_of_time_in_words(Time.now, page.updated_on)) : nil))
+ content << "\n" + render_page_hierarchy(pages, page.id, options) if pages[page.id]
content << "
\n"
end
content << "
\n"
@@ -223,8 +223,7 @@ module ApplicationHelper
# Renders the project quick-jump box
def render_project_jump_box
- # Retrieve them now to avoid a COUNT query
- projects = User.current.projects.all
+ projects = User.current.memberships.collect(&:project).compact.uniq
if projects.any?
s = '