##// END OF EJS Templates
Adds support for free ticket filtering and custom queries on Calendar....
Jean-Philippe Lang -
r1796:586f4e3831e3
parent child
Show More
@@ -0,0 +1,55
1 <% form_tag({}, :id => 'query_form') do %>
2 <% if @query.new_record? %>
3 <h2><%= l(:label_calendar) %></h2>
4 <fieldset id="filters"><legend><%= l(:label_filter_plural) %></legend>
5 <%= render :partial => 'queries/filters', :locals => {:query => @query} %>
6 </fieldset>
7 <% else %>
8 <h2><%=h @query.name %></h2>
9 <% html_title @query.name %>
10 <% end %>
11
12 <fieldset id="date-range"><legend><%= l(:label_date_range) %></legend>
13 <%= select_month(@month, :prefix => "month", :discard_type => true) %>
14 <%= select_year(@year, :prefix => "year", :discard_type => true) %>
15 </fieldset>
16
17 <p style="float:right; margin:0px;">
18 <%= link_to_remote ('&#171; ' + (@month==1 ? "#{month_name(12)} #{@year-1}" : "#{month_name(@month-1)}")),
19 {:update => "content", :url => { :year => (@month==1 ? @year-1 : @year), :month =>(@month==1 ? 12 : @month-1) }},
20 {:href => url_for(:action => 'calendar', :year => (@month==1 ? @year-1 : @year), :month =>(@month==1 ? 12 : @month-1))}
21 %> |
22 <%= link_to_remote ((@month==12 ? "#{month_name(1)} #{@year+1}" : "#{month_name(@month+1)}") + ' &#187;'),
23 {:update => "content", :url => { :year => (@month==12 ? @year+1 : @year), :month =>(@month==12 ? 1 : @month+1) }},
24 {:href => url_for(:action => 'calendar', :year => (@month==12 ? @year+1 : @year), :month =>(@month==12 ? 1 : @month+1))}
25 %>
26 </p>
27
28 <p class="buttons">
29 <%= link_to_remote l(:button_apply),
30 { :url => { :set_filter => (@query.new_record? ? 1 : nil) },
31 :update => "content",
32 :with => "Form.serialize('query_form')"
33 }, :class => 'icon icon-checked' %>
34
35 <%= link_to_remote l(:button_clear),
36 { :url => { :set_filter => (@query.new_record? ? 1 : nil) },
37 :update => "content",
38 }, :class => 'icon icon-reload' if @query.new_record? %>
39 </p>
40 <% end %>
41
42 <%= error_messages_for 'query' %>
43 <% if @query.valid? %>
44 <%= render :partial => 'common/calendar', :locals => {:calendar => @calendar} %>
45
46 <%= image_tag 'arrow_from.png' %>&nbsp;&nbsp;<%= l(:text_tip_task_begin_day) %><br />
47 <%= image_tag 'arrow_to.png' %>&nbsp;&nbsp;<%= l(:text_tip_task_end_day) %><br />
48 <%= image_tag 'arrow_bw.png' %>&nbsp;&nbsp;<%= l(:text_tip_task_begin_end_day) %><br />
49 <% end %>
50
51 <% content_for :sidebar do %>
52 <%= render :partial => 'issues/sidebar' %>
53 <% end %>
54
55 <% html_title(l(:label_calendar)) -%>
@@ -1,5 +1,5
1 # redMine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
@@ -20,7 +20,7 class IssuesController < ApplicationController
20
20
21 before_filter :find_issue, :only => [:show, :edit, :reply, :destroy_attachment]
21 before_filter :find_issue, :only => [:show, :edit, :reply, :destroy_attachment]
22 before_filter :find_issues, :only => [:bulk_edit, :move, :destroy]
22 before_filter :find_issues, :only => [:bulk_edit, :move, :destroy]
23 before_filter :find_project, :only => [:new, :update_form, :preview, :gantt]
23 before_filter :find_project, :only => [:new, :update_form, :preview, :gantt, :calendar]
24 before_filter :authorize, :except => [:index, :changes, :preview, :update_form, :context_menu]
24 before_filter :authorize, :except => [:index, :changes, :preview, :update_form, :context_menu]
25 before_filter :find_optional_project, :only => [:index, :changes]
25 before_filter :find_optional_project, :only => [:index, :changes]
26 accept_key_auth :index, :changes
26 accept_key_auth :index, :changes
@@ -354,6 +354,33 class IssuesController < ApplicationController
354 end
354 end
355 end
355 end
356
356
357 def calendar
358 if params[:year] and params[:year].to_i > 1900
359 @year = params[:year].to_i
360 if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
361 @month = params[:month].to_i
362 end
363 end
364 @year ||= Date.today.year
365 @month ||= Date.today.month
366
367 @calendar = Redmine::Helpers::Calendar.new(Date.civil(@year, @month, 1), current_language, :month)
368 retrieve_query
369 if @query.valid?
370 events = []
371 events += Issue.find(:all,
372 :include => [:tracker, :status, :assigned_to, :priority, :project],
373 :conditions => ["(#{@query.statement}) AND ((start_date BETWEEN ? AND ?) OR (due_date BETWEEN ? AND ?))", @calendar.startdt, @calendar.enddt, @calendar.startdt, @calendar.enddt]
374 )
375 events += Version.find(:all, :include => :project,
376 :conditions => ["(#{@query.project_statement}) AND effective_date BETWEEN ? AND ?", @calendar.startdt, @calendar.enddt])
377
378 @calendar.events = events
379 end
380
381 render :layout => false if request.xhr?
382 end
383
357 def context_menu
384 def context_menu
358 @issues = Issue.find_all_by_id(params[:ids], :include => :project)
385 @issues = Issue.find_all_by_id(params[:ids], :include => :project)
359 if (@issues.size == 1)
386 if (@issues.size == 1)
@@ -27,7 +27,7 class ProjectsController < ApplicationController
27 before_filter :find_optional_project, :only => :activity
27 before_filter :find_optional_project, :only => :activity
28 before_filter :authorize, :except => [ :index, :list, :add, :archive, :unarchive, :destroy, :activity ]
28 before_filter :authorize, :except => [ :index, :list, :add, :archive, :unarchive, :destroy, :activity ]
29 before_filter :require_admin, :only => [ :add, :archive, :unarchive, :destroy ]
29 before_filter :require_admin, :only => [ :add, :archive, :unarchive, :destroy ]
30 accept_key_auth :activity, :calendar
30 accept_key_auth :activity
31
31
32 helper :sort
32 helper :sort
33 include SortHelper
33 include SortHelper
@@ -246,34 +246,6 class ProjectsController < ApplicationController
246 end
246 end
247 end
247 end
248
248
249 def calendar
250 @trackers = @project.rolled_up_trackers
251 retrieve_selected_tracker_ids(@trackers)
252
253 if params[:year] and params[:year].to_i > 1900
254 @year = params[:year].to_i
255 if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
256 @month = params[:month].to_i
257 end
258 end
259 @year ||= Date.today.year
260 @month ||= Date.today.month
261 @calendar = Redmine::Helpers::Calendar.new(Date.civil(@year, @month, 1), current_language, :month)
262 @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1')
263 events = []
264 @project.issues_with_subprojects(@with_subprojects) do
265 events += Issue.find(:all,
266 :include => [:tracker, :status, :assigned_to, :priority, :project],
267 :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]
268 ) unless @selected_tracker_ids.empty?
269 events += Version.find(:all, :include => :project,
270 :conditions => ["effective_date BETWEEN ? AND ?", @calendar.startdt, @calendar.enddt])
271 end
272 @calendar.events = events
273
274 render :layout => false if request.xhr?
275 end
276
277 private
249 private
278 # Find project of id params[:id]
250 # Find project of id params[:id]
279 # if not found, redirect to project list
251 # if not found, redirect to project list
@@ -1,5 +1,5
1 # redMine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
@@ -254,9 +254,8 class Query < ActiveRecord::Base
254 def has_default_columns?
254 def has_default_columns?
255 column_names.nil? || column_names.empty?
255 column_names.nil? || column_names.empty?
256 end
256 end
257
257
258 def statement
258 def project_statement
259 # project/subprojects clause
260 project_clauses = []
259 project_clauses = []
261 if project && !@project.active_children.empty?
260 if project && !@project.active_children.empty?
262 ids = [project.id]
261 ids = [project.id]
@@ -274,12 +273,15 class Query < ActiveRecord::Base
274 elsif Setting.display_subprojects_issues?
273 elsif Setting.display_subprojects_issues?
275 ids += project.child_ids
274 ids += project.child_ids
276 end
275 end
277 project_clauses << "#{Issue.table_name}.project_id IN (%s)" % ids.join(',')
276 project_clauses << "#{Project.table_name}.id IN (%s)" % ids.join(',')
278 elsif project
277 elsif project
279 project_clauses << "#{Issue.table_name}.project_id = %d" % project.id
278 project_clauses << "#{Project.table_name}.id = %d" % project.id
280 end
279 end
281 project_clauses << Project.visible_by(User.current)
280 project_clauses << Project.visible_by(User.current)
282
281 project_clauses.join(' AND ')
282 end
283
284 def statement
283 # filters clauses
285 # filters clauses
284 filters_clauses = []
286 filters_clauses = []
285 filters.each_key do |field|
287 filters.each_key do |field|
@@ -356,7 +358,7 class Query < ActiveRecord::Base
356 filters_clauses << sql
358 filters_clauses << sql
357 end if filters and valid?
359 end if filters and valid?
358
360
359 (project_clauses + filters_clauses).join(' AND ')
361 (filters_clauses << project_statement).join(' AND ')
360 end
362 end
361
363
362 private
364 private
@@ -5,7 +5,7
5 <%= link_to l(:label_change_log), :controller => 'projects', :action => 'changelog', :id => @project %>
5 <%= link_to l(:label_change_log), :controller => 'projects', :action => 'changelog', :id => @project %>
6
6
7 <% planning_links = []
7 <% planning_links = []
8 planning_links << link_to_if_authorized(l(:label_calendar), :controller => 'projects', :action => 'calendar', :id => @project)
8 planning_links << link_to_if_authorized(l(:label_calendar), :action => 'calendar', :project_id => @project)
9 planning_links << link_to_if_authorized(l(:label_gantt), :action => 'gantt', :project_id => @project)
9 planning_links << link_to_if_authorized(l(:label_gantt), :action => 'gantt', :project_id => @project)
10 planning_links.compact!
10 planning_links.compact!
11 unless planning_links.empty? %>
11 unless planning_links.empty? %>
@@ -6,7 +6,6
6 </fieldset>
6 </fieldset>
7 <% else %>
7 <% else %>
8 <h2><%=h @query.name %></h2>
8 <h2><%=h @query.name %></h2>
9 <div id="query_form"></div>
10 <% html_title @query.name %>
9 <% html_title @query.name %>
11 <% end %>
10 <% end %>
12
11
@@ -57,7 +57,7
57
57
58 <% content_for :sidebar do %>
58 <% content_for :sidebar do %>
59 <% planning_links = []
59 <% planning_links = []
60 planning_links << link_to_if_authorized(l(:label_calendar), :action => 'calendar', :id => @project)
60 planning_links << link_to_if_authorized(l(:label_calendar), :controller => 'issues', :action => 'calendar', :project_id => @project)
61 planning_links << link_to_if_authorized(l(:label_gantt), :controller => 'issues', :action => 'gantt', :project_id => @project)
61 planning_links << link_to_if_authorized(l(:label_gantt), :controller => 'issues', :action => 'gantt', :project_id => @project)
62 planning_links.compact!
62 planning_links.compact!
63 unless planning_links.empty? %>
63 unless planning_links.empty? %>
@@ -46,7 +46,7 Redmine::AccessControl.map do |map|
46 map.permission :save_queries, {:queries => [:new, :edit, :destroy]}, :require => :loggedin
46 map.permission :save_queries, {:queries => [:new, :edit, :destroy]}, :require => :loggedin
47 # Gantt & calendar
47 # Gantt & calendar
48 map.permission :view_gantt, :issues => :gantt
48 map.permission :view_gantt, :issues => :gantt
49 map.permission :view_calendar, :projects => :calendar
49 map.permission :view_calendar, :issues => :calendar
50 # Watchers
50 # Watchers
51 map.permission :view_issue_watchers, {}
51 map.permission :view_issue_watchers, {}
52 map.permission :add_issue_watchers, {:watchers => :new}
52 map.permission :add_issue_watchers, {:watchers => :new}
@@ -166,11 +166,11 p.subtitle { font-size: 0.9em; margin: -6px 0 12px 0; font-style: italic; }
166
166
167 fieldset#filters, fieldset#date-range { padding: 0.7em; margin-bottom: 8px; }
167 fieldset#filters, fieldset#date-range { padding: 0.7em; margin-bottom: 8px; }
168 fieldset#filters p { margin: 1.2em 0 0.8em 2px; }
168 fieldset#filters p { margin: 1.2em 0 0.8em 2px; }
169 fieldset#filters .buttons { font-size: 0.9em; }
170 fieldset#filters table { border-collapse: collapse; }
169 fieldset#filters table { border-collapse: collapse; }
171 fieldset#filters table td { padding: 0; vertical-align: middle; }
170 fieldset#filters table td { padding: 0; vertical-align: middle; }
172 fieldset#filters tr.filter { height: 2em; }
171 fieldset#filters tr.filter { height: 2em; }
173 fieldset#filters td.add-filter { text-align: right; vertical-align: top; }
172 fieldset#filters td.add-filter { text-align: right; vertical-align: top; }
173 .buttons { font-size: 0.9em; }
174
174
175 div#issue-changesets {float:right; width:45%; margin-left: 1em; margin-bottom: 1em; background: #fff; padding-left: 1em; font-size: 90%;}
175 div#issue-changesets {float:right; width:45%; margin-left: 1em; margin-bottom: 1em; background: #fff; padding-left: 1em; font-size: 90%;}
176 div#issue-changesets .changeset { padding: 4px;}
176 div#issue-changesets .changeset { padding: 4px;}
@@ -341,7 +341,7 vertical-align: bottom;
341 }
341 }
342
342
343 /***** Calendar *****/
343 /***** Calendar *****/
344 table.cal {border-collapse: collapse; width: 100%; margin: 8px 0 6px 0;border: 1px solid #d7d7d7;}
344 table.cal {border-collapse: collapse; width: 100%; margin: 0px 0 6px 0;border: 1px solid #d7d7d7;}
345 table.cal thead th {width: 14%;}
345 table.cal thead th {width: 14%;}
346 table.cal tbody tr {height: 100px;}
346 table.cal tbody tr {height: 100px;}
347 table.cal th { background-color:#EEEEEE; padding: 4px; }
347 table.cal th { background-color:#EEEEEE; padding: 4px; }
@@ -1,5 +1,5
1 # redMine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
@@ -161,6 +161,13 class IssuesControllerTest < Test::Unit::TestCase
161 puts "RMagick not installed. Skipping tests !!!"
161 puts "RMagick not installed. Skipping tests !!!"
162 end
162 end
163
163
164 def test_calendar
165 get :calendar, :project_id => 1
166 assert_response :success
167 assert_template 'calendar'
168 assert_not_nil assigns(:calendar)
169 end
170
164 def test_changes
171 def test_changes
165 get :changes, :project_id => 1
172 get :changes, :project_id => 1
166 assert_response :success
173 assert_response :success
@@ -1,5 +1,5
1 # redMine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
@@ -208,30 +208,6 class ProjectsControllerTest < Test::Unit::TestCase
208 assert_template 'common/feed.atom.rxml'
208 assert_template 'common/feed.atom.rxml'
209 end
209 end
210
210
211 def test_calendar
212 get :calendar, :id => 1
213 assert_response :success
214 assert_template 'calendar'
215 assert_not_nil assigns(:calendar)
216 end
217
218 def test_calendar_with_subprojects_should_not_show_private_subprojects
219 get :calendar, :id => 1, :with_subprojects => 1, :tracker_ids => [1, 2]
220 assert_response :success
221 assert_template 'calendar'
222 assert_not_nil assigns(:calendar)
223 assert_no_tag :tag => 'a', :content => /#6/
224 end
225
226 def test_calendar_with_subprojects_should_show_private_subprojects
227 @request.session[:user_id] = 2
228 get :calendar, :id => 1, :with_subprojects => 1, :tracker_ids => [1, 2]
229 assert_response :success
230 assert_template 'calendar'
231 assert_not_nil assigns(:calendar)
232 assert_tag :tag => 'a', :content => /#6/
233 end
234
235 def test_archive
211 def test_archive
236 @request.session[:user_id] = 1 # admin
212 @request.session[:user_id] = 1 # admin
237 post :archive, :id => 1
213 post :archive, :id => 1
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now