Add contacts search
This commit is contained in:
parent
73ce521bb3
commit
f1e9c99866
8 changed files with 114 additions and 27 deletions
|
|
@ -32,7 +32,7 @@ app.views.PublisherMention = app.views.SearchBase.extend({
|
|||
typeaheadInput: this.typeaheadInput,
|
||||
customSearch: true,
|
||||
autoselect: true,
|
||||
prefetch: true
|
||||
remoteRoute: "/contacts/search"
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -37,14 +37,6 @@ app.views.SearchBase = app.views.Base.extend({
|
|||
};
|
||||
}
|
||||
|
||||
if (options.prefetch) {
|
||||
bloodhoundOptions.prefetch = {
|
||||
url: "/contacts.json",
|
||||
transform: this.transformBloodhoundResponse,
|
||||
cache: false
|
||||
};
|
||||
}
|
||||
|
||||
this.bloodhound = new Bloodhound(bloodhoundOptions);
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,17 @@ class ContactsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def search
|
||||
@people = Person.search(params[:q], current_user, only_contacts: true).limit(15)
|
||||
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
@people = @people.limit(15)
|
||||
render json: @people
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def spotlight
|
||||
@spotlight = true
|
||||
@people = Person.community_spotlight
|
||||
|
|
|
|||
|
|
@ -145,26 +145,23 @@ class Person < ActiveRecord::Base
|
|||
[where_clause, q_tokens]
|
||||
end
|
||||
|
||||
def self.search(query, user)
|
||||
return self.where("1 = 0") if query.to_s.blank? || query.to_s.length < 2
|
||||
def self.search(search_str, user, only_contacts: false)
|
||||
search_str.strip!
|
||||
return none if search_str.blank? || search_str.size < 2
|
||||
|
||||
sql, tokens = self.search_query_string(query)
|
||||
sql, tokens = search_query_string(search_str)
|
||||
|
||||
Person.searchable(user).where(sql, *tokens).joins(
|
||||
"LEFT OUTER JOIN contacts ON contacts.user_id = #{user.id} AND contacts.person_id = people.id"
|
||||
).includes(:profile).order(search_order)
|
||||
end
|
||||
query = if only_contacts
|
||||
joins(:contacts).where(contacts: {user_id: user.id})
|
||||
else
|
||||
joins(
|
||||
"LEFT OUTER JOIN contacts ON contacts.user_id = #{user.id} AND contacts.person_id = people.id"
|
||||
).searchable(user)
|
||||
end
|
||||
|
||||
# @return [Array<String>] postgreSQL and mysql deal with null values in orders differently, it seems.
|
||||
def self.search_order
|
||||
@search_order ||= Proc.new {
|
||||
order = if AppConfig.postgres?
|
||||
"ASC"
|
||||
else
|
||||
"DESC"
|
||||
end
|
||||
["contacts.user_id #{order}", "profiles.last_name ASC", "profiles.first_name ASC"]
|
||||
}.call
|
||||
query.where(sql, *tokens)
|
||||
.includes(:profile)
|
||||
.order(["contacts.user_id IS NULL", "profiles.last_name ASC", "profiles.first_name ASC"])
|
||||
end
|
||||
|
||||
def name(opts = {})
|
||||
|
|
|
|||
|
|
@ -155,6 +155,9 @@ Diaspora::Application.routes.draw do
|
|||
|
||||
|
||||
resources :contacts, only: %i(index)
|
||||
|
||||
get "contacts/search" => "contacts#search"
|
||||
|
||||
resources :aspect_memberships, :only => [:destroy, :create]
|
||||
resources :share_visibilities, :only => [:update]
|
||||
resources :blocks, :only => [:create, :destroy]
|
||||
|
|
|
|||
|
|
@ -72,6 +72,31 @@ describe ContactsController, :type => :controller do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#search" do
|
||||
before do
|
||||
@eugene = FactoryGirl.create(:person, profile: FactoryGirl.build(:profile, first_name: "Eugene", last_name: "W"))
|
||||
bob.share_with(@eugene, bob.aspects.first)
|
||||
@casey = FactoryGirl.create(:person, profile: FactoryGirl.build(:profile, first_name: "Casey", last_name: "W"))
|
||||
end
|
||||
|
||||
describe "via json" do
|
||||
it "succeeds" do
|
||||
get :search, q: "Eugene", format: "json"
|
||||
expect(response).to be_success
|
||||
end
|
||||
|
||||
it "responds with json" do
|
||||
get :search, q: "Eugene", format: "json"
|
||||
expect(response.body).to eq([@eugene].to_json)
|
||||
end
|
||||
|
||||
it "only returns contacts" do
|
||||
get :search, q: "Casey", format: "json"
|
||||
expect(response.body).to eq([].to_json)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#spotlight' do
|
||||
it 'succeeds' do
|
||||
get :spotlight
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ describe("app.views.PublisherMention", function() {
|
|||
expect(call.args[0].typeaheadInput.selector).toBe("#publisher .typeahead-mention-box");
|
||||
expect(call.args[0].customSearch).toBeTruthy();
|
||||
expect(call.args[0].autoselect).toBeTruthy();
|
||||
expect(call.args[0].prefetch).toBeTruthy();
|
||||
expect(call.args[0].remoteRoute).toBe("/contacts/search");
|
||||
});
|
||||
|
||||
it("calls bindTypeaheadEvents", function() {
|
||||
|
|
|
|||
|
|
@ -409,6 +409,65 @@ describe Person, :type => :model do
|
|||
people = Person.search("AAA", @user)
|
||||
expect(people.map { |p| p.name }).to eq([@casey_grippi, @yevgeniy_dodis, @robert_grimm, @eugene_weinstein].map { |p| p.name })
|
||||
end
|
||||
|
||||
context "only contacts" do
|
||||
before do
|
||||
@robert_contact = @user.contacts.create(person: @robert_grimm, aspects: [@user.aspects.first])
|
||||
@eugene_contact = @user.contacts.create(person: @eugene_weinstein, aspects: [@user.aspects.first])
|
||||
@invisible_contact = @user.contacts.create(person: @invisible_person, aspects: [@user.aspects.first])
|
||||
end
|
||||
|
||||
it "orders results by last name" do
|
||||
@robert_grimm.profile.first_name = "AAA"
|
||||
@robert_grimm.profile.save!
|
||||
|
||||
@eugene_weinstein.profile.first_name = "AAA"
|
||||
@eugene_weinstein.profile.save!
|
||||
|
||||
@casey_grippi.profile.first_name = "AAA"
|
||||
@casey_grippi.profile.save!
|
||||
|
||||
people = Person.search("AAA", @user, only_contacts: true)
|
||||
expect(people.map(&:name)).to eq([@robert_grimm, @eugene_weinstein].map(&:name))
|
||||
end
|
||||
|
||||
it "returns nothing on an empty query" do
|
||||
people = Person.search("", @user, only_contacts: true)
|
||||
expect(people).to be_empty
|
||||
end
|
||||
|
||||
it "returns nothing on a one-character query" do
|
||||
people = Person.search("i", @user, only_contacts: true)
|
||||
expect(people).to be_empty
|
||||
end
|
||||
|
||||
it "returns results for partial names" do
|
||||
people = Person.search("Eug", @user, only_contacts: true)
|
||||
expect(people.count).to eq(1)
|
||||
expect(people.first).to eq(@eugene_weinstein)
|
||||
|
||||
people = Person.search("wEi", @user, only_contacts: true)
|
||||
expect(people.count).to eq(1)
|
||||
expect(people.first).to eq(@eugene_weinstein)
|
||||
|
||||
@user.contacts.create(person: @casey_grippi, aspects: [@user.aspects.first])
|
||||
people = Person.search("gri", @user, only_contacts: true)
|
||||
expect(people.count).to eq(2)
|
||||
expect(people.first).to eq(@robert_grimm)
|
||||
expect(people.second).to eq(@casey_grippi)
|
||||
end
|
||||
|
||||
it "returns results for full names" do
|
||||
people = Person.search("Robert Grimm", @user, only_contacts: true)
|
||||
expect(people.count).to eq(1)
|
||||
expect(people.first).to eq(@robert_grimm)
|
||||
end
|
||||
|
||||
it "returns results for Diaspora handles" do
|
||||
people = Person.search(@robert_grimm.diaspora_handle, @user, only_contacts: true)
|
||||
expect(people).to eq([@robert_grimm])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'people finders for webfinger' do
|
||||
|
|
|
|||
Loading…
Reference in a new issue