Index: app/controllers/projects_controller.rb =================================================================== --- app/controllers/projects_controller.rb (revision 3764) +++ app/controllers/projects_controller.rb (working copy) @@ -15,6 +15,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +require 'vpim/icalendar' + class ProjectsController < ApplicationController menu_item :overview menu_item :activity, :only => :activity @@ -27,7 +29,7 @@ before_filter :authorize, :except => [ :index, :list, :add, :copy, :archive, :unarchive, :destroy, :activity ] before_filter :authorize_global, :only => :add before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy ] - accept_key_auth :activity + accept_key_auth :activity, :roadmap after_filter :only => [:add, :edit, :archive, :unarchive, :destroy] do |controller| if controller.request.post? @@ -318,7 +320,6 @@ @versions = @project.shared_versions.sort @versions.reject! {|version| version.closed? || version.completed? } unless params[:completed] - @issues_by_version = {} unless @selected_tracker_ids.empty? @versions.each do |version| @@ -328,8 +329,53 @@ :order => "#{Project.table_name}.lft, #{Tracker.table_name}.position, #{Issue.table_name}.id") @issues_by_version[version] = issues end + end + @versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].empty?} + respond_to do |format| + format.html + format.ics do + calendar = Vpim::Icalendar.create2('Redmine') + @versions.each do |version| + calendar.add_event do |event| + if version.effective_date + event.dtstart version.effective_date + event.dtend version.effective_date + event.summary "#{version.project.name} #{version.name}" + event.description version.description + event.url url_for(:controller => 'versions', :action => 'show', :id => version) + end + end + + @issues_by_version[version].each do |issue| + options = [] + options.push Vpim::DirectoryInfo::Field.create('SUMMARY', issue.subject) + options.push Vpim::DirectoryInfo::Field.create('DTSTART;VALUE=DATE', issue.start_date) if issue.start_date + options.push Vpim::DirectoryInfo::Field.create('DUE;VALUE=DATE', issue.due_date) if issue.due_date + options.push Vpim::DirectoryInfo::Field.create('DESCRIPTION', issue.description) if issue.description + options.push Vpim::DirectoryInfo::Field.create('URL', url_for(:controller => 'issues', :action => 'show', :id => issue)) + + # See http://tools.ietf.org/html/rfc2445#section-4.8.1.9 + if issue.priority + priority = case issue.priority.position + when Range.new(0, IssuePriority.active.default.position, true) then '9' + when IssuePriority.active.default.position then '5' + else '1' + end + options.push Vpim::DirectoryInfo::Field.create('PRIORITY', priority) + end + + # See http://tools.ietf.org/html/rfc2445#section-4.8.1.11 + if issue.closed? + options.push Vpim::DirectoryInfo::Field.create('STATUS', 'COMPLETED') + options.push Vpim::DirectoryInfo::Field.create('COMPLETED', issue.updated_on) + end + calendar.push Vpim::Icalendar::Vtodo.create(options) + end + end + render :text => calendar.encode + end end - @versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].empty?} + end def activity Index: app/views/projects/roadmap.rhtml =================================================================== --- app/views/projects/roadmap.rhtml (revision 3764) +++ app/views/projects/roadmap.rhtml (working copy) @@ -41,8 +41,13 @@

<%= l(:label_version_plural) %>

<% @versions.each do |version| %> -<%= link_to format_version_name(version), "##{version.name}" %>
+ <%= link_to format_version_name(version), "##{version.name}" %>
<% end %> + +

Export

+<%= link_to 'iCalendar', :controller => 'projects', :action => 'roadmap', :format => 'ics', :key => User.current.rss_key, :only_path => false, :protocol => 'webcal' %>
+<%= link_to 'iCalendar (ICS Export)', :controller => 'projects', :action => 'roadmap', :format => 'ics', :key => User.current.rss_key %> + <% end %> <% html_title(l(:label_roadmap)) %> Index: config/routes.rb =================================================================== --- config/routes.rb (revision 3764) +++ config/routes.rb (working copy) @@ -178,7 +178,8 @@ project_views.connect 'projects.:format', :action => 'index' project_views.connect 'projects/new', :action => 'add' project_views.connect 'projects/:id', :action => 'show' - project_views.connect 'projects/:id/:action', :action => /roadmap|destroy|settings/ + project_views.connect 'projects/:id/:action', :action => /destroy|settings/ + project_views.connect 'projects/:id/roadmap.:format', :action => 'roadmap' project_views.connect 'projects/:id/files', :action => 'list_files' project_views.connect 'projects/:id/files/new', :action => 'add_file' project_views.connect 'projects/:id/versions/new', :action => 'add_version'