diff --git a/app/controllers/calendars_controller.rb b/app/controllers/calendars_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f2af58086a7d0c86c41e7cd324b9a7ea2e750dcb
--- /dev/null
+++ b/app/controllers/calendars_controller.rb
@@ -0,0 +1,38 @@
+class CalendarsController < ApplicationController
+  before_filter :find_optional_project
+
+  rescue_from Query::StatementInvalid, :with => :query_statement_invalid
+
+  helper :issues
+  helper :projects
+  helper :queries
+  include QueriesHelper
+
+  def show
+    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
+    @query.group_by = nil
+    if @query.valid?
+      events = []
+      events += @query.issues(:include => [:tracker, :assigned_to, :priority],
+                              :conditions => ["((start_date BETWEEN ? AND ?) OR (due_date BETWEEN ? AND ?))", @calendar.startdt, @calendar.enddt, @calendar.startdt, @calendar.enddt]
+                              )
+      events += @query.versions(:conditions => ["effective_date BETWEEN ? AND ?", @calendar.startdt, @calendar.enddt])
+                                     
+      @calendar.events = events
+    end
+    
+    render :layout => false if request.xhr?
+  end
+  
+
+end
diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb
index 32fd83a896fb988be12399b194d0bc082fe45ac8..6b42ce62b6357596d4a898e1968b9f112fcad6ed 100644
--- a/app/controllers/issues_controller.rb
+++ b/app/controllers/issues_controller.rb
@@ -22,8 +22,8 @@ class IssuesController < ApplicationController
   before_filter :find_issue, :only => [:show, :edit, :update, :reply]
   before_filter :find_issues, :only => [:bulk_edit, :move, :destroy]
   before_filter :find_project, :only => [:new, :create, :update_form, :preview, :auto_complete]
-  before_filter :authorize, :except => [:index, :changes, :calendar, :preview, :context_menu]
-  before_filter :find_optional_project, :only => [:index, :changes, :calendar]
+  before_filter :authorize, :except => [:index, :changes, :preview, :context_menu]
+  before_filter :find_optional_project, :only => [:index, :changes]
   before_filter :check_for_default_issue_status, :only => [:new, :create]
   before_filter :build_new_issue_from_params, :only => [:new, :create]
   accept_key_auth :index, :show, :changes
@@ -318,32 +318,6 @@ 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
-    @query.group_by = nil
-    if @query.valid?
-      events = []
-      events += @query.issues(:include => [:tracker, :assigned_to, :priority],
-                              :conditions => ["((start_date BETWEEN ? AND ?) OR (due_date BETWEEN ? AND ?))", @calendar.startdt, @calendar.enddt, @calendar.startdt, @calendar.enddt]
-                              )
-      events += @query.versions(:conditions => ["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/views/issues/calendar.rhtml b/app/views/calendars/show.html.erb
similarity index 87%
rename from app/views/issues/calendar.rhtml
rename to app/views/calendars/show.html.erb
index 1df5aa3bb0ffc9cd2da3c51afd622d6a7ed205bb..7b5abd77b051f6212bd9db90bd043f52534856ae 100644
--- a/app/views/issues/calendar.rhtml
+++ b/app/views/calendars/show.html.erb
@@ -11,11 +11,11 @@
 <p style="float:right;">
 <%= 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))}
+                        {:href => url_for(:action => 'show', :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))}
+                        {:href => url_for(:action => 'show', :year => (@month==12 ? @year+1 : @year), :month =>(@month==12 ? 1 : @month+1))}
                         %>
 </p>
 
diff --git a/app/views/projects/show.rhtml b/app/views/projects/show.rhtml
index 909c876fc749446446aab0b6843cc40368102c64..fa97715212e7d93b3ea529a6620c22475dbd83aa 100644
--- a/app/views/projects/show.rhtml
+++ b/app/views/projects/show.rhtml
@@ -39,7 +39,7 @@
     <p>
     	<%= link_to l(:label_issue_view_all), :controller => 'issues', :action => 'index', :project_id => @project, :set_filter => 1 %>
 	    <% if User.current.allowed_to?(:view_calendar, @project, :global => true) %>
-				| <%= link_to(l(:label_calendar), :controller => 'issues', :action => 'calendar', :project_id => @project) %>
+				| <%= link_to(l(:label_calendar), :controller => 'calendars', :action => 'show', :project_id => @project) %>
 			<% end %>
 			<% if User.current.allowed_to?(:view_gantt, @project, :global => true) %>
 				| <%= link_to(l(:label_gantt), :controller => 'gantts', :action => 'show', :project_id => @project) %>
diff --git a/config/routes.rb b/config/routes.rb
index 8571e77d37f4b3c7729a1c4359e8de270a7521a8..58e620eabb6636f8fdcaf12ae643a70b1aa98bc8 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -111,7 +111,7 @@ ActionController::Routing::Routes.draw do |map|
       issues_views.connect 'projects/:project_id/issues.:format', :action => 'index'
       issues_views.connect 'projects/:project_id/issues/new', :action => 'new'
       issues_views.connect 'projects/:project_id/issues/gantt', :controller => 'gantts', :action => 'show'
