Added per user custom queries.

Any logged in user can now save queries (they are not visible to the other users).
Only users with explicit permission can manage queries that are visible to anyone.
The queries list is removed from the "Reports" view. It can now be accessed from the issues list.

git-svn-id: http://redmine.rubyforge.org/svn/trunk@566 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Jean-Philippe Lang 2007-06-23 13:49:29 +00:00
parent 5332c4362c
commit 1c44600c62
17 changed files with 112 additions and 74 deletions

View File

@ -288,8 +288,7 @@ class ProjectsController < ApplicationController
:conditions => @query.statement, :conditions => @query.statement,
:limit => @issue_pages.items_per_page, :limit => @issue_pages.items_per_page,
:offset => @issue_pages.current.offset :offset => @issue_pages.current.offset
end end
@trackers = Tracker.find :all, :order => 'position'
render :layout => false if request.xhr? render :layout => false if request.xhr?
end end
@ -400,22 +399,6 @@ class ProjectsController < ApplicationController
end end
end end
def add_query
@query = Query.new(params[:query])
@query.project = @project
@query.user = logged_in_user
params[:fields].each do |field|
@query.add_filter(field, params[:operators][field], params[:values][field])
end if params[:fields]
if request.post? and @query.save
flash[:notice] = l(:notice_successful_create)
redirect_to :controller => 'reports', :action => 'issue_report', :id => @project
end
render :layout => false if request.xhr?
end
# Add a news to @project # Add a news to @project
def add_news def add_news
@news = News.new(:project => @project) @news = News.new(:project => @project)

View File

@ -1,5 +1,5 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006-2007 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@ -16,9 +16,35 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class QueriesController < ApplicationController class QueriesController < ApplicationController
layout 'base' layout 'base'
before_filter :require_login, :find_query before_filter :require_login, :except => :index
before_filter :find_project, :check_project_privacy
def index
@queries = @project.queries.find(:all,
:order => "name ASC",
:conditions => ["is_public = ? or user_id = ?", true, (logged_in_user ? logged_in_user.id : 0)])
end
def new
@query = Query.new(params[:query])
@query.project = @project
@query.user = logged_in_user
@query.executed_by = logged_in_user
@query.is_public = false unless logged_in_user.authorized_to(@project, 'projects/add_query')
params[:fields].each do |field|
@query.add_filter(field, params[:operators][field], params[:values][field])
end if params[:fields]
if request.post? and @query.save
flash[:notice] = l(:notice_successful_create)
redirect_to :controller => 'projects', :action => 'list_issues', :id => @project, :query_id => @query
return
end
render :layout => false if request.xhr?
end
def edit def edit
if request.post? if request.post?
@query.filters = {} @query.filters = {}
@ -26,6 +52,7 @@ class QueriesController < ApplicationController
@query.add_filter(field, params[:operators][field], params[:values][field]) @query.add_filter(field, params[:operators][field], params[:values][field])
end if params[:fields] end if params[:fields]
@query.attributes = params[:query] @query.attributes = params[:query]
@query.is_public = false unless logged_in_user.authorized_to(@project, 'projects/add_query')
if @query.save if @query.save
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
@ -36,16 +63,19 @@ class QueriesController < ApplicationController
def destroy def destroy
@query.destroy if request.post? @query.destroy if request.post?
redirect_to :controller => 'reports', :action => 'issue_report', :id => @project redirect_to :controller => 'queries', :project_id => @project
end end
private private
def find_query def find_project
@query = Query.find(params[:id]) if params[:id]
@query.executed_by = logged_in_user @query = Query.find(params[:id])
@project = @query.project @query.executed_by = logged_in_user
# check if user is allowed to manage queries (same permission as add_query) @project = @query.project
authorize('projects', 'add_query') render_403 unless @query.editable_by?(logged_in_user)
else
@project = Project.find(params[:project_id])
end
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end

View File

@ -60,7 +60,6 @@ class ReportsController < ApplicationController
@report_title = l(:field_subproject) @report_title = l(:field_subproject)
render :template => "reports/issue_report_details" render :template => "reports/issue_report_details"
else else
@queries = @project.queries.find :all, :conditions => ["is_public=? or user_id=?", true, (logged_in_user ? logged_in_user.id : 0)]
@trackers = Tracker.find(:all, :order => 'position') @trackers = Tracker.find(:all, :order => 'position')
@versions = @project.versions.sort @versions = @project.versions.sort
@priorities = Enumeration::get_values('IPRI') @priorities = Enumeration::get_values('IPRI')

