mirror of
https://github.com/TracksApp/tracks.git
synced 2026-02-04 06:51:48 +01:00
* Converted Todo to acts_as_state_machine. It's states are active, deferred, completed, and project_hidden. This replaces the old single inheritance model of Immediate and Deferred. Also renamed todo.completed to todo.completed_at for clarity
* Consolidated toggle_check handling to todo_controller and rjs * Introduced user preference to show/hide hidden projects section in sidebar * Fixed a bug in parse_date_per_user_prefs that was causing due dates to be set in the todo model as Times and not Dates * Upgraded ARTS plugin * This changeset includes migrations, so remember to db:migrate. * Lots of code changes here, so bug reports will be gratefully accepted! git-svn-id: http://www.rousette.org.uk/svn/tracks-repos/trunk@343 a4c988fc-2ded-0310-b66e-134b36920a42
This commit is contained in:
parent
883bcb30bb
commit
c51587e422
47 changed files with 487 additions and 301 deletions
|
|
@ -83,23 +83,28 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
def parse_date_per_user_prefs( s )
|
||||
return nil if s == ''
|
||||
Chronic.parse(s)
|
||||
Chronic.parse(s).to_date
|
||||
end
|
||||
|
||||
def init_data_for_sidebar
|
||||
@projects = @user.projects
|
||||
@contexts = @user.contexts
|
||||
init_not_done_counts
|
||||
if @prefs.show_hidden_projects_in_sidebar
|
||||
init_project_hidden_todo_counts(['project'])
|
||||
end
|
||||
end
|
||||
|
||||
def init_not_done_counts(parents = ['project','context'])
|
||||
parents.each do |parent|
|
||||
eval("@#{parent}_not_done_counts = Todo.count(:all,
|
||||
:conditions => ['todos.user_id = ? and todos.type = ? and todos.done = ? and (projects.state != ? or todos.project_id is ?)',
|
||||
@user.id, \"Immediate\", false, \"hidden\", nil],
|
||||
:joins => 'LEFT JOIN projects on projects.id = todos.project_id',
|
||||
:group => :#{parent}_id)")
|
||||
eval("@#{parent}_not_done_counts = Todo.count(:conditions => ['user_id = ? and state = ?', @user.id, 'active'], :group => :#{parent}_id)")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def init_project_hidden_todo_counts(parents = ['project','context'])
|
||||
parents.each do |parent|
|
||||
eval("@#{parent}_project_hidden_todo_counts = Todo.count(:conditions => ['user_id = ? and state = ?', @user.id, 'project_hidden'], :group => :#{parent}_id)")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -102,29 +102,6 @@ class ContextController < ApplicationController
|
|||
redirect_to :controller => 'todo', :action => 'list'
|
||||
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
|
||||
if @saved
|
||||
@down_count = Todo.find(:all, :conditions => ["todos.user_id = ? and todos.done = ? and todos.context_id IN (?)", @user.id, false, @item.context_id]).size.to_s
|
||||
@done_count = Todo.find(:all, :conditions => ["todos.user_id = ? and todos.done = ? and todos.context_id IN (?)", @user.id, true, @item.context_id]).size.to_s
|
||||
end
|
||||
return if request.xhr?
|
||||
|
||||
if @saved
|
||||
flash[:notice] = "The action <strong>'#{@item.description}'</strong> was marked as <strong>#{@item.done? ? 'complete' : 'incomplete' }</strong>"
|
||||
else
|
||||
flash[:notice] = "The action <strong>'#{@item.description}'</strong> was NOT marked as <strong>#{@item.done? ? 'complete' : 'incomplete' } due to an error on the server.</strong>"
|
||||
end
|
||||
redirect_to :action => "list"
|
||||
end
|
||||
|
||||
# Edit the details of the context
|
||||
#
|
||||
|
|
@ -210,11 +187,9 @@ class ContextController < ApplicationController
|
|||
# If we exclude completed projects, then we can't display them in the sidebar
|
||||
# if the user sets the preference for them to be shown
|
||||
# @projects = @user.projects.reject { |x| x.completed? }
|
||||
@projects = @user.projects
|
||||
@contexts = @user.contexts
|
||||
init_data_for_sidebar
|
||||
@todos = @user.todos
|
||||
@done = Todo.find(:all, :conditions => ["todos.user_id = ? and todos.done = ?", @user.id, true], :include => [:project], :order => "completed DESC")
|
||||
init_not_done_counts
|
||||
@done = @user.todos.find_in_state(:all, :completed, :order => "todos.completed_at DESC")
|
||||
end
|
||||
|
||||
def init_todos
|
||||
|
|
@ -224,10 +199,7 @@ class ContextController < ApplicationController
|
|||
# TODO: Temporarily doing this search manually until I can work out a way
|
||||
# to do the same thing using not_done_todos acts_as_todo_container method
|
||||
# Hides actions in hidden projects from context.
|
||||
@not_done_todos = Todo.find(:all,
|
||||
:conditions => ["todos.context_id = ? and todos.done = ? and todos.type = ? and (projects.state != ? or todos.project_id is ?)", @context.id, false, "Immediate", "hidden", nil],
|
||||
:order => "todos.due IS NULL, todos.due ASC, todos.created_at ASC",
|
||||
:include => [:project])
|
||||
@not_done_todos = @context.todos.find_in_state(:all, :active, :order => "todos.due IS NULL, todos.due ASC, todos.created_at ASC")
|
||||
@count = @not_done_todos.size
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -12,16 +12,16 @@ class DeferredController < ApplicationController
|
|||
|
||||
def index
|
||||
@source_view = 'deferred'
|
||||
init_projects_and_contexts
|
||||
init_not_done_counts
|
||||
init_data_for_sidebar
|
||||
@page_title = "TRACKS::Tickler"
|
||||
@tickles = @user.todos.find(:all, :conditions => ['type = ?', "Deferred"], :order => "show_from ASC")
|
||||
@tickles = @user.todos.find_in_state(:all, :deferred, :order => "show_from ASC")
|
||||
@count = @tickles.size
|
||||
end
|
||||
|
||||
def create
|
||||
@source_view = 'deferred'
|
||||
@item = Deferred.new
|
||||
@item = Todo.new
|
||||
@item.defer!
|
||||
@item.attributes = params["todo"]
|
||||
if params["todo"]["show_from"]
|
||||
@item.show_from = parse_date_per_user_prefs(params["todo"]["show_from"])
|
||||
|
|
@ -37,7 +37,7 @@ class DeferredController < ApplicationController
|
|||
@saved = @item.save
|
||||
|
||||
if @saved
|
||||
@up_count = @user.todos.count(['type = ?', "Deferred"])
|
||||
@up_count = @user.todos.count_in_state(:deferred)
|
||||
end
|
||||
|
||||
respond_to do |wants|
|
||||
|
|
@ -84,7 +84,7 @@ class DeferredController < ApplicationController
|
|||
redirect_to :action => "index"
|
||||
end
|
||||
wants.js do
|
||||
@down_count = @user.todos.count(['type = ?', "Deferred"]) if @saved
|
||||
@down_count = @user.todos.count_in_state(:deferred) if @saved
|
||||
render
|
||||
end
|
||||
wants.xml { render :xml => @item.to_xml( :root => 'todo', :except => :user_id ) }
|
||||
|
|
@ -101,30 +101,22 @@ class DeferredController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
# Check for any due tickler items, change them to type Immediate.
|
||||
# Check for any due tickler items, activate them
|
||||
# Called by periodically_call_remote
|
||||
def check_tickler
|
||||
now = Date.today()
|
||||
@due_tickles = @user.todos.find(:all, :conditions => ['type = ? AND (show_from < ? OR show_from = ?)', "Deferred", now, now ], :order => "show_from ASC")
|
||||
# Change the due tickles to type "Immediate"
|
||||
@due_tickles = @user.todos.find_in_state(:all, :deferred, :conditions => ['show_from < ? OR show_from = ?', now, now ], :order => "show_from ASC")
|
||||
# Change the due tickles to active
|
||||
@due_tickles.each do |t|
|
||||
t[:type] = "Immediate"
|
||||
t.show_from = nil
|
||||
t.save_with_validation(false)
|
||||
t.activate!
|
||||
t.save
|
||||
end
|
||||
respond_to do |wants|
|
||||
wants.html { redirect_to :controller => 'todo', :action => 'index' }
|
||||
wants.js
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def init_projects_and_contexts
|
||||
@projects = @user.projects
|
||||
@contexts = @user.contexts
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def check_user_return_item
|
||||
|
|
|
|||
|
|
@ -84,9 +84,9 @@ protected
|
|||
options = Hash.new
|
||||
|
||||
if params.key?('done')
|
||||
condition_builder.add 'todos.done = ?', true
|
||||
condition_builder.add 'todos.state = ?', 'completed'
|
||||
else
|
||||
condition_builder.add 'todos.done = ?', false
|
||||
condition_builder.add 'todos.state = ?', 'active'
|
||||
end
|
||||
|
||||
if params.key?('limit')
|
||||
|
|
@ -107,7 +107,7 @@ protected
|
|||
|
||||
if params.key?('done')
|
||||
done_in_last = params['done'].to_i
|
||||
condition_builder.add('todos.completed >= ?', done_in_last.days.ago)
|
||||
condition_builder.add('todos.completed_at >= ?', done_in_last.days.ago)
|
||||
@title << " actions completed"
|
||||
@description << " in the last #{done_in_last.to_s} days"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ class MobileController < ApplicationController
|
|||
self.init
|
||||
@page_title = @desc = "All actions"
|
||||
@todos_pages, @todos = paginate( :todos, :order => 'due IS NULL, due ASC, created_at ASC',
|
||||
:conditions => ['user_id = ? and type = ? and done = ?', @user.id, "Immediate", false],
|
||||
:conditions => ['user_id = ? and state = ?', @user.id, "active"],
|
||||
:per_page => 6 )
|
||||
@count = @all_todos.reject { |x| x.done? || x.context.hide? }.size
|
||||
@count = @all_todos.reject { |x| !x.active? || x.context.hide? }.size
|
||||
end
|
||||
|
||||
def detail
|
||||
|
|
@ -32,10 +32,11 @@ class MobileController < ApplicationController
|
|||
@item = check_user_return_item
|
||||
else
|
||||
if params[:item][:"show_from(1i)"] == ""
|
||||
@item = Immediate.create(params[:item]) if params[:item]
|
||||
@item = Todo.create(params[:item]) if params[:item]
|
||||
else
|
||||
@item = Deferred.create(params[:item]) if params[:item]
|
||||
end
|
||||
@item = Todo.create(params[:item]) if params[:item]
|
||||
@item.defer!
|
||||
end
|
||||
end
|
||||
|
||||
@item.user_id = @user.id
|
||||
|
|
@ -64,14 +65,14 @@ class MobileController < ApplicationController
|
|||
@context = Context.find( params[:context][:id] )
|
||||
@page_title = @desc = "#{@context.name}"
|
||||
@todos_pages, @todos = paginate( :todos, :order => 'due IS NULL, due ASC, created_at ASC',
|
||||
:conditions => ['user_id = ? and type = ? and done = ? and context_id = ?', @user.id, "Immediate", false, @context.id], :per_page => 6 )
|
||||
@count = @all_todos.reject { |x| x.done? || x.context_id != @context.id }.size
|
||||
:conditions => ['user_id = ? and state = ? and context_id = ?', @user.id, "active", @context.id], :per_page => 6 )
|
||||
@count = @all_todos.reject { |x| x.completed? || x.context_id != @context.id }.size
|
||||
when 'project'
|
||||
@project = Project.find( params[:project][:id] )
|
||||
@page_title = @desc = "#{@project.name}"
|
||||
@todos_pages, @todos = paginate( :todos, :order => 'due IS NULL, due ASC, created_at ASC',
|
||||
:conditions => ['user_id = ? and type = ? and done = ? and project_id = ?', @user.id, "Immediate", false, @project.id], :per_page => 6 )
|
||||
@count = @all_todos.reject { |x| x.done? || x.project_id != @project.id }.size
|
||||
:conditions => ['user_id = ? and state = ? and project_id = ?', @user.id, "active", @project.id], :per_page => 6 )
|
||||
@count = @all_todos.reject { |x| x.completed? || x.project_id != @project.id }.size
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -88,11 +89,9 @@ class MobileController < ApplicationController
|
|||
end
|
||||
|
||||
def init
|
||||
@contexts = Context.find :all, :order => 'position ASC',
|
||||
:conditions => ['user_id = ?', @user.id]
|
||||
@projects = Project.find :all, :order => 'position ASC',
|
||||
:conditions => ['user_id = ? and state = ?', @user.id, "active"]
|
||||
@all_todos = Todo.find(:all, :conditions => ['user_id = ? and type = ?', @user.id, "Immediate"])
|
||||
@contexts = @user.contexts.find(:all, :order => 'position ASC')
|
||||
@projects = @user.projects.find_in_state(:all, :active, :order => 'position ASC')
|
||||
@all_todos = @user.todos.find(:all, :conditions => ['state = ? or state =?', "active", "completed"])
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ class ProjectController < ApplicationController
|
|||
#
|
||||
def list
|
||||
init
|
||||
init_project_hidden_todo_counts
|
||||
@page_title = "TRACKS::List Projects"
|
||||
respond_to do |wants|
|
||||
wants.html
|
||||
|
|
@ -125,38 +126,27 @@ class ProjectController < ApplicationController
|
|||
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
|
||||
if @saved
|
||||
@down_count = Todo.find(:all, :conditions => ["todos.user_id = ? and todos.done = ? and todos.project_id IN (?)", @user.id, false, @item.project_id]).size.to_s
|
||||
@done_count = Todo.find(:all, :conditions => ["todos.user_id = ? and todos.done = ? and todos.project_id IN (?)", @user.id, true, @item.project_id]).size.to_s
|
||||
end
|
||||
return if request.xhr?
|
||||
|
||||
if @saved
|
||||
flash[:notice] = "The action <strong>'#{@item.description}'</strong> was marked as <strong>#{@item.done? ? 'complete' : 'incomplete' }</strong>"
|
||||
else
|
||||
flash[:notice] = "The action <strong>'#{@item.description}'</strong> was NOT marked as <strong>#{@item.done? ? 'complete' : 'incomplete' } due to an error on the server.</strong>"
|
||||
end
|
||||
redirect_to :action => "list"
|
||||
end
|
||||
|
||||
# Edit the details of the project
|
||||
#
|
||||
def update
|
||||
self.init
|
||||
check_user_set_project
|
||||
@project.transition_to(params['project']['state'])
|
||||
params['project'].delete('state')
|
||||
@project.attributes = params['project']
|
||||
@project.name = deurlize(@project.name)
|
||||
if @project.save
|
||||
render :partial => 'project_listing', :object => @project
|
||||
if params['wants_render']
|
||||
if (@project.hidden?)
|
||||
@project_project_hidden_todo_counts = Hash.new
|
||||
@project_project_hidden_todo_counts[@project.id] = @project.reload().not_done_todo_count(:include_project_hidden_todos => true)
|
||||
else
|
||||
@project_not_done_counts[@project.id] = @project.reload().not_done_todo_count(:include_project_hidden_todos => true)
|
||||
end
|
||||
render :partial => 'project_listing', :object => @project
|
||||
else
|
||||
render :text => 'Success'
|
||||
end
|
||||
else
|
||||
flash[:warning] = "Couldn't update project"
|
||||
render :text => ''
|
||||
|
|
@ -242,14 +232,14 @@ class ProjectController < ApplicationController
|
|||
@projects = @user.projects
|
||||
@contexts = @user.contexts
|
||||
@todos = @user.todos
|
||||
@done = Todo.find(:all, :conditions => ["todos.user_id = ? and todos.done = ?", @user.id, true], :include => [:project], :order => "completed DESC")
|
||||
init_not_done_counts
|
||||
@done = @user.todos.find_in_state(:all, :completed, :order => "completed_at DESC")
|
||||
init_data_for_sidebar
|
||||
end
|
||||
|
||||
def init_todos
|
||||
check_user_set_project
|
||||
@done = @project.done_todos
|
||||
@not_done = @project.not_done_todos
|
||||
@not_done = @project.not_done_todos(:include_project_hidden_todos => true)
|
||||
@count = @not_done.size
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ class TodoController < ApplicationController
|
|||
@done = nil
|
||||
if max_completed > 0
|
||||
@done = Todo.find(:all,
|
||||
:conditions => ['todos.user_id = ? and todos.done = ?', @user.id, true],
|
||||
:order => 'todos.completed DESC',
|
||||
:conditions => ['todos.user_id = ? and todos.state = ?', @user.id, 'completed'],
|
||||
:order => 'todos.completed_at DESC',
|
||||
:limit => max_completed,
|
||||
:include => [ :project, :context ])
|
||||
end
|
||||
|
|
@ -39,7 +39,7 @@ class TodoController < ApplicationController
|
|||
end
|
||||
|
||||
# Set count badge to number of not-done, not hidden context items
|
||||
@count = @todos.reject { |x| x.done? || x.context.hide? }.size
|
||||
@count = @todos.reject { |x| !x.active? || x.context.hide? }.size
|
||||
|
||||
respond_to do |wants|
|
||||
wants.html
|
||||
|
|
@ -79,7 +79,7 @@ class TodoController < ApplicationController
|
|||
wants.js do
|
||||
if @saved
|
||||
init_todos
|
||||
@up_count = @todos.reject { |x| x.done? or x.context.hide? }.size.to_s
|
||||
@up_count = @todos.reject { |x| !x.active? or x.context.hide? }.size.to_s
|
||||
end
|
||||
render :action => 'create'
|
||||
end
|
||||
|
|
@ -119,21 +119,20 @@ class TodoController < ApplicationController
|
|||
#
|
||||
def toggle_check
|
||||
init
|
||||
|
||||
logger.info "source view is " + @source_view
|
||||
@item = check_user_return_item
|
||||
@item.toggle!('done')
|
||||
@item.completed = Time.now() # For some reason, the before_save in todo.rb stopped working
|
||||
@item.toggle_completion()
|
||||
@saved = @item.save
|
||||
@remaining_undone_in_context = @user.contexts.find(@item.context_id).not_done_todos.length
|
||||
if @saved
|
||||
@down_count = @todos.reject { |x| x.done? || x.context.hide? }.size.to_s
|
||||
@remaining_undone_in_context = @user.contexts.find(@item.context_id).not_done_todo_count
|
||||
determine_down_count
|
||||
end
|
||||
return if request.xhr?
|
||||
|
||||
if @saved
|
||||
redirect_with_notice "The action <strong>'#{@item.description}'</strong> was marked as <strong>#{@item.done? ? 'complete' : 'incomplete' }</strong>", :action => "index"
|
||||
redirect_with_notice "The action <strong>'#{@item.description}'</strong> was marked as <strong>#{@item.completed? ? 'complete' : 'incomplete' }</strong>", :action => "index"
|
||||
else
|
||||
redirect_with_notice "The action <strong>'#{@item.description}'</strong> was NOT marked as <strong>#{@item.done? ? 'complete' : 'incomplete' } due to an error on the server.</strong>", :action => "index"
|
||||
redirect_with_notice "The action <strong>'#{@item.description}'</strong> was NOT marked as <strong>#{@item.completed? ? 'complete' : 'incomplete' } due to an error on the server.</strong>", :action => "index"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -207,7 +206,7 @@ class TodoController < ApplicationController
|
|||
|
||||
wants.js do
|
||||
if @saved
|
||||
@down_count = determine_down_count
|
||||
determine_down_count
|
||||
source_view do |from|
|
||||
from.todo do
|
||||
@remaining_undone_in_context = @user.contexts.find(@context_id).not_done_todos.length
|
||||
|
|
@ -249,7 +248,7 @@ class TodoController < ApplicationController
|
|||
private
|
||||
|
||||
def check_user_return_item
|
||||
item = Todo.find( params['id'] )
|
||||
item = Todo.find( params['id'].to_i )
|
||||
if @user == item.user
|
||||
return item
|
||||
else
|
||||
|
|
@ -267,39 +266,30 @@ class TodoController < ApplicationController
|
|||
|
||||
def init
|
||||
@source_view = params['_source_view'] || 'todo'
|
||||
@projects = @user.projects
|
||||
@contexts = @user.contexts
|
||||
init_todos
|
||||
init_not_done_counts
|
||||
init_data_for_sidebar
|
||||
init_todos
|
||||
end
|
||||
|
||||
def init_todos
|
||||
# Exclude hidden projects from count on home page
|
||||
@todos = Todo.find(:all,
|
||||
:conditions => ['todos.user_id = ? and todos.type = ? and (projects.state != ? or todos.project_id is ?)', @user.id, "Immediate", "hidden", nil],
|
||||
:include => [ :project, :context ])
|
||||
@todos = @user.todos.find(:all, :conditions => ['todos.state = ? or todos.state = ?', 'active', 'complete'], :include => [ :project, :context ])
|
||||
|
||||
# Exclude hidden projects from the home page
|
||||
@not_done_todos = Todo.find(:all,
|
||||
:conditions => ['todos.user_id = ? and todos.type = ? and todos.done = ? and (projects.state != ? or todos.project_id is ?)', @user.id, "Immediate", false, "hidden", nil],
|
||||
:order => "todos.due IS NULL, todos.due ASC, todos.created_at ASC",
|
||||
:include => [ :project, :context ])
|
||||
@not_done_todos = @user.todos.find(:all, :conditions => ['todos.state = ?', 'active'], :order => "todos.due IS NULL, todos.due ASC, todos.created_at ASC", :include => [ :project, :context ])
|
||||
end
|
||||
|
||||
def determine_down_count
|
||||
source_view do |from|
|
||||
from.todo do
|
||||
@down_count = Todo.count(:conditions => ['todos.user_id = ? and todos.type = ? and todos.done = ? and contexts.hide = ?',
|
||||
@user.id, "Immediate", false, false],
|
||||
:include => [ :context ])
|
||||
@down_count = Todo.count_by_sql(['SELECT COUNT(*) FROM todos, contexts WHERE todos.context_id = contexts.id and todos.user_id = ? and todos.state = ? and contexts.hide = ?', @user.id, 'active', false])
|
||||
end
|
||||
from.context do
|
||||
@down_count = Todo.count(:conditions => ['todos.user_id = ? and todos.type = ? and todos.done = ? and todos.context_id = ?',
|
||||
@user.id, "Immediate", false, @context_id])
|
||||
@down_count = @user.contexts.find(@item.context_id).todos.count_in_state(:active)
|
||||
end
|
||||
from.project do
|
||||
@down_count = Todo.count(:conditions => ['todos.user_id = ? and todos.type = ? and todos.done = ? and todos.project_id = ?',
|
||||
@user.id, "Immediate", false, @project_id]) unless @project_id == nil
|
||||
unless @item.project_id == nil
|
||||
@down_count = @user.projects.find(@item.project_id).todos.count_in_state(:active)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -117,7 +117,11 @@ module ApplicationHelper
|
|||
# actions or multiple actions
|
||||
#
|
||||
def count_undone_todos(todos_parent, string="actions")
|
||||
count = eval "@#{todos_parent.class.to_s.downcase}_not_done_counts[#{todos_parent.id}]"
|
||||
if (todos_parent.is_a?(Project) && todos_parent.hidden?)
|
||||
count = eval "@project_project_hidden_todo_counts[#{todos_parent.id}]"
|
||||
else
|
||||
count = eval "@#{todos_parent.class.to_s.downcase}_not_done_counts[#{todos_parent.id}]"
|
||||
end
|
||||
count = 0 if count == nil
|
||||
#count = todos_parent.todos.select{|t| !t.done }.size
|
||||
if count == 1
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ module FeedHelper
|
|||
if item.context_id == context.id
|
||||
result_string << "\n" + context.name.upcase + ":\n" if result_string.empty?
|
||||
|
||||
if (item.done == 1 || item.done == true) && item.completed
|
||||
result_string << " [Completed: " + format_date(item.completed) + "] "
|
||||
if (item.completed?) && item.completed_at
|
||||
result_string << " [Completed: " + format_date(item.completed_at) + "] "
|
||||
end
|
||||
|
||||
if item.due
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ module TodoHelper
|
|||
{ :url => url_options, :confirm => "Are you sure that you want to delete the action, \'#{item.description}\'?" },
|
||||
{ :class => "icon" }
|
||||
) + "\n"
|
||||
if !item.done?
|
||||
if !item.completed?
|
||||
url_options[:action] = 'edit'
|
||||
str << link_to_remote( image_tag_for_edit(item),
|
||||
{ :url => url_options, :loading => visual_effect(:pulsate, "action-#{item.id}-edit-icon") },
|
||||
|
|
@ -42,7 +42,7 @@ module TodoHelper
|
|||
# * l3: created more than 3 x staleness_starts
|
||||
#
|
||||
def staleness_class(item)
|
||||
if item.due || item.done?
|
||||
if item.due || item.completed?
|
||||
return ""
|
||||
elsif item.created_at < (@user.preference.staleness_starts * 3).days.ago
|
||||
return " stale_l3"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
class Context < ActiveRecord::Base
|
||||
|
||||
has_many :todos, :dependent => true, :order => "completed DESC"
|
||||
has_many :todos, :dependent => true, :order => "completed_at DESC"
|
||||
belongs_to :user
|
||||
|
||||
acts_as_list :scope => :user
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
class Deferred < Todo
|
||||
validates_presence_of :show_from
|
||||
|
||||
def validate
|
||||
if show_from != nil && show_from < Date.today()
|
||||
errors.add("Show From", "must be a date in the future.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
class Immediate < Todo
|
||||
end
|
||||
|
|
@ -16,7 +16,7 @@ class Project < ActiveRecord::Base
|
|||
acts_as_todo_container :find_todos_include => :context
|
||||
|
||||
state :active
|
||||
state :hidden
|
||||
state :hidden, :enter => :hide_todos, :exit => :unhide_todos
|
||||
state :completed
|
||||
|
||||
event :activate do
|
||||
|
|
@ -44,6 +44,33 @@ class Project < ActiveRecord::Base
|
|||
def linkurl_present?
|
||||
attribute_present?("linkurl")
|
||||
end
|
||||
|
||||
def hide_todos
|
||||
todos.each do |t|
|
||||
t.hide! unless t.completed?
|
||||
t.save
|
||||
end
|
||||
end
|
||||
|
||||
def unhide_todos
|
||||
todos.each do |t|
|
||||
t.unhide! if t.project_hidden?
|
||||
t.save
|
||||
end
|
||||
end
|
||||
|
||||
def transition_to(candidate_state)
|
||||
case candidate_state.to_sym
|
||||
when current_state
|
||||
return
|
||||
when :hidden
|
||||
hide!
|
||||
when :active
|
||||
activate!
|
||||
when :completed
|
||||
complete!
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,34 @@ class Todo < ActiveRecord::Base
|
|||
belongs_to :project
|
||||
belongs_to :user
|
||||
|
||||
acts_as_state_machine :initial => :active, :column => 'state'
|
||||
|
||||
state :active, :enter => Proc.new { |t| t.show_from = nil }
|
||||
state :project_hidden
|
||||
state :completed, :enter => Proc.new { |t| t.completed_at = Time.now() }, :exit => Proc.new { |t| t.completed_at = nil }
|
||||
state :deferred
|
||||
|
||||
event :defer do
|
||||
transitions :to => :deferred, :from => [:active]
|
||||
end
|
||||
|
||||
event :complete do
|
||||
transitions :to => :completed, :from => [:active, :project_hidden, :deferred]
|
||||
end
|
||||
|
||||
event :activate do
|
||||
transitions :to => :active, :from => [:project_hidden, :completed, :deferred]
|
||||
end
|
||||
|
||||
event :hide do
|
||||
transitions :to => :project_hidden, :from => [:active, :deferred]
|
||||
end
|
||||
|
||||
event :unhide do
|
||||
transitions :to => :deferred, :from => [:project_hidden], :guard => Proc.new{|t| t.show_from != nil}
|
||||
transitions :to => :active, :from => [:project_hidden]
|
||||
end
|
||||
|
||||
attr_protected :user
|
||||
|
||||
# Description field can't be empty, and must be < 100 bytes
|
||||
|
|
@ -13,6 +41,21 @@ class Todo < ActiveRecord::Base
|
|||
validates_length_of :description, :maximum => 100
|
||||
validates_length_of :notes, :maximum => 60000, :allow_nil => true
|
||||
# validates_chronic_date :due, :allow_nil => true
|
||||
validates_presence_of :show_from, :if => :deferred?
|
||||
|
||||
def validate
|
||||
if deferred? && show_from != nil && show_from < Date.today()
|
||||
errors.add("Show From", "must be a date in the future.")
|
||||
end
|
||||
end
|
||||
|
||||
def toggle_completion
|
||||
if completed?
|
||||
activate!
|
||||
else
|
||||
complete!
|
||||
end
|
||||
end
|
||||
|
||||
alias_method :original_project, :project
|
||||
|
||||
|
|
@ -26,16 +69,16 @@ class Todo < ActiveRecord::Base
|
|||
|
||||
def self.find_completed(user_id)
|
||||
done = self.find(:all,
|
||||
:conditions => ['todos.user_id = ? and todos.done = ? and todos.completed is not null', user_id, true],
|
||||
:order => 'todos.completed DESC',
|
||||
:conditions => ['todos.user_id = ? and todos.state = ? and todos.completed_at is not null', user_id, 'completed'],
|
||||
:order => 'todos.completed_at DESC',
|
||||
:include => [ :project, :context ])
|
||||
|
||||
def done.completed_within( date )
|
||||
reject { |x| x.completed < date }
|
||||
reject { |x| x.completed_at < date }
|
||||
end
|
||||
|
||||
def done.completed_more_than( date )
|
||||
reject { |x| x.completed > date }
|
||||
reject { |x| x.completed_at > date }
|
||||
end
|
||||
|
||||
done
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ require 'digest/sha1'
|
|||
class User < ActiveRecord::Base
|
||||
has_many :contexts, :order => "position ASC"
|
||||
has_many :projects, :order => "position ASC"
|
||||
has_many :todos, :order => "completed DESC, created_at DESC"
|
||||
has_many :todos, :order => "completed_at DESC, created_at DESC"
|
||||
has_many :notes, :order => "created_at DESC"
|
||||
has_one :preference
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<% item = show_items %>
|
||||
|
||||
<% if !item.done? %>
|
||||
<% if !item.completed? %>
|
||||
<div id="item-<%= item.id %>-container">
|
||||
<%= form_remote_tag( :url => url_for( :controller => "context", :action => "toggle_check", :id => item.id ),
|
||||
:html => { :id=> "checkbox-notdone-#{item.id}", :class => "inline-form" },
|
||||
|
|
@ -82,7 +82,7 @@
|
|||
</div>
|
||||
<!-- end div.checkbox -->
|
||||
<div class="description">
|
||||
<span class="grey"><%= format_date( item.completed ) %></span>
|
||||
<span class="grey"><%= format_date( item.completed_at ) %></span>
|
||||
<%= sanitize(item.description) %>
|
||||
<% if item.project_id %>
|
||||
<%= link_to( "[P]", { :controller => "project", :action => "show", :name => urlize(item.project.name) }, :title => "View project: #{item.project.name}" ) %>
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
if @saved
|
||||
page.remove "item-#{@item.id}-container"
|
||||
if @item.done?
|
||||
# Don't try to insert contents into a non-existent container!
|
||||
unless @user.preference.hide_completed_actions?
|
||||
page.insert_html :top, "completed", :partial => 'todo/item', :locals => { :parent_container_type => "completed" }
|
||||
page.visual_effect :highlight, "item-#{@item.id}", {'startcolor' => "'#99ff99'"}
|
||||
if @down_count == '0'
|
||||
page["c#{@item.context_id}empty-nd"].show
|
||||
end
|
||||
page.hide "empty-d" # If we've checked something as done, completed items can't be empty
|
||||
end
|
||||
else
|
||||
page.call "todoItems.ensureVisibleWithEffectAppear", "c#{@item.context_id}"
|
||||
page.insert_html :bottom, "c#{@item.context_id}", :partial => 'todo/item', :locals => { :parent_container_type => "context" }
|
||||
page.visual_effect :highlight, "item-#{@item.id}", {'startcolor' => "'#99ff99'"}
|
||||
if @done_count == '0'
|
||||
page.show "empty-d"
|
||||
end
|
||||
page["c#{@item.context_id}empty-nd"].hide # If we've checked something as undone, uncompleted items can't be empty
|
||||
end
|
||||
page.hide "status"
|
||||
page.replace_html "badge_count", @down_count
|
||||
else
|
||||
page.replace_html "status", content_tag("div", content_tag("h2", "#{pluralize(@item.errors.count, "error")} prohibited this record from being saved") + content_tag("p", "There were problems with the following fields:") + content_tag("ul", @item.errors.each_full { |msg| content_tag("li", msg) }), "id" => "ErrorExplanation", "class" => "ErrorExplanation")
|
||||
end
|
||||
|
|
@ -11,7 +11,7 @@ xml.rss("version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/") do
|
|||
due = "<div>Due: #{format_date(i.due)}</div>\n" if i.due?
|
||||
toggle_link = link_to( "mark as done", {:only_path => false, :controller => "todo", :action => "toggle_check", :id => i.id})
|
||||
done = "<div>#{toggle_link}</div>" unless i.completed?
|
||||
done = "<div>Completed: #{format_date(i.completed)}</div>\n" if i.completed?
|
||||
done = "<div>Completed: #{format_date(i.completed_at)}</div>\n" if i.completed?
|
||||
context_link = link_to( i.context.name, { :only_path => false, :controller => "context", :action => "show", :name => urlize(i.context.name) } )
|
||||
if i.project_id?
|
||||
project_link = link_to (i.project.name, { :only_path => false, :controller => "project", :action => "show", :name => urlize(i.project.name)} )
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<% if @prefs["refresh"].to_i != 0 -%>
|
||||
<% if @prefs.refresh != 0 -%>
|
||||
<meta http-equiv="Refresh" content="<%= @prefs["refresh"].to_i*60 %>;url=<%= request.request_uri %>">
|
||||
<% end -%>
|
||||
<%= stylesheet_link_tag "standard" %>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
<table style="table-layout: fixed;" width="450">
|
||||
<%= render :partial => 'project_form', :object => project %>
|
||||
<tr>
|
||||
<td width="150"> </td>
|
||||
<td width="150"> <input type="hidden" name="wants_render" value="false" /></td>
|
||||
<td width="300"><input type="submit" value="Update" /> <a href="javascript:void(0);" onclick="Element.toggle('project-<%= project.id %>','project-<%= project.id %>-edit-form');Form.reset('form-project-<%= project.id %>');">Cancel</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<% item = show_items %>
|
||||
<% if !item.done? %>
|
||||
<% if !item.completed? %>
|
||||
<div id="item-<%= item.id %>-container">
|
||||
<%= form_remote_tag( :url => url_for( :controller => "project", :action => "toggle_check", :id => item.id ),
|
||||
:html => { :id=> "checkbox-notdone-#{item.id}", :class => "inline-form" },
|
||||
|
|
@ -82,7 +82,7 @@
|
|||
</div>
|
||||
<!-- end div.checkbox -->
|
||||
<div class="description">
|
||||
<span class="grey"><%= format_date( item.completed ) %></span>
|
||||
<span class="grey"><%= format_date( item.completed_at ) %></span>
|
||||
<%= sanitize(item.description) %>
|
||||
<% if item.project_id %>
|
||||
<%= link_to( "[C]", { :controller => "context", :action => "show", :name => urlize(item.context.name) }, :title => "View context: #{item.context.name}" ) %>
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
<h2>Status</h2>
|
||||
<div>
|
||||
<% ['active', 'hidden', 'completed'].each do | state | %>
|
||||
<% js = "new Ajax.Request('#{ url_for :controller => 'project', :action => 'update', :id => @project.id, 'project[state]' => state }', {asynchronous:true, evalScripts:true});" %>
|
||||
<% js = "new Ajax.Request('#{ url_for :controller => 'project', :action => 'update', :id => @project.id, :wants_render => false, 'project[state]' => state }', {asynchronous:true, evalScripts:true});" %>
|
||||
<%= radio_button(:project, 'state', state, {:class => 'project-done', :onclick => js}) %> <%= state.titlecase %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
if @saved
|
||||
page.remove "item-#{@item.id}-container"
|
||||
if @item.done?
|
||||
# Don't try to insert contents into a non-existent container!
|
||||
unless @user.preference.hide_completed_actions?
|
||||
page.insert_html :top, "completed", :partial => 'todo/item', :locals => { :parent_container_type => "project" }
|
||||
page.visual_effect :highlight, "item-#{@item.id}", {'startcolor' => "'#99ff99'"}
|
||||
if @down_count == '0'
|
||||
page["p#{@item.project_id}empty-nd"].show
|
||||
end
|
||||
page.hide "empty-d" # If we've checked something as done, completed items can't be empty
|
||||
end
|
||||
else
|
||||
page.call "todoItems.ensureVisibleWithEffectAppear", "p#{@item.project_id}"
|
||||
page.insert_html :bottom, "p#{@item.project_id}", :partial => 'todo/item', :locals => { :parent_container_type => "project" }
|
||||
page.visual_effect :highlight, "item-#{@item.id}", {'startcolor' => "'#99ff99'"}
|
||||
if @done_count == '0'
|
||||
page.show "empty-d"
|
||||
end
|
||||
page["p#{@item.project_id}empty-nd"].hide # If we've checked something as undone, uncompleted items can't be empty
|
||||
end
|
||||
page.hide "status"
|
||||
page.replace_html "badge_count", @down_count
|
||||
else
|
||||
page.replace_html "status", content_tag("div", content_tag("h2", "#{pluralize(@item.errors.count, "error")} prohibited this record from being saved") + content_tag("p", "There were problems with the following fields:") + content_tag("ul", @item.errors.each_full { |msg| content_tag("li", msg) }), "id" => "ErrorExplanation", "class" => "ErrorExplanation")
|
||||
end
|
||||
|
|
@ -6,13 +6,14 @@
|
|||
<% end -%>
|
||||
</ul>
|
||||
|
||||
<% if @user.preference.show_hidden_projects_in_sidebar %>
|
||||
<h3>Hidden Projects:</h3>
|
||||
<ul>
|
||||
<% for project in @projects.select{|p| p.hidden? } -%>
|
||||
<li id="sidebar-project-<%= project.id %>" class="sidebar-project"><%= link_to( sanitize(project.name), { :controller => "project", :action => "show", :name => urlize(project.name) } ) + " (" + count_undone_todos(project,"actions") + ")" %></li>
|
||||
<% end -%>
|
||||
</ul>
|
||||
|
||||
<% end %>
|
||||
|
||||
<% if @user.preference.show_completed_projects_in_sidebar %>
|
||||
<h3>Completed Projects:</h3>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<tr>
|
||||
<% if done.completed %>
|
||||
<% if done.completed_at %>
|
||||
<td valign="top"><%= image_tag( "done", :width=>"16", :height=>"16", :border=>"0") %></td>
|
||||
<td valign="top"><span class="grey"><%= format_date( done.completed ) %></span></td>
|
||||
<td valign="top"><span class="grey"><%= format_date( done.completed_at ) %></span></td>
|
||||
<td valign="top"><%= " " + sanitize(done.description) + " "%>
|
||||
|
||||
<% if done.project_id %>
|
||||
|
|
|
|||
|
|
@ -46,13 +46,13 @@
|
|||
<td class="label"><label for="item_due">Due</td>
|
||||
<td><input name="item[due]" id="due_<%= @item.id %>" type="text" value="<%= format_date(@item.due) %>" tabindex="5" size="10" onFocus="Calendar.setup" /></td>
|
||||
</tr>
|
||||
<% if @item.class == Deferred -%>
|
||||
<% if @item.current_state == :deferred -%>
|
||||
<tr>
|
||||
<td class="label"><label for="item_show_from">Show from</td>
|
||||
<td><input name="item[show_from]" id="show_from_<%= @item.id %>" type="text" value="<%= format_date(@item.show_from) %>" tabindex="5" size="10" onFocus="Calendar.setup" /></td>
|
||||
</tr>
|
||||
<% end -%>
|
||||
<% if controller.controller_name == "project" || @item.class == 'Deferred' -%>
|
||||
<% if controller.controller_name == "project" || @item.current_state == :deferred -%>
|
||||
<input type="hidden" name="on_project_page" value="true" />
|
||||
<% end -%>
|
||||
<tr>
|
||||
|
|
@ -62,6 +62,6 @@
|
|||
</table>
|
||||
|
||||
<%= calendar_setup( "due_#{@item.id}" ) %>
|
||||
<% if @item.class == Deferred -%>
|
||||
<% if @item.current_state == :deferred -%>
|
||||
<%= calendar_setup( "show_from_#{@item.id}" ) %>
|
||||
<% end -%>
|
||||
|
|
|
|||
|
|
@ -3,17 +3,17 @@
|
|||
<div id="item-<%= item.id %>">
|
||||
<%= link_to_remote_todo item %>
|
||||
<input type="checkbox" class="item-checkbox"
|
||||
onclick="new Ajax.Request('<%= url_for :controller => controller.controller_name, :action => 'toggle_check', :id => item.id %>', {asynchronous:true, evalScripts:true});"
|
||||
name="item_id" value="<%= item.id %>"<% if item.done? %> checked="checked" <% end %> />
|
||||
onclick="new Ajax.Request('<%= url_for :controller => 'todo', :action => 'toggle_check', :id => item.id, :_source_view => @source_view %>', {asynchronous:true, evalScripts:true});"
|
||||
name="item_id" value="<%= item.id %>"<% if item.completed? %> checked="checked" <% end %> />
|
||||
<div class="description<%= staleness_class( item ) %>"><% # start of div which has a class 'description', and possibly 'stale_11', 'stale_12', 'stale_13' etc %>
|
||||
<% if item.done? -%>
|
||||
<span class="grey"><%= format_date( item.completed ) %></span>
|
||||
<% if item.completed? -%>
|
||||
<span class="grey"><%= format_date( item.completed_at ) %></span>
|
||||
<% else -%>
|
||||
<%= due_date( item.due ) -%>
|
||||
<% end -%>
|
||||
|
||||
<%= sanitize(item.description) %>
|
||||
<% if item.done? -%>
|
||||
<% if item.completed? -%>
|
||||
(<%= item.context.name %><%= ", " + item.project.name if item.project_id %>)
|
||||
<% else -%>
|
||||
<% if parent_container_type == "project" -%>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,33 @@
|
|||
if @saved
|
||||
|
||||
item_container_id = "c#{@item.context_id}"
|
||||
parent_container_type = "context"
|
||||
if source_view_is :context
|
||||
empty_container_msg_div_id = "c#{@item.context_id}empty-nd"
|
||||
elsif source_view_is :project
|
||||
item_container_id = "p#{@item.project_id}"
|
||||
empty_container_msg_div_id = "p#{@item.project_id}empty-nd"
|
||||
parent_container_type = "project"
|
||||
end
|
||||
|
||||
page.remove "item-#{@item.id}-container"
|
||||
# For some reason, the code below works on the project and context pages, but
|
||||
# not on the todo/list page when the item being deleted has just been added
|
||||
# page.call "fadeAndRemoveItem", "item-#{@item.id}-container"
|
||||
if @item.done?
|
||||
if @item.completed?
|
||||
# Don't try to insert contents into a non-existent container!
|
||||
unless @user.preference.hide_completed_actions?
|
||||
page.insert_html :top, "completed", :partial => 'todo/item', :locals => { :parent_container_type => "completed" }
|
||||
page.visual_effect :highlight, "item-#{@item.id}", {'startcolor' => "'#99ff99'"}
|
||||
page[empty_container_msg_div_id].show if @down_count == '0' && !empty_container_msg_div_id.nil?
|
||||
page.hide "empty-d" # If we've checked something as done, completed items can't be empty
|
||||
end
|
||||
if @remaining_undone_in_context == 0
|
||||
page.visual_effect :fade, "c#{@item.context_id}", :duration => 0.4
|
||||
if @remaining_undone_in_context == 0 && source_view_is(:todo)
|
||||
page.visual_effect :fade, item_container_id, :duration => 0.4
|
||||
end
|
||||
else
|
||||
page.call "todoItems.ensureVisibleWithEffectAppear", "c#{@item.context_id}"
|
||||
page.insert_html :bottom, "c#{@item.context_id}", :partial => 'todo/item', :locals => { :parent_container_type => "context" }
|
||||
page.call "todoItems.ensureVisibleWithEffectAppear", item_container_id
|
||||
page.insert_html :bottom, item_container_id, :partial => 'todo/item', :locals => { :parent_container_type => parent_container_type }
|
||||
page.visual_effect :highlight, "item-#{@item.id}", {'startcolor' => "'#99ff99'"}
|
||||
page.show "empty-d" if @done_count == '0'
|
||||
page[empty_container_msg_div_id].hide unless empty_container_msg_div_id.nil? # If we've checked something as undone, uncompleted items can't be empty
|
||||
end
|
||||
page.hide "status"
|
||||
page.replace_html "badge_count", @down_count
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
<%= row_with_select_field("week_starts", Preference.day_number_to_name_map.invert.sort{|a,b| a[1]<=>b[1]})%>
|
||||
<%= row_with_select_field("due_style", [['Due in ___ days',0],['Due on _______',1]]) %>
|
||||
<%= row_with_select_field("show_completed_projects_in_sidebar") %>
|
||||
<%= row_with_select_field("show_hidden_projects_in_sidebar") %>
|
||||
<%= row_with_select_field("show_hidden_contexts_in_sidebar") %>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
<li>Week starts on: <span class="highlight"><%= Preference.day_number_to_name_map[@prefs.week_starts] %></span></li>
|
||||
<li>Show the last <span class="highlight"><%= @prefs.show_number_completed %></span> completed items on the home page</li>
|
||||
<li>Show completed projects in sidebar: <span class="highlight"><%= @prefs.show_completed_projects_in_sidebar %></span></li>
|
||||
<li>Show hidden projects in sidebar: <span class="highlight"><%= @prefs.show_hidden_projects_in_sidebar %></span></li>
|
||||
<li>Show hidden contexts in sidebar: <span class="highlight"><%= @prefs.show_hidden_contexts_in_sidebar %></span></li>
|
||||
<li>Staleness starts after <span class="highlight"><%= @prefs.staleness_starts %></span> days</li>
|
||||
<li>Due style: <span class="highlight">
|
||||
|
|
|
|||
44
tracks/db/migrate/019_convert_todo_to_state_machine.rb
Normal file
44
tracks/db/migrate/019_convert_todo_to_state_machine.rb
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
class ConvertTodoToStateMachine < ActiveRecord::Migration
|
||||
|
||||
class Todo < ActiveRecord::Base; belongs_to :project; end
|
||||
class Immediate < Todo; end
|
||||
class Deferred < Todo; end
|
||||
class Project < ActiveRecord::Base; end
|
||||
|
||||
def self.up
|
||||
ActiveRecord::Base.transaction do
|
||||
add_column :todos, :state, :string, :limit => 20, :default => "immediate", :null => false
|
||||
@todos = Todo.find(:all)
|
||||
@todos.each do |todo|
|
||||
if todo.done?
|
||||
todo.state = 'completed'
|
||||
elsif todo.type == 'Deferred'
|
||||
todo.state = 'deferred'
|
||||
elsif !todo.project.nil? && todo.project.state == 'hidden'
|
||||
todo.state = 'project_hidden'
|
||||
else
|
||||
todo.state = 'active'
|
||||
end
|
||||
todo.save
|
||||
end
|
||||
rename_column :todos, :completed, :completed_at
|
||||
remove_column :todos, :done
|
||||
remove_column :todos, :type
|
||||
end
|
||||
end
|
||||
|
||||
def self.down
|
||||
ActiveRecord::Base.transaction do
|
||||
add_column :todos, :done, :integer, :limit => 4, :default => 0, :null => false
|
||||
add_column :todos, :type, :string, :default => "Immediate", :null => false
|
||||
rename_column :todos, :completed_at, :completed
|
||||
@todos = Todo.find(:all)
|
||||
@todos.each do |todo|
|
||||
todo.done = todo.state == 'completed'
|
||||
todo.type = todo.type == 'deferred' ? 'Deferred' : 'Immediate'
|
||||
todo.save
|
||||
end
|
||||
remove_column :todos, :state
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
class PrefToShowHiddenProjectsInSidebar < ActiveRecord::Migration
|
||||
|
||||
class Preferences < ActiveRecord::Base; end
|
||||
|
||||
def self.up
|
||||
add_column :preferences, :show_hidden_projects_in_sidebar, :boolean, :default => true, :null => false
|
||||
end
|
||||
|
||||
def self.down
|
||||
remove_column :preferences, :show_hidden_projects_in_sidebar
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -2,13 +2,13 @@
|
|||
# migrations feature of ActiveRecord to incrementally modify your database, and
|
||||
# then regenerate this schema definition.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 18) do
|
||||
ActiveRecord::Schema.define(:version => 20) do
|
||||
|
||||
create_table "contexts", :force => true do |t|
|
||||
t.column "name", :string, :default => "", :null => false
|
||||
t.column "hide", :integer, :limit => 4, :default => 0, :null => false
|
||||
t.column "position", :integer, :default => 0, :null => false
|
||||
t.column "hide", :boolean, :default => false
|
||||
t.column "user_id", :integer, :default => 1
|
||||
t.column "user_id", :integer, :default => 0, :null => false
|
||||
end
|
||||
|
||||
create_table "notes", :force => true do |t|
|
||||
|
|
@ -50,12 +50,13 @@ ActiveRecord::Schema.define(:version => 18) do
|
|||
t.column "admin_email", :string, :default => "butshesagirl@rousette.org.uk", :null => false
|
||||
t.column "refresh", :integer, :default => 0, :null => false
|
||||
t.column "verbose_action_descriptors", :boolean, :default => false, :null => false
|
||||
t.column "show_hidden_projects_in_sidebar", :boolean, :default => true, :null => false
|
||||
end
|
||||
|
||||
create_table "projects", :force => true do |t|
|
||||
t.column "name", :string, :default => "", :null => false
|
||||
t.column "position", :integer, :default => 0, :null => false
|
||||
t.column "user_id", :integer, :default => 1
|
||||
t.column "user_id", :integer, :default => 0, :null => false
|
||||
t.column "description", :text
|
||||
t.column "state", :string, :limit => 20, :default => "active", :null => false
|
||||
end
|
||||
|
|
@ -70,23 +71,22 @@ ActiveRecord::Schema.define(:version => 18) do
|
|||
|
||||
create_table "todos", :force => true do |t|
|
||||
t.column "context_id", :integer, :default => 0, :null => false
|
||||
t.column "project_id", :integer
|
||||
t.column "description", :string, :default => "", :null => false
|
||||
t.column "description", :string, :limit => 100, :default => "", :null => false
|
||||
t.column "notes", :text
|
||||
t.column "done", :boolean, :default => false, :null => false
|
||||
t.column "created_at", :datetime
|
||||
t.column "due", :date
|
||||
t.column "completed", :datetime
|
||||
t.column "user_id", :integer, :default => 1
|
||||
t.column "type", :string, :default => "Immediate", :null => false
|
||||
t.column "completed_at", :datetime
|
||||
t.column "project_id", :integer
|
||||
t.column "user_id", :integer, :default => 0, :null => false
|
||||
t.column "show_from", :date
|
||||
t.column "state", :string, :limit => 20, :default => "immediate", :null => false
|
||||
end
|
||||
|
||||
create_table "users", :force => true do |t|
|
||||
t.column "login", :string, :limit => 80, :default => "", :null => false
|
||||
t.column "password", :string, :limit => 40, :default => "", :null => false
|
||||
t.column "login", :string, :limit => 80
|
||||
t.column "password", :string, :limit => 40
|
||||
t.column "word", :string
|
||||
t.column "is_admin", :boolean, :default => false, :null => false
|
||||
t.column "is_admin", :integer, :limit => 4, :default => 0, :null => false
|
||||
t.column "first_name", :string
|
||||
t.column "last_name", :string
|
||||
t.column "auth_type", :string, :default => "database", :null => false
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ module Tracks
|
|||
|
||||
module InstanceMethods
|
||||
|
||||
def not_done_todos
|
||||
@not_done_todos = self.find_not_done_todos if @not_done_todos == nil
|
||||
def not_done_todos(opts={})
|
||||
@not_done_todos = self.find_not_done_todos(opts) if @not_done_todos == nil
|
||||
@not_done_todos
|
||||
end
|
||||
|
||||
|
|
@ -33,19 +33,41 @@ module Tracks
|
|||
@done_todos
|
||||
end
|
||||
|
||||
def find_not_done_todos
|
||||
def find_not_done_todos(opts={})
|
||||
where_state_sql = "todos.state = 'active'"
|
||||
if opts.has_key?(:include_project_hidden_todos) && (opts[:include_project_hidden_todos] == true)
|
||||
where_state_sql = "(todos.state = 'active' or todos.state = 'project_hidden')"
|
||||
end
|
||||
todos = Todo.find(:all,
|
||||
:conditions => ["todos.#{self.class.base_class.name.singularize.downcase}_id = ? and todos.type = ? and todos.done = ?", id, "Immediate", false],
|
||||
:conditions => ["todos.#{self.class.base_class.name.singularize.downcase}_id = ? and #{where_state_sql}", id],
|
||||
:order => "todos.due IS NULL, todos.due ASC, todos.created_at ASC",
|
||||
:include => find_todos_include)
|
||||
|
||||
end
|
||||
|
||||
def find_done_todos
|
||||
todos = Todo.find :all, :conditions => ["todos.#{self.class.base_class.name.singularize.downcase}_id = ? AND todos.type = ? AND todos.done = ?", id, "Immediate", true],
|
||||
:order => "completed DESC",
|
||||
todos = Todo.find(:all, :conditions => ["todos.#{self.class.base_class.name.singularize.downcase}_id = ? AND todos.state = ?", id, "completed"],
|
||||
:order => "completed_at DESC",
|
||||
:include => find_todos_include,
|
||||
:limit => @user.preference.show_number_completed
|
||||
:limit => @user.preference.show_number_completed)
|
||||
end
|
||||
|
||||
def not_done_todo_count(opts={})
|
||||
where_state_sql = "todos.state = 'active'"
|
||||
if opts.has_key?(:include_project_hidden_todos) && (opts[:include_project_hidden_todos] == true)
|
||||
where_state_sql = "(todos.state = 'active' or todos.state = 'project_hidden')"
|
||||
end
|
||||
Todo.count(:conditions => ["todos.#{self.class.base_class.name.singularize.downcase}_id = ? and #{where_state_sql}", id],
|
||||
:order => "todos.due IS NULL, todos.due ASC, todos.created_at ASC",
|
||||
:include => find_todos_include)
|
||||
|
||||
end
|
||||
|
||||
def done_todo_count
|
||||
Todo.count(:conditions => ["todos.#{self.class.base_class.name.singularize.downcase}_id = ? AND todos.state = ?", id, "completed"],
|
||||
:order => "completed_at DESC",
|
||||
:include => find_todos_include,
|
||||
:limit => @user.preference.show_number_completed)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
2
tracks/test/fixtures/preferences.yml
vendored
2
tracks/test/fixtures/preferences.yml
vendored
|
|
@ -7,6 +7,7 @@ admin_user_prefs:
|
|||
show_number_completed: 5
|
||||
show_completed_projects_in_sidebar: true
|
||||
show_hidden_contexts_in_sidebar: true
|
||||
show_hidden_projects_in_sidebar: true
|
||||
admin_email: butshesagirl@rousette.org.uk
|
||||
week_starts: 1
|
||||
due_style: 0
|
||||
|
|
@ -21,6 +22,7 @@ other_user_prefs:
|
|||
show_number_completed: 5
|
||||
show_completed_projects_in_sidebar: true
|
||||
show_hidden_contexts_in_sidebar: true
|
||||
show_hidden_projects_in_sidebar: true
|
||||
admin_email: butshesagirl@rousette.org.uk
|
||||
week_starts: 1
|
||||
due_style: 0
|
||||
|
|
|
|||
56
tracks/test/fixtures/todos.yml
vendored
56
tracks/test/fixtures/todos.yml
vendored
|
|
@ -25,10 +25,10 @@ end
|
|||
project_id: 2
|
||||
description: Call Bill Gates to find out how much he makes per day
|
||||
notes: ~
|
||||
done: false
|
||||
state: active
|
||||
created_at: <%= last_week %>
|
||||
due: <%= two_weeks_hence %>
|
||||
completed: ~
|
||||
completed_at: ~
|
||||
user_id: 1
|
||||
|
||||
2:
|
||||
|
|
@ -37,10 +37,10 @@ end
|
|||
project_id: 3
|
||||
description: Call dinosaur exterminator
|
||||
notes: Ask him if I need to hire a skip for the corpses.
|
||||
done: false
|
||||
state: active
|
||||
created_at: <%= today %>
|
||||
due: <%= two_weeks_hence %>
|
||||
completed: ~
|
||||
completed_at: ~
|
||||
user_id: 1
|
||||
|
||||
3:
|
||||
|
|
@ -49,10 +49,10 @@ end
|
|||
project_id: ~
|
||||
description: Buy milk
|
||||
notes: ~
|
||||
done: 1
|
||||
state: completed
|
||||
created_at: <%= today %>
|
||||
due: ~
|
||||
completed: <%= today %>
|
||||
completed_at: <%= today %>
|
||||
user_id: 1
|
||||
|
||||
4:
|
||||
|
|
@ -61,10 +61,10 @@ end
|
|||
project_id: ~
|
||||
description: Buy bread
|
||||
notes: ~
|
||||
done: 1
|
||||
state: completed
|
||||
created_at: <%= today %>
|
||||
due: ~
|
||||
completed: <%= today %>
|
||||
completed_at: <%= today %>
|
||||
user_id: 1
|
||||
|
||||
5:
|
||||
|
|
@ -73,10 +73,10 @@ end
|
|||
project_id: 1
|
||||
description: Construct time dilation device
|
||||
notes: ~
|
||||
done: false
|
||||
state: active
|
||||
created_at: <%= today %>
|
||||
due: ~
|
||||
completed: ~
|
||||
completed_at: ~
|
||||
user_id: 1
|
||||
|
||||
6:
|
||||
|
|
@ -85,10 +85,10 @@ end
|
|||
project_id: 1
|
||||
description: Phone Grandfather to ask about the paradox
|
||||
notes: Added some _notes_.
|
||||
done: false
|
||||
state: active
|
||||
created_at: <%= today %>
|
||||
due: <%= last_week %>
|
||||
completed: ~
|
||||
completed_at: ~
|
||||
user_id: 1
|
||||
|
||||
7:
|
||||
|
|
@ -97,10 +97,10 @@ end
|
|||
project_id: 3
|
||||
description: Get a book out of the library
|
||||
notes: 'Dinosaurs''R'
|
||||
done: false
|
||||
state: active
|
||||
created_at: <%= today %>
|
||||
due: ~
|
||||
completed: ~
|
||||
completed_at: ~
|
||||
user_id: 1
|
||||
|
||||
8:
|
||||
|
|
@ -109,10 +109,10 @@ end
|
|||
project_id: ~
|
||||
description: Upgrade to Rails 0.9.1
|
||||
notes: ~
|
||||
done: true
|
||||
state: completed
|
||||
created_at: <%= today %>
|
||||
due: <%= today %>
|
||||
completed: <%= today %>
|
||||
completed_at: <%= today %>
|
||||
user_id: 1
|
||||
|
||||
9:
|
||||
|
|
@ -121,10 +121,10 @@ end
|
|||
project_id: ~
|
||||
description: This should be due today
|
||||
notes: ~
|
||||
done: false
|
||||
state: active
|
||||
created_at: <%= today %>
|
||||
due: <%= today %>
|
||||
completed: ~
|
||||
completed_at: ~
|
||||
user_id: 1
|
||||
|
||||
10:
|
||||
|
|
@ -133,10 +133,10 @@ end
|
|||
project_id: ~
|
||||
description: foo
|
||||
notes: ~
|
||||
done: 1
|
||||
state: completed
|
||||
created_at: <%= today %>
|
||||
due: <%= two_weeks_hence %>
|
||||
completed: <%= today %>
|
||||
completed_at: <%= today %>
|
||||
user_id: 1
|
||||
|
||||
11:
|
||||
|
|
@ -145,10 +145,10 @@ end
|
|||
project_id: 2
|
||||
description: Buy shares
|
||||
notes: ~
|
||||
done: false
|
||||
state: active
|
||||
created_at: <%= today %>
|
||||
due: <%= next_week %>
|
||||
completed: ~
|
||||
completed_at: ~
|
||||
user_id: 1
|
||||
|
||||
12:
|
||||
|
|
@ -157,10 +157,10 @@ end
|
|||
project_id: 3
|
||||
description: Buy stegosaurus bait
|
||||
notes: ~
|
||||
done: false
|
||||
state: active
|
||||
created_at: <%= today %>
|
||||
due: <%= next_week %>
|
||||
completed: ~
|
||||
completed_at: ~
|
||||
user_id: 1
|
||||
|
||||
13:
|
||||
|
|
@ -169,10 +169,10 @@ end
|
|||
project_id: 3
|
||||
description: New action in context
|
||||
notes: Some notes
|
||||
done: false
|
||||
state: active
|
||||
created_at: <%= today %>
|
||||
due: <%= next_week %>
|
||||
completed: ~
|
||||
completed_at: ~
|
||||
user_id: 1
|
||||
|
||||
14:
|
||||
|
|
@ -181,8 +181,8 @@ end
|
|||
project_id: 2
|
||||
description: Call stock broker
|
||||
notes: 'tel: 12345'
|
||||
done: false
|
||||
state: active
|
||||
created_at: <%= last_week %>
|
||||
due: ~
|
||||
completed: ~
|
||||
completed_at: ~
|
||||
user_id: 1
|
||||
|
|
|
|||
|
|
@ -6,12 +6,17 @@ require 'context_controller'
|
|||
class ContextController; def rescue_action(e) raise e end; end
|
||||
|
||||
class ContextControllerTest < TodoContainerControllerTestBase
|
||||
fixtures :users, :contexts
|
||||
fixtures :users, :preferences, :contexts
|
||||
|
||||
def setup
|
||||
perform_setup(Context, ContextController)
|
||||
end
|
||||
|
||||
def test_contexts_list
|
||||
@request.session['user_id'] = users(:admin_user).id
|
||||
get :list
|
||||
end
|
||||
|
||||
def test_create_context_via_ajax_increments_number_of_context
|
||||
assert_ajax_create_increments_count '@newcontext'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,11 +6,16 @@ require 'project_controller'
|
|||
class ProjectController; def rescue_action(e) raise e end; end
|
||||
|
||||
class ProjectControllerTest < TodoContainerControllerTestBase
|
||||
fixtures :users, :projects
|
||||
fixtures :users, :todos, :preferences, :projects
|
||||
|
||||
def setup
|
||||
perform_setup(Project, ProjectController)
|
||||
end
|
||||
|
||||
def test_projects_list
|
||||
@request.session['user_id'] = users(:admin_user).id
|
||||
get :list
|
||||
end
|
||||
|
||||
def test_create_project_via_ajax_increments_number_of_projects
|
||||
assert_ajax_create_increments_count 'My New Project'
|
||||
|
|
@ -37,4 +42,28 @@ class ProjectControllerTest < TodoContainerControllerTestBase
|
|||
assert_rjs :visual_effect, :appear, "warning", :duration => '0.5'
|
||||
end
|
||||
|
||||
def test_todo_state_is_project_hidden_after_hiding_project
|
||||
p = projects(:timemachine)
|
||||
todos = p.todos.find_in_state(:all, :active)
|
||||
@request.session['user_id'] = users(:admin_user).id
|
||||
xhr :post, :update, :id => 1, "project"=>{"name"=>p.name, "description"=>p.description, "state"=>"hidden"}
|
||||
todos.each do |t|
|
||||
assert_equal :project_hidden, t.reload().current_state
|
||||
end
|
||||
assert p.reload().hidden?
|
||||
end
|
||||
|
||||
def test_not_done_counts_after_hiding_and_unhiding_project
|
||||
p = projects(:timemachine)
|
||||
todos = p.todos.find_in_state(:all, :active)
|
||||
@request.session['user_id'] = users(:admin_user).id
|
||||
xhr :post, :update, :id => 1, "project"=>{"name"=>p.name, "description"=>p.description, "state"=>"hidden"}
|
||||
xhr :post, :update, :id => 1, "project"=>{"name"=>p.name, "description"=>p.description, "state"=>"active"}
|
||||
todos.each do |t|
|
||||
assert_equal :active, t.reload().current_state
|
||||
end
|
||||
assert p.reload().active?
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,13 +12,11 @@ class TodoControllerTest < Test::Unit::TestCase
|
|||
@request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
|
||||
end
|
||||
|
||||
# Test whether unlogged in users are redirected to login
|
||||
#
|
||||
def test_get_index
|
||||
def test_get_index_when_not_logged_in
|
||||
get :index
|
||||
assert_redirected_to :controller => 'login', :action => 'login'
|
||||
end
|
||||
|
||||
|
||||
def test_not_done_counts
|
||||
@request.session['user_id'] = users(:admin_user).id
|
||||
get :index
|
||||
|
|
@ -26,7 +24,7 @@ class TodoControllerTest < Test::Unit::TestCase
|
|||
assert_equal 3, assigns['context_not_done_counts'][contexts(:call).id]
|
||||
assert_equal 1, assigns['context_not_done_counts'][contexts(:lab).id]
|
||||
end
|
||||
|
||||
|
||||
def test_not_done_counts_after_hiding_project
|
||||
p = Project.find(1)
|
||||
p.hide!
|
||||
|
|
@ -37,5 +35,36 @@ class TodoControllerTest < Test::Unit::TestCase
|
|||
assert_equal 2, assigns['context_not_done_counts'][contexts(:call).id]
|
||||
assert_equal nil, assigns['context_not_done_counts'][contexts(:lab).id]
|
||||
end
|
||||
|
||||
def test_not_done_counts_after_hiding_and_unhiding_project
|
||||
p = Project.find(1)
|
||||
p.hide!
|
||||
p.save!
|
||||
p.activate!
|
||||
p.save!
|
||||
@request.session['user_id'] = users(:admin_user).id
|
||||
get :index
|
||||
assert_equal 2, assigns['project_not_done_counts'][projects(:timemachine).id]
|
||||
assert_equal 3, assigns['context_not_done_counts'][contexts(:call).id]
|
||||
assert_equal 1, assigns['context_not_done_counts'][contexts(:lab).id]
|
||||
end
|
||||
|
||||
def test_destroy_item
|
||||
@request.session['user_id'] = users(:admin_user).id
|
||||
xhr :post, :destroy, :id => 1, :_source_view => 'todo'
|
||||
assert_rjs :page, "item-1-container", :remove
|
||||
#assert_rjs :replace_html, "badge-count", '9'
|
||||
end
|
||||
|
||||
def test_update_item
|
||||
t = Todo.find(1)
|
||||
@request.session['user_id'] = users(:admin_user).id
|
||||
xhr :post, :update, :id => 1, :_source_view => 'todo', "item"=>{"context_id"=>"1", "project_id"=>"2", "id"=>"1", "notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"11/30/2006"}
|
||||
#assert_rjs :page, "item-1-container", :visual_effect, :highlight, :duration => '1'
|
||||
t = Todo.find(1)
|
||||
assert_equal "Call Warren Buffet to find out how much he makes per day", t.description
|
||||
assert_equal Date.parse("11/30/2006"), t.due
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -37,9 +37,6 @@ class UserControllerTest < Test::Unit::TestCase
|
|||
assert_template 'user/preference_edit_form'
|
||||
end
|
||||
|
||||
# Test updating of preferences
|
||||
# FIXME seems to be difficult to test serialization of preferences using YAML
|
||||
#
|
||||
def test_update_preferences
|
||||
@request.session['user_id'] = users(:admin_user).id # log in the admin user
|
||||
post :update_preferences, {:user => { :first_name => 'Jane', :last_name => 'Doe'}, :prefs => { :date_format => "%m-%d-%Y", :week_starts => "0", :show_number_completed => "10", :show_completed_projects_in_sidebar => "false", :show_hidden_contexts_in_sidebar => "false", :staleness_starts => "14", :due_style => "1", :admin_email => "my.email@domain.com" }}
|
||||
|
|
|
|||
|
|
@ -18,17 +18,17 @@ class TodoTest < Test::Unit::TestCase
|
|||
assert_equal 2, @not_completed1.project_id
|
||||
assert_equal "Call Bill Gates to find out how much he makes per day", @not_completed1.description
|
||||
assert_nil @not_completed1.notes
|
||||
assert @not_completed1.done == false || @not_completed1.done == 0
|
||||
assert @not_completed1.completed? == false
|
||||
assert_equal 1.week.ago.strftime("%Y-%m-%d %H:%M"), @not_completed1.created_at.strftime("%Y-%m-%d %H:%M")
|
||||
assert_equal 2.week.from_now.strftime("%Y-%m-%d"), @not_completed1.due.strftime("%Y-%m-%d")
|
||||
assert_nil @not_completed1.completed
|
||||
assert_nil @not_completed1.completed_at
|
||||
assert_equal 1, @not_completed1.user_id
|
||||
end
|
||||
|
||||
def test_completed
|
||||
assert_kind_of Todo, @completed
|
||||
assert @completed.done
|
||||
assert_not_nil @completed.completed
|
||||
assert @completed.completed?
|
||||
assert_not_nil @completed.completed_at
|
||||
end
|
||||
|
||||
# Validation tests
|
||||
|
|
|
|||
8
tracks/vendor/plugins/arts/README
vendored
8
tracks/vendor/plugins/arts/README
vendored
|
|
@ -19,4 +19,10 @@ Usage:
|
|||
assert_rjs :show, "post_1", "post_2", "post_3"
|
||||
assert_rjs :sortable, 'sortable_item'
|
||||
assert_rjs :toggle, "post_1", "post_2", "post_3"
|
||||
assert_rjs :visual_effect, :highlight, "posts", :duration => '1.0'
|
||||
assert_rjs :visual_effect, :highlight, "posts", :duration => '1.0'
|
||||
|
||||
For the square bracket syntax (page['some_id'].toggle) use :page followed by the id and then subsequent method calls. Assignment requires a '=' at the end of the method name followed by the value.
|
||||
|
||||
assert_rjs :page, 'some_id', :toggle
|
||||
assert_rjs :page, 'some_id', :style, :color=, 'red'
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@ author: Kevin Clark
|
|||
summary: RJS Assertion Plugin
|
||||
homepage: http://glu.ttono.us
|
||||
plugin:
|
||||
version: 0.1
|
||||
version: 0.5
|
||||
license: MIT
|
||||
rails_version: 1.1.2+
|
||||
3
tracks/vendor/plugins/arts/init.rb
vendored
3
tracks/vendor/plugins/arts/init.rb
vendored
|
|
@ -1,2 +1,3 @@
|
|||
# Give testing some culture
|
||||
Test::Unit::TestCase.send :include, Arts
|
||||
require 'test/unit/testcase'
|
||||
Test::Unit::TestCase.send :include, Arts
|
||||
|
|
|
|||
25
tracks/vendor/plugins/arts/lib/arts.rb
vendored
25
tracks/vendor/plugins/arts/lib/arts.rb
vendored
|
|
@ -85,8 +85,31 @@ module Arts
|
|||
end
|
||||
end
|
||||
|
||||
# To deal with [] syntax. I hate JavaScriptProxy so.. SO very much
|
||||
def assert_rjs_page(*args)
|
||||
content = build_method_chain!(args)
|
||||
assert_match Regexp.new(Regexp.escape(content)), @response.body,
|
||||
"Content did not include:\n #{content.to_s}"
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def build_method_chain!(args)
|
||||
content = create_generator.send(:[], args.shift) # start $('some_id')....
|
||||
|
||||
while !args.empty?
|
||||
if (method = args.shift.to_s) =~ /(.*)=$/
|
||||
content = content.__send__(method, args.shift)
|
||||
break
|
||||
else
|
||||
content = content.__send__(method)
|
||||
content = content.__send__(:function_chain).first if args.empty?
|
||||
end
|
||||
end
|
||||
|
||||
content
|
||||
end
|
||||
|
||||
def lined_response
|
||||
@response.body.split("\n")
|
||||
end
|
||||
|
|
@ -107,4 +130,4 @@ module Arts
|
|||
return create_generator.send(:arguments_for_call, args)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
41
tracks/vendor/plugins/arts/test/arts_test.rb
vendored
41
tracks/vendor/plugins/arts/test/arts_test.rb
vendored
|
|
@ -102,6 +102,18 @@ class ArtsController < ActionController::Base
|
|||
end
|
||||
end
|
||||
|
||||
def page_with_one_chained_method
|
||||
render :update do |page|
|
||||
page['some_id'].toggle
|
||||
end
|
||||
end
|
||||
|
||||
def page_with_assignment
|
||||
render :update do |page|
|
||||
page['some_id'].style.color = 'red'
|
||||
end
|
||||
end
|
||||
|
||||
def rescue_errors(e) raise e end
|
||||
|
||||
end
|
||||
|
|
@ -358,4 +370,33 @@ class ArtsTest < Test::Unit::TestCase
|
|||
assert_no_rjs :visual_effect, :highlight, "posts", :duration => '1.0'
|
||||
end
|
||||
end
|
||||
|
||||
# [] support
|
||||
|
||||
def test_page_with_one_chained_method
|
||||
get :page_with_one_chained_method
|
||||
assert_nothing_raised do
|
||||
assert_rjs :page, 'some_id', :toggle
|
||||
assert_no_rjs :page, 'some_other_id', :toggle
|
||||
end
|
||||
|
||||
assert_raises(Test::Unit::AssertionFailedError) do
|
||||
assert_rjs :page, 'some_other_id', :toggle
|
||||
assert_no_rjs :page, 'some_id', :toggle
|
||||
end
|
||||
end
|
||||
|
||||
def test_page_with_assignment
|
||||
get :page_with_assignment
|
||||
|
||||
assert_nothing_raised do
|
||||
assert_rjs :page, 'some_id', :style, :color=, 'red'
|
||||
assert_no_rjs :page, 'some_id', :color=, 'red'
|
||||
end
|
||||
|
||||
assert_raises(Test::Unit::AssertionFailedError) do
|
||||
assert_no_rjs :page, 'some_id', :style, :color=, 'red'
|
||||
assert_rjs :page, 'some_other_id', :style, :color=, 'red'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue