You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ode.apache.org by as...@apache.org on 2008/05/17 02:05:44 UTC

svn commit: r657254 - in /ode/sandbox/singleshot: app/controllers/ app/helpers/ app/models/ app/views/activities/ app/views/layouts/ app/views/sandwiches/ app/views/tasks/ config/ lib/tasks/ public/javascripts/ public/stylesheets/

Author: assaf
Date: Fri May 16 17:05:43 2008
New Revision: 657254

URL: http://svn.apache.org/viewvc?rev=657254&view=rev
Log:
Merge changes for SVN.

Modified:
    ode/sandbox/singleshot/app/controllers/activities_controller.rb
    ode/sandbox/singleshot/app/controllers/sandwiches_controller.rb
    ode/sandbox/singleshot/app/controllers/tasks_controller.rb
    ode/sandbox/singleshot/app/helpers/application_helper.rb
    ode/sandbox/singleshot/app/helpers/task_helper.rb
    ode/sandbox/singleshot/app/models/activity.rb
    ode/sandbox/singleshot/app/models/sandwich.rb
    ode/sandbox/singleshot/app/views/activities/show.html.erb
    ode/sandbox/singleshot/app/views/activities/show.ics.ical
    ode/sandbox/singleshot/app/views/layouts/application.html.erb
    ode/sandbox/singleshot/app/views/layouts/head.html.erb
    ode/sandbox/singleshot/app/views/sandwiches/show.html.erb
    ode/sandbox/singleshot/app/views/tasks/index.html.erb
    ode/sandbox/singleshot/app/views/tasks/show.html.erb
    ode/sandbox/singleshot/config/routes.rb
    ode/sandbox/singleshot/lib/tasks/database.rake
    ode/sandbox/singleshot/lib/tasks/development.rake
    ode/sandbox/singleshot/public/javascripts/application.js
    ode/sandbox/singleshot/public/stylesheets/default.css

Modified: ode/sandbox/singleshot/app/controllers/activities_controller.rb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/controllers/activities_controller.rb?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/controllers/activities_controller.rb (original)
+++ ode/sandbox/singleshot/app/controllers/activities_controller.rb Fri May 16 17:05:43 2008
@@ -3,6 +3,7 @@
   access_key_authentication :only=>[:show]
 
   def show
+    @title = 'Activities'
     @alternate = { Mime::ATOM=>formatted_activity_url(:format=>:atom, :access_key=>authenticated.access_key),
                    Mime::ICS=>formatted_activity_url(:format=>:ics, :access_key=>authenticated.access_key) }
     @activities = Activity.for_stakeholder(authenticated)
@@ -10,7 +11,7 @@
     dates = day ? day..day + 1.day : Date.today - 3.day..Date.today + 1.day
     @activities = @activities.for_dates(dates)
     respond_to do |want|
-      want.html { @days = @activities.by_day }
+      want.html { @days = @activities.group_by_day }
       want.atom
       want.ics
     end

Modified: ode/sandbox/singleshot/app/controllers/sandwiches_controller.rb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/controllers/sandwiches_controller.rb?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/controllers/sandwiches_controller.rb (original)
+++ ode/sandbox/singleshot/app/controllers/sandwiches_controller.rb Fri May 16 17:05:43 2008
@@ -2,6 +2,8 @@
 
   before_filter :instance
   before_filter :update_instance, :only=>[:update, :create]
+  skip_filter :authenticate
+  layout false
 
   def show
     @read_only = true unless params['perform'] == 'true'

Modified: ode/sandbox/singleshot/app/controllers/tasks_controller.rb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/controllers/tasks_controller.rb?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/controllers/tasks_controller.rb (original)
+++ ode/sandbox/singleshot/app/controllers/tasks_controller.rb Fri May 16 17:05:43 2008
@@ -1,10 +1,10 @@
 class TasksController < ApplicationController
 
-  access_key_authentication :only=>:index
+  access_key_authentication :only=>[:index, :activity]
 
   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
+  instance :task, :only=>[:show, :activity, :update, :complete, :destroy], :check=>:instance_accessible
   before_filter :forbid_reserved, :except=>[:update, :destroy]
 
   def index
@@ -13,8 +13,34 @@
     @tasks = Task.with_stakeholders.for_stakeholder(authenticated).pending.prioritized
   end
 
