class TodoController < ApplicationController
model :user
model :project
model :context
helper :todo
prepend_before_filter :login_required
layout "standard"
def index
list
render_action "list"
end
# Main method for listing tasks
# Set page title, and fill variables with contexts and done and not-done tasks
# Number of completed actions to show is determined by a setting in settings.yml
#
def list
self.init
@on_page = "home"
@page_title = "TRACKS::List tasks"
# If you've set no_completed to zero, the completed items box
# isn't shown on the home page
max_completed = @user.preferences["no_completed"].to_i-1
@done = (max_completed > 0) ? @done[0..max_completed] : nil
@contexts_to_show = @contexts.reject {|x| x.hide? }
if @contexts.empty?
flash['warning'] = 'You must add at least one context before adding next actions.'
end
# Set count badge to number of not-done, not hidden context items
@count = @todos.reject { |x| x.done? || x.context.hide? }.size
respond_to do |wants|
wants.html
wants.xml { render :action => 'list.rxml', :layout => false }
end
end
# Is this used? Seems like it should be deleted. -lukemelia, 2006-07-16
def update_element
end
# Called by a form button
# Parameters from form fields are passed to create new action
# in the selected context.
def add_item
self.init
@item = @user.todos.build
@item.attributes = params["todo"]
@on_page = "home"
perform_add_item('list')
end
# Adding deferred actions from form on todo/tickler
#
def add_deferred_item
self.init
@item = Deferred.create(params["todo"])
@item.user_id = @user.id
@on_page = "tickler"
perform_add_item('tickler')
end
def edit_action
self.init
@item = check_user_return_item
render :layout => false
end
def show
self.init
item = check_user_return_item
respond_to do |wants|
wants.xml { render :xml => item.to_xml( :root => 'todo', :except => :user_id ) }
end
end
# Toggles the 'done' status of the action
#
def toggle_check
self.init
@item = check_user_return_item
@item.toggle!('done')
@item.completed = Time.now() # For some reason, the before_save in todo.rb stopped working
@saved = @item.save
@on_page = "home"
if @saved
@down_count = @todos.collect { |x| ( !x.done? and !x.context.hide? ) ? x:nil }.compact.size.to_s
end
return if request.xhr?
if @saved
flash['notice'] = "The action '#{@item.description}' was marked as #{@item.done? ? 'complete' : 'incomplete' }"
else
flash['notice'] = "The action '#{@item.description}' was NOT marked as #{@item.done? ? 'complete' : 'incomplete' } due to an error on the server."
end
redirect_to :action => "list"
end
# Edit the details of an action
#
def update_action
self.init
if params["on_project_page"] == true
@on_page = "project"
end
@item = check_user_return_item
@original_item_context_id = @item.context_id
@item.attributes = params["item"]
if @item.due?
@item.due = Date.strptime(params["item"]["due"], @user.preferences["date_format"])
else
@item.due = ""
end
@saved = @item.save
end
def deferred_update_action
#self.init
@tickle = check_user_return_item
@original_item_context_id = @tickle.context_id
@tickle.attributes = params["item"]
if @tickle.due?
@tickle.due = Date.strptime(params["item"]["due"], @user.preferences["date_format"])
else
@tickle.due = ""
end
@saved = @tickle.save
end
def update_context
self.init
@item = check_user_return_item
context = Context.find(params['context_id']);
if @user == context.user
@original_item_context_id = @item.context_id
@item.context_id = context.id
@item.context = context
@saved = @item.save
render :action => 'update_action'
else
render :update do |page|
page.replace_html "info", content_tag("div", "Error updating the context of the dragged item. Item and context user mis-match: #{@item.user.name} and #{@context.user.name}! - refresh the page to see them.", "class" => "warning")
end
end
end
def update_project
self.init
@item = check_user_return_item
project = Project.find(params['project_id']);
if @user == project.user
@original_item_context_id = @item.context_id
@item.project_id = project.id
@item.project = project
@saved = @item.save
render :action => 'update_action'
else
render :update do |page|
page.replace_html "info", content_tag("div", "Error updating the project of the dragged item. Item and project user mis-match: #{@item.user.name} and #{@project.user.name}! - refresh the page to see them.", "class" => "warning")
end
end
end
# Delete a next action
#
def destroy_action
self.init
@item = check_user_return_item
@saved = @item.destroy
@on_page = "home"
if @saved
self.init
@down_count = @todos.reject { |x| x.done? or x.context.hide? }.size.to_s
end
return if request.xhr?
# fallback for standard requests
if @saved
flash["notice"] = 'Successfully deleted next action'
redirect_to :action => 'list'
else
render :action => 'list'
end
rescue
if request.xhr? # be sure to include an error.rjs
render :action => 'error'
else
flash["warning"] = 'An error occurred on the server.'
render :action => 'list'
end
end
# List the completed tasks, sorted by completion date
# @done_today: in the last 24 hours
# @done_this_week: in the last week
# @done_this_month: in the last 4 weeks (<=28 days)
def completed
self.init
@page_title = "TRACKS::Completed tasks"
unless @done.nil?
@done_today = @done.collect { |x| x.completed >= 1.day.ago ? x:nil }.compact
@done_this_week = @done.collect { |x| 1.week.ago <= x.completed ? x:nil }.compact
@done_this_month = @done.collect { |x| 4.week.ago <= x.completed ? x:nil }.compact
end
end
# Archived completed items, older than 28 days
#
def completed_archive
self.init
@page_title = "TRACKS::Archived completed tasks"
@done_archive = @done.collect { |x| 28.day.ago > x.completed ? x:nil }.compact
end
def feeds
self.init
@page_title = "TRACKS::Feeds"
end
def tickler
self.init
@page_title = "TRACKS::Tickler"
@tickles = @user.todos.find(:all, :conditions => ['type = ?', "Deferred"], :order => "show_from ASC")
@count = @tickles.size
@on_page = "tickler"
end
# Called by periodically_call_remote
# Check for any due tickler items, change them to type Immediate and show
# on the page
#
def check_tickler
self.init
now = Date.today()
@due_tickles = @user.todos.find(:all, :conditions => ['type = ? AND (show_from < ? OR show_from = ?)', "Deferred", now, now ], :order => "show_from ASC")
unless @due_tickles.empty?
# Change the due tickles to type "Immediate"
@due_tickles.each do |t|
t[:type] = "Immediate"
t.show_from = nil
t.save
end
end
end
protected
def check_user_return_item
item = Todo.find( params['id'] )
if @user == item.user
return item
else
flash["warning"] = "Item and session user mis-match: #{item.user.name} and #{@user.name}!"
render_text ""
end
end
def init
@projects = @user.projects
@contexts = @user.contexts
init_todos
end
def init_todos
@todos = Todo.find(:all, :conditions => ['user_id = ? and type = ?', @user.id, "Immediate"])
@done = Todo.find(:all, :conditions => ['user_id = ? and done = ?', @user.id, true], :order => 'completed DESC')
end
def perform_add_item(redirect_action)
if @item.due?
@item.due = Date.strptime(params["todo"]["due"], @user.preferences["date_format"])
else
@item.due = ""
end
@saved = @item.save
if @saved
init_todos
@up_count = @todos.reject { |x| x.done? or x.context.hide? }.size.to_s
end
respond_to do |wants|
wants.html { redirect_to :action => redirect_action }
wants.js
wants.xml { render :xml => @item.to_xml( :root => 'todo', :except => :user_id ) }
end
# if you're seeing the message 'An error occurred on the server.' and you want to debug, comment out the rescue section and check the Ajax response for an exception message
rescue
respond_to do |wants|
wants.html { render :action => redirect_action } # TODO: would prefer something like: flash["warning"] = 'An error occurred on the server.' render :action => 'list'
wants.js { render :action => 'error' }
wants.xml { render :text => 'An error occurred on the server.' + $! }
end
end
end