Tweak the context_listing/edit_then_delete test to run more reliably

More adjustments to the time zone calculations. Fixes #450
Add context and project finders as Association Extensions on the User model to simplify controllers and address the feed bug identified by Ryan. Fixes #446 and #444
Replaced usages of "uncompleted" with "incomplete"



git-svn-id: http://www.rousette.org.uk/svn/tracks-repos/trunk@454 a4c988fc-2ded-0310-b66e-134b36920a42
This commit is contained in:
lukemelia 2007-02-23 13:38:36 +00:00
parent 0a28edb2d8
commit 139051f55f
15 changed files with 70 additions and 62 deletions

View file

@ -116,21 +116,9 @@ class ContextsController < ApplicationController
end
def check_user_set_context
if params['url_friendly_name']
@context = @user.contexts.find_by_url_friendly_name(params['url_friendly_name'])
elsif params['id'] && params['id'] =~ /^\d+$/
@context = @user.contexts.find(params['id'])
elsif params['id']
@context = @user.contexts.find_by_url_friendly_name(params['id'])
else
redirect_to :action => 'index'
end
if @context && @user == @context.user
return @context
else
@context = nil # Should be nil anyway.
notify :warning, "Item and session user mis-match: #{@context.user_id} and #{@user.id}!"
render :text => ''
@context = @user.contexts.find_by_params(params)
if @context.nil?
render :text => "Context not found.", :status => 404
end
end

View file

@ -16,7 +16,7 @@ class FeedController < ApplicationController
headers["Content-Type"] = "text/xml; charset=utf-8"
end
# Builds a plain text page listing uncompleted next actions,
# Builds a plain text page listing incomplete next actions,
# grouped by context (contexts are sorted by position, as on the home page).
# Showing notes doesn't make much sense here so they are omitted.
# Hidden contexts are also hidden in the text view
@ -26,20 +26,20 @@ class FeedController < ApplicationController
#
def text
if params.key?('context')
@contexts = [ @user.contexts.find(params['context']) ]
@contexts = [ @user.contexts.find_by_params(params) ]
else
@contexts = @user.contexts.find_all_by_hide(false, "position ASC")
end
headers["Content-Type"] = "text/plain; charset=utf-8"
end
# Builds an iCal compatible export of uncompleted todos
# Builds an iCal compatible export of incomplete todos
# so that each action forms a VTODO in your iCal calendar.
# Due dates are supported, and notes are included.
#
def ical
if params.key?('context')
@contexts = [ @user.contexts.find(params['context']) ]
@contexts = [ @user.contexts.find_by_params(params) ]
else
@contexts = @user.contexts.find_all_by_hide(false, "position ASC")
end
@ -69,15 +69,16 @@ protected
if params.key?('limit')
options[:limit] = limit = params['limit']
@description = limit ? "Lists the last #{limit} uncompleted next actions" : "Lists uncompleted next actions"
@description = limit ? "Lists the last #{limit} incomplete next actions" : "Lists incomplete next actions"
end
@title = "Tracks - Next Actions"
@description = "Filter: "
if params.key?('due')
due_within = params['due'].to_i
condition_builder.add('todos.due <= ?', due_within.days.from_now.utc)
due_within_date_s = @user.prefs.tz.adjust(due_within.days.from_now.utc).strftime("%Y-%m-%d")
due_within_when = @user.time + due_within.days
condition_builder.add('todos.due <= ?', due_within_when)
due_within_date_s = due_within_when.strftime("%Y-%m-%d")
@title << " due today" if (due_within == 0)
@title << " due within a week" if (due_within == 6)
@description << " with a due date #{due_within_date_s} or earlier"
@ -85,20 +86,20 @@ protected
if params.key?('done')
done_in_last = params['done'].to_i
condition_builder.add('todos.completed_at >= ?', done_in_last.days.ago.utc)
condition_builder.add('todos.completed_at >= ?', @user.time - done_in_last.days)
@title << " actions completed"
@description << " in the last #{done_in_last.to_s} days"
end
if params.key?('context')
context = @user.contexts.find(params['context'])
context = @user.contexts.find_by_params(params)
condition_builder.add('todos.context_id = ?', context.id)
@title << " in #{context.name}"
@description << " in context '#{context.name}'"
end
if params.key?('project')
project = @user.projects.find(params['project'])
project = @user.projects.find_by_params(params)
condition_builder.add('todos.project_id = ?', project.id)
@title << " for #{project.name}"
@description << " for project '#{project.name}'"

