mirror of
https://github.com/TracksApp/tracks.git
synced 2026-01-04 00:08:50 +01:00
#300: Disambiguation of predecessors by using project and context names
This commit is contained in:
parent
061e20bf7d
commit
93a914fdb3
4 changed files with 56 additions and 36 deletions
|
|
@ -236,7 +236,7 @@ class TodosController < ApplicationController
|
|||
@original_item_was_deferred = @todo.deferred?
|
||||
@original_item_due = @todo.due
|
||||
@original_item_due_id = get_due_id_for_calendar(@todo.due)
|
||||
@original_item_predecessor_list = @todo.predecessors.collect{|t| t.description}.join(', ')
|
||||
@original_item_predecessor_list = @todo.predecessors.map{|t| t.specification}.join(', ')
|
||||
|
||||
if params['todo']['project_id'].blank? && !params['project_name'].nil?
|
||||
if params['project_name'] == 'None'
|
||||
|
|
@ -604,7 +604,7 @@ class TodosController < ApplicationController
|
|||
get_todo_from_params
|
||||
# Begin matching todos in current project
|
||||
@items = current_user.todos.find(:all,
|
||||
:select => :description,
|
||||
:select => 'description, project_id, context_id, created_at',
|
||||
:conditions => [ '(todos.state = ? OR todos.state = ?) AND ' +
|
||||
'NOT (id = ?) AND lower(description) LIKE ? AND project_id = ?',
|
||||
'active', 'pending',
|
||||
|
|
@ -616,7 +616,7 @@ class TodosController < ApplicationController
|
|||
)
|
||||
if @items.empty? # Match todos in other projects
|
||||
@items = current_user.todos.find(:all,
|
||||
:select => :description,
|
||||
:select => 'description, project_id, context_id, created_at',
|
||||
:conditions => [ '(todos.state = ? OR todos.state = ?) AND ' +
|
||||
'NOT (id = ?) AND lower(description) LIKE ?',
|
||||
'active', 'pending',
|
||||
|
|
@ -628,7 +628,7 @@ class TodosController < ApplicationController
|
|||
else
|
||||
# New todo - TODO: Filter on project
|
||||
@items = current_user.todos.find(:all,
|
||||
:select => :description,
|
||||
:select => 'description, project_id, context_id, created_at',
|
||||
:conditions => [ '(todos.state = ? OR todos.state = ?) AND lower(description) LIKE ?',
|
||||
'active', 'pending',
|
||||
'%' + params[:predecessor_list].downcase + '%' ],
|
||||
|
|
@ -636,7 +636,7 @@ class TodosController < ApplicationController
|
|||
:limit => 10
|
||||
)
|
||||
end
|
||||
render :inline => "<%= auto_complete_result(@items, :description) %>"
|
||||
render :inline => "<%= auto_complete_result2(@items) %>"
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -134,20 +134,10 @@ module TodosHelper
|
|||
if tag_list.empty? then "" else "<span class=\"tags\">#{tag_list}</span>" end
|
||||
end
|
||||
|
||||
# TODO: Use DELIMITER
|
||||
def predecessor_list_text
|
||||
@todo.predecessors.collect{|t| t.description}.join(', ')
|
||||
@todo.predecessors.map{|t| t.specification}.join(', ')
|
||||
end
|
||||
|
||||
def predecessor_list
|
||||
predecessor_list = @todo.predecessors.collect{|t|
|
||||
'<span class="predecessor #{t.description}">' +
|
||||
link_to(t.name, :controller => "todos", :action => "tag", :id => t.name) +
|
||||
"</span>"
|
||||
}.join('')
|
||||
'<span class="predecessors">#{predecessor_list}</span>'
|
||||
end
|
||||
|
||||
|
||||
def deferred_due_date
|
||||
if @todo.deferred? && @todo.due
|
||||
"(action due on #{format_date(@todo.due)})"
|
||||
|
|
@ -316,4 +306,14 @@ module TodosHelper
|
|||
class_str = todo.starred? ? "starred_todo" : "unstarred_todo"
|
||||
image_tag("blank.png", :title =>"Star action", :class => class_str)
|
||||
end
|
||||
|
||||
def auto_complete_result2(entries, phrase = nil)
|
||||
return unless entries
|
||||
items = entries.map do |entry|
|
||||
item = entry.specification()
|
||||
content_tag("li", phrase ? highlight(h(item), phrase) : h(item))
|
||||
end
|
||||
content_tag("ul", items.uniq)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -75,52 +75,72 @@ class Todo < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def no_uncompleted_predecessors_or_deferral?
|
||||
value = (show_from.blank? or Time.zone.now > show_from and uncompleted_predecessors.empty?)
|
||||
logger.debug "=== no_uncompleted_predecessors_or_deferral #{value}"
|
||||
return value
|
||||
return (show_from.blank? or Time.zone.now > show_from and uncompleted_predecessors.empty?)
|
||||
end
|
||||
|
||||
def no_uncompleted_predecessors?
|
||||
value = self.uncompleted_predecessors.empty?
|
||||
logger.debug "=== no_uncompleted_predecessor #{value}"
|
||||
return value
|
||||
return uncompleted_predecessors.empty?
|
||||
end
|
||||
|
||||
|
||||
def todo_from_string(specification)
|
||||
# Split specification into parts: description <project, context>
|
||||
parts = specification.split(%r{\ \<|; |\>})
|
||||
return nil unless parts.length == 3
|
||||
todos = Todo.all(:joins => [:project, :context],
|
||||
:include => [:context, :project],
|
||||
:conditions => {:description => parts[0],
|
||||
:contexts => {:name => parts[2]}})
|
||||
return nil if todos.empty?
|
||||
# todos now contains all todos with matching description and context
|
||||
# TODO: Is this possible to do with a single query?
|
||||
todos.each do |todo|
|
||||
project_name = todo.project.is_a?(NullProject) ? "(none)" : todo.project.name
|
||||
return todo if project_name == parts[1]
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
# TODO: Handle duplicate descriptions
|
||||
def validate
|
||||
if !show_from.blank? && show_from < user.date
|
||||
errors.add("show_from", "must be a date in the future")
|
||||
end
|
||||
unless @predecessor_array.nil? # Only validate predecessors if they changed
|
||||
@predecessor_array.each do |description|
|
||||
t = Todo.find_by_description(description)
|
||||
@predecessor_array.each do |specification|
|
||||
t = todo_from_string(specification)
|
||||
if t.nil?
|
||||
errors.add("Depends on:", "Could not find action '#{description}'")
|
||||
errors.add("Depends on:", "Could not find action '#{h(specification)}'")
|
||||
else
|
||||
errors.add("Depends on:", "Adding '#{description}' would create a circular dependency") if is_successor?(t)
|
||||
errors.add("Depends on:", "Adding '#{h(specification)}' would create a circular dependency") if is_successor?(t)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Returns a string with description, project and context
|
||||
def specification
|
||||
project_name = project.is_a?(NullProject) ? "(none)" : project.name
|
||||
return "#{description} <#{project_name}; #{context.title}>"
|
||||
end
|
||||
|
||||
def save_predecessors
|
||||
unless @predecessor_array.nil? # Only save predecessors if they changed
|
||||
current_array = predecessors.map(&:description)
|
||||
current_array = predecessors.map{|p| p.specification}
|
||||
remove_array = current_array - @predecessor_array
|
||||
add_array = @predecessor_array - current_array
|
||||
|
||||
# This is probably a bit naive code...
|
||||
remove_array.each do |description|
|
||||
t = Todo.find_by_description(description)
|
||||
self.predecessors.delete(t)
|
||||
remove_array.each do |specification|
|
||||
t = todo_from_string(specification)
|
||||
self.predecessors.delete(t) unless t.nil?
|
||||
end
|
||||
# ... as is this?
|
||||
add_array.each do |description|
|
||||
t = Todo.find_by_description(description)
|
||||
add_array.each do |specification|
|
||||
t = todo_from_string(specification)
|
||||
unless t.nil?
|
||||
self.predecessors << t unless self.predecessors.include?(t)
|
||||
else
|
||||
logger.error "Could not find #{description}" # Unexpected since validation passed
|
||||
logger.error "Could not find #{specification}" # Unexpected since validation passed
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -235,7 +255,6 @@ class Todo < ActiveRecord::Base
|
|||
end
|
||||
|
||||
# TODO: DELIMITER
|
||||
# TODO: Handle todos with the same description
|
||||
# TODO: Should possibly handle state changes also?
|
||||
def add_predecessor_list(predecessor_list)
|
||||
if predecessor_list.kind_of? String
|
||||
|
|
|
|||
|
|
@ -1270,6 +1270,7 @@ div.auto_complete ul {
|
|||
list-style-type:none;
|
||||
}
|
||||
div.auto_complete ul li {
|
||||
font-size: 1.0em;
|
||||
margin:0;
|
||||
padding:3px;
|
||||
list-style-type: none;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue