mirror of
https://github.com/TracksApp/tracks.git
synced 2025-12-17 07:40:12 +01:00
Merge branch 'svn-tracking' to svn rev 856
* svn-tracking: Removed outer tracks directory. regenerates compressed stylesheet adds a search textbox in the menu at top-right updates the compressed stylesheet because of changed of last commit adds search to tracks. you can search now on todos, projects and notes. This patch was contributed by Jeffrey Gipson. Thanks Jeffrey! Conflicts: README README_FIRST app/controllers/todos_controller.rb app/helpers/todos_helper.rb app/models/todo.rb app/views/layouts/standard.html.erb app/views/notes/_notes.rhtml app/views/projects/_project.rhtml app/views/projects/_project_listing.rhtml app/views/todos/_todo.html.erb public/stylesheets/standard.css test/functional/todos_controller_test.rb tracks/README_FIRST
This commit is contained in:
commit
2ac1a14c04
16 changed files with 111 additions and 20 deletions
27
app/controllers/search_controller.rb
Normal file
27
app/controllers/search_controller.rb
Normal file
|
|
@ -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
|
||||||
|
|
@ -67,6 +67,9 @@ class TodosController < ApplicationController
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to :action => "index" }
|
format.html { redirect_to :action => "index" }
|
||||||
format.m do
|
format.m do
|
||||||
|
@return_path=cookies[:mobile_url]
|
||||||
|
# todo: use function for this fixed path
|
||||||
|
@return_path='/mobile' if @return_path.nil?
|
||||||
if @saved
|
if @saved
|
||||||
redirect_to mobile_abbrev_url
|
redirect_to mobile_abbrev_url
|
||||||
else
|
else
|
||||||
|
|
|
||||||
3
app/helpers/search_helper.rb
Normal file
3
app/helpers/search_helper.rb
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
module SearchHelper
|
||||||
|
|
||||||
|
end
|
||||||
|
|
@ -120,10 +120,10 @@ module TodosHelper
|
||||||
str += @todo.project.name unless should_suppress_project
|
str += @todo.project.name unless should_suppress_project
|
||||||
str = "(#{str})" unless str.blank?
|
str = "(#{str})" unless str.blank?
|
||||||
else
|
else
|
||||||
if (['project', 'tag', 'stats'].include?(parent_container_type))
|
if (['project', 'tag', 'stats', 'search'].include?(parent_container_type))
|
||||||
str << item_link_to_context( @todo )
|
str << item_link_to_context( @todo )
|
||||||
end
|
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 )
|
str << item_link_to_project( @todo )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ class Todo < ActiveRecord::Base
|
||||||
|
|
||||||
acts_as_state_machine :initial => :active, :column => 'state'
|
acts_as_state_machine :initial => :active, :column => 'state'
|
||||||
|
|
||||||
# when entering active state, also remove completed_at date.
|
# when entering active state, also remove completed_at date. Looks like :exit
|
||||||
# Looks like :exit of state completed is not run, see #679
|
# of state completed is not run, see #679
|
||||||
state :active, :enter => Proc.new { |t| t[:show_from], t.completed_at = nil, nil }
|
state :active, :enter => Proc.new { |t| t[:show_from], t.completed_at = nil, nil }
|
||||||
state :project_hidden
|
state :project_hidden
|
||||||
state :completed, :enter => Proc.new { |t| t.completed_at = Time.now.utc }, :exit => Proc.new { |t| t.completed_at = nil }
|
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
|
attr_protected :user
|
||||||
|
|
||||||
# Description field can't be empty, and must be < 100 bytes
|
# Description field can't be empty, and must be < 100 bytes Notes must be <
|
||||||
# Notes must be < 60,000 bytes (65,000 actually, but I'm being cautious)
|
# 60,000 bytes (65,000 actually, but I'm being cautious)
|
||||||
validates_presence_of :description
|
validates_presence_of :description
|
||||||
validates_length_of :description, :maximum => 100
|
validates_length_of :description, :maximum => 100
|
||||||
validates_length_of :notes, :maximum => 60000, :allow_nil => true
|
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
|
alias_method :original_run_initial_state_actions, :run_initial_state_actions
|
||||||
|
|
||||||
def 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
|
if self.class.initial_state.to_sym == current_state
|
||||||
original_run_initial_state_actions
|
original_run_initial_state_actions
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,13 @@ window.onload=function(){
|
||||||
page.select('body .todo_notes').each { |e| e.toggle }
|
page.select('body .todo_notes').each { |e| e.toggle }
|
||||||
end
|
end
|
||||||
-%> |
|
-%> |
|
||||||
<%= link_to "Logout (#{current_user.display_name}) »", logout_path %>
|
<%= link_to "Logout (#{current_user.display_name}) »", logout_path %><br/><%
|
||||||
|
form_tag({:controller => :search, :action => :results}, {:class => "inline-form"}) do %>
|
||||||
|
<br/><%= text_field_tag(:search, params[:search]) %>
|
||||||
|
<button type="submit" class="search_submit"><%=
|
||||||
|
image_tag("system-search.png", :alt => "Search") -%>
|
||||||
|
</button>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="navcontainer">
|
<div id="navcontainer">
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
:html => { :id => dom_id(note, 'edit_form'), :class => "inline-form" },
|
:html => { :id => dom_id(note, 'edit_form'), :class => "inline-form" },
|
||||||
:update => dom_id(note, 'container'),
|
:update => dom_id(note, 'container'),
|
||||||
:complete => visual_effect(:appear, dom_id(note, 'container')) do -%>
|
: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 -%>
|
<% end -%>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,13 @@
|
||||||
<span class="in_place_editor_field" id="project_name_in_place_editor"><%= project.name %></span>
|
<span class="in_place_editor_field" id="project_name_in_place_editor"><%= project.name %></span>
|
||||||
<%= 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'}" } %>
|
<%= 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'}" } %>
|
||||||
</h2>
|
</h2>
|
||||||
<% unless @project.description.blank? -%>
|
<% unless project.description.blank? -%>
|
||||||
<div class="project_description"><%= sanitize(@project.description) %></div>
|
<div class="project_description"><%= sanitize(project.description) %></div>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
|
|
||||||
<% if @project.completed? -%>
|
<% if project.completed? -%>
|
||||||
<p class="project_completed">Project has been marked as completed</p>
|
<p class="project_completed">Project has been marked as completed</p>
|
||||||
<% elsif @project.completed? -%>
|
<% elsif project.completed? -%>
|
||||||
<p class="project_completed">Project has been marked as hidden</p>
|
<p class="project_completed">Project has been marked as hidden</p>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
<div id="p<%= project.id %>items" class="items toggle_target">
|
<div id="p<%= project.id %>items" class="items toggle_target">
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
<% project = project_listing
|
<% project = project_listing
|
||||||
|
suppress_drag_handle ||= false
|
||||||
|
suppress_edit_button ||= false
|
||||||
@project_listing_zindex = @project_listing_zindex.nil? ? 200 : @project_listing_zindex - 1
|
@project_listing_zindex = @project_listing_zindex.nil? ? 200 : @project_listing_zindex - 1
|
||||||
-%>
|
-%>
|
||||||
<div id="<%= dom_id(project, "container") %>" class="list" style="z-index:<%= @project_listing_zindex %>">
|
<div id="<%= dom_id(project, "container") %>" class="list" style="z-index:<%= @project_listing_zindex %>">
|
||||||
<div id="<%= dom_id(project) %>" class="project sortable_row" style="display:''">
|
<div id="<%= dom_id(project) %>" class="project sortable_row" style="display:''">
|
||||||
|
<% unless suppress_drag_handle -%>
|
||||||
<div class="position">
|
<div class="position">
|
||||||
<span class="handle">DRAG</span>
|
<span class="handle">DRAG</span>
|
||||||
</div>
|
</div>
|
||||||
|
<% end -%>
|
||||||
<div class="data">
|
<div class="data">
|
||||||
<%= link_to_project( project ) %><%= " (" + count_undone_todos_and_notes_phrase(project,"actions") + ")" %>
|
<%= link_to_project( project ) %><%= " (" + count_undone_todos_and_notes_phrase(project,"actions") + ")" %>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -22,12 +26,14 @@
|
||||||
page << remote_to_href(:method => 'delete')
|
page << remote_to_href(:method => 'delete')
|
||||||
end
|
end
|
||||||
end -%>
|
end -%>
|
||||||
|
<% unless suppress_edit_button -%>
|
||||||
<a class="edit_project_button" id="<%= dom_id(project, 'editbutton') %>" href="<%= formatted_edit_project_path(project, :js) %>" title="delete the project '<%= project.name %>'"><%= image_tag( "blank.png", :title => "Edit project", :class=>"edit_item") %></a>
|
<a class="edit_project_button" id="<%= dom_id(project, 'editbutton') %>" href="<%= formatted_edit_project_path(project, :js) %>" title="delete the project '<%= project.name %>'"><%= image_tag( "blank.png", :title => "Edit project", :class=>"edit_item") %></a>
|
||||||
<%= apply_behavior 'a.edit_project_button:click', { :prevent_default => true, :external => true } do |page, element|
|
<%= apply_behavior 'a.edit_project_button:click', { :prevent_default => true, :external => true } do |page, element|
|
||||||
element.up('div.project').start_waiting
|
element.up('div.project').start_waiting
|
||||||
page << remote_to_href(:method => 'get')
|
page << remote_to_href(:method => 'get')
|
||||||
end
|
end
|
||||||
-%>
|
-%>
|
||||||
|
<% end -%>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
6
app/views/search/index.rhtml
Normal file
6
app/views/search/index.rhtml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<div id="display_box_search">
|
||||||
|
<% form_tag(:action => :results) do %>
|
||||||
|
<%= text_field_tag(:search, params[:search]) %>
|
||||||
|
<%= submit_tag "Search" %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
32
app/views/search/results.rhtml
Normal file
32
app/views/search/results.rhtml
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
<div id="display_box_results">
|
||||||
|
<% if @count == 0 -%>
|
||||||
|
<div class="message"><p>Your search yielded no results.</p></div>
|
||||||
|
<% else -%>
|
||||||
|
<% source_view_is = :search %>
|
||||||
|
<% parent_container_type = 'search' %>
|
||||||
|
<% if not @found_todos.empty? -%>
|
||||||
|
<div id="found-todos-container" class="container">
|
||||||
|
<h2><span id="found-todos-count" class="badge"><%= @found_todos.size %></span>Todos matching query</h2>
|
||||||
|
<%= render :partial => "todos/todo", :collection => @found_todos, :locals => { :parent_container_type => 'search', :suppress_context => false, :suppress_project => false, :suppress_edit_button => true } %>
|
||||||
|
</div>
|
||||||
|
<% end -%>
|
||||||
|
|
||||||
|
<% if not @found_projects.empty? -%>
|
||||||
|
<div id="found-projects-container" class="container">
|
||||||
|
<h2><span id="found-projects-count" class="badge"><%= @found_projects.size %></span>Projects matching query</h2>
|
||||||
|
<%= render :partial => "projects/project_listing", :collection => @found_projects, :locals => { :suppress_drag_handle => true, :suppress_edit_button => true } %>
|
||||||
|
</div>
|
||||||
|
<% end -%>
|
||||||
|
|
||||||
|
<% if not @found_notes.empty? -%>
|
||||||
|
<div id="found-notes-container" class="container">
|
||||||
|
<h2><span id="found-notes-count" class="badge"><%= @found_notes.size %></span>Notes matching query</h2>
|
||||||
|
<% for notes in @found_notes -%>
|
||||||
|
<div class="container" id="note-<%= notes.id %>-wrapper">
|
||||||
|
<%= render :partial => "notes/notes_summary", :object => notes %>
|
||||||
|
</div>
|
||||||
|
<% end -%>
|
||||||
|
</div>
|
||||||
|
<% end -%>
|
||||||
|
<% end -%>
|
||||||
|
</div>
|
||||||
|
|
@ -2,11 +2,12 @@
|
||||||
@todo = todo
|
@todo = todo
|
||||||
suppress_context ||= false
|
suppress_context ||= false
|
||||||
suppress_project ||= false
|
suppress_project ||= false
|
||||||
|
suppress_edit_button ||= false
|
||||||
%>
|
%>
|
||||||
<div id="<%= dom_id(todo) %>" class="item-container">
|
<div id="<%= dom_id(todo) %>" class="item-container">
|
||||||
<div id="<%= dom_id(todo, 'line') %>">
|
<div id="<%= dom_id(todo, 'line') %>">
|
||||||
<%= remote_delete_icon %>
|
<%= remote_delete_icon %>
|
||||||
<%= remote_edit_icon %>
|
<%= remote_edit_icon unless suppress_edit_button %>
|
||||||
<%= remote_star_icon %>
|
<%= remote_star_icon %>
|
||||||
<%= remote_toggle_checkbox unless source_view_is :deferred %>
|
<%= remote_toggle_checkbox unless source_view_is :deferred %>
|
||||||
<div class="description<%= staleness_class( todo ) %>">
|
<div class="description<%= staleness_class( todo ) %>">
|
||||||
|
|
|
||||||
BIN
public/images/system-search.png
Normal file
BIN
public/images/system-search.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 935 B |
|
|
@ -609,6 +609,11 @@ div#list-active-projects, div#list-hidden-projects, div#list-completed-projects,
|
||||||
.project-state-group h2 {
|
.project-state-group h2 {
|
||||||
margin:20px 0px 8px 13px;
|
margin:20px 0px 8px 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search-result-group h2 {
|
||||||
|
margin:20px 0px 8px 13px
|
||||||
|
}
|
||||||
|
|
||||||
div.alpha_sort {
|
div.alpha_sort {
|
||||||
margin-top:-20px;
|
margin-top:-20px;
|
||||||
float:right;
|
float:right;
|
||||||
|
|
@ -999,7 +1004,7 @@ table.export_table {
|
||||||
|
|
||||||
/* STANDARD */
|
/* STANDARD */
|
||||||
|
|
||||||
button:hover, .widgets a:hover{
|
.widgets a:hover{
|
||||||
background-color:#dff4ff;
|
background-color:#dff4ff;
|
||||||
border:1px solid #c2e1ef;
|
border:1px solid #c2e1ef;
|
||||||
color:#336699;
|
color:#336699;
|
||||||
|
|
|
||||||
|
|
@ -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.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}
|
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}
|
.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}
|
div.alpha_sort {margin-top:-20px; float:right}
|
||||||
.container td {border: none; padding-bottom: 5px}
|
.container td {border: none; padding-bottom: 5px}
|
||||||
.container form {border: none}
|
.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{ width:auto; overflow:visible; padding:3px 5px 5px 5px}
|
||||||
.widgets button[type]{ padding:3px 5px 4px 5px; line-height:15px}
|
.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}
|
.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}
|
.widgets a:active{ background-color:#6299c5; border:1px solid #6299c5; color:#fff}
|
||||||
button.positive, .widgets a.positive{ color: #498111}
|
button.positive, .widgets a.positive{ color: #498111}
|
||||||
.widgets a.positive:hover, button.positive:hover{ background-color:#E6EFC2; border:1px solid #C6D880; color:#529214}
|
.widgets a.positive:hover, button.positive:hover{ background-color:#E6EFC2; border:1px solid #C6D880; color:#529214}
|
||||||
|
|
@ -347,7 +347,7 @@ class TodosControllerTest < Test::Rails::TestCase
|
||||||
"due(1i)"=>"2007", "due(2i)"=>"1", "due(3i)"=>"2",
|
"due(1i)"=>"2007", "due(2i)"=>"1", "due(3i)"=>"2",
|
||||||
"show_from(1i)"=>"", "show_from(2i)"=>"", "show_from(3i)"=>"",
|
"show_from(1i)"=>"", "show_from(2i)"=>"", "show_from(3i)"=>"",
|
||||||
"project_id"=>"1",
|
"project_id"=>"1",
|
||||||
"notes"=>"test notes", "state"=>"0"}}
|
"notes"=>"test notes", "state"=>"0"}, "tag_list"=>"test, test2"}
|
||||||
assert_template 'todos/new'
|
assert_template 'todos/new'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue