summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorJean-Philippe Lang <jp_lang@yahoo.fr>2007-08-31 17:02:44 +0000
committerJean-Philippe Lang <jp_lang@yahoo.fr>2007-08-31 17:02:44 +0000
commit404bfce446915fe9dadcfce7b36d732813523e28 (patch)
tree3564a673930e64592c6d923f452baf905f9f750d /app
parent1187ad96ac4922ddd61d4292453a9bec9614abdd (diff)
downloadredmine-404bfce446915fe9dadcfce7b36d732813523e28.tar.gz
redmine-404bfce446915fe9dadcfce7b36d732813523e28.zip
Added a cross-project issue list. It displays the issues of all the projects visible by the user.
The users list available in the filters ('assigned to' / 'created by') is made of the members of all projects the current user belongs to. For now, this view is only accessible from 'My page' ('issues assigned to me' or 'issues reported by me' blocks, to view the full lists) On 'My page', assigned issue are now sorted by priority. git-svn-id: http://redmine.rubyforge.org/svn/trunk@684 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app')
-rw-r--r--app/controllers/issues_controller.rb45
-rw-r--r--app/models/project.rb6
-rw-r--r--app/models/query.rb29
-rw-r--r--app/views/issues/index.rhtml55
-rw-r--r--app/views/my/blocks/_issuesassignedtome.rhtml4
-rw-r--r--app/views/my/blocks/_issuesreportedbyme.rhtml4
6 files changed, 123 insertions, 20 deletions
diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb
index 56a9b11ca..fe1c78884 100644
--- a/app/controllers/issues_controller.rb
+++ b/app/controllers/issues_controller.rb
@@ -17,7 +17,7 @@
class IssuesController < ApplicationController
layout 'base', :except => :export_pdf
- before_filter :find_project, :authorize
+ before_filter :find_project, :authorize, :except => :index
cache_sweeper :issue_sweeper, :only => [ :edit, :change_status, :destroy ]
@@ -32,8 +32,27 @@ class IssuesController < ApplicationController
helper :watchers
include WatchersHelper
helper :attachments
- include AttachmentsHelper
+ include AttachmentsHelper
+ helper :queries
+ helper :sort
+ include SortHelper
+ def index
+ sort_init "#{Issue.table_name}.id", "desc"
+ sort_update
+ retrieve_query
+ if @query.valid?
+ @issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
+ @issue_pages = Paginator.new self, @issue_count, 25, params['page']
+ @issues = Issue.find :all, :order => sort_clause,
+ :include => [ :assigned_to, :status, :tracker, :project, :priority ],
+ :conditions => @query.statement,
+ :limit => @issue_pages.items_per_page,
+ :offset => @issue_pages.current.offset
+ end
+ render :layout => false if request.xhr?
+ end
+
def show
@status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
@custom_values = @issue.custom_values.find(:all, :include => :custom_field)
@@ -149,5 +168,25 @@ private
@html_title = "#{@project.name} - #{@issue.tracker.name} ##{@issue.id}"
rescue ActiveRecord::RecordNotFound
render_404
- end
+ end
+
+ # Retrieve query from session or build a new query
+ def retrieve_query
+ if params[:set_filter] or !session[:query] or session[:query].project_id
+ # Give it a name, required to be valid
+ @query = Query.new(:name => "_", :executed_by => logged_in_user)
+ if params[:fields] and params[:fields].is_a? Array
+ params[:fields].each do |field|
+ @query.add_filter(field, params[:operators][field], params[:values][field])
+ end
+ else
+ @query.available_filters.keys.each do |field|
+ @query.add_short_filter(field, params[field]) if params[field]
+ end
+ end
+ session[:query] = @query
+ else
+ @query = session[:query]
+ end
+ end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 241c65817..f994ed6a5 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -77,11 +77,11 @@ class Project < ActiveRecord::Base
def self.visible_by(user=nil)
if user && user.admin?
- return ["#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"]
+ return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"
elsif user && user.memberships.any?
- return ["#{Project.table_name}.status=#{Project::STATUS_ACTIVE} AND (#{Project.table_name}.is_public = ? or #{Project.table_name}.id IN (#{user.memberships.collect{|m| m.project_id}.join(',')}))", true]
+ return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE} AND (#{Project.table_name}.is_public = #{connection.quoted_true} or #{Project.table_name}.id IN (#{user.memberships.collect{|m| m.project_id}.join(',')}))"
else
- return ["#{Project.table_name}.status=#{Project::STATUS_ACTIVE} AND #{Project.table_name}.is_public = ?", true]
+ return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE} AND #{Project.table_name}.is_public = #{connection.quoted_true}"
end
end
diff --git a/app/models/query.rb b/app/models/query.rb
index ff519d71c..c700242ed 100644
--- a/app/models/query.rb
+++ b/app/models/query.rb
@@ -91,14 +91,20 @@ class Query < ActiveRecord::Base
"updated_on" => { :type => :date_past, :order => 10 },
"start_date" => { :type => :date, :order => 11 },
"due_date" => { :type => :date, :order => 12 } }
- unless project.nil?
- # project specific filters
- user_values = []
+
+ user_values = []
+ if project
+ user_values += project.users.collect{|s| [s.name, s.id.to_s] }
+ elsif executed_by
user_values << ["<< #{l(:label_me)} >>", "me"] if executed_by
- user_values += @project.users.collect{|s| [s.name, s.id.to_s] }
-
- @available_filters["assigned_to_id"] = { :type => :list_optional, :order => 4, :values => user_values }
- @available_filters["author_id"] = { :type => :list, :order => 5, :values => user_values }
+ # members of the user's projects
+ user_values += executed_by.projects.collect(&:users).flatten.uniq.sort.collect{|s| [s.name, s.id.to_s] }
+ end
+ @available_filters["assigned_to_id"] = { :type => :list_optional, :order => 4, :values => user_values } unless user_values.empty?
+ @available_filters["author_id"] = { :type => :list, :order => 5, :values => user_values } unless user_values.empty?
+
+ if project
+ # project specific filters
@available_filters["category_id"] = { :type => :list_optional, :order => 6, :values => @project.issue_categories.collect{|s| [s.name, s.id.to_s] } }
@available_filters["fixed_version_id"] = { :type => :list_optional, :order => 7, :values => @project.versions.sort.collect{|s| [s.name, s.id.to_s] } }
unless @project.active_children.empty?
@@ -166,7 +172,7 @@ class Query < ActiveRecord::Base
def statement
# project/subprojects clause
clause = ''
- if has_filter?("subproject_id")
+ if project && has_filter?("subproject_id")
subproject_ids = []
if operator_for("subproject_id") == "="
subproject_ids = values_for("subproject_id").each(&:to_i)
@@ -174,8 +180,10 @@ class Query < ActiveRecord::Base
subproject_ids = project.active_children.collect{|p| p.id}
end
clause << "#{Issue.table_name}.project_id IN (%d,%s)" % [project.id, subproject_ids.join(",")] if project
+ elsif project
+ clause << "#{Issue.table_name}.project_id=%d" % project.id
else
- clause << "#{Issue.table_name}.project_id=%d" % project.id if project
+ clause << Project.visible_by(executed_by)
end
# filters clauses
@@ -239,7 +247,8 @@ class Query < ActiveRecord::Base
filters_clauses << sql
end if filters and valid?
- clause << (' AND ' + filters_clauses.join(' AND ')) unless filters_clauses.empty?
+ clause << ' AND ' unless clause.empty?
+ clause << filters_clauses.join(' AND ') unless filters_clauses.empty?
clause
end
end
diff --git a/app/views/issues/index.rhtml b/app/views/issues/index.rhtml
new file mode 100644
index 000000000..0f63ba96f
--- /dev/null
+++ b/app/views/issues/index.rhtml
@@ -0,0 +1,55 @@
+<h2><%=l(:label_issue_plural)%></h2>
+
+<% form_tag({}, :id => 'query_form') do %>
+<%= render :partial => 'queries/filters', :locals => {:query => @query} %>
+<% end %>
+<div class="contextual">
+<%= link_to_remote l(:button_apply),
+ { :url => { :set_filter => 1 },
+ :update => "content",
+ :with => "Form.serialize('query_form')"
+ }, :class => 'icon icon-edit' %>
+
+<%= link_to_remote l(:button_clear),
+ { :url => { :set_filter => 1 },
+ :update => "content",
+ }, :class => 'icon icon-reload' %>
+</div>
+<br />&nbsp;
+
+<%= error_messages_for 'query' %>
+<% if @query.valid? %>
+<% if @issues.empty? %>
+<p><i><%= l(:label_no_data) %></i></p>
+<% else %>
+&nbsp;
+<table class="list">
+ <thead><tr>
+ <%= sort_header_tag("#{Issue.table_name}.id", :caption => '#') %>
+ <%= sort_header_tag("#{Project.table_name}.name", :caption => l(:field_project)) %>
+ <%= sort_header_tag("#{Issue.table_name}.tracker_id", :caption => l(:field_tracker)) %>
+ <%= sort_header_tag("#{IssueStatus.table_name}.name", :caption => l(:field_status)) %>
+ <%= sort_header_tag("#{Issue.table_name}.priority_id", :caption => l(:field_priority)) %>
+ <th><%=l(:field_subject)%></th>
+ <%= sort_header_tag("#{User.table_name}.lastname", :caption => l(:field_assigned_to)) %>
+ <%= sort_header_tag("#{Issue.table_name}.updated_on", :caption => l(:field_updated_on)) %>
+ </tr></thead>
+ <tbody>
+ <% for issue in @issues %>
+ <tr class="<%= cycle("odd", "even") %>">
+ <td align="center" valign="top"><%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %></td>
+ <td align="center" valign="top" nowrap><%=h issue.project.name %></td>
+ <td align="center" valign="top" nowrap><%= issue.tracker.name %></td>
+ <td valign="top"nowrap><div class="square" style="background:#<%= issue.status.html_color %>;"></div> <%= issue.status.name %></td>
+ <td align="center" valign="top"><%= issue.priority.name %></td>
+ <td><%= link_to h(issue.subject), :controller => 'issues', :action => 'show', :id => issue %></td>
+ <td align="center" valign="top" nowrap><%= issue.assigned_to.name if issue.assigned_to %></td>
+ <td align="center" valign="top" nowrap><%= format_time(issue.updated_on) %></td>
+ </tr>
+ <% end %>
+ </tbody>
+</table>
+<p><%= pagination_links_full @issue_pages %>
+[ <%= @issue_pages.current.first_item %> - <%= @issue_pages.current.last_item %> / <%= @issue_count %> ]</p>
+<% end %>
+<% end %>
diff --git a/app/views/my/blocks/_issuesassignedtome.rhtml b/app/views/my/blocks/_issuesassignedtome.rhtml
index 0d49279f4..9b97cb39d 100644
--- a/app/views/my/blocks/_issuesassignedtome.rhtml
+++ b/app/views/my/blocks/_issuesassignedtome.rhtml
@@ -3,8 +3,8 @@
:conditions => ["assigned_to_id=? AND #{IssueStatus.table_name}.is_closed=? AND #{Project.table_name}.status=#{Project::STATUS_ACTIVE}", user.id, false],
:limit => 10,
:include => [ :status, :project, :tracker ],
- :order => "#{Issue.table_name}.updated_on DESC") %>
+ :order => "#{Issue.table_name}.priority_id DESC, #{Issue.table_name}.updated_on DESC") %>
<%= render :partial => 'issues/list_simple', :locals => { :issues => assigned_issues } %>
<% if assigned_issues.length > 0 %>
-<p><%=lwr(:label_last_updates, assigned_issues.length)%></p>
+<p class="small"><%= link_to l(:label_issue_view_all), :controller => 'issues', :action => 'index', :set_filter => 1, :assigned_to_id => 'me' %></p>
<% end %>
diff --git a/app/views/my/blocks/_issuesreportedbyme.rhtml b/app/views/my/blocks/_issuesreportedbyme.rhtml
index 250e8265d..a0770846c 100644
--- a/app/views/my/blocks/_issuesreportedbyme.rhtml
+++ b/app/views/my/blocks/_issuesreportedbyme.rhtml
@@ -6,5 +6,5 @@
:order => "#{Issue.table_name}.updated_on DESC") %>
<%= render :partial => 'issues/list_simple', :locals => { :issues => reported_issues } %>
<% if reported_issues.length > 0 %>
-<p><%=lwr(:label_last_updates, reported_issues.length)%></p>
-<% end %> \ No newline at end of file
+<p class="small"><%= link_to l(:label_issue_view_all), :controller => 'issues', :action => 'index', :set_filter => 1, :author_id => 'me' %></p>
+<% end %>