-      issues_views.connect 'projects/:project_id/issues/calendar', :action => 'calendar'
+      issues_views.connect 'projects/:project_id/issues/calendar', :controller => 'calendars', :action => 'show'
       issues_views.connect 'projects/:project_id/issues/:copy_from/copy', :action => 'new'
       issues_views.connect 'issues/:id', :action => 'show', :id => /\d+/
       issues_views.connect 'issues/:id.:format', :action => 'show', :id => /\d+/
@@ -122,6 +122,7 @@ ActionController::Routing::Routes.draw do |map|
       issues_actions.connect 'issues', :action => 'index'
       issues_actions.connect 'projects/:project_id/issues', :action => 'create'
       issues_actions.connect 'projects/:project_id/issues/gantt', :controller => 'gantts', :action => 'show'
+      issues_actions.connect 'projects/:project_id/issues/calendar', :controller => 'calendars', :action => 'show'
       issues_actions.connect 'issues/:id/quoted', :action => 'reply', :id => /\d+/
       issues_actions.connect 'issues/:id/:action', :action => /edit|move|destroy/, :id => /\d+/
       issues_actions.connect 'issues.:format', :action => 'create', :format => /xml/
@@ -134,6 +135,7 @@ ActionController::Routing::Routes.draw do |map|
       issues_actions.connect 'issues/:id.:format', :action => 'destroy', :id => /\d+/, :format => /xml/
     end
     issues_routes.connect 'issues/gantt', :controller => 'gantts', :action => 'show'
+    issues_routes.connect 'issues/calendar', :controller => 'calendars', :action => 'show'
     issues_routes.connect 'issues/:action'
   end
   
diff --git a/lib/redmine.rb b/lib/redmine.rb
index d2a1cdb915ee2a5760dac9253b0964432cce4a50..238ee110a124e0f702fa40b3f99d954ec502a68d 100644
--- a/lib/redmine.rb
+++ b/lib/redmine.rb
@@ -76,7 +76,7 @@ Redmine::AccessControl.map do |map|
     map.permission :save_queries, {:queries => [:new, :edit, :destroy]}, :require => :loggedin
     # Gantt & calendar
     map.permission :view_gantt, :gantts => :show
-    map.permission :view_calendar, :issues => :calendar
+    map.permission :view_calendar, :calendars => :show
     # Watchers
     map.permission :view_issue_watchers, {}
     map.permission :add_issue_watchers, {:watchers => :new}
diff --git a/test/functional/calendars_controller_test.rb b/test/functional/calendars_controller_test.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fa07fdd47f89add8139188a87edfbfce6de45c36
--- /dev/null
+++ b/test/functional/calendars_controller_test.rb
@@ -0,0 +1,20 @@
+require 'test_helper'
+
+class CalendarsControllerTest < ActionController::TestCase
+  fixtures :all
+
+  def test_calendar
+    get :show, :project_id => 1
+    assert_response :success
+    assert_template 'calendar'
+    assert_not_nil assigns(:calendar)
+  end
+  
+  def test_cross_project_calendar
+    get :show
+    assert_response :success
+    assert_template 'calendar'
+    assert_not_nil assigns(:calendar)
+  end
+  
+end
diff --git a/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb
index 1097419ff23bd3707ffcbfd3c4e22e0b15506b68..670fb2d7eb3a1e0f2847b050c457fbaadc8d4f3b 100644
--- a/test/functional/issues_controller_test.rb
+++ b/test/functional/issues_controller_test.rb
@@ -231,20 +231,6 @@ class IssuesControllerTest < ActionController::TestCase
     assert_equal columns, session[:query][:column_names].map(&:to_s)
   end
 
-  def test_calendar
-    get :calendar, :project_id => 1
-    assert_response :success
-    assert_template 'calendar'
-    assert_not_nil assigns(:calendar)
-  end
-  
-  def test_cross_project_calendar
-    get :calendar
-    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/integration/routing_test.rb b/test/integration/routing_test.rb
index c4736d41500add68fd2b97f12e31902f17dee1cf..f8476df567cecd4dbc624c66848db9abc8824313 100644
--- a/test/integration/routing_test.rb
+++ b/test/integration/routing_test.rb
@@ -90,10 +90,10 @@ class RoutingTest < ActionController::IntegrationTest
     
     should_route :post, "/issues/1/quoted", :controller => 'issues', :action => 'reply', :id => '1'
 
-    should_route :get, "/issues/calendar", :controller => 'issues', :action => 'calendar'
-    should_route :post, "/issues/calendar", :controller => 'issues', :action => 'calendar'
-    should_route :get, "/projects/project-name/issues/calendar", :controller => 'issues', :action => 'calendar', :project_id => 'project-name'
-    should_route :post, "/projects/project-name/issues/calendar", :controller => 'issues', :action => 'calendar', :project_id => 'project-name'
+    should_route :get, "/issues/calendar", :controller => 'calendars', :action => 'show'
+    should_route :post, "/issues/calendar", :controller => 'calendars', :action => 'show'
+    should_route :get, "/projects/project-name/issues/calendar", :controller => 'calendars', :action => 'show', :project_id => 'project-name'
+    should_route :post, "/projects/project-name/issues/calendar", :controller => 'calendars', :action => 'show', :project_id => 'project-name'
 
     should_route :get, "/issues/gantt", :controller => 'gantts', :action => 'show'
     should_route :post, "/issues/gantt", :controller => 'gantts', :action => 'show'