-  def following
-    @tasks = Task.with_stakeholders.for_stakeholder(authenticated).following
+  def show
+    @alternate = { Mime::ICS=>formatted_tasks_url(:format=>:ics, :access_key=>authenticated.access_key) }
+    respond_to do |format|
+      format.html do
+        @activities = Activity.for_task(@task)
+        render :layout=>'head'
+      end
+      format.xml  { render :xml=>@task }
+      format.json { render :json=>@task }
+      format.ics  do
+        @tasks = [@task]
+        #render :action=>'index'
+      end
+    end
+  end
+
+  def activity
+    @title = "Activities &mdash; #{@task.title}"
+    @alternate = { Mime::ATOM=>formatted_activity_task_url(@task, :atom, :access_key=>authenticated.access_key),
+                   Mime::ICS=>formatted_activity_task_url(@task, :ics, :access_key=>authenticated.access_key) }
+    @activities = Activity.for_task(@task)
+    respond_to do |want|
+      want.html do
+        @days = @activities.group_by_day
+        render :template=>'activities/show'
+      end
+      want.any { render :template=>'activities/show' }
+    end
   end
 
   def new
@@ -39,13 +65,6 @@
     end
   end
 
-  def show
-    respond_to do |format|
-      format.html
-      format.xml  { render :xml=>@task }
-      format.json { render :json=>@task }
-    end
-  end
 
   def update
     # TODO: conditional put

Modified: ode/sandbox/singleshot/app/helpers/application_helper.rb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/helpers/application_helper.rb?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/helpers/application_helper.rb (original)
+++ ode/sandbox/singleshot/app/helpers/application_helper.rb Fri May 16 17:05:43 2008
@@ -19,7 +19,7 @@
       'Today'
     elsif date == today - 1.day
       'Yesterday'
-    elsif date.cweek == today.cweek
+    elsif date > today && date < today.next_week
       date.strftime('%A')
     elsif date.year == today.year
       date.strftime('%B %d')

Modified: ode/sandbox/singleshot/app/helpers/task_helper.rb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/helpers/task_helper.rb?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/helpers/task_helper.rb (original)
+++ ode/sandbox/singleshot/app/helpers/task_helper.rb Fri May 16 17:05:43 2008
@@ -1,46 +1,24 @@
 module TaskHelper
 
   def task_actions(task)
-    actions = []
-    actions << button_to('Manage', edit_task_url(task), :method=>:get, :title=>'Edit task') if task.admin?(authenticated)
-    actions << button_to('Cancel', task_url(task), :method=>:delete, :title=>'Cancel this task') if task.can_cancel?(authenticated)
-    actions << button_to('Claim', task_url(task, 'task[owner]'=>authenticated.identity), :method=>:put,
-                         :title=>'Claim task', :disabled=>!task.can_claim?(authenticated)) if task.active? || task.ready?
-    actions.join(' ')
+    manage = task.admin?(authenticated)
+    cancel = task.can_cancel?(authenticated)
+    claim = task.can_claim?(authenticated)
+    actions = [
+      manage && button_to('Manage', edit_task_url(task), :method=>:get, :title=>'Managed this task', :disabled=>!manage),
+      cancel && button_to('Cancel', task_url(task), :method=>:delete, :title=>'Cancel this task', :disabled=>!cancel),
+      claim && button_to('Claim', task_url(task, 'task[owner]'=>authenticated.identity), :method=>:put, :title=>'Claim task', :disabled=>!claim)
+    ].select { |action| action }.join(' ')
   end
 
   def task_vitals(task)
     vitals = ['Created ' + relative_date_abbr(task.created_at, :class=>'published')]
     vitals.first << ' by ' + link_to_person(task.creator) if task.creator
     vitals << (task.status == 'completed' ? "completed by " : "assigned to ") + link_to_person(task.owner) if task.owner
-    vitals << "due on #{task.due_on.to_formatted_s(:long)}" if task.due_on
+    vitals << "due #{relative_date_abbr(task.due_on)}" if task.due_on
     vitals.to_sentence
   end
 
-
-  def task_bar_vitals(task, person = authenticated)
-    case task.status
-    when :suspended
-      vitals = 'suspended'
-    when :cancelled
-      vitals = "cancelled #{relative_date_with_abbr(task.updated_at)}"
-    when :completed
-      vitals = "completed #{relative_date_with_abbr(task.updated_at)} by #{link_to_person(task.owner)}"
-    else
-      vitals = []
-      if creator = task.creator
-        vitals << "created by #{link_to_person(task.creator)}" unless creator == person
-      end
-      if owner = task.owner
-        vitals << (person == owner ? 'assigned to you' : 'assigned to ' + link_to_person(owner))
-      end
-      vitals << "due #{relative_date_with_abbr(task.due_on)}" if task.due_on
-      priority = [nil, 'medium', 'high'][task.priority - 1]
-      vitals << "#{priority} priority" if priority
-    end
-    Array(vitals).join(', ').gsub(/^\w/) { |w| w.upcase }
-  end
-
   def task_iframe_url(task, person = authenticated)
     task_uri = URI(task_url(task))
     task_uri.user, task_uri.password = '_token', task.token_for(person)

