Merge branch 'master' into new-gui

This commit is contained in:
Reinier Balt 2013-09-25 16:22:47 +02:00
commit d44538f604
18 changed files with 328 additions and 119 deletions

View file

@ -5,19 +5,12 @@ class SearchController < ApplicationController
def results
@source_view = params['_source_view'] || 'search'
@page_title = "TRACKS::Search Results for #{params[:search]}"
terms = "%#{params[:search]}%"
@found_not_complete_todos = incomplete_todos(terms)
@found_complete_todos = complete_todos(terms)
@found_todos = @found_not_complete_todos + @found_complete_todos
searcher = Search::SearchResults.new(current_user, params[:search])
searcher.search
@found_projects = current_user.projects.with_name_or_description(terms);
@found_notes = current_user.notes.with_body(terms);
@found_contexts = current_user.contexts.with_name(terms)
# TODO: limit search to tags on todos
@found_tags = todo_tags_by_name(current_user, terms)
@count = @found_todos.size + @found_projects.size + @found_notes.size + @found_contexts.size + @found_tags.size
@results = searcher.results
@count = searcher.number_of_finds
init_not_done_counts
init_project_hidden_todo_counts
@ -26,30 +19,4 @@ class SearchController < ApplicationController
def index
@page_title = "TRACKS::Search"
end
private
def incomplete_todos(terms)
current_user.todos.
where("(todos.description LIKE ? OR todos.notes LIKE ?) AND todos.completed_at IS NULL", terms, terms).
includes(Todo::DEFAULT_INCLUDES).
reorder("todos.due IS NULL, todos.due ASC, todos.created_at ASC")
end
def complete_todos(terms)
current_user.todos.
where("(todos.description LIKE ? OR todos.notes LIKE ?) AND NOT (todos.completed_at IS NULL)", terms, terms).
includes(Todo::DEFAULT_INCLUDES).
reorder("todos.completed_at DESC")
end
def todo_tags_by_name(current_user, terms)
Tagging.find_by_sql([
"SELECT DISTINCT tags.name as name "+
"FROM tags "+
"LEFT JOIN taggings ON tags.id = taggings.tag_id "+
"LEFT JOIN todos ON taggings.taggable_id = todos.id "+
"WHERE todos.user_id=? "+
"AND tags.name LIKE ? ", current_user.id, terms])
end
end

View file

@ -27,12 +27,16 @@ module FeedlistHelper
return html.html_safe
end
def all_feed_links(object, symbol)
feed_links([:rss, :txt, :ical], { :controller=> 'todos', :action => 'index', symbol => object.to_param }, content_tag(:strong, object.name))
end
def all_feed_links_for_project(project)
feed_links([:rss, :txt, :ical], { :controller=> 'todos', :action => 'index', :project_id => project.to_param }, content_tag(:strong, project.name))
all_feed_links(project, :project_id)
end
def all_feed_links_for_context(context)
feed_links([:rss, :txt, :ical], { :controller=> 'todos', :action => 'index', :context_id => context.to_param }, content_tag(:strong, context.name))
all_feed_links(context, :context_id)
end
protected
@ -44,5 +48,6 @@ module FeedlistHelper
def user_token_hash
{ :token => current_user.token }
end
end

View file

