]> source.dussan.org Git - redmine.git/commitdiff
Adds support for free ticket filtering and custom queries on Calendar.
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Thu, 11 Sep 2008 17:03:26 +0000 (17:03 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Thu, 11 Sep 2008 17:03:26 +0000 (17:03 +0000)
ProjectsController#calendar moved to IssuesController.

git-svn-id: http://redmine.rubyforge.org/svn/trunk@1798 e93f8b46-1217-0410-a6f0-8f06a7374b81

12 files changed:
app/controllers/issues_controller.rb
app/controllers/projects_controller.rb
app/models/query.rb
app/views/issues/_sidebar.rhtml
app/views/issues/calendar.rhtml [new file with mode: 0644]
app/views/issues/gantt.rhtml
app/views/projects/calendar.rhtml [deleted file]
app/views/projects/show.rhtml
lib/redmine.rb
public/stylesheets/application.css
test/functional/issues_controller_test.rb
test/functional/projects_controller_test.rb

index 43a04f26d31c8ee1eeaebcbbe47f44a68e6784f4..7d39e45528168dd8d0eac2a2cc86810f8a5f9151 100644 (file)
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2007  Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2008  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
@@ -20,7 +20,7 @@ class IssuesController < ApplicationController
   
   before_filter :find_issue, :only => [:show, :edit, :reply, :destroy_attachment]
   before_filter :find_issues, :only => [:bulk_edit, :move, :destroy]
-  before_filter :find_project, :only => [:new, :update_form, :preview, :gantt]
+  before_filter :find_project, :only => [:new, :update_form, :preview, :gantt, :calendar]
   before_filter :authorize, :except => [:index, :changes, :preview, :update_form, :context_menu]
   before_filter :find_optional_project, :only => [:index, :changes]
   accept_key_auth :index, :changes
@@ -354,6 +354,33 @@ class IssuesController < ApplicationController
     end
   end
   
+  def calendar
+    if params[:year] and params[:year].to_i > 1900
+      @year = params[:year].to_i
+      if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
+        @month = params[:month].to_i
+      end    
+    end
+    @year ||= Date.today.year
+    @month ||= Date.today.month
+    
+    @calendar = Redmine::Helpers::Calendar.new(Date.civil(@year, @month, 1), current_language, :month)
+    retrieve_query
+    if @query.valid?
+      events = []
+      events += Issue.find(:all, 
+                           :include => [:tracker, :status, :assigned_to, :priority, :project], 
+                           :conditions => ["(#{@query.statement}) AND ((start_date BETWEEN ? AND ?) OR (due_date BETWEEN ? AND ?))", @calendar.startdt, @calendar.enddt, @calendar.startdt, @calendar.enddt]
+                           )
+      events += Version.find(:all, :include => :project,
+                                   :conditions => ["(#{@query.project_statement}) AND effective_date BETWEEN ? AND ?", @calendar.startdt, @calendar.enddt])
+                                     
+      @calendar.events = events
+    end
+    
+    render :layout => false if request.xhr?
+  end
+  
   def context_menu
     @issues = Issue.find_all_by_id(params[:ids], :include => :project)
     if (@issues.size == 1)
index 9e1df29a233c58eab5bcb91c0256447bced335e7..fc33336a06798835e6bcf45feaf672353d6a1691 100644 (file)
@@ -27,7 +27,7 @@ class ProjectsController < ApplicationController
   before_filter :find_optional_project, :only => :activity
   before_filter :authorize, :except => [ :index, :list, :add, :archive, :unarchive, :destroy, :activity ]
   before_filter :require_admin, :only => [ :add, :archive, :unarchive, :destroy ]
-  accept_key_auth :activity, :calendar
+  accept_key_auth :activity
   
   helper :sort
   include SortHelper
@@ -246,34 +246,6 @@ class ProjectsController < ApplicationController
     end
   end
   
-  def calendar
-    @trackers = @project.rolled_up_trackers
-    retrieve_selected_tracker_ids(@trackers)
-    
-    if params[:year] and params[:year].to_i > 1900
-      @year = params[:year].to_i
-      if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
-        @month = params[:month].to_i
-      end    
-    end
-    @year ||= Date.today.year
-    @month ||= Date.today.month    
-    @calendar = Redmine::Helpers::Calendar.new(Date.civil(@year, @month, 1), current_language, :month)
-    @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1')
-    events = []
-    @project.issues_with_subprojects(@with_subprojects) do
-      events += Issue.find(:all, 
-                           :include => [:tracker, :status, :assigned_to, :priority, :project], 
-                           :conditions => ["((start_date BETWEEN ? AND ?) OR (due_date BETWEEN ? AND ?)) AND #{Issue.table_name}.tracker_id IN (#{@selected_tracker_ids.join(',')})", @calendar.startdt, @calendar.enddt, @calendar.startdt, @calendar.enddt]
-                           ) unless @selected_tracker_ids.empty?
-      events += Version.find(:all, :include => :project,
-                                   :conditions => ["effective_date BETWEEN ? AND ?", @calendar.startdt, @calendar.enddt])
-    end
-    @calendar.events = events
-    
-    render :layout => false if request.xhr?
-  end
-  
 private
   # Find project of id params[:id]
   # if not found, redirect to project list
index 0ce9a6a215ddf75f2e80960c1823ef77002ca0be..f8c2361455f6b3295d039984e0a8e032a89c51eb 100644 (file)
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2007  Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2008  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
@@ -254,9 +254,8 @@ class Query < ActiveRecord::Base
   def has_default_columns?
     column_names.nil? || column_names.empty?
   end
-
-  def statement
-    # project/subprojects clause
+  
+  def project_statement
     project_clauses = []
     if project && !@project.active_children.empty?
       ids = [project.id]
@@ -274,12 +273,15 @@ class Query < ActiveRecord::Base
       elsif Setting.display_subprojects_issues?
         ids += project.child_ids
       end
-      project_clauses << "#{Issue.table_name}.project_id IN (%s)" % ids.join(',')
+      project_clauses << "#{Project.table_name}.id IN (%s)" % ids.join(',')
     elsif project
-      project_clauses << "#{Issue.table_name}.project_id = %d" % project.id
+      project_clauses << "#{Project.table_name}.id = %d" % project.id
     end
     project_clauses <<  Project.visible_by(User.current)
-    
+    project_clauses.join(' AND ')
+  end
+
+  def statement
     # filters clauses
     filters_clauses = []
     filters.each_key do |field|
@@ -356,7 +358,7 @@ class Query < ActiveRecord::Base
       filters_clauses << sql
     end if filters and valid?
     
-    (project_clauses + filters_clauses).join(' AND ')
+    (filters_clauses << project_statement).join(' AND ')
   end
   
   private
index bf989493917739942585ae669078eec7eba24e9f..db9351666f0960482d58ad2bad999c3aed227661 100644 (file)
@@ -5,7 +5,7 @@
 <%= link_to l(:label_change_log), :controller => 'projects', :action => 'changelog', :id => @project %>
 
 <% planning_links = []
-  planning_links << link_to_if_authorized(l(:label_calendar), :controller => 'projects', :action => 'calendar', :id => @project)
+  planning_links << link_to_if_authorized(l(:label_calendar), :action => 'calendar', :project_id => @project)
   planning_links << link_to_if_authorized(l(:label_gantt), :action => 'gantt', :project_id => @project)
   planning_links.compact!
   unless planning_links.empty? %>
diff --git a/app/views/issues/calendar.rhtml b/app/views/issues/calendar.rhtml
new file mode 100644 (file)
index 0000000..0894829
--- /dev/null
@@ -0,0 +1,55 @@
+<% form_tag({}, :id => 'query_form') do %>
+<% if @query.new_record? %>
+    <h2><%= l(:label_calendar) %></h2>
+    <fieldset id="filters"><legend><%= l(:label_filter_plural) %></legend>
+    <%= render :partial => 'queries/filters', :locals => {:query => @query} %>
+    </fieldset>
+<% else %>
+    <h2><%=h @query.name %></h2>
+    <% html_title @query.name %>
+<% end %>
+
+<fieldset id="date-range"><legend><%= l(:label_date_range) %></legend>
+    <%= select_month(@month, :prefix => "month", :discard_type => true) %>
+    <%= select_year(@year, :prefix => "year", :discard_type => true) %>
+</fieldset>
+
+<p style="float:right; margin:0px;">
+<%= link_to_remote ('&#171; ' + (@month==1 ? "#{month_name(12)} #{@year-1}" : "#{month_name(@month-1)}")), 
+                        {:update => "content", :url => { :year => (@month==1 ? @year-1 : @year), :month =>(@month==1 ? 12 : @month-1) }},
+                        {:href => url_for(:action => 'calendar', :year => (@month==1 ? @year-1 : @year), :month =>(@month==1 ? 12 : @month-1))}
+                        %> |
+<%= link_to_remote ((@month==12 ? "#{month_name(1)} #{@year+1}" : "#{month_name(@month+1)}") + ' &#187;'), 
+                        {:update => "content", :url => { :year => (@month==12 ? @year+1 : @year), :month =>(@month==12 ? 1 : @month+1) }},
+                        {:href => url_for(:action => 'calendar', :year => (@month==12 ? @year+1 : @year), :month =>(@month==12 ? 1 : @month+1))}
+                        %>
+</p>
+
+<p class="buttons">
+<%= link_to_remote l(:button_apply), 
+                   { :url => { :set_filter => (@query.new_record? ? 1 : nil) },
+                     :update => "content",
+                     :with => "Form.serialize('query_form')"
+                   }, :class => 'icon icon-checked' %>
+                   
+<%= link_to_remote l(:button_clear),
+                   { :url => { :set_filter => (@query.new_record? ? 1 : nil) }, 
+                     :update => "content",
+                   }, :class => 'icon icon-reload' if @query.new_record? %>
+</p>
+<% end %>
+
+<%= error_messages_for 'query' %>
+<% if @query.valid? %>
+<%= render :partial => 'common/calendar', :locals => {:calendar => @calendar} %>
+
+<%= image_tag 'arrow_from.png' %>&nbsp;&nbsp;<%= l(:text_tip_task_begin_day) %><br />
+<%= image_tag 'arrow_to.png' %>&nbsp;&nbsp;<%= l(:text_tip_task_end_day) %><br />
+<%= image_tag 'arrow_bw.png' %>&nbsp;&nbsp;<%= l(:text_tip_task_begin_end_day) %><br />
+<% end %>
+
+<% content_for :sidebar do %>
+    <%= render :partial => 'issues/sidebar' %>
+<% end %>
+
+<% html_title(l(:label_calendar)) -%>
index 7da657711b2ae1240b759ec95166df7414f6b937..b9af1f961b890eb9df6dbb7c34c3313c3a4b6110 100644 (file)
@@ -6,7 +6,6 @@
     </fieldset>
 <% else %>
     <h2><%=h @query.name %></h2>
-    <div id="query_form"></div>
     <% html_title @query.name %>
 <% end %>
 
diff --git a/app/views/projects/calendar.rhtml b/app/views/projects/calendar.rhtml
deleted file mode 100644 (file)
index 048d8a5..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-<h2><%= "#{month_name(@month)} #{@year}" %></h2>
-
-<table width="100%">
-<tr><td align="left">
-    <%= link_to_remote ('&#171; ' + (@month==1 ? "#{month_name(12)} #{@year-1}" : "#{month_name(@month-1)}")), 
-                        {:update => "content", :url => { :year => (@month==1 ? @year-1 : @year), :month =>(@month==1 ? 12 : @month-1), :tracker_ids => @selected_tracker_ids, :with_subprojects => params[:with_subprojects] }},
-                        {:href => url_for(:action => 'calendar', :year => (@month==1 ? @year-1 : @year), :month =>(@month==1 ? 12 : @month-1), :tracker_ids => @selected_tracker_ids, :with_subprojects => params[:with_subprojects])}
-                        %>
-</td><td align="right">
-    <%= link_to_remote ((@month==12 ? "#{month_name(1)} #{@year+1}" : "#{month_name(@month+1)}") + ' &#187;'), 
-                        {:update => "content", :url => { :year => (@month==12 ? @year+1 : @year), :month =>(@month==12 ? 1 : @month+1), :tracker_ids => @selected_tracker_ids, :with_subprojects => params[:with_subprojects] }},
-                        {:href => url_for(:action => 'calendar', :year => (@month==12 ? @year+1 : @year), :month =>(@month==12 ? 1 : @month+1), :tracker_ids => @selected_tracker_ids, :with_subprojects => params[:with_subprojects])}
-                        %>
-</td></tr>
-</table>
-
-<%= render :partial => 'common/calendar', :locals => {:calendar => @calendar} %>
-
-<%= image_tag 'arrow_from.png' %>&nbsp;&nbsp;<%= l(:text_tip_task_begin_day) %><br />
-<%= image_tag 'arrow_to.png' %>&nbsp;&nbsp;<%= l(:text_tip_task_end_day) %><br />
-<%= image_tag 'arrow_bw.png' %>&nbsp;&nbsp;<%= l(:text_tip_task_begin_end_day) %><br />
-
-<% content_for :sidebar do %>
-    <h3><%= l(:label_calendar) %></h3>
-    
-    <% form_tag({}, :method => :get) do %>
-    <p><%= select_month(@month, :prefix => "month", :discard_type => true) %>
-    <%= select_year(@year, :prefix => "year", :discard_type => true) %></p>
-    
-    <% @trackers.each do |tracker| %>
-      <label><%= check_box_tag "tracker_ids[]", tracker.id, (@selected_tracker_ids.include? tracker.id.to_s) %> <%= tracker.name %></label><br />
-    <% end %>
-    <% if @project.active_children.any? %>
-    <br /><label><%= check_box_tag 'with_subprojects', 1, @with_subprojects %> <%=l(:label_subproject_plural)%></label>
-    <%= hidden_field_tag 'with_subprojects', 0 %>
-    <% end %>
-    <p><%= submit_tag l(:button_apply), :class => 'button-small', :name => nil %></p>
-    <% end %>
-<% end %>
-
-<% html_title(l(:label_calendar)) -%>
index fa0a60cdc5f827c55c220e24942cbfb03bbc8fc6..c1d8bb2c6e834b858f855a553704f287beb952c9 100644 (file)
@@ -57,7 +57,7 @@
 
 <% content_for :sidebar do %>
     <% planning_links = []
-      planning_links << link_to_if_authorized(l(:label_calendar), :action => 'calendar', :id => @project)
+      planning_links << link_to_if_authorized(l(:label_calendar), :controller => 'issues', :action => 'calendar', :project_id => @project)
       planning_links << link_to_if_authorized(l(:label_gantt), :controller => 'issues', :action => 'gantt', :project_id => @project)
       planning_links.compact!
       unless planning_links.empty? %>
index 882c1c917791677e70c8874535d7f6c73066ec38..8045f30f1db66a3e438c4c7e7e513d5d2d4e1287 100644 (file)
@@ -46,7 +46,7 @@ Redmine::AccessControl.map do |map|
     map.permission :save_queries, {:queries => [:new, :edit, :destroy]}, :require => :loggedin
     # Gantt & calendar
     map.permission :view_gantt, :issues => :gantt
-    map.permission :view_calendar, :projects => :calendar
+    map.permission :view_calendar, :issues => :calendar
     # Watchers
     map.permission :view_issue_watchers, {}
     map.permission :add_issue_watchers, {:watchers => :new}
index 327965281d25f344e4f5378ad6a4c9ed8fa3ed39..643ebe7987406aaf931529372794ce10d68c61e3 100644 (file)
@@ -166,11 +166,11 @@ p.subtitle { font-size: 0.9em; margin: -6px 0 12px 0; font-style: italic; }
 
 fieldset#filters, fieldset#date-range { padding: 0.7em; margin-bottom: 8px; }
 fieldset#filters p { margin: 1.2em 0 0.8em 2px; }
-fieldset#filters .buttons { font-size: 0.9em; }
 fieldset#filters table { border-collapse: collapse; }
 fieldset#filters table td { padding: 0; vertical-align: middle; }
 fieldset#filters tr.filter { height: 2em; }
 fieldset#filters td.add-filter { text-align: right; vertical-align: top; }
+.buttons { font-size: 0.9em; }
 
 div#issue-changesets {float:right; width:45%; margin-left: 1em; margin-bottom: 1em; background: #fff; padding-left: 1em; font-size: 90%;}
 div#issue-changesets .changeset { padding: 4px;}
@@ -341,7 +341,7 @@ vertical-align: bottom;
 }
 
 /***** Calendar *****/