Modified: ode/sandbox/singleshot/app/models/activity.rb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/models/activity.rb?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/models/activity.rb (original)
+++ ode/sandbox/singleshot/app/models/activity.rb Fri May 16 17:05:43 2008
@@ -32,12 +32,8 @@
 
   attr_readonly :person, :task, :action
 
-  named_scope :for_stakeholder, lambda { |person|
-    { :joins=>'JOIN stakeholders AS involved ON involved.task_id=tasks.id',
-      :conditions=>["involved.person_id=? AND involved.role != 'excluded'", person.id],
-      :include=>[:task, :person], :order=>'activities.created_at DESC' }
-  } do
-    def by_day
+  module GroupByDay
+    def group_by_day
       self.inject([]) { |days, activity|
         created = activity.created_at.to_date
         day = days.last if days.last && days.last.first == created
@@ -47,7 +43,14 @@
       }
     end
   end
-  named_scope :for_dates, lambda { |dates| { :conditions=>{ :created_at=>dates } } }
 
-end
+  named_scope :for_stakeholder,
+    lambda { |person| { :joins=>'JOIN stakeholders AS involved ON involved.task_id=tasks.id',
+      :conditions=>["involved.person_id=? AND involved.role != 'excluded'", person.id],
+      :include=>[:task, :person], :order=>'activities.created_at DESC', :extend=>GroupByDay } }
+  named_scope :for_dates,
+    lambda { |dates| { :conditions=>{ :created_at=>dates } } }
+  named_scope :for_task,
+    lambda { |task| { :conditions=>{ :task_id=>task }, :include=>[:task, :person], :order=>'activities.created_at', :extend=>GroupByDay } }
 
+end

Modified: ode/sandbox/singleshot/app/models/sandwich.rb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/models/sandwich.rb?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/models/sandwich.rb (original)
+++ ode/sandbox/singleshot/app/models/sandwich.rb Fri May 16 17:05:43 2008
@@ -6,7 +6,7 @@
     (data && data['toppings']) || ''
   end
 
-  validates_presence_of :bread, :on=>:complete, :message=>'Spread without a bread?', :if=>:spread
-  validates_length_of   :toppings, :on=>:complete, :minimum=>1, :message=>'Your sandwich is short on toppings!'
+#  validates_presence_of :bread, :on=>:complete, :message=>'Spread without a bread?', :if=>:spread
+ # validates_length_of   :toppings, :on=>:complete, :minimum=>1, :message=>'Your sandwich is short on toppings!'
 
 end

Modified: ode/sandbox/singleshot/app/views/activities/show.html.erb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/views/activities/show.html.erb?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/views/activities/show.html.erb (original)
+++ ode/sandbox/singleshot/app/views/activities/show.html.erb Fri May 16 17:05:43 2008
@@ -1,7 +1,7 @@
 <ol class='activities hfeed'>
   <% for day in @days %>
     <li class='day'>
-      <h3><%= day.first.to_formatted_s(:long) %></h3>
+      <h3><%= relative_date(day.first) %></h3>
       <% for activity in day.last %>
       <% content_tag_for 'li', activity, :class=>'hentry entry-title' do %>
           <%= link_to activity.person.fullname, activity.person.identity %>

Modified: ode/sandbox/singleshot/app/views/activities/show.ics.ical
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/views/activities/show.ics.ical?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/views/activities/show.ics.ical (original)
+++ ode/sandbox/singleshot/app/views/activities/show.ics.ical Fri May 16 17:05:43 2008
@@ -1,9 +1,8 @@
 calendar.prodid = 'Apache Singleshot'
 for activity in @activities
   calendar.event do |event|
-    event.dtstamp activity.created_at
-    event.dtstart activity.created_at.to_date
     event.summary "#{activity.person.fullname} #{activity.action} #{activity.task.title}"
+    event.description activity.task.description
     event.url task_url(activity.task)
   end
 end

Modified: ode/sandbox/singleshot/app/views/layouts/application.html.erb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/views/layouts/application.html.erb?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/views/layouts/application.html.erb (original)
+++ ode/sandbox/singleshot/app/views/layouts/application.html.erb Fri May 16 17:05:43 2008
@@ -23,12 +23,12 @@
         <li><%= link_to 'Activity', activity_url %></a></li>
         <li><a href='#'>Start &hellip;</a></li>
       </ul>
-      <% if @alternate %>
-        <ul class='alternate'>
-          <li id='atom'><%= link_to image_tag('feed.png') + ' Feed', @alternate[Mime::ATOM], :title=>'Subscribe with your feed reader' %></li>
-          <li id='ical'><%= link_to image_tag('calendar.png') + ' Calendar', @alternate[Mime::ICS], :title=>'Add this link to your calendar' %></li>
-        </ul>
-      <% end %>
+      <ul class='alternate'>
+        <%= content_tag 'li', link_to(image_tag('feed.png') + ' Feed', @alternate[Mime::ATOM],
+                                      :rel=>'alternate', :title=>'Subscribe with your feed reader') if @alternate && @alternate[Mime::ATOM] %>
+        <%= content_tag 'li', link_to(image_tag('calendar.png') + ' Calendar', @alternate[Mime::ICS],
+                                      :rel=>'alternate', :title=>'Add to your calendar') if @alternate && @alternate[Mime::ICS] %>
+      </ul>
     </div>
     <div id='main'>
 <%= yield %>

