Author: assaf
Date: Fri May 16 01:38:11 2008
New Revision: 656967
URL: http://svn.apache.org/viewvc?rev=656967&view=rev
Log:
Added iCal for tasks and more auto-magic in iCal template.
Added:
ode/sandbox/singleshot/app/views/tasks/index.atom.builder
ode/sandbox/singleshot/app/views/tasks/index.ics.ical
Modified:
ode/sandbox/singleshot/app/controllers/activities_controller.rb
ode/sandbox/singleshot/app/controllers/application.rb
ode/sandbox/singleshot/app/controllers/tasks_controller.rb
ode/sandbox/singleshot/app/models/task.rb
ode/sandbox/singleshot/lib/extensions/ical_template.rb
Modified: ode/sandbox/singleshot/app/controllers/activities_controller.rb
URL:
http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/controllers/activities_controller.rb?rev=656967&r1=656966&r2=656967&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/controllers/activities_controller.rb (original)
+++ ode/sandbox/singleshot/app/controllers/activities_controller.rb Fri May 16
01:38:11 2008
@@ -1,6 +1,6 @@
class ActivitiesController < ApplicationController
- prepend_before_filter :authenticate_with_access_key, :unless=>lambda {
|controller| controller.request.format.html? }
+ access_key_authentication :only=>[:show]
def show
@alternate = { Mime::ATOM=>formatted_activity_url(:format=>:atom,
:access_key=>authenticated.access_key),
Modified: ode/sandbox/singleshot/app/controllers/application.rb
URL:
http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/controllers/application.rb?rev=656967&r1=656966&r2=656967&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/controllers/application.rb (original)
+++ ode/sandbox/singleshot/app/controllers/application.rb Fri May 16 01:38:11
2008
@@ -31,6 +31,12 @@
end
end
+ def self.access_key_authentication(options = {})
+ formats = options[:formats] || ['atom', 'ics']
+ options[:if] ||= lambda { |controller|
formats.include?(controller.request.format) }
+ prepend_before_filter :authenticate_with_access_key, options
+ end
+
# Access key authentication, used for feeds, iCal and other type of requets
that
# do not support HTTP authentication or sessions. Can only be used for GET
requests.
#
Modified: ode/sandbox/singleshot/app/controllers/tasks_controller.rb
URL:
http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/controllers/tasks_controller.rb?rev=656967&r1=656966&r2=656967&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/controllers/tasks_controller.rb (original)
+++ ode/sandbox/singleshot/app/controllers/tasks_controller.rb Fri May 16
01:38:11 2008
@@ -1,12 +1,12 @@
class TasksController < ApplicationController
+ access_key_authentication :only=>:index
+
verify :params=>:task, :only=>:update, :render=>{:text=>'Missing task',
:status=>:bad_request}
before_filter :authenticate, :except=>[:show, :update, :complete, :destroy]
instance :task, :only=>[:show, :update, :complete, :destroy],
:check=>:instance_accessible
before_filter :forbid_reserved, :except=>[:update, :destroy]
- layout 'application'
-
def index
@alternate = { Mime::ATOM=>formatted_tasks_url(:format=>:atom,
:access_key=>authenticated.access_key),
Mime::ICS=>formatted_tasks_url(:format=>:ics,
:access_key=>authenticated.access_key) }
Modified: ode/sandbox/singleshot/app/models/task.rb
URL:
http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/models/task.rb?rev=656967&r1=656966&r2=656967&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/models/task.rb (original)
+++ ode/sandbox/singleshot/app/models/task.rb Fri May 16 01:38:11 2008
@@ -106,6 +106,10 @@
end
end
+ def status
+ state
+ end
+
# -- Common task attributes --
@@ -164,9 +168,9 @@
# --- Priority and ordering ---
- # Task priority: 1 is the lowest (and default) priority.
+ # Task priority: 1 is the highest, 3 the lowest, average is the default.
PRIORITIES = 1..3
- before_validation { |task| task.priority ||= PRIORITIES.min }
+ before_validation { |task| task.priority ||= (PRIORITIES.min +
PRIORITIES.max) >> 1 }
validates_inclusion_of :priority, :in=>PRIORITIES
def over_due?
@@ -215,6 +219,10 @@
end
end
+ def completed_on
+ # TODO: should be attribute
+ end
+
def complete!(data = nil)
self.status = :completed
self.data = data if data
Added: ode/sandbox/singleshot/app/views/tasks/index.atom.builder
URL:
http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/views/tasks/index.atom.builder?rev=656967&view=auto
==============================================================================
--- ode/sandbox/singleshot/app/views/tasks/index.atom.builder (added)
+++ ode/sandbox/singleshot/app/views/tasks/index.atom.builder Fri May 16
01:38:11 2008
@@ -0,0 +1,14 @@
+atom_feed :root_url=>tasks_url do |feed|
+ feed.title 'Singleshot: Tasks'
+ feed.updated @tasks.map(&:updated_at).max
+
+ for task in @tasks
+ feed.entry task do |entry|
+ entry.title task.title
+ entry.content :type=>'html' do |content|
+ content.text! "<p>#{h(task.description)}</p>"
+ # TODO: task stats and actions
+ end
+ end
+ end
+end
Added: ode/sandbox/singleshot/app/views/tasks/index.ics.ical
URL:
http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/views/tasks/index.ics.ical?rev=656967&view=auto
==============================================================================
--- ode/sandbox/singleshot/app/views/tasks/index.ics.ical (added)
+++ ode/sandbox/singleshot/app/views/tasks/index.ics.ical Fri May 16 01:38:11
2008
@@ -0,0 +1,14 @@
+calendar.prodid = 'Apache Singleshot'
+for task in @tasks
+ calendar.todo task do |todo|
+ todo.summary task.title
+ todo.description task.description
+ todo.url task_url(task)
+ todo.due task.due_on if task.due_on
+ todo.priority [1,5,9][task.priority - 1]
+ status = { 'ready'=>'NEEDS-ACTION', 'active'=>'IN-PROCESS' }[task.status]
|| task.status.upcase
+ todo.status status
+ todo.organizer "MAILTO:#{task.creator.email}" if task.creator
+ todo.completed task.completed_on if task.completed_on
+ end
+end
Modified: ode/sandbox/singleshot/lib/extensions/ical_template.rb
URL:
http://svn.apache.org/viewvc/ode/sandbox/singleshot/lib/extensions/ical_template.rb?rev=656967&r1=656966&r2=656967&view=diff
==============================================================================
--- ode/sandbox/singleshot/lib/extensions/ical_template.rb (original)
+++ ode/sandbox/singleshot/lib/extensions/ical_template.rb Fri May 16 01:38:11
2008
@@ -1,53 +1,89 @@
module ActionView
class ICalBuilder
- class Event
+ class Component
- def initialize
+ def initialize(request, record = nil)
@properties = {}
+ # TODO: created, last-mod, uid
+ if record
+ uid "#{request.host}:#{record.class}/#{record.id}"
+ dtstamp record.created_at.utc.strftime('%Y%m%dT%H%M%SZ') if
record.respond_to?(:created_at)
+ last_modified record.updated_at.utc.strftime('%Y%m%dT%H%M%SZ') if
record.respond_to?(:updated_at)
+ sequence record.send(record.class.locking_column) if
record.locking_enabled?
+ end
end
attr_accessor :properties
def to_ical
- properties = @properties.map { |name, value|
"#{name.to_s.upcase}:#{stringify(value)}" }
- "BEGIN:VEVENT\n#{properties.join("\n")}\nEND:VEVENT"
+ properties = @properties.map { |name, value| property(name, value) }
+ "BEGIN:#{self.class.const_get
:NAME}\n#{properties.join("\n")}\nEND:#{self.class.const_get :NAME}"
end
private
+ def property(name, value)
+ value = { :value=>value } unless Hash === value
+ name.to_s.underscore.upcase +
+ value.except(:value).map { |name, value|
";#{name.to_s.underscore}=#{stringify(value)}" }.join +
+ ":#{stringify(value[:value])}"
+ end
+
def stringify(value)
case value
when String then value
when Date then value.strftime('%Y%m%d')
- when Time then value.strftime('%Y%m%dT%H%M%S')
+ when Time then value.strftime(value.utc? ? '%Y%m%dT%H%M%SZ' :
'%Y%m%dT%H%M%S')
else value.to_s
end
end
- def method_missing(name, arg)
- @properties[name] = arg
+ def method_missing(name, *args)
+ options = args.extract_options!
+ options[:value] = args.first
+ @properties[name] = options
end
end
- def initialize(prodid = nil)
- @prodid = prodid
- @events = []
+ class Event < Component
+
+ NAME = 'VEVENT'
+
+ end
+
+
+ class Todo < Component
+
+ NAME = 'VTODO'
+
+ end
+
+ def initialize(request)
+ @request =request
+ @components = []
end
attr_accessor :prodid
- attr_reader :events
+ attr_reader :components
- def event
- returning Event.new do |event|
+ def event(record = nil)
+ returning Event.new(@request, record) do |event|
yield event if block_given?
- @events << event
+ @components << event
+ end
+ end
+
+ def todo(record = nil)
+ returning Todo.new(@request, record) do |todo|
+ yield todo if block_given?
+ @components << todo
end
end
def to_ical
-
"BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:#{prodid}\n#{events.map(&:to_ical).join("\n")}\nEND:VCALENDAR\n"
+ "BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:[EMAIL
PROTECTED](&:to_ical).join("\n")}\nEND:VCALENDAR\n"
end
end
@@ -63,7 +99,7 @@
def compile(template)
content_type_handler =
(@view.send!(:controller).respond_to?(:response) ? "controller.response" :
"controller")
"#{content_type_handler}.content_type ||= Mime::ICS\n" +
- "calendar = ::ActionView::ICalBuilder.new\n" +
+ "calendar = ::ActionView::ICalBuilder.new(request)\n" +
template.source +
"\ncalendar.to_ical\n"
end