-table.cal {border-collapse: collapse; width: 100%; margin: 8px 0 6px 0;border: 1px solid #d7d7d7;}
+table.cal {border-collapse: collapse; width: 100%; margin: 0px 0 6px 0;border: 1px solid #d7d7d7;}
 table.cal thead th {width: 14%;}
 table.cal tbody tr {height: 100px;}
 table.cal th { background-color:#EEEEEE; padding: 4px; }
index 67e7f1f911643db62c2543521edd1a79af0e22f4..52426b4d9098d0e04ed5cb5036af3f508006f14a 100644 (file)
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2007  Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2008  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
@@ -161,6 +161,13 @@ class IssuesControllerTest < Test::Unit::TestCase
     puts "RMagick not installed. Skipping tests !!!"
   end
   
+  def test_calendar
+    get :calendar, :project_id => 1
+    assert_response :success
+    assert_template 'calendar'
+    assert_not_nil assigns(:calendar)
+  end
+  
   def test_changes
     get :changes, :project_id => 1
     assert_response :success
index 3d969d11f38900d9f06f637a54aac29c5ec4f822..45af4e33efc285310d05ccf4d0c855f7ce052295 100644 (file)
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2007  Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2008  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
@@ -208,30 +208,6 @@ class ProjectsControllerTest < Test::Unit::TestCase
     assert_template 'common/feed.atom.rxml'
   end
   
-  def test_calendar
-    get :calendar, :id => 1
-    assert_response :success
-    assert_template 'calendar'
-    assert_not_nil assigns(:calendar)
-  end
-
-  def test_calendar_with_subprojects_should_not_show_private_subprojects
-    get :calendar, :id => 1, :with_subprojects => 1, :tracker_ids => [1, 2]
-    assert_response :success
-    assert_template 'calendar'
-    assert_not_nil assigns(:calendar)
-    assert_no_tag :tag => 'a', :content => /#6/
-  end
-  
-  def test_calendar_with_subprojects_should_show_private_subprojects
-    @request.session[:user_id] = 2
-    get :calendar, :id => 1, :with_subprojects => 1, :tracker_ids => [1, 2]
-    assert_response :success
-    assert_template 'calendar'
-    assert_not_nil assigns(:calendar)
-    assert_tag :tag => 'a', :content => /#6/
-  end
-  
   def test_archive    
     @request.session[:user_id] = 1 # admin
     post :archive, :id => 1