@ -3,27 +3,14 @@ class MessageGateway < ActionMailer::Base
extend ActionView::Helpers::SanitizeHelper::ClassMethods
def receive(email)
user = get_user_from_email_address(email)
user = get_receiving_user_from_email_address(email)
return false if user.nil?
return false unless check_sender_is_in_mailmap(user, email)
context = user.prefs.sms_context
description = nil
notes = nil
if email.multipart?
description = get_text_or_nil(email.subject)
notes = get_first_text_plain_part(email)
else
if email.subject.blank?
description = get_decoded_text_or_nil(email.body)
notes = nil
else
description = get_text_or_nil(email.subject)
notes = get_decoded_text_or_nil(email.body)
end
end
todo_params = get_todo_params(email)
todo_builder = TodoFromRichMessage.new(user, context.id, description, notes)
todo_builder = TodoFromRichMessage.new(user, context.id, todo_params[:description], todo_params[:notes])
todo = todo_builder.construct
todo.save!
Rails.logger.info "Saved email as todo for user #{user.login} in context #{context.name}"
@ -32,32 +19,60 @@ class MessageGateway < ActionMailer::Base
private
def get_address(email)
return SITE_CONFIG['email_dispatch'] == 'to' ? email.to[0] : email.from[0]
end
def get_user_from_env_setting
def get_todo_params(email)
params = {}
if email.multipart?
params[:description] = get_text_or_nil(email.subject)
params[:notes] = get_first_text_plain_part(email)
else
if email.subject.blank?
params[:description] = get_decoded_text_or_nil(email.body)
params[:notes] = nil
else
params[:description] = get_text_or_nil(email.subject)
params[:notes] = get_decoded_text_or_nil(email.body)
end
end
params
end
def get_receiving_user_from_email_address(email)
SITE_CONFIG['email_dispatch'] == 'single_user' ? get_receiving_user_from_env_setting : get_receiving_user_from_mail_header(email)
end
def get_receiving_user_from_env_setting
Rails.logger.info "All received email goes to #{ENV['TRACKS_MAIL_RECEIVER']}"
user = User.where(:login => ENV['TRACKS_MAIL_RECEIVER']).first
Rails.logger.info "WARNING: Unknown user set for TRACKS_MAIL_RECEIVER (#{ENV['TRACKS_MAIL_RECEIVER']})" if user.nil?
return user
end
def get_user_from_mail_header(email)
address = get_address(email)
Rails.logger.info "Looking for user with email #{address}"
user = User.where("preferences.sms_email" => address.strip).includes(:preference).first
if user.nil?
user = User.where("preferences.sms_email" => address.strip[1.100]).includes(:preference).first
end
if user.present? and !sender_is_in_mailmap?(user,email)
Rails.logger.warn "#{email.from[0]} not found in mailmap for #{user.login}"
return nil
end
Rails.logger.info(!user.nil? ? "Email belongs to #{user.login}" : "User unknown")
def get_receiving_user_from_mail_header(email)
user = get_receiving_user_from_sms_email( get_address(email) )
Rails.logger.info(user.nil? ? "User unknown": "Email belongs to #{user.login}")
return user
end
def get_address(email)
return SITE_CONFIG['email_dispatch'] == 'to' ? email.to[0] : email.from[0]
end
def get_receiving_user_from_sms_email(address)
Rails.logger.info "Looking for user with email #{address}"
user = User.where("preferences.sms_email" => address.strip).includes(:preference).first
user = User.where("preferences.sms_email" => address.strip[1.100]).includes(:preference).first if user.nil?
return user
end
def check_sender_is_in_mailmap(user, email)
if user.present? and !sender_is_in_mailmap?(user,email)
Rails.logger.warn "#{email.from[0]} not found in mailmap for #{user.login}"
return false
end
return true
end
def sender_is_in_mailmap?(user,email)
if SITE_CONFIG['mailmap'].is_a? Hash and SITE_CONFIG['email_dispatch'] == 'to'
# Look for the sender in the map of allowed senders
@ -69,11 +84,6 @@ class MessageGateway < ActionMailer::Base
end
end
def get_user_from_email_address(email)
SITE_CONFIG['email_dispatch'] == 'single_user' ? get_user_from_env_setting : get_user_from_mail_header(email)
end
def get_text_or_nil(text)
return text ? sanitize(text.strip) : nil
end

View file

@ -0,0 +1,54 @@
module Search
class SearchResults
attr_reader :results
def initialize(user, terms)
@user = user
@terms = "%#{terms}%"
@results = {}
end
def search
results[:not_complete_todos] = incomplete_todos(@terms)
results[:complete_todos] = complete_todos(@terms)
results[:todos] = results[:not_complete_todos] + results[:complete_todos]
results[:projects] = @user.projects.with_name_or_description(@terms)
results[:notes] = @user.notes.with_body(@terms)
results[:contexts] = @user.contexts.with_name(@terms)
results[:tags] = todo_tags_by_name(@terms)
end
def number_of_finds
results[:todos].size + results[:projects].size + results[:notes].size + results[:contexts].size + results[:tags].size
end
private
def incomplete_todos(terms)
@user.todos.
where("(todos.description LIKE ? OR todos.notes LIKE ?) AND todos.completed_at IS NULL", terms, terms).
includes(Todo::DEFAULT_INCLUDES).
reorder("todos.due IS NULL, todos.due ASC, todos.created_at ASC")
end
def complete_todos(terms)
@user.todos.
where("(todos.description LIKE ? OR todos.notes LIKE ?) AND NOT (todos.completed_at IS NULL)", terms, terms).
includes(Todo::DEFAULT_INCLUDES).
reorder("todos.completed_at DESC")
end
def todo_tags_by_name(terms)
Tagging.find_by_sql([
"SELECT DISTINCT tags.name as name "+
"FROM tags "+
"LEFT JOIN taggings ON tags.id = taggings.tag_id "+
"LEFT JOIN todos ON taggings.taggable_id = todos.id "+
"WHERE todos.user_id=? "+
"AND tags.name LIKE ? ", @user.id, terms])
end
end
end

