Merge branch 'calendar'

This commit is contained in:
Reinier Balt 2008-10-04 15:59:40 +02:00
commit 4c89133561
9 changed files with 228 additions and 6 deletions

View file

@ -2,9 +2,9 @@ class TodosController < ApplicationController
helper :todos
skip_before_filter :login_required, :only => [:index]
prepend_before_filter :login_or_feed_token_required, :only => [:index]
append_before_filter :init, :except => [ :destroy, :completed, :completed_archive, :check_deferred, :toggle_check, :toggle_star, :edit, :update, :create ]
skip_before_filter :login_required, :only => [:index, :calendar]
prepend_before_filter :login_or_feed_token_required, :only => [:index, :calendar]
append_before_filter :init, :except => [ :destroy, :completed, :completed_archive, :check_deferred, :toggle_check, :toggle_star, :edit, :update, :create, :calendar ]
append_before_filter :get_todo_from_params, :only => [ :edit, :toggle_check, :toggle_star, :show, :update, :destroy ]
session :off, :only => :index, :if => Proc.new { |req| is_feed_request(req) }
@ -128,8 +128,10 @@ class TodosController < ApplicationController
# Toggles the 'done' status of the action
#
def toggle_check
@source_view = params['_source_view'] || 'todo'
@original_item_due = @todo.due
@saved = @todo.toggle_completion!
# check if this todo has a related recurring_todo. If so, create next todo
check_for_next_todo if @saved
@ -139,6 +141,8 @@ class TodosController < ApplicationController
determine_remaining_in_context_count(@todo.context_id)
determine_down_count
determine_completed_count if @todo.completed?
@original_item_due_id = get_due_id_for_calendar(@original_item_due)
@old_due_empty = is_old_due_empty(@original_item_due_id)
end
render
end
@ -172,6 +176,9 @@ class TodosController < ApplicationController
@original_item_context_id = @todo.context_id
@original_item_project_id = @todo.project_id
@original_item_was_deferred = @todo.deferred?
@original_item_due = @todo.due
@original_item_due_id = get_due_id_for_calendar(@todo.due)
if params['todo']['project_id'].blank? && !params['project_name'].nil?
if params['project_name'] == 'None'
project = Project.null_object
@ -222,6 +229,17 @@ class TodosController < ApplicationController
@context_changed = @original_item_context_id != @todo.context_id
@todo_was_activated_from_deferred_state = @original_item_was_deferred && @todo.active?
@due_date_changed = @original_item_due != @todo.due
if @due_date_changed
@old_due_empty = is_old_due_empty(@original_item_due_id)
if @todo.due.nil?
# do not act further on date change when date is changed to nil
@due_date_changed = false
else
@new_due_id = get_due_id_for_calendar(@todo.due)
end
end
if @context_changed
determine_remaining_in_context_count(@original_item_context_id)
else
@ -251,6 +269,7 @@ class TodosController < ApplicationController
def destroy
@todo = get_todo_from_params
@original_item_due = @todo.due
@context_id = @todo.context_id
@project_id = @todo.project_id
@ -277,6 +296,8 @@ class TodosController < ApplicationController
if source_view_is_one_of(:todo, :deferred)
determine_remaining_in_context_count(@context_id)
end
@original_item_due_id = get_due_id_for_calendar(@original_item_due)
@old_due_empty = is_old_due_empty(@original_item_due_id)
end
render
end
@ -404,7 +425,47 @@ class TodosController < ApplicationController
format.js {render :action => 'update'}
end
end
def calendar
@source_view = params['_source_view'] || 'calendar'
@page_title = "TRACKS::Calendar"
due_today_date = Time.zone.now
due_this_week_date = Time.zone.now.end_of_week
due_next_week_date = due_this_week_date + 7.days
due_this_month_date = Time.zone.now.end_of_month
@due_today = current_user.todos.find(:all,
:include => [:taggings, :tags],
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due <= ?', 'active', 'deferred', due_today_date],
:order => "due")
@due_this_week = current_user.todos.find(:all,
:include => [:taggings, :tags],
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due > ? AND todos.due <= ?', 'active', 'deferred', due_today_date, due_this_week_date],
:order => "due")
@due_next_week = current_user.todos.find(:all,
:include => [:taggings, :tags],
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due > ? AND todos.due <= ?', 'active', 'deferred', due_this_week_date, due_next_week_date],
:order => "due")
@due_this_month = current_user.todos.find(:all,
:include => [:taggings, :tags],
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due > ? AND todos.due <= ?', 'active', 'deferred', due_next_week_date, due_this_month_date],
:order => "due")
@due_after_this_month = current_user.todos.find(:all,
:include => [:taggings, :tags],
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due > ?', 'active', 'deferred', due_this_month_date],
:order => "due")
respond_to do |format|
format.html
format.ics {
@due_all = current_user.todos.find(:all,
:conditions => ['(todos.state = ? OR todos.state = ?) AND NOT todos.due IS NULL', 'active', 'deferred'],
:order => "due")
render :action => 'calendar', :layout => false, :content_type => Mime::ICS
}
end
end
private
@ -718,6 +779,51 @@ class TodosController < ApplicationController
end
end
end
def get_due_id_for_calendar(due)
due_today_date = Time.zone.now
due_this_week_date = Time.zone.now.end_of_week
due_next_week_date = due_this_week_date + 7.days
due_this_month_date = Time.zone.now.end_of_month
if due <= due_today_date
new_due_id = "due_today"
elsif due <= due_this_week_date
new_due_id = "due_this_week"
elsif due <= due_next_week_date
new_due_id = "due_next_week"
elsif due <= due_this_month_date
new_due_id = "due_this_month"
else
new_due_id = "due_after_this_month"
end
return new_due_id
end
def is_old_due_empty(id)
due_today_date = Time.zone.now
due_this_week_date = Time.zone.now.end_of_week
due_next_week_date = due_this_week_date + 7.days
due_this_month_date = Time.zone.now.end_of_month
case id
when "due_today"
return 0 == current_user.todos.count(:all,
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due <= ?', 'active', 'deferred', due_today_date])
when "due_this_week"
return 0 == current_user.todos.count(:all,
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due > ? AND todos.due <= ?', 'active', 'deferred', due_today_date, due_this_week_date])
when "due_next_week"
return 0 == current_user.todos.count(:all,
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due > ? AND todos.due <= ?', 'active', 'deferred', due_this_week_date, due_next_week_date])
when "due_this_month"
return 0 == current_user.todos.count(:all,
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due > ? AND todos.due <= ?', 'active', 'deferred', due_next_week_date, due_this_month_date])
when "due_after_this_month"
return 0 == current_user.todos.count(:all,
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due > ?', 'active', 'deferred', due_this_month_date])
else
raise Exception.new, "unknown due id for calendar: '#{id}'"
end
end
class FindConditionBuilder

View file

@ -54,6 +54,7 @@ window.onload=function(){
<% if current_user.is_admin? -%>
<li><%= navigation_link("Admin", users_path, {:accesskey => "a", :title => "Add or delete users"} ) %></li>
<% end -%>
<li><%= navigation_link(image_tag("x-office-calendar.png", :size => "16X16", :border => 0), calendar_path, :title => "Calendar of due actions" ) %></li>
<li><%= navigation_link(image_tag("recurring_menu16x16.png", :size => "16X16", :border => 0), {:controller => "recurring_todos", :action => "index"}, :title => "Manage recurring actions" ) %></li>
<li><%= navigation_link(image_tag("feed-icon.png", :size => "16X16", :border => 0), {:controller => "feedlist", :action => "index"}, :title => "See a list of available feeds" ) %></li>
<li><%= navigation_link(image_tag("menustar.gif", :size => "16X16", :border => 0), tag_path("starred"), :title => "See your starred actions" ) %></li>

View file

@ -0,0 +1,68 @@
<div id="display_box">
<div class="container">
<h2>Due today</h2>
<div id="empty_due_today" <%= "style=\"display:none\"" unless @due_today.empty? %>>
No actions due today
</div>
<div id="due_today">
<%= render :partial => "todos/todo", :collection => @due_today %>
</div>
</div>
<div class="container">
<h2>Due in rest of this week</h2>
<div id="empty_due_this_week" <%= "style=\"display:none\"" unless @due_this_week.empty? %>>
No actions due in rest of this week
</div>
<div id="due_this_week">
<%= render :partial => "todos/todo", :collection => @due_this_week %>
</div>
</div>
<div class="container">
<h2>Due next week</h2>
<div id="empty_due_next_week" <%= "style=\"display:none\"" unless @due_next_week.empty? %>>
No actions due in next week
</div>
<div id="due_next_week">
<%= render :partial => "todos/todo", :collection => @due_next_week %>
</div>
</div>
<div class="container">
<h2>Due in rest of this month</h2>
<div id="empty_due_this_month" <%= "style=\"display:none\"" unless @due_this_month.empty? %>>
No actions due in rest of this month
</div>
<div id="due_this_month">
<%= render :partial => "todos/todo", :collection => @due_this_month %>
</div>
</div>
<div class="container">
<h2>Due next month and later</h2>
<div id="empty_due_after_this_month" <%= "style=\"display:none\"" unless @due_after_this_month.empty? %>>
No actions due after this month
</div>
<div id="due_after_this_month">
<%= render :partial => "todos/todo", :collection => @due_after_this_month %>
</div>
</div>
</div><!-- End of display_box -->
<div class="input_box" id="input_box">
<!--
<input class="hide_tickler" id="hide_tickler" type="checkbox" tabindex="5" name="hide_tickler" checked="true"/>
<label for="hide_tickler"> Show actions in tickler</label>
<br/><br/>
-->
<p><%= link_to('<span class="feed">iCal</span>', {:format => 'ics', :token => current_user.token}, :title => "iCal feed" ) %>
- Get this calendar in iCal format</p>
</div>
<%
apply_behavior 'input.hide_tickler:click', :prevent_default => true do |page|
page << "alert('hiding action in tickler from calendar is not yet implemented');"
end
%>

View file

@ -0,0 +1,25 @@
BEGIN:VCALENDAR
PRODID:-//TRACKS//<%= TRACKS_VERSION %>//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:Tracks
<% for todo in @due_all -%>
BEGIN:VEVENT
DTSTART;VALUE=DATE:<%= todo.due.strftime("%Y%m%d") %>
DTEND;VALUE=DATE:<%= (todo.due+1.day).strftime("%Y%m%d") %>
DTSTAMP:<%= todo.due.strftime("%Y%m%dT%H%M%SZ") %>
UID:<%= todo_url(todo) %>
CLASS:PUBLIC
CATEGORIES:Tracks
CREATED:<%= todo.created_at.strftime("%Y%m%dT%H%M%SZ") %>
DESCRIPTION:<%= format_ical_notes(todo.notes) %>
LAST-MODIFIED:<%= todo.due.strftime("%Y%m%dT%H%M%SZ") %>
LOCATION:
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:<%= todo.description %>
TRANSP:TRANSPARENT
END:VEVENT
<% end -%>
END:VCALENDAR

View file

@ -1,5 +1,6 @@
if @saved
page[@todo].remove
page.show "empty_"+@original_item_due_id if @old_due_empty
page['badge_count'].replace_html @down_count
# remove context if empty

View file

@ -1,5 +1,6 @@
if @saved
page[@todo].remove
page.show "empty_"+@original_item_due_id if @old_due_empty
if @todo.completed?
# completed todos move from their context to the completed container
@ -26,7 +27,7 @@ if @saved
page.notify :notice, "There is no next action after the recurring action you just finished. The recurrence is completed", 6.0 if @new_recurring_todo.nil?
end
end
else
# todo is activated from completed container
page.call "todoItems.ensureVisibleWithEffectAppear", item_container_id(@todo)

View file

@ -101,6 +101,23 @@ if @saved
elsif source_view_is :stats
page.replace dom_id(@todo), :partial => 'todos/todo', :locals => { :parent_container_type => parent_container_type }
page.visual_effect :highlight, dom_id(@todo), :duration => 3
elsif source_view_is :calendar
if @due_date_changed
page[@todo].remove
page.show "empty_"+@original_item_due_id if @old_due_empty
page.hide "empty_"+@new_due_id
page.insert_html :bottom, @new_due_id, :partial => 'todos/todo'
page.visual_effect :highlight, dom_id(@todo), :duration => 3
else
if @todo.due.nil?
# due date removed
page[@todo].remove
page.show "empty_"+@original_item_due_id if @old_due_empty
else
page.replace dom_id(@todo), :partial => 'todos/todo', :locals => { :parent_container_type => parent_container_type }
page.visual_effect :highlight, dom_id(@todo), :duration => 3
end
end
else
logger.error "unexpected source_view '#{params[:_source_view]}'"
end

View file

@ -46,6 +46,9 @@ ActionController::Routing::Routes.draw do |map|
todos.tag 'todos/tag/:name.m', :action => "tag", :format => 'm'
todos.tag 'todos/tag/:name', :action => "tag", :name => /.*/
todos.calendar 'calendar.ics', :action => "calendar", :format => 'ics'
todos.calendar 'calendar', :action => "calendar"
todos.mobile 'mobile', :action => "index", :format => 'm'
todos.mobile_abbrev 'm', :action => "index", :format => 'm'
todos.mobile_abbrev_new 'm/new', :action => "new", :format => 'm'

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 B