View file

@ -138,22 +138,8 @@ class ProjectsController < ApplicationController
end
def check_user_set_project
if params["url_friendly_name"]
@project = @user.projects.find_by_url_friendly_name(params["url_friendly_name"])
elsif params['id'] && params['id'] =~ /^\d+$/
@project = @user.projects.find(params["id"])
elsif params['id']
@project = @user.projects.find_by_url_friendly_name(params["id"])
else
redirect_to :action => 'index'
end
if @user == @project.user
return @project
else
@project = nil # Should be nil anyway
notify :warning, "Project and session user mis-match: #{@project.user_id} and #{@user.id}!"
render :text => ''
end
@project = @user.projects.find_by_params(params)
render :text => 'Project not found', :status => 404 if @project.nil?
end
def check_user_matches_project_user(id)

View file

@ -213,15 +213,15 @@ class TodosController < ApplicationController
def completed
@page_title = "TRACKS::Completed tasks"
@done = @user.completed_todos
@done_today = @done.completed_within 1.day.ago.utc
@done_this_week = @done.completed_within 1.week.ago.utc
@done_this_month = @done.completed_within 4.week.ago.utc
@done_today = @done.completed_within user_time - 1.day
@done_this_week = @done.completed_within user_time - 1.week
@done_this_month = @done.completed_within user_time - 4.week
end
def completed_archive
@page_title = "TRACKS::Archived completed tasks"
@done = @user.completed_todos
@done_archive = @done.completed_more_than 28.day.ago.utc
@done_archive = @done.completed_more_than user_time - 28.days
end
def list_deferred

View file

@ -15,7 +15,7 @@ module ApplicationHelper
end
def user_time
@user.prefs.tz.adjust(Time.now.utc)
@user.time
end

View file

@ -1,7 +1,7 @@
module TodosHelper
require 'users_controller'
# Counts the number of uncompleted items in the specified context
# Counts the number of incomplete items in the specified context
#
def count_items(context)
count = Todo.find_all("done=0 AND context_id=#{context.id}").length
@ -91,11 +91,11 @@ module TodosHelper
def staleness_class(item)
if item.due || item.completed?
return ""
elsif item.created_at < (@user.prefs.staleness_starts * 3).days.ago.utc
elsif item.created_at < user_time - (@user.prefs.staleness_starts * 3).days
return " stale_l3"
elsif item.created_at < (@user.prefs.staleness_starts * 2).days.ago.utc
elsif item.created_at < user_time - (@user.prefs.staleness_starts * 2).days
return " stale_l2"
elsif item.created_at < (@user.prefs.staleness_starts).days.ago.utc
elsif item.created_at < user_time - (@user.prefs.staleness_starts).days
return " stale_l1"
else
return ""

View file

@ -45,7 +45,7 @@ class Todo < ActiveRecord::Base
validates_presence_of :context
def validate
if deferred? && !show_from.blank? && show_from < Time.now.utc.to_date
if deferred? && !show_from.blank? && show_from < user.date
errors.add("Show From", "must be a date in the future.")
end
end
@ -65,7 +65,7 @@ class Todo < ActiveRecord::Base
def show_from=(date)
activate! if deferred? && date.blank?
defer! if active? && !date.blank? && date > Time.now.utc.to_date
defer! if active? && !date.blank? && date > user.date
self[:show_from] = date
end

View file