Modified: ode/sandbox/singleshot/app/views/layouts/head.html.erb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/views/layouts/head.html.erb?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/views/layouts/head.html.erb (original)
+++ ode/sandbox/singleshot/app/views/layouts/head.html.erb Fri May 16 17:05:43 2008
@@ -2,11 +2,13 @@
   <head>
     <title>Singleshot<%= " &mdash; #{escape_once(@title)}" if @title %></title>
     <%= javascript_include_tag :all, :cache=>true %>
-    <%= stylesheet_link_tag 'screen', 'buttons', 'default', :cache=>true %>
+    <%= stylesheet_link_tag 'default', :cache=>true %>
     <%= stylesheet_link_tag 'print', :media=>'print', :cache=>true %>
     <% @alternate.each do |mime, url| %>
       <%= auto_discovery_link_tag mime.to_sym, url %>
     <% end if @alternate %>
   </head>
+  <body>
 <%= yield %>
+  </body>
 </html>

Modified: ode/sandbox/singleshot/app/views/sandwiches/show.html.erb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/views/sandwiches/show.html.erb?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/views/sandwiches/show.html.erb (original)
+++ ode/sandbox/singleshot/app/views/sandwiches/show.html.erb Fri May 16 17:05:43 2008
@@ -1,37 +1,46 @@
-<script>
-  function roomForNewTopping() {
-    var lastTopping = $('last_topping').parentNode;
-    var newTopping = lastTopping.cloneNode(true);
-    newTopping.firstChild.value = null;
-    lastTopping.parentNode.insertBefore(newTopping, lastTopping.nextSibling);
-  }
-</script>
-<div style='padding:2em 5em 2em 5em'>
-  <% form_for :sandwich, @sandwich, :html=>{ :id=>'sandwich' } do |f| %>
-    <%= content_tag 'p', flash[:success], :class=>'success' if flash[:success] %>
-    <%= error_messages_for :sandwich, :message=>"Sudo can't make this sandwich ...", :header_message=>nil, :class=>'error' %>
-    <dl>
-      <dt><%= f.label :bread, 'Pick your bread' %></dt>
-      <dd><%= f.select :bread, ['Crusty', 'Toasty', 'French'].map { |s| [s, s.split.first.downcase] } + [['Atkins style', '']],
-                {}, :disabled=>@read_only %></dd>
-      <dt><%= f.label :spread, 'Choose your spread' %></dt>
-      <dd><%= f.select :spread, ['Creamy', 'Eggy', 'Not butter'].map { |s| [s, s.sub(/ /, '_').downcase] } + [['Air like', '']],
-                {}, :disabled=>@read_only %></dd>
-      <dt><%= f.label :toppings, 'Top it with' %>
-          <%= '(' + link_to_function('add topping', 'roomForNewTopping()') + ')' unless @read_only %></dt>
-      <% @sandwich.toppings.split(/;/).each do |topping| %>
-        <dd><%= text_field_tag 'sandwich[toppings][]', topping, :disabled=>@read_only %></dd>
+<html>
+  <head>
+    <title>Sudo, make me a sandwich!</title>
+    <%= javascript_include_tag :all, :cache=>true %>
+    <%= stylesheet_link_tag 'default', :cache=>true %>
+    <script>
+      function roomForNewTopping() {
+        var lastTopping = $('last_topping').parentNode;
+        var newTopping = lastTopping.cloneNode(true);
+        newTopping.firstChild.value = null;
+        lastTopping.parentNode.insertBefore(newTopping, lastTopping.nextSibling);
+      }
+    </script>
+  </head>
+  <body>
+    <div style='padding:2em 5em 2em 5em'>
+      <% form_for :sandwich, @sandwich, :html=>{ :id=>'sandwich' } do |f| %>
+        <%= content_tag 'p', flash[:success], :class=>'success' if flash[:success] %>
+        <%= error_messages_for :sandwich, :message=>"Sudo can't make this sandwich ...", :header_message=>nil, :class=>'error' %>
+        <dl>
+          <dt><%= f.label :bread, 'Pick your bread' %></dt>
+          <dd><%= f.select :bread, ['Crusty', 'Toasty', 'French'].map { |s| [s, s.split.first.downcase] } + [['Atkins style', '']],
+                    {}, :disabled=>@read_only %></dd>
+          <dt><%= f.label :spread, 'Choose your spread' %></dt>
+          <dd><%= f.select :spread, ['Creamy', 'Eggy', 'Not butter'].map { |s| [s, s.sub(/ /, '_').downcase] } + [['Air like', '']],
+                    {}, :disabled=>@read_only %></dd>
+          <dt><%= f.label :toppings, 'Top it with' %>
+              <%= '(' + link_to_function('add topping', 'roomForNewTopping()') + ')' unless @read_only %></dt>
+          <% @sandwich.toppings.split(/;/).each do |topping| %>
+            <dd><%= text_field_tag 'sandwich[toppings][]', topping, :disabled=>@read_only %></dd>
+          <% end %>
+          <dd><%= text_field_tag 'sandwich[toppings][]', '', :id=>'last_topping', :disabled=>@read_only %></dd>
+        </dl>
+        <% unless @read_only %>
+          <hr>
+          <p>
+            <%= content_tag :button, 'Make!', :class=>'positive' %>
+            <%= content_tag :button, 'Save and continue', :name=>:_method, :value=>:put %>
+          </p>
+        <% end %>
+        <%= hidden_field_tag 'task_url', @task_url %>
       <% end %>
