1
0
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:
Jean-Philippe Lang 2006-12-09 12:01:20 +00:00
parent d5192b82aa
commit da91e5e95a
12 changed files with 333 additions and 25 deletions

View File

@ -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

View 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

View File

@ -0,0 +1,2 @@
module QueriesHelper
end

View 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

View File

@ -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>
&nbsp;
<table class="listTableContent">
<tr>

View 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>

View 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]-->

View 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 %>

View 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' %>

View 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 %>

View 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' %>

View File

@ -213,7 +213,7 @@ select {
vertical-align: middle;
}
select.select-small
.select-small
{
border: 1px solid #7F9DB9;
padding: 1px;