View file

@ -2,24 +2,24 @@
<div class="message"><p><%= t('search.no_results') %></p></div>
<% else -%>
<%= render :layout => 'show_results_collection', :object => @found_todos, :locals => { :collection_name => "found-todos", :collection_title => t('search.todos_matching_query')} do %>
<%= render :partial => "todos/todo", :collection => @found_todos, :locals => { :parent_container_type => 'search', :suppress_context => false, :suppress_project => false, :suppress_edit_button => false } %>
<%= render :layout => 'show_results_collection', :object => @results[:todos], :locals => { :collection_name => "found-todos", :collection_title => t('search.todos_matching_query')} do %>
<%= render :partial => "todos/todo", :collection => @results[:todos], :locals => { :parent_container_type => 'search', :suppress_context => false, :suppress_project => false, :suppress_edit_button => false } %>
<% end -%>
<%= render :layout => 'show_results_collection', :object => @found_projects, :locals => { :collection_name => "found-project", :collection_title => t('search.projects_matching_query')} do %>
<%= render :partial => "projects/project_listing", :collection => @found_projects, :locals => { :suppress_drag_handle => true, :suppress_edit_button => true, :suppress_delete_button => true } %>
<%= render :layout => 'show_results_collection', :object => @results[:projects], :locals => { :collection_name => "found-project", :collection_title => t('search.projects_matching_query')} do %>
<%= render :partial => "projects/project_listing", :collection => @results[:projects], :locals => { :suppress_drag_handle => true, :suppress_edit_button => true, :suppress_delete_button => true } %>
<% end -%>
<%= render :layout => 'show_results_collection', :object => @found_notes, :locals => { :collection_name => "found-notes", :collection_title => t('search.notes_matching_query')} do %>
<%= render :partial => "notes/notes_summary", :collection=> @found_notes %>
<%= render :layout => 'show_results_collection', :object => @results[:notes], :locals => { :collection_name => "found-notes", :collection_title => t('search.notes_matching_query')} do %>
<%= render :partial => "notes/notes_summary", :collection=> @results[:notes] %>
<% end -%>
<%= render :layout => 'show_results_collection', :object => @found_contexts, :locals => { :collection_name => "found-contexts", :collection_title => t('search.contexts_matching_query')} do %>
<%= render :partial => "contexts/context_listing", :collection => @found_contexts, :locals => { :suppress_drag_handle => true, :suppress_edit_button => true } %>
<%= render :layout => 'show_results_collection', :object => @results[:contexts], :locals => { :collection_name => "found-contexts", :collection_title => t('search.contexts_matching_query')} do %>
<%= render :partial => "contexts/context_listing", :collection => @results[:contexts], :locals => { :suppress_drag_handle => true, :suppress_edit_button => true } %>
<% end -%>
<%= render :layout => 'show_results_collection', :object => @found_tags, :locals => { :collection_name => "found-tags", :collection_title => t('search.tags_matching_query')} do %>
<span class="tags"><% @found_tags.each do |tag| -%>
<%= render :layout => 'show_results_collection', :object => @results[:tags], :locals => { :collection_name => "found-tags", :collection_title => t('search.tags_matching_query')} do %>
<span class="tags"><% @results[:tags].each do |tag| -%>
<span class="tag"><%= link_to tag.name, tag_path(tag.name) -%></span>
<% end %>
</span><br/><br/>