-      <dd><%= text_field_tag 'sandwich[toppings][]', '', :id=>'last_topping', :disabled=>@read_only %></dd>
-    </dl>
-    <% unless @read_only %>
-      <hr>
-      <p>
-        <%= content_tag :button, 'Make!', :class=>'positive' %>
-        <%= content_tag :button, 'Save and continue', :name=>:_method, :value=>:put %>
-      </p>
-    <% end %>
-    <%= hidden_field_tag 'task_url', @task_url %>
-  <% end %>
-  <%= javascript_tag "$('sandwich').focusFirstElement()" %>
-</div>
+      <%= javascript_tag "$('sandwich').focusFirstElement()" %>
+    </div>
+  </body>
+</html>

Modified: ode/sandbox/singleshot/app/views/tasks/index.html.erb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/views/tasks/index.html.erb?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/views/tasks/index.html.erb (original)
+++ ode/sandbox/singleshot/app/views/tasks/index.html.erb Fri May 16 17:05:43 2008
@@ -1,3 +1,4 @@
+<% @title = 'Tasks' %>
 <ol class='tasks hfeed'>
   <% @tasks.each do |task| %>
     <% content_tag_for 'li', task, :class=>'hentry' do %>

Modified: ode/sandbox/singleshot/app/views/tasks/show.html.erb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/views/tasks/show.html.erb?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/views/tasks/show.html.erb (original)
+++ ode/sandbox/singleshot/app/views/tasks/show.html.erb Fri May 16 17:05:43 2008
@@ -1,15 +1,35 @@
-<% @title = @task.title %>
-<body id='task'>
-  <div id='task_bar'>
-    <div id='summary'>
-      <span class='column prepend-1'><%= link_to 'Singleshot', root_url, :title=>'Switch back to dashboard' %></span>
-      <span class='column prepend-1'><%= task_bar_vitals(@task) %></span>
-      <span class='column push-0 append-1 last'><%= task_bar_actions(@task) %> <%= link_to_function 'More Options', "Singleshot.expand(event, 'expanded')" %></span>
-    </div>
-    <div id='expanded' style='display:none'>
-      Nothing to see ... move right along.
+<% # TODO: trim
+@title = @task.title %>
+<div id='task_bar'>
+  <div id='summary'>
+    <h1><%= link_to 'Singleshot', root_url %></h1>
+    <div class='vitals'><%= task_vitals(@task) %></div>
+    <div class='actions'><%= task_actions(@task) %> <%= link_to_function 'More Options', "Singleshot.expand(event, 'expanded')", :class=>'button-to' %></div>
+  </div>
+  <div id='expanded' style='display:none'>
+    <%= link_to image_tag('calendar.png') + ' Calendar', formatted_task_url(@task, 'ics'), :rel=>'alternate', :title=>'Add this task to your calendar' %>
+    <%= link_to image_tag('feed.png') + ' Activities', activity_task_url(@task), :rel=>'alternate', :title=>'Subscribe to see changes to this task' %>
+    <dl>
+      <dt>Task</dt><dd><%= h(@task.title) %></dd>
+      <dt>Description</dt><dd><%= h(@task.description) %></dd>
+      <dt>Priority</dt><dd><%= ['High', 'Medium', 'Low'][@task.priority - 1] %></dd>
+      <dt>Recent activity</dt>
+      <dd>
+        <ol class='activities hfeed'>
+          <% for activity in @activities %>
+            <% content_tag_for 'li', activity, :class=>'hentry entry-title' do %>
+              <%= link_to activity.person.fullname, activity.person.identity %>
+              <%= activity.action %>
+              <%= link_to activity.task.title, task_url(activity.task), :rel=>'bookmark' %>
+            <% end %>
+          <% end %>
+        </ol>
+      </dd>
+    </dl>
+    <div class='actions' style='text-align:right'>
+      <%= task_actions(@task) %>
     </div>
   </div>