View File

@ -57,7 +57,6 @@ class Query < ActiveRecord::Base
def initialize(attributes = nil) def initialize(attributes = nil)
super attributes super attributes
self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} } self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} }
self.is_public = true
end end
def executed_by=(user) def executed_by=(user)
@ -75,6 +74,12 @@ class Query < ActiveRecord::Base
end if filters end if filters
end end
def editable_by?(user)
return false unless user
return true if !is_public && self.user_id == user.id
is_public && user.authorized_to(project, "projects/add_query")
end
def available_filters def available_filters
return @available_filters if @available_filters return @available_filters if @available_filters
@available_filters = { "status_id" => { :type => :list_status, :order => 1, :values => IssueStatus.find(:all, :order => 'position').collect{|s| [s.name, s.id.to_s] } }, @available_filters = { "status_id" => { :type => :list_status, :order => 1, :values => IssueStatus.find(:all, :order => 'position').collect{|s| [s.name, s.id.to_s] } },

View File

@ -125,10 +125,17 @@ class User < ActiveRecord::Base
end end
def role_for_project(project) def role_for_project(project)
return nil unless project
member = memberships.detect {|m| m.project_id == project.id} member = memberships.detect {|m| m.project_id == project.id}
member ? member.role : nil member ? member.role : nil
end end
def authorized_to(project, action)
return true if self.admin?
role = role_for_project(project)
role && Permission.allowed_to_role(action, role)
end
def pref def pref
self.preference ||= UserPreference.new(:user => self) self.preference ||= UserPreference.new(:user => self)
end end

View File

@ -1,5 +0,0 @@
<% if authorize_for('projects', 'add_issue') %>
<% form_tag({ :controller => 'projects', :action => 'add_issue', :id => @project }, :method => 'get') do %>
<%= l(:label_issue_new) %>: <%= select_tag 'tracker_id', ("<option></option>" + options_from_collection_for_select(trackers, 'id', 'name')), :onchange => "if (this.value!='') {this.form.submit();}" %>
<% end %>
<% end %>

View File

@ -77,6 +77,9 @@
<%= link_to l(:label_calendar), {:controller => 'projects', :action => 'calendar', :id => @project }, :class => "menuItem" %> <%= link_to l(:label_calendar), {:controller => 'projects', :action => 'calendar', :id => @project }, :class => "menuItem" %>
<%= link_to l(:label_gantt), {:controller => 'projects', :action => 'gantt', :id => @project }, :class => "menuItem" %> <%= link_to l(:label_gantt), {:controller => 'projects', :action => 'gantt', :id => @project }, :class => "menuItem" %>
<%= link_to l(:label_issue_plural), {:controller => 'projects', :action => 'list_issues', :id => @project }, :class => "menuItem" %> <%= link_to l(:label_issue_plural), {:controller => 'projects', :action => 'list_issues', :id => @project }, :class => "menuItem" %>
<% if @project && authorize_for('projects', 'add_issue') %>
<a class="menuItem" href="#" onmouseover="menuItemMouseover(event,'menuNewIssue');" onclick="this.blur(); return false;"><span class="menuItemText"><%= l(:label_issue_new) %></span><span class="menuItemArrow">&#9654;</span></a>
<% end %>
<%= link_to l(:label_report_plural), {:controller => 'reports', :action => 'issue_report', :id => @project }, :class => "menuItem" %> <%= link_to l(:label_report_plural), {:controller => 'reports', :action => 'issue_report', :id => @project }, :class => "menuItem" %>
<%= link_to l(:label_activity), {:controller => 'projects', :action => 'activity', :id => @project }, :class => "menuItem" %> <%= link_to l(:label_activity), {:controller => 'projects', :action => 'activity', :id => @project }, :class => "menuItem" %>
<%= link_to l(:label_news_plural), {:controller => 'projects', :action => 'list_news', :id => @project }, :class => "menuItem" %> <%= link_to l(:label_news_plural), {:controller => 'projects', :action => 'list_news', :id => @project }, :class => "menuItem" %>
@ -91,6 +94,14 @@
<%= link_to_if_authorized l(:label_settings), {:controller => 'projects', :action => 'settings', :id => @project }, :class => "menuItem" %> <%= link_to_if_authorized l(:label_settings), {:controller => 'projects', :action => 'settings', :id => @project }, :class => "menuItem" %>
</div> </div>
<% end %> <% end %>
<% if @project && authorize_for('projects', 'add_issue') %>
<div id="menuNewIssue" class="menu" onmouseover="menuMouseover(event)">
<% Tracker.find(:all, :order => 'position').each do |tracker| %>
<%= link_to tracker.name, {:controller => 'projects', :action => 'add_issue', :id => @project, :tracker_id => tracker}, :class => "menuItem" %>
<% end %>
</div>
<% end %>
<% if loggedin? and @logged_in_user.memberships.any? %> <% if loggedin? and @logged_in_user.memberships.any? %>
<div id="menuAllProjects" class="menu" onmouseover="menuMouseover(event)"> <div id="menuAllProjects" class="menu" onmouseover="menuMouseover(event)">

View File

@ -1,6 +0,0 @@
<h2><%= l(:label_query_new) %></h2>
<% form_tag({:action => 'add_query', :id => @project}) do %>
<%= render :partial => 'queries/form', :locals => {:query => @query} %>
<%= submit_tag l(:button_create) %>
<% end %>

View File

@ -1,6 +1,6 @@
<% if @query.new_record? %> <% if @query.new_record? %>
<div class="contextual"> <div class="contextual">
<%= render :partial => 'issues/add_shortcut', :locals => {:trackers => @trackers } %> <%= link_to l(:label_query_plural), :controller => 'queries', :project_id => @project %>
</div> </div>
<h2><%=l(:label_issue_plural)%></h2> <h2><%=l(:label_issue_plural)%></h2>
@ -19,9 +19,9 @@
:update => "content", :update => "content",
}, :class => 'icon icon-reload' %> }, :class => 'icon icon-reload' %>
<% if authorize_for('projects', 'add_query') %> <% if loggedin? %>
<%= link_to_remote l(:button_save), <%= link_to_remote l(:button_save),
{ :url => { :controller => 'projects', :action => "add_query", :id => @project }, { :url => { :controller => 'queries', :action => 'new', :project_id => @project },
:method => 'get', :method => 'get',
:update => "content", :update => "content",
:with => "Form.serialize('query_form')" :with => "Form.serialize('query_form')"
@ -31,12 +31,8 @@
<br /> <br />
<% else %> <% else %>
<div class="contextual"> <div class="contextual">
<%= render :partial => 'issues/add_shortcut', :locals => {:trackers => @trackers } %> <%= link_to l(:label_query_plural), {:controller => 'queries', :project_id => @project} %> |
<%= link_to l(:button_clear), {:controller => 'projects', :action => 'list_issues', :id => @project, :set_filter => 1}, :class => 'icon icon-reload' %> <%= link_to l(:label_issue_view_all), {:controller => 'projects', :action => 'list_issues', :id => @project, :set_filter => 1} %>
<% if authorize_for('projects', 'add_query') %>
<%= link_to l(:button_edit), {:controller => 'queries', :action => 'edit', :id => @query}, :class => 'icon icon-edit' %>
<%= link_to l(:button_delete), {:controller => 'queries', :action => 'destroy', :id => @query}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
<% end %>
</div> </div>
<h2><%= @query.name %></h2> <h2><%= @query.name %></h2>
<% end %> <% end %>

View File

@ -20,9 +20,6 @@
</ul> </ul>
<div class="box"> <div class="box">
<div class="contextual">
<%= render :partial => 'issues/add_shortcut', :locals => {:trackers => @trackers } %>
</div>
<h3 class="icon22 icon22-tracker"><%=l(:label_issue_tracking)%></h3> <h3 class="icon22 icon22-tracker"><%=l(:label_issue_tracking)%></h3>
<ul> <ul>
<% for tracker in @trackers %> <% for tracker in @trackers %>

View File

@ -55,7 +55,7 @@ function toggle_multi_select(field) {
//]]> //]]>
</script> </script>
<fieldset style="margin:0;"><legend><%= l(:label_filter_plural) %></legend> <fieldset><legend><%= l(:label_filter_plural) %></legend>
<table width="100%"> <table width="100%">
<tr> <tr>
<td> <td>

View File

@ -1,12 +1,15 @@
<%= error_messages_for 'query' %> <%= error_messages_for 'query' %>
<!--[form:query]-->
<div class="box"> <div class="box">
<div class="tabular"> <div class="tabular">
<p><label for="query_name"><%=l(:field_name)%></label> <p><label for="query_name"><%=l(:field_name)%></label>
<%= text_field 'query', 'name', :size => 80 %></p> <%= text_field 'query', 'name', :size => 80 %></p>
<% if authorize_for('projects', 'add_query') %>
<p><label for="query_is_public"><%=l(:field_is_public)%></label>
<%= check_box 'query', 'is_public' %></p>
<% end %>
</div> </div>
<%= render :partial => 'queries/filters', :locals => {:query => query}%> <%= render :partial => 'queries/filters', :locals => {:query => query}%>
</div> </div>
<!--[eoform:query]-->

View File

@ -3,4 +3,4 @@
<% form_tag({:action => 'edit', :id => @query}) do %> <% form_tag({:action => 'edit', :id => @query}) do %>
<%= render :partial => 'form', :locals => {:query => @query} %> <%= render :partial => 'form', :locals => {:query => @query} %>
<%= submit_tag l(:button_save) %> <%= submit_tag l(:button_save) %>
<% end %> <% end %>

View File

@ -0,0 +1,29 @@
<div class="contextual">
<% if loggedin? %>
<%= link_to l(:label_query_new), {:controller => 'queries', :action => 'new', :project_id => @project}, :class => 'icon icon-add' %>
<% end %>
</div>
<h2><%= l(:label_query_plural) %></h2>
<% if @queries.empty? %>
<p><i><%=l(:label_no_data)%></i></p>
<% else %>
<table class="list">
<% @queries.each do |query| %>
<tr class="<%= cycle('odd', 'even') %>">
<td>
<%= link_to query.name, :controller => 'projects', :action => 'list_issues', :id => @project, :query_id => query %>
</td>
<td align="right">
<small>
<% if query.editable_by?(@logged_in_user) %>
<%= link_to l(:button_edit), {:controller => 'queries', :action => 'edit', :id => query}, :class => 'icon icon-edit' %>
<%= link_to l(:button_delete), {:controller => 'queries', :action => 'destroy', :id => query}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
</small>
<% end %>
</td>
</tr>
<% end %>
</table>
<% end %>

View File

@ -0,0 +1,6 @@
<h2><%= l(:label_query_new) %></h2>
<% form_tag({:action => 'new', :project_id => @query.project}) do %>
<%= render :partial => 'form', :locals => {:query => @query} %>
<%= submit_tag l(:button_save) %>
<% end %>

View File

@ -1,27 +1,10 @@
<h2><%=l(:label_report_plural)%></h2> <h2><%=l(:label_report_plural)%></h2>
<div class="splitcontentleft">
<div class="contextual">
<%= link_to_if_authorized l(:label_query_new), {:controller => 'projects', :action => 'add_query', :id => @project}, :class => 'icon icon-add' %>
</div>
<h3><%= l(:label_query_plural) %></h3>
<% if @queries.empty? %><p><i><%=l(:label_no_data)%></i></p><% end %>
<ul>
<% @queries.each do |query| %>
<li><%= link_to query.name, :controller => 'projects', :action => 'list_issues', :id => @project, :query_id => query %></li>
<% end %>
</ul>
</div>
<div class="splitcontentright">
<% if @total_hours %> <% if @total_hours %>
<h3 class="textright"><%= l(:label_spent_time) %>: <h3 class="textright"><%= l(:label_spent_time) %>:
<%= link_to(lwr(:label_f_hour, @total_hours), {:controller => 'timelog', :action => 'details', :project_id => @project}, :class => 'icon icon-time') %> <%= link_to(lwr(:label_f_hour, @total_hours), {:controller => 'timelog', :action => 'details', :project_id => @project}, :class => 'icon icon-time') %>
</h3> </h3>
<% end %> <% end %>
</div>
<div class="clear"></div>
<div class="splitcontentleft"> <div class="splitcontentleft">
<h3><%=l(:field_tracker)%>&nbsp;&nbsp;<%= link_to image_tag('zoom_in.png'), :detail => 'tracker' %></h3> <h3><%=l(:field_tracker)%>&nbsp;&nbsp;<%= link_to image_tag('zoom_in.png'), :detail => 'tracker' %></h3>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 591 B

After

Width:  |  Height:  |  Size: 498 B