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(){ 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 @@ + 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