-  <%= content_tag 'iframe', nil, :id=>'task_frame', :src=>task_iframe_url(@task) %>
-  <%= javascript_tag 'Singleshot.taskView()' %>
-</body>
+</div>
+<%= content_tag 'iframe', nil, :id=>'task_frame', :src=>task_iframe_url(@task) %>
+<%= javascript_tag 'Singleshot.taskView()' %>

Modified: ode/sandbox/singleshot/config/routes.rb
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/config/routes.rb?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/config/routes.rb (original)
+++ ode/sandbox/singleshot/config/routes.rb Fri May 16 17:05:43 2008
@@ -1,7 +1,7 @@
 ActionController::Routing::Routes.draw do |map|
 
   map.resource 'session'
-  map.resources 'tasks', :collection=>{ 'following'=>:get, 'completed'=>:get }
+  map.resources 'tasks', :collection=>{ 'following'=>:get, 'completed'=>:get }, :member=>{ 'activity'=>:get }
   map.resource 'activity'
   map.day_activity 'activity/:year/:month/:day', :controller=>'activities', :action=>'show', :year =>/\d{4}/, :month=>/\d{1,2}/, :day=>/\d{1,2}/
   map.root :controller=>'tasks'

Modified: ode/sandbox/singleshot/lib/tasks/database.rake
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/lib/tasks/database.rake?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/lib/tasks/database.rake (original)
+++ ode/sandbox/singleshot/lib/tasks/database.rake Fri May 16 17:05:43 2008
@@ -16,7 +16,7 @@
     end
 
     puts "Populating database for #{you.identity}"
-    url = 'http://localhost:3001/sandwhich'
+    url = 'http://localhost:3001/sandwich'
     other = Person.identify('anon') || Person.create(:email=>'anon@apache.org')
     create = lambda do |attributes|
       attributes = { :title=>Faker::Lorem.sentence, :description=>Faker::Lorem.paragraph,

Modified: ode/sandbox/singleshot/lib/tasks/development.rake
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/lib/tasks/development.rake?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/lib/tasks/development.rake (original)
+++ ode/sandbox/singleshot/lib/tasks/development.rake Fri May 16 17:05:43 2008
@@ -2,9 +2,9 @@
 task 'run' do
   at_exit do
     puts 'Stopping Thin ...'
-    system 'thin stop'
+    system 'thin stop -s2'
   end
   puts 'Starting Thin ...'
-  system 'thin', 'start', '-d', '-p', ENV['PORT'] || '3000'
+  system "thin start -d -s2 -p #{ENV['PORT'] || '3000'}"
   system 'tail -f log/development.log'
 end

Modified: ode/sandbox/singleshot/public/javascripts/application.js
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/public/javascripts/application.js?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/public/javascripts/application.js (original)
+++ ode/sandbox/singleshot/public/javascripts/application.js Fri May 16 17:05:43 2008
@@ -1,2 +1,47 @@
 // Place your application-specific JavaScript functions and classes here
 // This file is automatically included by javascript_include_tag :defaults
+//
+var Singleshot = {
+  // Returns the SingleShot.TaskView object.
+  taskView: function() {
+    var taskView = new Singleshot.TaskView();
+    Singleshot.taskView = function() { return taskView };
+    return taskView;
+  },
+
+  expand: function(event, target, alternative) {
+    event = event || window.event;
+    var source = Event.element(event);
+    target = $(target);
+    if (target.visible()) {
+      source.innerHTML = source.originalText; 
+      target.hide();
+    } else if (event.shiftKey || event.ctrlKey || event.metaKey) {
+      return;
+    } else {
+      source.originalText = source.innerHTML;
+      if (alternative)
+        source.innerHTML = alternative;
+      target.show();
+    }
+    Event.stop(event);
+  }
+}
+
+Singleshot.TaskView = Class.create({
+  initialize: function() {
+    this.adjustFrame('task_frame');
+  },
+
+  adjustFrame: function(ifr) {
+    // Adjust lower frame to expand and fit the reminder of the window.
+    // Do it once now, and each time the window is resized.
+    if (ifr = $(ifr)) {
+      var adjust = function() {
+        ifr.style.height = window.innerHeight - ifr.offsetTop;
+      }
+      Event.observe(window, 'resize', adjust);
+      adjust();
+    }
+  }
+});

Modified: ode/sandbox/singleshot/public/stylesheets/default.css
URL: http://svn.apache.org/viewvc/ode/sandbox/singleshot/public/stylesheets/default.css?rev=657254&r1=657253&r2=657254&view=diff
==============================================================================
--- ode/sandbox/singleshot/public/stylesheets/default.css (original)
+++ ode/sandbox/singleshot/public/stylesheets/default.css Fri May 16 17:05:43 2008
@@ -1,3 +1,5 @@
+/** Main styles **/
+
 body {
   font: 10pt "Lucida Grande", Helvetica, Sans;
   color: #000;
@@ -6,39 +8,62 @@
   padding: 0;
 }
 
+abbr {
+  text-decoration: none;
+  border: none;
+}
+
+
+/** Forms and controls **/
 
 /** Form controls **/
 
 input[type=text], input[type=password], select {
-  background: transparent url(/images/textfield.png) bottom left repeat-x;
-  padding: 0.25em 0.5em;
+  padding: 0.3em;
   border: 1px solid #ccc;
-  margin: 0;
   width:30em;
 }
 input[type=text]:hover, input[type=password]:hover, select:hover {
-  border: 1px solid #888;
+  border: 1px solid #444;
 }
 input[type=text]:focus, input[type=password]:focus, select:focus {
-  border: 1px solid #000;
+  border: 1px solid #444;
+}
+input[type=text][disabled], input[type=password][disabled], select[disabled] {
+  border: 1px solid #ccc;
 }
 option {
-  margin-top: 0.3em;
 }
 optgroup {
   margin-bottom: 0.3em;
   padding-bottom: 0.3em;
   border-bottom: 1px solid #ccc;
 }
-/*
-form div.fieldWithErrors {
-  color: red;
+
+form.button-to, form.button-to div {
   display: inline;
 }
-*/
-div#errorExplanation p, div#errorExplanation ul {
+form.button-to input, a.button-to, button {
+  font-size: 1em;
+  font-weight: bold;
+  border: none;
+  padding: 0.3em 0.6em 0.3em 0.6em;
   margin: 0;
-  list-style: none;
+  color: #fff;
+  background-color: #646060;
+  cursor: pointer;
+  text-decoration: none;
+  -moz-border-radius: 2px;
+  -webkit-border-radius: 4px;
+}
+form.button-to input:hover, a.button-to:hover, button:hover {
+  border: none;
+  color: #fff;
+  background-color: #4c4848;
+}
+form.button-to input[disabled], button[disabled] {
+  background-color: #ccc;
+  cursor: default;
 }
 
 form dl {
@@ -47,97 +72,27 @@
 form dl dt {
 }
 form dl dd {
-  margin: 0 0 1em 0;
-}
-
-
-/** Header **/
-
-#header {
-}
-
-
-/** Main **/
-
-#main {
+  margin: 0.3em 0 1em 0;
 }
 