@ -3,10 +3,34 @@ require 'digest/sha1'
class User < ActiveRecord::Base
has_many :contexts,
:order => 'position ASC',
:dependent => :delete_all
:dependent => :delete_all do
def find_by_params(params)
if params['url_friendly_name']
find_by_url_friendly_name(params['url_friendly_name'])
elsif params['id'] && params['id'] =~ /^\d+$/
find(params['id'])
elsif params['id']
find_by_url_friendly_name(params['id'])
elsif params['context']
find_by_url_friendly_name(params['context'])
end
end
end
has_many :projects,
:order => 'position ASC',
:dependent => :delete_all
:dependent => :delete_all do
def find_by_params(params)
if params['url_friendly_name']
find_by_url_friendly_name(params['url_friendly_name'])
elsif params['id'] && params['id'] =~ /^\d+$/
find(params['id'])
elsif params['id']
find_by_url_friendly_name(params['id'])
elsif params['project']
find_by_url_friendly_name(params['project'])
end
end
end
has_many :todos,
:order => 'completed_at DESC, todos.created_at DESC',
:dependent => :delete_all
@ -91,6 +115,14 @@ class User < ActiveRecord::Base
def crypt_word
write_attribute("word", self.class.sha1(login + Time.now.to_i.to_s + rand.to_s))
end
def time
prefs.tz.adjust(Time.now.utc)
end
def date
time.to_date
end
protected

View file

@ -28,7 +28,7 @@
</h2>
<div id="c<%= context.id %>items" class="items toggle_target">
<div id="c<%= context.id %>empty-nd" style="display:<%= @not_done.empty? ? 'block' : 'none'%>;">
<div class="message"><p>Currently there are no uncompleted actions in this context</p></div>
<div class="message"><p>Currently there are no incomplete actions in this context</p></div>
</div>
<%= render :partial => "todos/todo", :collection => @not_done, :locals => { :parent_container_type => "context" } %>
</div><!-- [end:items] -->

View file

@ -54,7 +54,7 @@
<%= text_formatted_link({:controller => 'projects', :action => 'index', :only_active_with_no_next_actions => true}) %>
Active projects with no next actions
</li>
<li><h4>Feeds for uncompleted actions in a specific context:</h4>
<li><h4>Feeds for incomplete actions in a specific context:</h4>
<ul>
<% for context in @contexts %>
<li>
@ -66,7 +66,7 @@
<% end %>
</ul>
</li>
<li><h4>Feeds for uncompleted actions in a specific project:</h4>
<li><h4>Feeds for incomplete actions in a specific project:</h4>
<ul>
<% for project in @projects %>
<li>

View file

@ -1,6 +1,6 @@
<%= render_flash %>
<% if @todos.length == 0 -%>
<p>There are no uncompleted actions in this <%= @type %></p>
<p>There are no incomplete actions in this <%= @type %></p>
<% else -%>
<ul>
<% for todo in @todos -%>

View file

@ -18,7 +18,7 @@
<% end -%>
<div class="items toggle_target">
<div id="p<%= project.id %>empty-nd" style="display:<%= @not_done.empty? ? 'block' : 'none'%>;">
<div class="message"><p>Currently there are no uncompleted actions in this project</p></div>
<div class="message"><p>Currently there are no incomplete actions in this project</p></div>
</div>
<%= render :partial => "todos/todo", :collection => @not_done, :locals => { :parent_container_type => "project" } %>
</div><!-- [end:items] -->

View file

@ -17,7 +17,7 @@ if @saved
page.insert_html :bottom, item_container_id, :partial => 'todos/todo', :locals => { :parent_container_type => parent_container_type }
page.visual_effect :highlight, dom_id(@todo, 'line'), {'startcolor' => "'#99ff99'"}
page.show "empty-d" if @completed_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
page[empty_container_msg_div_id].hide unless empty_container_msg_div_id.nil? # If we've checked something as undone, incomplete items can't be empty
end
page.hide "status"
page.replace_html "badge_count", @down_count

View file

@ -98,6 +98,7 @@ class FeedSmokeTest < ActionController::IntegrationTest
def assert_success(url)
get url
assert_response :success
#puts @response.body
end
end

View file

@ -11,5 +11,5 @@ wait_for_visible "context_3"
click "css=#context_3 .buttons img.delete_item"
assert_confirmation "Are you sure that you want to delete the context 'telegraph'?"
wait_for_visible "flash"
assert_text "flash", "Deleted context 'telegraph'"
assert_element_not_present "context_3"
wait_for_text "flash", "Deleted context 'telegraph'"
wait_for_element_not_present "context_3"