diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
new file mode 100644
index 00000000..baaa25dd
--- /dev/null
+++ b/app/controllers/search_controller.rb
@@ -0,0 +1,27 @@
+class SearchController < ApplicationController
+
+ helper :todos, :application, :notes, :projects
+
+ def results
+ @source_view = params['_source_view'] || 'search'
+ @page_title = "TRACKS::Search Results for #{params[:search]}"
+ terms = '%' + params[:search] + '%'
+ @found_todos = current_user.todos.find(:all, :conditions => ["todos.description LIKE ? OR todos.notes LIKE ?", terms, terms], :include => [:tags, :project, :context])
+ @found_projects = current_user.projects.find(:all, :conditions => ["name LIKE ? or description LIKE ?", terms, terms])
+ @found_notes = current_user.notes.find(:all, :conditions => ["body LIKE ?", terms])
+
+ @count = @found_todos.size + @found_projects.size + @found_notes.size
+
+ init_not_done_counts(['project'])
+ init_project_hidden_todo_counts(['project'])
+ end
+
+ def index
+ @page_title = "TRACKS::Search"
+ end
+
+ def init
+ @source_view = params['_source_view'] || 'search'
+ end
+
+end
diff --git a/app/controllers/todos_controller.rb b/app/controllers/todos_controller.rb
index ffb03d5d..a334e189 100644
--- a/app/controllers/todos_controller.rb
+++ b/app/controllers/todos_controller.rb
@@ -67,6 +67,9 @@ class TodosController < ApplicationController
respond_to do |format|
format.html { redirect_to :action => "index" }
format.m do
+ @return_path=cookies[:mobile_url]
+ # todo: use function for this fixed path
+ @return_path='/mobile' if @return_path.nil?
if @saved
redirect_to mobile_abbrev_url
else
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
new file mode 100644
index 00000000..56867b18
--- /dev/null
+++ b/app/helpers/search_helper.rb
@@ -0,0 +1,3 @@
+module SearchHelper
+
+end
diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb
index d171f746..869f82e1 100644
--- a/app/helpers/todos_helper.rb
+++ b/app/helpers/todos_helper.rb
@@ -120,10 +120,10 @@ module TodosHelper
str += @todo.project.name unless should_suppress_project
str = "(#{str})" unless str.blank?
else
- if (['project', 'tag', 'stats'].include?(parent_container_type))
+ if (['project', 'tag', 'stats', 'search'].include?(parent_container_type))
str << item_link_to_context( @todo )
end
- if (['context', 'tickler', 'tag', 'stats'].include?(parent_container_type)) && @todo.project_id
+ if (['context', 'tickler', 'tag', 'stats', 'search'].include?(parent_container_type)) && @todo.project_id
str << item_link_to_project( @todo )
end
end
diff --git a/app/models/todo.rb b/app/models/todo.rb
index c3754e53..c7a3c38d 100644
--- a/app/models/todo.rb
+++ b/app/models/todo.rb
@@ -8,8 +8,8 @@ class Todo < ActiveRecord::Base
acts_as_state_machine :initial => :active, :column => 'state'
- # when entering active state, also remove completed_at date.
- # Looks like :exit of state completed is not run, see #679
+ # when entering active state, also remove completed_at date. Looks like :exit
+ # of state completed is not run, see #679
state :active, :enter => Proc.new { |t| t[:show_from], t.completed_at = nil, nil }
state :project_hidden
state :completed, :enter => Proc.new { |t| t.completed_at = Time.now.utc }, :exit => Proc.new { |t| t.completed_at = nil }
@@ -38,8 +38,8 @@ class Todo < ActiveRecord::Base
attr_protected :user
- # Description field can't be empty, and must be < 100 bytes
- # Notes must be < 60,000 bytes (65,000 actually, but I'm being cautious)
+ # Description field can't be empty, and must be < 100 bytes Notes must be <
+ # 60,000 bytes (65,000 actually, but I'm being cautious)
validates_presence_of :description
validates_length_of :description, :maximum => 100
validates_length_of :notes, :maximum => 60000, :allow_nil => true
@@ -91,7 +91,8 @@ class Todo < ActiveRecord::Base
alias_method :original_run_initial_state_actions, :run_initial_state_actions
def run_initial_state_actions
- #only run the initial state actions if the standard initial state hasn't been changed
+ # only run the initial state actions if the standard initial state hasn't
+ # been changed
if self.class.initial_state.to_sym == current_state
original_run_initial_state_actions
end
diff --git a/app/views/layouts/standard.html.erb b/app/views/layouts/standard.html.erb
index d0f0e14e..b9f7251e 100644
--- a/app/views/layouts/standard.html.erb
+++ b/app/views/layouts/standard.html.erb
@@ -36,11 +36,17 @@ window.onload=function(){
- <%= link_to_function("Toggle notes", nil, {:accesskey => "S", :title => "Toggle all notes", :id => "toggle-notes-nav"}) do |page|
+ <%= link_to_function("Toggle notes", nil, {:accesskey => "S", :title => "Toggle all notes", :id => "toggle-notes-nav"}) do |page|
page.select('body .todo_notes').each { |e| e.toggle }
end
-%> |
- <%= link_to "Logout (#{current_user.display_name}) »", logout_path %>
+ <%= link_to "Logout (#{current_user.display_name}) »", logout_path %>
<%
+ form_tag({:controller => :search, :action => :results}, {:class => "inline-form"}) do %>
+
<%= text_field_tag(:search, params[:search]) %>
+
+ <% end %>
diff --git a/app/views/notes/_notes.rhtml b/app/views/notes/_notes.rhtml
index 2d4c3a1a..5dfd5048 100644
--- a/app/views/notes/_notes.rhtml
+++ b/app/views/notes/_notes.rhtml
@@ -32,7 +32,7 @@
:html => { :id => dom_id(note, 'edit_form'), :class => "inline-form" },
:update => dom_id(note, 'container'),
:complete => visual_effect(:appear, dom_id(note, 'container')) do -%>
- <%= render :partial => "note_edit_form", :object => note %>
+ <%= render :partial => "notes/note_edit_form", :object => note %>
<% end -%>
diff --git a/app/views/projects/_project.rhtml b/app/views/projects/_project.rhtml
index e027e2da..5888814c 100644
--- a/app/views/projects/_project.rhtml
+++ b/app/views/projects/_project.rhtml
@@ -8,13 +8,13 @@
<%= project.name %>
<%= in_place_editor 'project_name_in_place_editor', { :url => { :controller => 'projects', :action => 'update', :id => project.id, :field => 'name', :wants_render => false, :escape => false} , :options=>"{method:'put'}" } %>
- <% unless @project.description.blank? -%>
- <%= sanitize(@project.description) %>
+ <% unless project.description.blank? -%>
+ <%= sanitize(project.description) %>
<% end -%>
- <% if @project.completed? -%>
+ <% if project.completed? -%>
Project has been marked as completed
- <% elsif @project.completed? -%>
+ <% elsif project.completed? -%>
Project has been marked as hidden
<% end -%>
diff --git a/app/views/projects/_project_listing.rhtml b/app/views/projects/_project_listing.rhtml
index dfe0dd41..72f67071 100644
--- a/app/views/projects/_project_listing.rhtml
+++ b/app/views/projects/_project_listing.rhtml
@@ -1,11 +1,15 @@
<% project = project_listing
+ suppress_drag_handle ||= false
+ suppress_edit_button ||= false
@project_listing_zindex = @project_listing_zindex.nil? ? 200 : @project_listing_zindex - 1
-%>
" class="list" style="z-index:<%= @project_listing_zindex %>">
-
+ <% unless suppress_drag_handle -%>
+
DRAG
-
+
+ <% end -%>
<%= link_to_project( project ) %><%= " (" + count_undone_todos_and_notes_phrase(project,"actions") + ")" %>
@@ -22,12 +26,14 @@
page << remote_to_href(:method => 'delete')
end
end -%>
+ <% unless suppress_edit_button -%>
<%= image_tag( "blank.png", :title => "Edit project", :class=>"edit_item") %>
<%= apply_behavior 'a.edit_project_button:click', { :prevent_default => true, :external => true } do |page, element|
element.up('div.project').start_waiting
page << remote_to_href(:method => 'get')
end
-%>
+ <% end -%>
diff --git a/app/views/search/index.rhtml b/app/views/search/index.rhtml
new file mode 100644
index 00000000..7065746b
--- /dev/null
+++ b/app/views/search/index.rhtml
@@ -0,0 +1,6 @@
+
+ <% form_tag(:action => :results) do %>
+ <%= text_field_tag(:search, params[:search]) %>
+ <%= submit_tag "Search" %>
+ <% end %>
+
diff --git a/app/views/search/results.rhtml b/app/views/search/results.rhtml
new file mode 100644
index 00000000..679360c5
--- /dev/null
+++ b/app/views/search/results.rhtml
@@ -0,0 +1,32 @@
+
+ <% if @count == 0 -%>
+
Your search yielded no results.
+ <% else -%>
+ <% source_view_is = :search %>
+ <% parent_container_type = 'search' %>
+ <% if not @found_todos.empty? -%>
+
+
<%= @found_todos.size %>Todos matching query
+ <%= render :partial => "todos/todo", :collection => @found_todos, :locals => { :parent_container_type => 'search', :suppress_context => false, :suppress_project => false, :suppress_edit_button => true } %>
+
+ <% end -%>
+
+ <% if not @found_projects.empty? -%>
+
+
<%= @found_projects.size %>Projects matching query
+ <%= render :partial => "projects/project_listing", :collection => @found_projects, :locals => { :suppress_drag_handle => true, :suppress_edit_button => true } %>
+
+ <% end -%>
+
+ <% if not @found_notes.empty? -%>
+
+
<%= @found_notes.size %>Notes matching query
+ <% for notes in @found_notes -%>
+
+ <%= render :partial => "notes/notes_summary", :object => notes %>
+
+ <% end -%>
+
+ <% end -%>
+ <% end -%>
+
diff --git a/app/views/todos/_todo.html.erb b/app/views/todos/_todo.html.erb
index 6f8579c2..30090ab4 100644
--- a/app/views/todos/_todo.html.erb
+++ b/app/views/todos/_todo.html.erb
@@ -2,11 +2,12 @@
@todo = todo
suppress_context ||= false
suppress_project ||= false
+ suppress_edit_button ||= false
%>
<%= remote_delete_icon %>
- <%= remote_edit_icon %>
+ <%= remote_edit_icon unless suppress_edit_button %>
<%= remote_star_icon %>
<%= remote_toggle_checkbox unless source_view_is :deferred %>
diff --git a/public/images/system-search.png b/public/images/system-search.png
new file mode 100644
index 00000000..fd7f0b07
Binary files /dev/null and b/public/images/system-search.png differ
diff --git a/public/stylesheets/standard.css b/public/stylesheets/standard.css
index 79c26892..38ad2c69 100644
--- a/public/stylesheets/standard.css
+++ b/public/stylesheets/standard.css
@@ -609,6 +609,11 @@ div#list-active-projects, div#list-hidden-projects, div#list-completed-projects,
.project-state-group h2 {
margin:20px 0px 8px 13px;
}
+
+.search-result-group h2 {
+ margin:20px 0px 8px 13px
+}
+
div.alpha_sort {
margin-top:-20px;
float:right;
@@ -999,7 +1004,7 @@ table.export_table {
/* STANDARD */
-button:hover, .widgets a:hover{
+.widgets a:hover{
background-color:#dff4ff;
border:1px solid #c2e1ef;
color:#336699;
diff --git a/public/stylesheets/tracks_844.css b/public/stylesheets/tracks_855.css
similarity index 99%
rename from public/stylesheets/tracks_844.css
rename to public/stylesheets/tracks_855.css
index b13d08e9..9249f293 100644
--- a/public/stylesheets/tracks_844.css
+++ b/public/stylesheets/tracks_855.css
@@ -117,6 +117,7 @@ img.position, a:hover img.position {text-align: left; vertical-align: middle; ba
div.buttons, div.buttons a, div.buttons a:hover {text-align: right; margin-right: 0px; vertical-align: middle; background-color: transparent}
div#list-active-projects, div#list-hidden-projects, div#list-completed-projects, div#list-contexts, div#projects-empty-nd {clear:right; border: 1px solid #999}
.project-state-group h2 {margin:20px 0px 8px 13px}
+.search-result-group h2 {margin:20px 0px 8px 13px }
div.alpha_sort {margin-top:-20px; float:right}
.container td {border: none; padding-bottom: 5px}
.container form {border: none}
@@ -186,7 +187,7 @@ table.export_table {border: 1px solid #666; background-color: #fff; border-spaci
.widgets button{ width:auto; overflow:visible; padding:3px 5px 5px 5px}
.widgets button[type]{ padding:3px 5px 4px 5px; line-height:15px}
.widgets button img, .widgets a img{ margin:0 3px -3px 0 !important; padding:0; border:none; width:16px; height:16px}
-button:hover, .widgets a:hover{ background-color:#dff4ff; border:1px solid #c2e1ef; color:#336699}
+.widgets a:hover{ background-color:#dff4ff; border:1px solid #c2e1ef; color:#336699}
.widgets a:active{ background-color:#6299c5; border:1px solid #6299c5; color:#fff}
button.positive, .widgets a.positive{ color: #498111}
.widgets a.positive:hover, button.positive:hover{ background-color:#E6EFC2; border:1px solid #C6D880; color:#529214}
diff --git a/test/functional/todos_controller_test.rb b/test/functional/todos_controller_test.rb
index f623421f..a2fa5ee3 100644
--- a/test/functional/todos_controller_test.rb
+++ b/test/functional/todos_controller_test.rb
@@ -347,7 +347,7 @@ class TodosControllerTest < Test::Rails::TestCase
"due(1i)"=>"2007", "due(2i)"=>"1", "due(3i)"=>"2",
"show_from(1i)"=>"", "show_from(2i)"=>"", "show_from(3i)"=>"",
"project_id"=>"1",
- "notes"=>"test notes", "state"=>"0"}}
+ "notes"=>"test notes", "state"=>"0"}, "tag_list"=>"test, test2"}
assert_template 'todos/new'
end