-
-/** Footer **/
-
-#footer {
-}
-
-
-/** Login **/
-form.login {
-  width: 30em;
-  margin: 2em auto 2em auto;
-}
-form.login dl {
-  width: 25em;
-  margin: 0 auto 0 auto;
+fieldset {
+  border: 2pt solid #ccc;
+  padding: 1em;
 }
-form.login input {
-  width: 100%;
-}
-
 
-
-/** Task view: bar and frame **/
-body#task {
-  margin:0;
-}
-body#task #task_bar {
-  position:absolute;
-  width:100%;
-  margin:0;
-  padding:0;
-}
-
-body#task #summary {
-  height:2em;
-  padding-top:0.3em;
-  background:#383838;
-  color:#d8d8d8;
-}
-body#task #summary a {
-  color:white;
-  text-decoration:none;
-}
-body#task #summary a:hover {
-  text-decoration:underline;
-}
-body#task #summary form.button-to input {
-  border:none;
-  font-size:100%;
-  line-height:100%;
-  background:transparent;
-  color:white;
-  padding:0;
-  margin:0 1em 0 0;
-}
-body#task #summary form.button-to input:hover {
-  text-decoration:underline;
+/*
+form div.fieldWithErrors {
+  color: red;
+  display: inline;
 }
-
-body#task #expanded {
-  clear:both;
-  background:#eee;
-  padding:1em;
-  border-bottom:0.05em solid #383838;
-  margin:0;
+*/
+div#errorExplanation p, div#errorExplanation ul {
+  margin: 0;
+  list-style: none;
 }
 
-body#task iframe#task_frame {
-  border:0;
-  width:100%;
-  height:0;
-  padding:0;
-  margin:2em 0 0 0;
-  background:transparent;
-}
 
+/** Header **/
 
 #header {
   background-color: #e0e0e0;
@@ -185,8 +140,7 @@
   text-decoration: none;
   background-color: #046380;
   padding: 0.3em 0.6em 0.3em 0.6em;
-  -moz-border-radius-topright: 4px;
-  -moz-border-radius-topleft: 4px;
+  -moz-border-radius: 4px 4px 0 0;
   -webkit-border-top-left-radius: 6px;
   -webkit-border-top-right-radius: 6px;
 }
