From: Jean-Philippe Lang Date: Thu, 11 Sep 2008 17:03:26 +0000 (+0000) Subject: Adds support for free ticket filtering and custom queries on Calendar. X-Git-Tag: 0.8.0-RC1~257 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=586f4e3831e31aef7d2a0e837c1c9fb6fc5c52ce;p=redmine.git Adds support for free ticket filtering and custom queries on Calendar. ProjectsController#calendar moved to IssuesController. git-svn-id: http://redmine.rubyforge.org/svn/trunk@1798 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 43a04f26d..7d39e4552 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -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) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 9e1df29a2..fc33336a0 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -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 diff --git a/app/models/query.rb b/app/models/query.rb index 0ce9a6a21..f8c236145 100644 --- a/app/models/query.rb +++ b/app/models/query.rb @@ -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 diff --git a/app/views/issues/_sidebar.rhtml b/app/views/issues/_sidebar.rhtml index bf9894939..db9351666 100644 --- a/app/views/issues/_sidebar.rhtml +++ b/app/views/issues/_sidebar.rhtml @@ -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 index 000000000..089482927 --- /dev/null +++ b/app/views/issues/calendar.rhtml @@ -0,0 +1,55 @@ +<% form_tag({}, :id => 'query_form') do %> +<% if @query.new_record? %> +

<%= l(:label_calendar) %>

+
<%= l(:label_filter_plural) %> + <%= render :partial => 'queries/filters', :locals => {:query => @query} %> +
+<% else %> +

<%=h @query.name %>

+ <% html_title @query.name %> +<% end %> + +
<%= l(:label_date_range) %> + <%= select_month(@month, :prefix => "month", :discard_type => true) %> + <%= select_year(@year, :prefix => "year", :discard_type => true) %> +
+ +

+<%= link_to_remote ('« ' + (@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)}") + ' »'), + {: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))} + %> +

+ +

+<%= 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? %> +

+<% end %> + +<%= error_messages_for 'query' %> +<% if @query.valid? %> +<%= render :partial => 'common/calendar', :locals => {:calendar => @calendar} %> + +<%= image_tag 'arrow_from.png' %>  <%= l(:text_tip_task_begin_day) %>
+<%= image_tag 'arrow_to.png' %>  <%= l(:text_tip_task_end_day) %>
+<%= image_tag 'arrow_bw.png' %>  <%= l(:text_tip_task_begin_end_day) %>
+<% end %> + +<% content_for :sidebar do %> + <%= render :partial => 'issues/sidebar' %> +<% end %> + +<% html_title(l(:label_calendar)) -%> diff --git a/app/views/issues/gantt.rhtml b/app/views/issues/gantt.rhtml index 7da657711..b9af1f961 100644 --- a/app/views/issues/gantt.rhtml +++ b/app/views/issues/gantt.rhtml @@ -6,7 +6,6 @@ <% else %>

<%=h @query.name %>

-
<% html_title @query.name %> <% end %> diff --git a/app/views/projects/calendar.rhtml b/app/views/projects/calendar.rhtml deleted file mode 100644 index 048d8a5df..000000000 --- a/app/views/projects/calendar.rhtml +++ /dev/null @@ -1,41 +0,0 @@ -

<%= "#{month_name(@month)} #{@year}" %>

- - - -
- <%= link_to_remote ('« ' + (@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])} - %> - - <%= link_to_remote ((@month==12 ? "#{month_name(1)} #{@year+1}" : "#{month_name(@month+1)}") + ' »'), - {: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])} - %> -
- -<%= render :partial => 'common/calendar', :locals => {:calendar => @calendar} %> - -<%= image_tag 'arrow_from.png' %>  <%= l(:text_tip_task_begin_day) %>
-<%= image_tag 'arrow_to.png' %>  <%= l(:text_tip_task_end_day) %>
-<%= image_tag 'arrow_bw.png' %>  <%= l(:text_tip_task_begin_end_day) %>
- -<% content_for :sidebar do %> -

<%= l(:label_calendar) %>

- - <% form_tag({}, :method => :get) do %> -

<%= select_month(@month, :prefix => "month", :discard_type => true) %> - <%= select_year(@year, :prefix => "year", :discard_type => true) %>

- - <% @trackers.each do |tracker| %> -
- <% end %> - <% if @project.active_children.any? %> -
- <%= hidden_field_tag 'with_subprojects', 0 %> - <% end %> -

<%= submit_tag l(:button_apply), :class => 'button-small', :name => nil %>

- <% end %> -<% end %> - -<% html_title(l(:label_calendar)) -%> diff --git a/app/views/projects/show.rhtml b/app/views/projects/show.rhtml index fa0a60cdc..c1d8bb2c6 100644 --- a/app/views/projects/show.rhtml +++ b/app/views/projects/show.rhtml @@ -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? %> diff --git a/lib/redmine.rb b/lib/redmine.rb index 882c1c917..8045f30f1 100644 --- a/lib/redmine.rb +++ b/lib/redmine.rb @@ -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} diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index 327965281..643ebe798 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -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; } diff --git a/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb index 67e7f1f91..52426b4d9 100644 --- a/test/functional/issues_controller_test.rb +++ b/test/functional/issues_controller_test.rb @@ -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 diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index 3d969d11f..45af4e33e 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -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