diff options
-rw-r--r-- | app/controllers/public_body_controller.rb | 12 | ||||
-rw-r--r-- | app/controllers/request_controller.rb | 6 | ||||
-rw-r--r-- | app/views/layouts/default.rhtml | 5 | ||||
-rw-r--r-- | app/views/public_body/_search_ahead.rhtml | 18 | ||||
-rw-r--r-- | app/views/public_body/show.rhtml | 3 | ||||
-rw-r--r-- | app/views/request/select_authority.rhtml | 49 | ||||
-rw-r--r-- | config/routes.rb | 7 | ||||
-rw-r--r-- | public/stylesheets/main.css | 24 | ||||
-rw-r--r-- | spec/controllers/public_body_controller_spec.rb | 35 |
9 files changed, 153 insertions, 6 deletions
diff --git a/app/controllers/public_body_controller.rb b/app/controllers/public_body_controller.rb index 05acf4868..ea1ffb619 100644 --- a/app/controllers/public_body_controller.rb +++ b/app/controllers/public_body_controller.rb @@ -168,5 +168,17 @@ class PublicBodyController < ApplicationController :filename => 'all-authorities.csv', :disposition =>'attachment', :encoding => 'utf8') end + + # Type ahead search + def search_typeahead + # Since acts_as_xapian doesn't support the Partial match flag, we work around it + # by making the last work a wildcard, which is quite the same + query = params[:q] + '*' + + query = query.split(' ').join(' OR ') # XXX: HACK for OR instead of default AND! + @xapian_requests = perform_search([PublicBody], query, 'relevant', 'request_collapse', 5) + + render :partial => "public_body/search_ahead" + end end diff --git a/app/controllers/request_controller.rb b/app/controllers/request_controller.rb index f36fae463..d39b78f36 100644 --- a/app/controllers/request_controller.rb +++ b/app/controllers/request_controller.rb @@ -22,6 +22,10 @@ class RequestController < ApplicationController rescue MissingSourceFile, NameError end + def select_authority + medium_cache + end + def show medium_cache @locale = self.locale_from_params() @@ -66,7 +70,7 @@ class RequestController < ApplicationController @last_info_request_event_id = @info_request.last_event_id_needing_description @new_responses_count = @info_request.events_needing_description.select {|i| i.event_type == 'response'}.size -1 + # Sidebar stuff # ... requests that have similar imporant terms behavior_cache :tag => ['similar', @info_request.id] do diff --git a/app/views/layouts/default.rhtml b/app/views/layouts/default.rhtml index a14dfcf8e..97462fc91 100644 --- a/app/views/layouts/default.rhtml +++ b/app/views/layouts/default.rhtml @@ -80,11 +80,12 @@ <%= submit_tag _("Search") %> </p> <% end %> - </div> + <div id="topnav"> <ul id="navigation"> - <li><%= link_to _("Make request"), frontpage_url %></li> + <li><%= link_to _("Home"), frontpage_url %></li> + <li><%= link_to _("Make request"), select_authority_url %></li> <li><%= link_to _("View requests"), request_list_successful_url %></li> <li><%= link_to _("View authorities"), list_public_bodies_default %></li> <% if @user %> diff --git a/app/views/public_body/_search_ahead.rhtml b/app/views/public_body/_search_ahead.rhtml new file mode 100644 index 000000000..19c7eb4e8 --- /dev/null +++ b/app/views/public_body/_search_ahead.rhtml @@ -0,0 +1,18 @@ +<p> + <% if @xapian_requests.results.size > 0 %> + <h3><%= _('Top search results:') %></h3> + <p> + <%= _('Select one to see more information about the authority.')%> + </p> + <% else %> + <h3><%= _('No results found.') %></h3> + <% end %> + <div id="authority_search_ahead_results"> + <% for result in @xapian_requests.results %> + <%= render :partial => 'body_listing_single', :locals => { :public_body => result[:model] } %> + <% end %> + </div> +</p> + + + diff --git a/app/views/public_body/show.rhtml b/app/views/public_body/show.rhtml index 3d325e2b8..78a326d72 100644 --- a/app/views/public_body/show.rhtml +++ b/app/views/public_body/show.rhtml @@ -21,6 +21,7 @@ <%= link_to _('View FOI email address'), view_public_body_email_url(@public_body.url_name) %><br> </div> +<div id="main_content"> <h1><%=h(@public_body.name)%></h1> <p class="subtitle"> @@ -99,4 +100,4 @@ <% end %> <p> <%= _('The search index is currently offline, so we can\'t show the Freedom of Information requests that have been made to this authority.')%></p> <% end %> - +</div> diff --git a/app/views/request/select_authority.rhtml b/app/views/request/select_authority.rhtml new file mode 100644 index 000000000..024cc162f --- /dev/null +++ b/app/views/request/select_authority.rhtml @@ -0,0 +1,49 @@ +<script type="text/javascript" src="/javascripts/ba-throttle-debounce.js"></script> +<script> + $(document).ready(function(){ + $("#authority_preview").hide(); + + // Avoid triggering too often (on each keystroke) by using the debounce jQuery plugin: + // http://benalman.com/projects/jquery-throttle-debounce-plugin/ + $("#query").keypress($.debounce( 300, function() { + // Do a type ahead search and display results + $("#typeahead_response").load("<%=search_ahead_bodies_url%>?q="+encodeURI(this.value), function() { + $("#authority_preview").hide(); // Hide the preview, since results have changed + + // We're using the existing body list: we intercept the clicks on the titles to + // display a preview on the right hand side of the screen + $("#typeahead_response a").click(function() { + $("#authority_preview").load(this.href+" #main_content", function() { + $("#authority_preview").show(); + }); + return false; + }); + }); + })); + }); +</script> + +<% @title = _("Select the authority to write to") %> + + <h1 style="clear: left"><%= _('1. Select an authority') %></h1> + + <div> + <% form_tag({:controller => "general", :action => "search_redirect"}, {:id => "search_form"}) do %> + <p> + <p> + <%= _('First, type in the <strong>name of the UK public authority</strong> you\'d + <br>like information from. <strong>By law, they have to respond</strong> + (<a href="{{url}}">why?</a>).', :url=>help_about_url) %> + </p> + <%= text_field_tag 'query', params[:query], { :size => 30 } %> + <%= hidden_field_tag 'bodies', 1 %> + <%= submit_tag _('Search') %> + </p> + <% end %> + <div id="typeahead_response"> + </div> + </div> + + <div id="authority_preview"> + </div> +
\ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 7da279002..24af73229 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -35,9 +35,13 @@ ActionController::Routing::Routes.draw do |map| request.request_list_successful '/list/successful', :action => 'list', :view => 'successful' request.request_list '/list', :action => 'list' + request.select_authority '/select_authority', :action => 'select_authority' + request.new_request '/new', :action => 'new' request.new_request_to_body '/new/:url_name', :action => 'new' + request.search_ahead '/request/search_ahead', :action => 'search_typeahead' + request.show_request '/request/:url_title.:format', :action => 'show' request.show_new_request '/request/:url_title/new', :action => 'show' request.details_request '/details/request/:url_title', :action => 'details' @@ -52,8 +56,6 @@ ActionController::Routing::Routes.draw do |map| request.info_request_event '/request_event/:info_request_event_id', :action => 'show_request_event' request.upload_response "/upload/request/:url_title", :action => 'upload_response' - - request.search_ahead '/request_search_ahead', :action => 'search_typeahead' end # Use /profile for things to do with the currently signed in user. @@ -81,6 +83,7 @@ ActionController::Routing::Routes.draw do |map| end map.with_options :controller => 'public_body' do |body| + body.search_ahead_bodies '/body/search_ahead', :action => 'search_typeahead' body.list_public_bodies "/body", :action => 'list' body.list_public_bodies "/body/list/:tag", :action => 'list' body.list_public_bodies_redirect "/local/:tag", :action => 'list_redirect' diff --git a/public/stylesheets/main.css b/public/stylesheets/main.css index 0c669e8ef..b6e7c1b1a 100644 --- a/public/stylesheets/main.css +++ b/public/stylesheets/main.css @@ -312,6 +312,7 @@ h1, h2, h3 line-height: 1em; letter-spacing: 0em; color: #555; + clear: left; } h1 { font-size: 1.8em;} h2 { font-size: 1.4em;} @@ -927,6 +928,29 @@ a img.attachment_image { #body_sidebar a { text-decoration: none; } +/*------------------------------------------------ selecting an authority */ + +#authority_search_ahead_results +{ + width: 26em; + float: left; +} + +#authority_preview +{ + width: 26em; + float: right; + background-color: #FFFFE0; + padding-left: 1em; + padding-right: 1em; +} + + #authority_preview #stepwise_make_request + { + margin: 0; + } + + /*------------------------------------------------ making a request / sign up / sign in */ #request_advice diff --git a/spec/controllers/public_body_controller_spec.rb b/spec/controllers/public_body_controller_spec.rb index d15482e51..f157d4ac4 100644 --- a/spec/controllers/public_body_controller_spec.rb +++ b/spec/controllers/public_body_controller_spec.rb @@ -139,6 +139,41 @@ describe PublicBodyController, "when showing JSON version for API" do end +describe PublicBodyController, "when doing type ahead searches" do + fixtures :info_requests, :info_request_events, :public_bodies, :public_body_translations, :users, :incoming_messages, :raw_emails, :outgoing_messages, :comments + it "should return nothing for the empty query string" do + get :search_typeahead, :q => "" + response.should render_template('public_body/_search_ahead') + assigns[:xapian_requests].results.size.should == 0 + end + + it "should return a body matching the given keyword, but not users with a matching description" do + get :search_typeahead, :q => "Geraldine" + response.should render_template('public_body/_search_ahead') + assigns[:xapian_requests].results.size.should == 1 + assigns[:xapian_requests].results[0][:model].name.should == public_bodies(:geraldine_public_body).name + end + it "should return all requests matching any of the given keywords" do + get :search_typeahead, :q => "Geraldine Humpadinking" + response.should render_template('public_body/_search_ahead') + assigns[:xapian_requests].results.size.should == 2 + assigns[:xapian_requests].results[0][:model].name.should == public_bodies(:humpadink_public_body).name + assigns[:xapian_requests].results[1][:model].name.should == public_bodies(:geraldine_public_body).name + end + it "should return requests matching the given keywords in any of their locales" do + get :search_typeahead, :q => "baguette" # part of the spanish notes + response.should render_template('public_body/_search_ahead') + assigns[:xapian_requests].results.size.should == 1 + assigns[:xapian_requests].results[0][:model].name.should == public_bodies(:humpadink_public_body).name + end + + it "should return partial matches" do + get :search_typeahead, :q => "geral" # 'geral' for 'Geraldine' + response.should render_template('public_body/_search_ahead') + assigns[:xapian_requests].results.size.should == 1 + assigns[:xapian_requests].results[0][:model].name.should == public_bodies(:geraldine_public_body).name + end +end |