@@ -205,63 +159,68 @@
   -webkit-border-top-left-radius: 0.3em;
 }
 
-ul.alternate {
+#header ul.alternate {
   list-style: none;
   float: right;
   position: relative;
   margin-top: -1.3em;
   font-size: 1.2em;
 }
-ul.alternate li {
+#header ul.alternate li {
   display: inline;
 }
-ul.alternate a {
+#header ul.alternate a {
   padding-left: 1em;
   text-decoration: none;
 }
-ul.alternate img {
+#header ul.alternate img {
   border: none;
   vertical-align: bottom;
   margin: 0.1em;
 }
 
-ol.tasks {
+
+/** Tasks list **/
+
+#main ol.tasks {
   list-style: none;
   margin: 2em 3.5em 0 3.5em;
   padding: 0;
 }
-ol.tasks li.task {
+#main ol.tasks li.task {
   border-bottom: 1px solid #ccc;
   margin-bottom: 1.5em;
 }
-ol.tasks li.task .entry-title {
+#main ol.tasks li.task .entry-title {
   font-size: 1.2em;
   margin: 0;
 }
-ol.tasks li.task .entry-title.priority_1:before {
+#main ol.tasks li.task .entry-title.priority_1:before {
   content: '✭ ';
   color: red;
 }
-ol.tasks li.task .entry-title.overdue a {
+#main ol.tasks li.task .entry-title.overdue a {
   color: red;
 }
-ol.tasks li.task a {
+#main ol.tasks li.task a {
   text-decoration: none;
 }
-ol.tasks li.task .description {
+#main ol.tasks li.task .description {
   color: #222;
 }
-ol.tasks li.task .actions {
+#main ol.tasks li.task .actions {
   float: right;
 }
-ol.tasks li.task .actions form {
+#main ol.tasks li.task .actions form {
   margin-left: 0.1em;
 }
-ol.tasks li.task p.vitals {
+#main ol.tasks li.task p.vitals {
   color: #808080;
 }
 
 
+/** Activities **/
+
 ol.activities {
   list-style: none;
   margin: 2em 3.5em 0 3.5em;
@@ -275,32 +234,98 @@
 }
 
 
-form.button-to, form.button-to div {
+/** Task bar **/
+
+#task_bar {
+  position:absolute;
+  width:100%;
+  margin:0;
+  padding:0;
+  border-bottom: solid 2px #046380;
+}
+#task_bar #summary {
+  height:2em;
+  padding-top:0.3em;
+  background-color: #e0e0e0;
+  padding: 0.5em 3em 3px 3em;
+}
+#task_bar #summary h1 {
+  margin: 0;
+  font-size: 1.5em;
   display: inline;
 }
-form.button-to input {
-  font-size: 1em;
+#task_bar #summary h1 a {
+  color: #000;
+  text-decoration: none;
+}
+#task_bar #summary div.vitals {
+  display: inline;
+  margin-left: 2em;
+}
+#task_bar #summary div.actions {
+  display: inline;
+  position: absolute;
+  right: 2em;
+  top: 0.5em;
+}
+#task_bar #summary .button-to {
+  margin-left: 1em;
+}
+
+#task_bar #expanded {
+  clear: both;
+  background: #fff;
+  padding: 2em 3em 2em 3em;
+  border-bottom: 0.05em solid #383838;
+  margin: 0;
+}
+#task_bar #expanded dt {
   font-weight: bold;
-  border: none;
-  padding: 0.3em 0.6em 0.3em 0.6em;
+  display: inline;
+  float: left;
+}
+#task_bar #expanded dd {
+  margin: 0 0 1em 10em;
+}
+#task_bar #expanded dd ol.activities {
   margin: 0;
-  color: #fff;
-  background-color: #646060;
-  cursor:pointer;
-  -moz-border-radius: 2px;
-  -webkit-border-radius: 4px;
 }
-form.button-to input:hover {
+#task_bar #expanded a[rel=alternate] {
+  float: right;
+  padding-left: 1em;
+  text-decoration: none;
+}
+#task_bar #expanded a[rel=alternate] img {
   border: none;
-  color: #fff;
-  background-color: #4c4848;
+  vertical-align: bottom;
+  margin: 0.1em;
 }
-form.button-to input[disabled] {
-  background-color: #eee;
-  cursor:default;
+
+iframe#task_frame {
+  border:0;
+  width:100%;
+  height:0;
+  padding:0;
+  margin:2em 0 0 0;
+  background:transparent;
 }
 
-abbr {
-  text-decoration: none;
-  border: none;
+
+/** Footer **/
+
+#footer {
+}
+
+
+/** Login **/
+form.login {
+  width: 30em;
+  margin: 2em auto 2em auto;
+}
+form.login dl {
+  width: 25em;
+  margin: 0 auto 0 auto;
+}
+form.login input {
+  width: 100%;
 }