mirror of
https://github.com/meineerde/redmine.git
synced 2026-03-12 04:03:08 +00:00
query model/controller added
git-svn-id: http://redmine.rubyforge.org/svn/branches/work@79 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
d5192b82aa
commit
da91e5e95a
@ -208,8 +208,10 @@ class ProjectsController < ApplicationController
|
||||
sort_init 'issues.id', 'desc'
|
||||
sort_update
|
||||
|
||||
search_filter_init_list_issues
|
||||
search_filter_update if params[:set_filter]
|
||||
@query = Query.new
|
||||
params[:fields].each do |field|
|
||||
@query.add_filter(field, params[:operators][field], params[:values][field])
|
||||
end if params[:fields]
|
||||
|
||||
@results_per_page_options = [ 15, 25, 50, 100 ]
|
||||
if params[:per_page] and @results_per_page_options.include? params[:per_page].to_i
|
||||
@ -219,11 +221,11 @@ class ProjectsController < ApplicationController
|
||||
@results_per_page = session[:results_per_page] || 25
|
||||
end
|
||||
|
||||
@issue_count = Issue.count(:include => [:status, :project], :conditions => search_filter_clause)
|
||||
@issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
|
||||
@issue_pages = Paginator.new self, @issue_count, @results_per_page, @params['page']
|
||||
@issues = Issue.find :all, :order => sort_clause,
|
||||
:include => [ :author, :status, :tracker, :project ],
|
||||
:conditions => search_filter_clause,
|
||||
:conditions => @query.statement,
|
||||
:limit => @issue_pages.items_per_page,
|
||||
:offset => @issue_pages.current.offset
|
||||
|
||||
|
||||
55
queries/trunk/app/controllers/queries_controller.rb
Normal file
55
queries/trunk/app/controllers/queries_controller.rb
Normal file
@ -0,0 +1,55 @@
|
||||
class QueriesController < ApplicationController
|
||||
layout 'base'
|
||||
|
||||
def index
|
||||
list
|
||||
render :action => 'list'
|
||||
end
|
||||
|
||||
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
|
||||
verify :method => :post, :only => [ :destroy, :create, :update ],
|
||||
:redirect_to => { :action => :list }
|
||||
|
||||
def list
|
||||
@query_pages, @queries = paginate :queries, :per_page => 10
|
||||
end
|
||||
|
||||
def show
|
||||
@query = Query.find(params[:id])
|
||||
end
|
||||
|
||||
def new
|
||||
@query = Query.new(params[: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] = 'Query was successfully created.'
|
||||
redirect_to :action => 'list'
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@query = Query.find(params[:id])
|
||||
|
||||
if request.post?
|
||||
@query.filters = {}
|
||||
params[:fields].each do |field|
|
||||
@query.add_filter(field, params[:operators][field], params[:values][field])
|
||||
end if params[:fields]
|
||||
@query.attributes = params[:query]
|
||||
|
||||
if @query.save
|
||||
flash[:notice] = 'Query was successfully updated.'
|
||||
redirect_to :action => 'show', :id => @query
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
Query.find(params[:id]).destroy
|
||||
redirect_to :action => 'list'
|
||||
end
|
||||
end
|
||||
2
queries/trunk/app/helpers/queries_helper.rb
Normal file
2
queries/trunk/app/helpers/queries_helper.rb
Normal file
@ -0,0 +1,2 @@
|
||||
module QueriesHelper
|
||||
end
|
||||
123
queries/trunk/app/models/query.rb
Normal file
123
queries/trunk/app/models/query.rb
Normal file
@ -0,0 +1,123 @@
|
||||
class Query < ActiveRecord::Base
|
||||
serialize :filters
|
||||
|
||||
validates_presence_of :name
|
||||
|
||||
@@operators = { "=" => "Egal",
|
||||
"!" => "Different",
|
||||
"o" => "Ouvert",
|
||||
"c" => "Ferme",
|
||||
"!*" => "Aucun",
|
||||
"*" => "Tous",
|
||||
"<t+" => "Dans moins de",
|
||||
">t+" => "Dans plus de",
|
||||
"t+" => "Dans exactement",
|
||||
"t" => "Aujourd'hui",
|
||||
">t-" => "Il y a moins de",
|
||||
"<t-" => "Il y a plus de",
|
||||
"t-" => "Il y a exactement" }
|
||||
|
||||
@@operators_by_filter_type = { :list => [ "=", "!" ],
|
||||
:list_status => [ "o", "=", "!", "c" ],
|
||||
:list_optional => [ "=", "!", "!*", "*" ],
|
||||
:date => [ "<t+", ">t+", "t+", "t", ">t-", "<t-", "t-" ],
|
||||
:date_past => [ ">t-", "<t-", "t-", "t" ] }
|
||||
|
||||
@@available_filters = { "status_id" => { :type => :list_status, :order => 1,
|
||||
:values => IssueStatus.find(:all).collect{|s| [s.name, s.id.to_s] } },
|
||||
"tracker_id" => { :type => :list, :order => 2,
|
||||
:values => Tracker.find(:all).collect{|s| [s.name, s.id.to_s] } },
|
||||
"assigned_to_id" => { :type => :list_optional, :order => 3,
|
||||
:values => User.find(:all).collect{|s| [s.display_name, s.id.to_s] } },
|
||||
"priority_id" => { :type => :list, :order => 4,
|
||||
:values => Enumeration.find(:all, :conditions => ['opt=?','IPRI']).collect{|s| [s.name, s.id.to_s] } },
|
||||
"created_on" => { :type => :date_past, :order => 5 },
|
||||
"updated_on" => { :type => :date_past, :order => 6 },
|
||||
"start_date" => { :type => :date, :order => 7 },
|
||||
"due_date" => { :type => :date, :order => 8 } }
|
||||
|
||||
cattr_accessor :available_filters
|
||||
|
||||
def initialize(attributes = nil)
|
||||
super
|
||||
self.filters ||= { 'status_id' => {:operator => "o"} }
|
||||
end
|
||||
|
||||
def validate
|
||||
errors.add_to_base "Au moins un critere doit etre selectionne" unless filters && !filters.empty?
|
||||
filters.each_key do |field|
|
||||
errors.add field.gsub(/\_id$/, ""), "doit etre renseigne" unless
|
||||
# filter requires one or more values
|
||||
(values_for(field) and !values_for(field).first.empty?) or
|
||||
# filter doesn't require any value
|
||||
["o", "c", "!*", "*", "t"].include? operator_for(field)
|
||||
end if filters
|
||||
end
|
||||
|
||||
def add_filter(field, operator, values)
|
||||
# values must be an array
|
||||
return unless values and values.is_a? Array
|
||||
# check if field is defined as an available filter
|
||||
if @@available_filters.has_key? field
|
||||
filter_options = @@available_filters[field]
|
||||
# check if operator is allowed for that filter
|
||||
if @@operators_by_filter_type[filter_options[:type]].include? operator
|
||||
filters[field] = {:operator => operator, :values => values }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def has_filter?(field)
|
||||
filters and filters[field]
|
||||
end
|
||||
|
||||
def operator_for(field)
|
||||
has_filter?(field) ? filters[field][:operator] : nil
|
||||
end
|
||||
|
||||
def values_for(field)
|
||||
has_filter?(field) ? filters[field][:values] : nil
|
||||
end
|
||||
|
||||
def statement
|
||||
sql = "1=1"
|
||||
filters.each_key do |field|
|
||||
sql = sql + " AND " unless sql.empty?
|
||||
v = values_for field
|
||||
case operator_for field
|
||||
when "="
|
||||
sql = sql + "issues.#{field} IN (" + v.each(&:to_i).join(",") + ")"
|
||||
when "!"
|
||||
sql = sql + "issues.#{field} NOT IN (" + v.each(&:to_i).join(",") + ")"
|
||||
when "!*"
|
||||
sql = sql + "issues.#{field} IS NULL"
|
||||
when "*"
|
||||
sql = sql + "issues.#{field} IS NOT NULL"
|
||||
when "o"
|
||||
sql = sql + "issue_statuses.is_closed=#{connection.quoted_false}" if field == "status_id"
|
||||
when "c"
|
||||
sql = sql + "issue_statuses.is_closed=#{connection.quoted_true}" if field == "status_id"
|
||||
when ">t-"
|
||||
sql = sql + "issues.#{field} >= '%s'" % connection.quoted_date(Date.today - v.first.to_i)
|
||||
when "<t-"
|
||||
sql = sql + "issues.#{field} <= '" + (Date.today - v.first.to_i).strftime("%Y-%m-%d") + "'"
|
||||
when "t-"
|
||||
sql = sql + "issues.#{field} = '" + (Date.today - v.first.to_i).strftime("%Y-%m-%d") + "'"
|
||||
when ">t+"
|
||||
sql = sql + "issues.#{field} >= '" + (Date.today + v.first.to_i).strftime("%Y-%m-%d") + "'"
|
||||
when "<t+"
|
||||
sql = sql + "issues.#{field} <= '" + (Date.today + v.first.to_i).strftime("%Y-%m-%d") + "'"
|
||||
when "t+"
|
||||
sql = sql + "issues.#{field} = '" + (Date.today + v.first.to_i).strftime("%Y-%m-%d") + "'"
|
||||
when "t"
|
||||
sql = sql + "issues.#{field} = '%s'" % connection.quoted_date(Date.today)
|
||||
end
|
||||
end if filters
|
||||
sql
|
||||
end
|
||||
|
||||
def self.operators_for_select(filter_type)
|
||||
@@operators_by_filter_type[filter_type].collect {|o| [@@operators[o], o]}
|
||||
end
|
||||
|
||||
end
|
||||
@ -7,28 +7,12 @@
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= start_form_tag :action => 'list_issues' %>
|
||||
<table cellpadding=2>
|
||||
<tr>
|
||||
<td valign="bottom"><small><%=l(:field_status)%>:</small><br /><%= search_filter_tag 'status_id', :class => 'select-small' %></td>
|
||||
<td valign="bottom"><small><%=l(:field_tracker)%>:</small><br /><%= search_filter_tag 'tracker_id', :class => 'select-small' %></td>
|
||||
<td valign="bottom"><small><%=l(:field_priority)%>:</small><br /><%= search_filter_tag 'priority_id', :class => 'select-small' %></td>
|
||||
<td valign="bottom"><small><%=l(:field_category)%>:</small><br /><%= search_filter_tag 'category_id', :class => 'select-small' %></td>
|
||||
<td valign="bottom"><small><%=l(:field_fixed_version)%>:</small><br /><%= search_filter_tag 'fixed_version_id', :class => 'select-small' %></td>
|
||||
<td valign="bottom"><small><%=l(:field_author)%>:</small><br /><%= search_filter_tag 'author_id', :class => 'select-small' %></td>
|
||||
<td valign="bottom"><small><%=l(:field_assigned_to)%>:</small><br /><%= search_filter_tag 'assigned_to_id', :class => 'select-small' %></td>
|
||||
<td valign="bottom"><small><%=l(:label_subproject_plural)%>:</small><br /><%= search_filter_tag 'subproject_id', :class => 'select-small' %></td>
|
||||
<td valign="bottom">
|
||||
<%= hidden_field_tag 'set_filter', 1 %>
|
||||
<%= submit_tag l(:button_apply), :class => 'button-small' %>
|
||||
</td>
|
||||
<td valign="bottom">
|
||||
<%= link_to l(:button_clear), :action => 'list_issues', :id => @project, :set_filter => 1 %>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<%= render :partial => 'queries/filters', :locals => {:query => @query} %>
|
||||
<%= submit_tag l(:button_apply), :class => "button-small" %>
|
||||
<%= end_form_tag %>
|
||||
|
||||
</div>
|
||||
|
||||
<table class="listTableContent">
|
||||
<tr>
|
||||
|
||||
72
queries/trunk/app/views/queries/_filters.rhtml
Normal file
72
queries/trunk/app/views/queries/_filters.rhtml
Normal file
@ -0,0 +1,72 @@
|
||||
<script>
|
||||
|
||||
function toggle_filter(field) {
|
||||
check_box = $('cb_' + field);
|
||||
|
||||
if (check_box.checked) {
|
||||
Element.show("operators[" + field + "]");
|
||||
toggle_operator(field);
|
||||
} else {
|
||||
Element.hide("operators[" + field + "]");
|
||||
Element.hide("values_div[" + field + "]");
|
||||
}
|
||||
}
|
||||
|
||||
function toggle_operator(field) {
|
||||
operator = $("operators[" + field + "]");
|
||||
switch (operator.value) {
|
||||
case "!*":
|
||||
case "*":
|
||||
case "t":
|
||||
case "o":
|
||||
case "c":
|
||||
Element.hide("values_div[" + field + "]");
|
||||
break;
|
||||
default:
|
||||
Element.show("values_div[" + field + "]");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function toggle_multi_select(field) {
|
||||
select = $('values[' + field + '][]');
|
||||
if (select.multiple == true) {
|
||||
select.multiple = false;
|
||||
} else {
|
||||
select.multiple = true;
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<fieldset><legend>Filtres</legend>
|
||||
<table>
|
||||
<% Query.available_filters.sort{|a,b| a[1][:order]<=>b[1][:order]}.each do |filter| %>
|
||||
<% field = filter[0]
|
||||
options = filter[1] %>
|
||||
<tr>
|
||||
<td valign="top" width="200">
|
||||
<%= check_box_tag 'fields[]', field, query.has_filter?(field), :onclick => "toggle_filter('#{field}');", :id => "cb_#{field}" %>
|
||||
<label for="cb_<%= field %>"><%= l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) %></label>
|
||||
</td>
|
||||
<td valign="top" width="150">
|
||||
<%= select_tag "operators[#{field}]", options_for_select(Query.operators_for_select(options[:type]), query.operator_for(field)), :onchange => "toggle_operator('#{field}');", :class => "select-small", :style => "vertical-align: top;" %>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<div id="values_div[<%= field %>]">
|
||||
<% case options[:type]
|
||||
when :list, :list_optional, :list_status %>
|
||||
<select <%= "multiple=true" if query.values_for(field) and query.values_for(field).length > 1 %>" name="values[<%= field %>][]" id="values[<%= field %>][]" class="select-small" style="vertical-align: top;">
|
||||
<%= options_for_select options[:values], query.values_for(field) %>
|
||||
</select>
|
||||
<%= link_to_function '+', "toggle_multi_select('#{field}');" %>
|
||||
<% when :date, :date_past %>
|
||||
<%= text_field_tag "values[#{field}][]", query.values_for(field), :size => 3, :class => "select-small" %> jours
|
||||
<% end %>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<script>toggle_filter('<%= field %>');</script>
|
||||
<% end %>
|
||||
</table>
|
||||
</fieldset>
|
||||
18
queries/trunk/app/views/queries/_form.rhtml
Normal file
18
queries/trunk/app/views/queries/_form.rhtml
Normal file
@ -0,0 +1,18 @@
|
||||
<%= error_messages_for 'query' %>
|
||||
|
||||
<!--[form:query]-->
|
||||
<div class="box">
|
||||
|
||||
<div class="tabular">
|
||||
<p><label for="query_name">Name</label>
|
||||
<%= text_field 'query', 'name', :size => 80 %></p>
|
||||
|
||||
<p><label for="query_is_public">Public</label>
|
||||
<%= check_box 'query', 'is_public' %></p>
|
||||
</div>
|
||||
|
||||
<%= render :partial => 'filters', :locals => {:query => query}%>
|
||||
|
||||
</div>
|
||||
<!--[eoform:query]-->
|
||||
|
||||
8
queries/trunk/app/views/queries/edit.rhtml
Normal file
8
queries/trunk/app/views/queries/edit.rhtml
Normal file
@ -0,0 +1,8 @@
|
||||
<h1>Editing query</h1>
|
||||
|
||||
<%= start_form_tag :action => 'edit', :id => @query %>
|
||||
<%= render :partial => 'form', :locals => {:query => @query} %>
|
||||
<%= submit_tag 'Edit' %>
|
||||
<%= end_form_tag %>
|
||||
|
||||
<%= debug @query.statement %>
|
||||
27
queries/trunk/app/views/queries/list.rhtml
Normal file
27
queries/trunk/app/views/queries/list.rhtml
Normal file
@ -0,0 +1,27 @@
|
||||
<h1>Listing queries</h1>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<% for column in Query.content_columns %>
|
||||
<th><%= column.human_name %></th>
|
||||
<% end %>
|
||||
</tr>
|
||||
|
||||
<% for query in @queries %>
|
||||
<tr>
|
||||
<% for column in Query.content_columns %>
|
||||
<td><%=h query.send(column.name) %></td>
|
||||
<% end %>
|
||||
<td><%= link_to 'Show', :action => 'show', :id => query %></td>
|
||||
<td><%= link_to 'Edit', :action => 'edit', :id => query %></td>
|
||||
<td><%= link_to 'Destroy', { :action => 'destroy', :id => query }, :confirm => 'Are you sure?', :post => true %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
|
||||
<%= link_to 'Previous page', { :page => @query_pages.current.previous } if @query_pages.current.previous %>
|
||||
<%= link_to 'Next page', { :page => @query_pages.current.next } if @query_pages.current.next %>
|
||||
|
||||
<br />
|
||||
|
||||
<%= link_to 'New query', :action => 'new' %>
|
||||
9
queries/trunk/app/views/queries/new.rhtml
Normal file
9
queries/trunk/app/views/queries/new.rhtml
Normal file
@ -0,0 +1,9 @@
|
||||
<h1>New query</h1>
|
||||
|
||||
<%= start_form_tag :action => 'new' %>
|
||||
<%= render :partial => 'form', :locals => {:query => @query} %>
|
||||
<%= submit_tag "Create" %>
|
||||
<%= end_form_tag %>
|
||||
|
||||
<%= debug @query %>
|
||||
<%= debug params %>
|
||||
8
queries/trunk/app/views/queries/show.rhtml
Normal file
8
queries/trunk/app/views/queries/show.rhtml
Normal file
@ -0,0 +1,8 @@
|
||||
<% for column in Query.content_columns %>
|
||||
<p>
|
||||
<b><%= column.human_name %>:</b> <%=h @query.send(column.name) %>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<%= link_to 'Edit', :action => 'edit', :id => @query %> |
|
||||
<%= link_to 'Back', :action => 'list' %>
|
||||
@ -213,7 +213,7 @@ select {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
select.select-small
|
||||
.select-small
|
||||
{
|
||||
border: 1px solid #7F9DB9;
|
||||
padding: 1px;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user