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 @@