aboutsummaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/new-request.js14
-rw-r--r--app/assets/javascripts/select-authorities.js67
-rw-r--r--app/assets/stylesheets/main.scss47
-rw-r--r--app/controllers/admin_user_controller.rb1
-rw-r--r--app/controllers/application_controller.rb4
-rw-r--r--app/controllers/comment_controller.rb4
-rw-r--r--app/controllers/info_request_batch_controller.rb16
-rw-r--r--app/controllers/request_controller.rb284
-rw-r--r--app/controllers/track_controller.rb2
-rw-r--r--app/controllers/user_controller.rb3
-rw-r--r--app/mailers/info_request_batch_mailer.rb25
-rw-r--r--app/models/comment.rb2
-rw-r--r--app/models/info_request.rb31
-rw-r--r--app/models/info_request_batch.rb73
-rw-r--r--app/models/outgoing_message.rb18
-rw-r--r--app/models/public_body.rb1
-rw-r--r--app/models/track_thing.rb2
-rw-r--r--app/models/user.rb6
-rw-r--r--app/views/admin_user/_form.html.erb9
-rw-r--r--app/views/comment/_comment_form.html.erb2
-rw-r--r--app/views/info_request_batch/_info_request_batch.html.erb15
-rw-r--r--app/views/info_request_batch/show.html.erb25
-rw-r--r--app/views/info_request_batch_mailer/batch_sent.text.erb15
-rw-r--r--app/views/request/batch_not_allowed.html.erb1
-rw-r--r--app/views/request/new.html.erb142
-rw-r--r--app/views/request/preview.html.erb24
-rw-r--r--app/views/request/select_authorities.html.erb77
-rw-r--r--app/views/request/select_authority.html.erb7
-rw-r--r--app/views/track/_tracking_links.html.erb2
-rw-r--r--app/views/user/show.html.erb11
30 files changed, 772 insertions, 158 deletions
diff --git a/app/assets/javascripts/new-request.js b/app/assets/javascripts/new-request.js
new file mode 100644
index 000000000..f8f2a0665
--- /dev/null
+++ b/app/assets/javascripts/new-request.js
@@ -0,0 +1,14 @@
+$(document).ready(function() {
+ $('.batch_public_body_list').hide();
+ var showtext = $('.batch_public_body_toggle').attr('data-showtext');
+ var hidetext = $('.batch_public_body_toggle').attr('data-hidetext');
+ $('.toggle-message').text(showtext);
+ $('.batch_public_body_toggle').click(function(){
+ $('.batch_public_body_list').toggle();
+ if ($('.toggle-message').text() == showtext){
+ $('.toggle-message').text(hidetext);
+ }else{
+ $('.toggle-message').text(showtext);
+ }
+ })
+})
diff --git a/app/assets/javascripts/select-authorities.js b/app/assets/javascripts/select-authorities.js
new file mode 100644
index 000000000..843f5c0ad
--- /dev/null
+++ b/app/assets/javascripts/select-authorities.js
@@ -0,0 +1,67 @@
+$(document).ready(function() {
+
+ function add_option(selector, value, text) {
+ var optionExists = ($(selector + ' option[value=' + value + ']').length > 0);
+ if(!optionExists){
+ $(selector).append("<option value=" + value + ">" + text + "</option>");
+ }
+ }
+ // Transfer a set of select options defined by 'from_selector' to another select,
+ // defined by 'to_selector'
+ function transfer_options(from_selector, to_selector){
+ $(from_selector).each(function()
+ {
+ add_option(to_selector, $(this).val(), $(this).text());
+ $(this).remove();
+ })
+ $('#public_body_query').val('');
+ return false;
+ }
+
+ // Submit the search form once the text reaches a certain length
+ $("#public_body_query").keypress($.debounce( 300, function() {
+ if ($('#public_body_query').val().length >= 3) {
+ $('#body_search_form').submit();
+ }
+ }));
+
+ // Populate the candidate list with json search results
+ $('#body_search_form').on('ajax:success', function(event, data, status, xhr) {
+ $('#select_body_candidates').empty();
+ $.each(data, function(key, value)
+ {
+ add_option('#select_body_candidates', value['id'], value['name']);
+ });
+ });
+
+ // Add a hidden element to the submit form for every option in the selected list
+ $('#body_submit_button').click(function(){
+ $('#select_body_selections option').each(function()
+ {
+ $('#body_submit_form').append('<input type="hidden" value="' + $(this).val() + '" name="public_body_ids[]">' );
+ })
+ })
+
+ // Transfer selected candidates to selected list
+ $('#body_select_button').click(function(){
+ return transfer_options('#select_body_candidates option:selected', '#select_body_selections');
+ })
+
+ // Transfer selected selected options back to candidate list
+ $('#body_deselect_button').click(function(){
+ return transfer_options('#select_body_selections option:selected', '#select_body_candidates');
+ })
+
+ // Transfer all candidates to selected list
+ $('#body_select_all_button').click(function(){
+ return transfer_options('#select_body_candidates option', '#select_body_selections');
+ })
+
+ // Transfer all selected back to candidate list
+ $('#body_deselect_all_button').click(function(){
+ return transfer_options('#select_body_selections option', '#select_body_candidates');
+ })
+
+ // Show the buttons for selecting and deselecting all
+ $('.select_all_button').show();
+})
diff --git a/app/assets/stylesheets/main.scss b/app/assets/stylesheets/main.scss
index 6405d1dc3..3118eab3d 100644
--- a/app/assets/stylesheets/main.scss
+++ b/app/assets/stylesheets/main.scss
@@ -1722,7 +1722,7 @@ padding-right:50px;
margin-bottom:10px;
}
-div.ff-icon-printfix,.comment_in_request_text img.comment_quote,body.front #other-country-notice,#other-country-notice,#authority_preview .public-body-name-prefix,#authority_preview #list-filter,#authority_preview h2.foi_results,div#show_response_view p.event_actions {
+div.ff-icon-printfix,.comment_in_request_text img.comment_quote,body.front #other-country-notice,#other-country-notice,#authority_preview .public-body-name-prefix,#authority_preview #list-filter,#authority_preview h2.foi_results,div#show_response_view p.event_actions, div.batch_public_body_toggle {
display:none;
}
@@ -1777,3 +1777,48 @@ text-decoration:none;
the axes black rather than transparent grey for the moment: */
color: #000 !important;
}
+
+
+#body_selection .body_list {
+ width: 45%;
+}
+
+#body_selection .body_list input[type='submit'] {
+ margin: 10px 0;
+ width: 45%;
+}
+
+#body_selection .body_list #body_select_all_button,
+#body_selection .body_list #body_deselect_button{
+ float: right;
+}
+
+#body_selection #body_candidates {
+ float: left;
+}
+
+#body_selection #body_selections {
+ float: right;
+}
+
+#body_selection #body_submission input[type='submit'] {
+ margin: 10px 0;
+ width:100%;
+}
+
+#body_selection .select_all_button {
+ display: none;
+}
+
+#body_selection .body_select {
+ width: 100%;
+}
+
+.batch_public_body_list {
+ margin-left: 110px;
+}
+
+.batch_public_body_toggle {
+ color: #0000EE;
+ font-size: 0.9em;
+}
diff --git a/app/controllers/admin_user_controller.rb b/app/controllers/admin_user_controller.rb
index 929b93e0e..940a5fe8f 100644
--- a/app/controllers/admin_user_controller.rb
+++ b/app/controllers/admin_user_controller.rb
@@ -48,6 +48,7 @@ class AdminUserController < AdminController
@admin_user.ban_text = params[:admin_user][:ban_text]
@admin_user.about_me = params[:admin_user][:about_me]
@admin_user.no_limit = params[:admin_user][:no_limit]
+ @admin_user.can_make_batch_requests = params[:admin_user][:can_make_batch_requests]
if @admin_user.valid?
@admin_user.save!
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 7c122917d..370e8e15c 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -369,9 +369,9 @@ class ApplicationController < ActionController::Base
return page
end
- def perform_search_typeahead(query, model)
+ def perform_search_typeahead(query, model, per_page=25)
@page = get_search_page_from_params
- @per_page = 10
+ @per_page = per_page
query_words = query.split(/ +(?![-+]+)/)
if query_words.last.nil? || query_words.last.strip.length < 3
xapian_requests = nil
diff --git a/app/controllers/comment_controller.rb b/app/controllers/comment_controller.rb
index d4b17e9d2..cda56a211 100644
--- a/app/controllers/comment_controller.rb
+++ b/app/controllers/comment_controller.rb
@@ -38,7 +38,7 @@ class CommentController < ApplicationController
if params[:comment]
# XXX this check should theoretically be a validation rule in the model
- @existing_comment = Comment.find_by_existing_comment(@info_request.id, params[:comment][:body])
+ @existing_comment = Comment.find_existing(@info_request.id, params[:comment][:body])
else
# Default to subscribing to request when first viewing form
params[:subscribe_to_request] = true
@@ -68,7 +68,7 @@ class CommentController < ApplicationController
if params[:subscribe_to_request]
@track_thing = TrackThing.create_track_for_request(@info_request)
- @existing_track = TrackThing.find_by_existing_track(@user, @track_thing)
+ @existing_track = TrackThing.find_existing(@user, @track_thing)
if @user && @info_request.user == @user
# don't subscribe to own request!
elsif !@existing_track
diff --git a/app/controllers/info_request_batch_controller.rb b/app/controllers/info_request_batch_controller.rb
new file mode 100644
index 000000000..b66658757
--- /dev/null
+++ b/app/controllers/info_request_batch_controller.rb
@@ -0,0 +1,16 @@
+class InfoRequestBatchController < ApplicationController
+
+ def show
+ @info_request_batch = InfoRequestBatch.find(params[:id])
+ @per_page = 25
+ @page = get_search_page_from_params
+ if @info_request_batch.sent_at
+ @info_requests = @info_request_batch.info_requests.visible.all(:offset => (@page - 1) * @per_page,
+ :limit => @per_page)
+ else
+ @public_bodies = @info_request_batch.public_bodies.all(:offset => (@page - 1) * @per_page,
+ :limit => @per_page)
+ end
+ end
+
+end
diff --git a/app/controllers/request_controller.rb b/app/controllers/request_controller.rb
index b79ead73d..a94461758 100644
--- a/app/controllers/request_controller.rb
+++ b/app/controllers/request_controller.rb
@@ -11,7 +11,7 @@ require 'open-uri'
class RequestController < ApplicationController
before_filter :check_read_only, :only => [ :new, :show_response, :describe_state, :upload_response ]
protect_from_forgery :only => [ :new, :show_response, :describe_state, :upload_response ] # See ActionController::RequestForgeryProtection for details
-
+ before_filter :check_batch_requests_and_user_allowed, :only => [ :select_authorities, :new_batch ]
MAX_RESULTS = 500
PER_PAGE = 25
@@ -43,6 +43,32 @@ class RequestController < ApplicationController
medium_cache
end
+ def select_authorities
+ if !params[:public_body_query].nil?
+ @search_bodies = perform_search_typeahead(params[:public_body_query], PublicBody, 1000)
+ end
+ respond_to do |format|
+ format.html do
+ if !params[:public_body_ids].nil?
+ if !params[:remove_public_body_ids].nil?
+ body_ids = params[:public_body_ids] - params[:remove_public_body_ids]
+ else
+ body_ids = params[:public_body_ids]
+ end
+ @public_bodies = PublicBody.where({:id => body_ids}).all
+ end
+ end
+ format.json do
+ if @search_bodies
+ render :json => @search_bodies.results.map{ |result| {:name => result[:model].name,
+ :id => result[:model].id } }
+ else
+ render :json => []
+ end
+ end
+ end
+ end
+
def show
if !AlaveteliConfiguration::varnish_host.blank?
# If varnish is set up to accept PURGEs, then cache for a
@@ -167,6 +193,69 @@ class RequestController < ApplicationController
end
end
+ def new_batch
+ if params[:public_body_ids].blank?
+ redirect_to select_authorities_path and return
+ end
+
+ # TODO: Decide if we make batch requesters describe their undescribed requests
+ # before being able to make a new batch request
+
+ if !authenticated_user.can_file_requests?
+ @details = authenticated_user.can_fail_html
+ render :template => 'user/banned' and return
+ end
+
+ @batch = true
+
+ I18n.with_locale(@locale) do
+ @public_bodies = PublicBody.where({:id => params[:public_body_ids]}).
+ includes(:translations).
+ order('public_body_translations.name').all
+ end
+ if params[:submitted_new_request].nil? || params[:reedit]
+ return render_new_compose(batch=true)
+ end
+
+ # Check for double submission of batch
+ @existing_batch = InfoRequestBatch.find_existing(authenticated_user,
+ params[:info_request][:title],
+ params[:outgoing_message][:body],
+ params[:public_body_ids])
+
+ @info_request = InfoRequest.create_from_attributes(params[:info_request],
+ params[:outgoing_message],
+ authenticated_user)
+ @outgoing_message = @info_request.outgoing_messages.first
+ @info_request.is_batch_request_template = true
+ if !@existing_batch.nil? || !@info_request.valid?
+ # We don't want the error "Outgoing messages is invalid", as in this
+ # case the list of errors will also contain a more specific error
+ # describing the reason it is invalid.
+ @info_request.errors.delete(:outgoing_messages)
+ render :action => 'new'
+ return
+ end
+
+ # Show preview page, if it is a preview
+ if params[:preview].to_i == 1
+ return render_new_preview
+ end
+
+ @info_request_batch = InfoRequestBatch.create!(:title => params[:info_request][:title],
+ :body => params[:outgoing_message][:body],
+ :public_bodies => @public_bodies,
+ :user => authenticated_user)
+ flash[:notice] = _("<p>Your {{law_used_full}} requests will be <strong>sent</strong> shortly!</p>
+ <p><strong>We will email you</strong> when they have been sent.
+ We will also email you when there is a response to any of them, or after {{late_number_of_days}} working days if the authorities still haven't
+ replied by then.</p>
+ <p>If you write about these requests (for example in a forum or a blog) please link to this page.</p>",
+ :law_used_full=>@info_request.law_used_full,
+ :late_number_of_days => AlaveteliConfiguration::reply_late_after_days)
+ redirect_to info_request_batch_path(@info_request_batch)
+ end
+
# Page new form posts to
def new
# All new requests are of normal_sort
@@ -211,71 +300,19 @@ class RequestController < ApplicationController
render :template => 'user/rate_limited'
return
end
-
- params[:info_request] = { } if !params[:info_request]
-
- # Read parameters in - first the public body (by URL name or id)
- if params[:url_name]
- if params[:url_name].match(/^[0-9]+$/)
- params[:info_request][:public_body] = PublicBody.find(params[:url_name])
- else
- public_body = PublicBody.find_by_url_name_with_historic(params[:url_name])
- raise ActiveRecord::RecordNotFound.new("None found") if public_body.nil? # XXX proper 404
- params[:info_request][:public_body] = public_body
- end
- elsif params[:public_body_id]
- params[:info_request][:public_body] = PublicBody.find(params[:public_body_id])
- # Explicitly load the association as this isn't done automatically in newer Rails versions
- elsif params[:info_request][:public_body_id]
- params[:info_request][:public_body] = PublicBody.find(params[:info_request][:public_body_id])
- end
- if !params[:info_request][:public_body]
- # compulsory to have a body by here, or go to front page which is start of process
- redirect_to frontpage_url
- return
- end
-
- # ... next any tags or other things
- params[:info_request][:title] = params[:title] if params[:title]
- params[:info_request][:tag_string] = params[:tags] if params[:tags]
-
- @info_request = InfoRequest.new(params[:info_request])
- params[:info_request_id] = @info_request.id
- params[:outgoing_message] = {} if !params[:outgoing_message]
- params[:outgoing_message][:body] = params[:body] if params[:body]
- params[:outgoing_message][:default_letter] = params[:default_letter] if params[:default_letter]
- params[:outgoing_message][:info_request] = @info_request
- @outgoing_message = OutgoingMessage.new(params[:outgoing_message])
- @outgoing_message.set_signature_name(@user.name) if !@user.nil?
-
- if @info_request.public_body.is_requestable?
- render :action => 'new'
- else
- if @info_request.public_body.not_requestable_reason == 'bad_contact'
- render :action => 'new_bad_contact'
- else
- # if not requestable because defunct or not_apply, redirect to main page
- # (which doesn't link to the /new/ URL)
- redirect_to public_body_url(@info_request.public_body)
- end
- end
- return
+ return render_new_compose(batch=false)
end
# See if the exact same request has already been submitted
# XXX this check should theoretically be a validation rule in the
# model, except we really want to pass @existing_request to the view so
# it can link to it.
- @existing_request = InfoRequest.find_by_existing_request(params[:info_request][:title], params[:info_request][:public_body_id], params[:outgoing_message][:body])
+ @existing_request = InfoRequest.find_existing(params[:info_request][:title], params[:info_request][:public_body_id], params[:outgoing_message][:body])
# Create both FOI request and the first request message
- @info_request = InfoRequest.new(params[:info_request])
- @outgoing_message = OutgoingMessage.new(params[:outgoing_message].merge({
- :status => 'ready',
- :message_type => 'initial_request'
- }))
- @info_request.outgoing_messages << @outgoing_message
- @outgoing_message.info_request = @info_request
+ @info_request = InfoRequest.create_from_attributes(params[:info_request],
+ params[:outgoing_message])
+ @outgoing_message = @info_request.outgoing_messages.first
# Maybe we lost the address while they're writing it
if !@info_request.public_body.is_requestable?
@@ -296,24 +333,7 @@ class RequestController < ApplicationController
# Show preview page, if it is a preview
if params[:preview].to_i == 1
- message = ""
- if @outgoing_message.contains_email?
- if @user.nil?
- message += _("<p>You do not need to include your email in the request in order to get a reply, as we will ask for it on the next screen (<a href=\"{{url}}\">details</a>).</p>", :url => (help_privacy_path+"#email_address").html_safe);
- else
- message += _("<p>You do not need to include your email in the request in order to get a reply (<a href=\"{{url}}\">details</a>).</p>", :url => (help_privacy_path+"#email_address").html_safe);
- end
- message += _("<p>We recommend that you edit your request and remove the email address.
- If you leave it, the email address will be sent to the authority, but will not be displayed on the site.</p>")
- end
- if @outgoing_message.contains_postcode?
- message += _("<p>Your request contains a <strong>postcode</strong>. Unless it directly relates to the subject of your request, please remove any address as it will <strong>appear publicly on the Internet</strong>.</p>");
- end
- if not message.empty?
- flash.now[:error] = message.html_safe
- end
- render :action => 'preview'
- return
+ return render_new_preview
end
if user_exceeded_limit
@@ -669,7 +689,7 @@ class RequestController < ApplicationController
end
if !incoming_message.user_can_view?(authenticated_user)
@incoming_message = incoming_message # used by view
- return render_hidden_message
+ return render_hidden('request/hidden_correspondence')
end
# Is this a completely public request that we can cache attachments for
# to be served up without authentication?
@@ -883,19 +903,10 @@ class RequestController < ApplicationController
private
- def render_hidden
+ def render_hidden(template='request/hidden')
respond_to do |format|
response_code = 403 # forbidden
- format.html{ render :template => 'request/hidden', :status => response_code }
- format.any{ render :nothing => true, :status => response_code }
- end
- false
- end
-
- def render_hidden_message
- respond_to do |format|
- response_code = 403 # forbidden
- format.html{ render :template => 'request/hidden_correspondence', :status => response_code }
+ format.html{ render :template => template, :status => response_code }
format.any{ render :nothing => true, :status => response_code }
end
false
@@ -967,6 +978,103 @@ class RequestController < ApplicationController
"request/similar/#{info_request.id}/#{locale}"
end
+ def check_batch_requests_and_user_allowed
+ if !AlaveteliConfiguration::allow_batch_requests
+ raise RouteNotFound.new("Page not enabled")
+ end
+ if !authenticated?(
+ :web => _("To make a batch request"),
+ :email => _("Then you can make a batch request"),
+ :email_subject => _("Make a batch request"),
+ :user_name => "a user who has been authorised to make batch requests")
+ # do nothing - as "authenticated?" has done the redirect to signin page for us
+ return
+ end
+ if !@user.can_make_batch_requests?
+ return render_hidden('request/batch_not_allowed')
+ end
+ end
+
+ def render_new_compose(batch)
+
+ params[:info_request] = { } if !params[:info_request]
+ # Read parameters in
+ unless batch
+ # first the public body (by URL name or id)
+ if params[:url_name]
+ if params[:url_name].match(/^[0-9]+$/)
+ params[:info_request][:public_body] = PublicBody.find(params[:url_name])
+ else
+ public_body = PublicBody.find_by_url_name_with_historic(params[:url_name])
+ raise ActiveRecord::RecordNotFound.new("None found") if public_body.nil? # XXX proper 404
+ params[:info_request][:public_body] = public_body
+ end
+ elsif params[:public_body_id]
+ params[:info_request][:public_body] = PublicBody.find(params[:public_body_id])
+ # Explicitly load the association as this isn't done automatically in newer Rails versions
+ elsif params[:info_request][:public_body_id]
+ params[:info_request][:public_body] = PublicBody.find(params[:info_request][:public_body_id])
+ end
+ if !params[:info_request][:public_body]
+ # compulsory to have a body by here, or go to front page which is start of process
+ redirect_to frontpage_url
+ return
+ end
+ end
+
+ # ... next any tags or other things
+ params[:info_request][:title] = params[:title] if params[:title]
+ params[:info_request][:tag_string] = params[:tags] if params[:tags]
+
+ @info_request = InfoRequest.new(params[:info_request])
+ if batch
+ @info_request.is_batch_request_template = true
+ end
+ params[:info_request_id] = @info_request.id
+ params[:outgoing_message] = {} if !params[:outgoing_message]
+ params[:outgoing_message][:body] = params[:body] if params[:body]
+ params[:outgoing_message][:default_letter] = params[:default_letter] if params[:default_letter]
+ params[:outgoing_message][:info_request] = @info_request
+ @outgoing_message = OutgoingMessage.new(params[:outgoing_message])
+ @outgoing_message.set_signature_name(@user.name) if !@user.nil?
+
+ if batch
+ render :action => 'new'
+ else
+ if @info_request.public_body.is_requestable?
+ render :action => 'new'
+ else
+ if @info_request.public_body.not_requestable_reason == 'bad_contact'
+ render :action => 'new_bad_contact'
+ else
+ # if not requestable because defunct or not_apply, redirect to main page
+ # (which doesn't link to the /new/ URL)
+ redirect_to public_body_url(@info_request.public_body)
+ end
+ end
+ end
+ return
+ end
+
+ def render_new_preview
+ message = ""
+ if @outgoing_message.contains_email?
+ if @user.nil?
+ message += _("<p>You do not need to include your email in the request in order to get a reply, as we will ask for it on the next screen (<a href=\"{{url}}\">details</a>).</p>", :url => (help_privacy_path+"#email_address").html_safe);
+ else
+ message += _("<p>You do not need to include your email in the request in order to get a reply (<a href=\"{{url}}\">details</a>).</p>", :url => (help_privacy_path+"#email_address").html_safe);
+ end
+ message += _("<p>We recommend that you edit your request and remove the email address.
+ If you leave it, the email address will be sent to the authority, but will not be displayed on the site.</p>")
+ end
+ if @outgoing_message.contains_postcode?
+ message += _("<p>Your request contains a <strong>postcode</strong>. Unless it directly relates to the subject of your request, please remove any address as it will <strong>appear publicly on the Internet</strong>.</p>");
+ end
+ if not message.empty?
+ flash.now[:error] = message.html_safe
+ end
+ render :action => 'preview'
+ end
end
diff --git a/app/controllers/track_controller.rb b/app/controllers/track_controller.rb
index 1123903f9..83e05ebbc 100644
--- a/app/controllers/track_controller.rb
+++ b/app/controllers/track_controller.rb
@@ -116,7 +116,7 @@ class TrackController < ApplicationController
# Generic request tracker - set @track_thing before calling
def track_set
if @user
- @existing_track = TrackThing.find_by_existing_track(@user, @track_thing)
+ @existing_track = TrackThing.find_existing(@user, @track_thing)
if @existing_track
flash[:notice] = _("You are already following updates about {{track_description}}", :track_description => @track_thing.params[:list_description])
return true
diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb
index 175425280..8d6522923 100644
--- a/app/controllers/user_controller.rb
+++ b/app/controllers/user_controller.rb
@@ -26,12 +26,15 @@ class UserController < ApplicationController
if params[:view].nil?
@show_requests = true
@show_profile = true
+ @show_batches = false
elsif params[:view] == 'profile'
@show_profile = true
@show_requests = false
+ @show_batches = false
elsif params[:view] == 'requests'
@show_profile = false
@show_requests = true
+ @show_batches = true
end
@display_user = User.find(:first, :conditions => [ "url_name = ? and email_confirmed = ?", params[:url_name], true ])
diff --git a/app/mailers/info_request_batch_mailer.rb b/app/mailers/info_request_batch_mailer.rb
new file mode 100644
index 000000000..a2becfb24
--- /dev/null
+++ b/app/mailers/info_request_batch_mailer.rb
@@ -0,0 +1,25 @@
+# models/info_request_batch_mailer.rb:
+# Emails relating to user accounts. e.g. Confirming a new account
+#
+# Copyright (c) 2013 UK Citizens Online Democracy. All rights reserved.
+# Email: hello@mysociety.org; WWW: http://www.mysociety.org/
+
+class InfoRequestBatchMailer < ApplicationMailer
+
+ def batch_sent(info_request_batch, unrequestable, user)
+ @info_request_batch, @unrequestable = info_request_batch, unrequestable
+ headers('Return-Path' => blackhole_email, 'Reply-To' => contact_from_name_and_email)
+
+ # Make a link going to the info request batch page, which logs the user in.
+ post_redirect = PostRedirect.new(
+ :uri => info_request_batch_url(@info_request_batch),
+ :user_id => info_request_batch.user_id)
+ post_redirect.save!
+ @url = confirm_url(:email_token => post_redirect.email_token)
+
+ mail(:from => contact_from_name_and_email,
+ :to => user.name_and_email,
+ :subject => _("Your batch request \"{{title}}\" has been sent",
+ :title => info_request_batch.title))
+ end
+end
diff --git a/app/models/comment.rb b/app/models/comment.rb
index 75d37e04f..b4c099123 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -62,7 +62,7 @@ class Comment < ActiveRecord::Base
end
# When posting a new comment, use this to check user hasn't double submitted.
- def Comment.find_by_existing_comment(info_request_id, body)
+ def Comment.find_existing(info_request_id, body)
# XXX can add other databases here which have regexp_replace
if ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
# Exclude spaces from the body comparison using regexp_replace
diff --git a/app/models/info_request.rb b/app/models/info_request.rb
index def319ad4..47ad435cb 100644
--- a/app/models/info_request.rb
+++ b/app/models/info_request.rb
@@ -1,5 +1,6 @@
# encoding: utf-8
# == Schema Information
+# Schema version: 20131024114346
#
# Table name: info_requests
#
@@ -21,6 +22,7 @@
# external_url :string(255)
# attention_requested :boolean default(FALSE)
# comments_allowed :boolean default(TRUE), not null
+# info_request_batch_id :integer
#
require 'digest/sha1'
@@ -40,7 +42,8 @@ class InfoRequest < ActiveRecord::Base
validate :must_be_internal_or_external
belongs_to :public_body, :counter_cache => true
- validates_presence_of :public_body_id
+ belongs_to :info_request_batch
+ validates_presence_of :public_body_id, :unless => Proc.new { |info_request| info_request.is_batch_request_template? }
has_many :outgoing_messages, :order => 'created_at'
has_many :incoming_messages, :order => 'created_at'
@@ -50,6 +53,7 @@ class InfoRequest < ActiveRecord::Base
has_many :comments, :order => 'created_at'
has_many :censor_rules, :order => 'created_at desc'
has_many :mail_server_logs, :order => 'mail_server_log_done_id'
+ attr_accessor :is_batch_request_template
has_tag_string
@@ -126,6 +130,10 @@ class InfoRequest < ActiveRecord::Base
!InfoRequest.enumerate_states.include? described_state
end
+ def is_batch_request_template?
+ is_batch_request_template == true
+ end
+
# The request must either be internal, in which case it has
# a foreign key reference to a User object and no external_url or external_user_name,
# or else be external in which case it has no user_id but does have an external_url,
@@ -383,7 +391,7 @@ public
# repeated requests, say once a quarter for time information, then might need to do that.
# XXX this *should* also check outgoing message joined to is an initial
# request (rather than follow up)
- def InfoRequest.find_by_existing_request(title, public_body_id, body)
+ def InfoRequest.find_existing(title, public_body_id, body)
return InfoRequest.find(:first, :conditions => [ "title = ? and public_body_id = ? and outgoing_messages.body = ?", title, public_body_id, body ], :include => [ :outgoing_messages ] )
end
@@ -932,6 +940,20 @@ public
self.idhash = InfoRequest.hash_from_id(self.id)
end
+ def InfoRequest.create_from_attributes(info_request_atts, outgoing_message_atts, user=nil)
+ info_request = new(info_request_atts)
+ default_message_params = {
+ :status => 'ready',
+ :message_type => 'initial_request',
+ :what_doing => 'normal_sort'
+ }
+ outgoing_message = OutgoingMessage.new(outgoing_message_atts.merge(default_message_params))
+ info_request.outgoing_messages << outgoing_message
+ outgoing_message.info_request = info_request
+ info_request.user = user
+ info_request
+ end
+
def InfoRequest.hash_from_id(id)
return Digest::SHA1.hexdigest(id.to_s + AlaveteliConfiguration::incoming_email_secret)[0,8]
end
@@ -1078,7 +1100,10 @@ public
# Get the list of censor rules that apply to this request
def applicable_censor_rules
- applicable_rules = [self.censor_rules, self.public_body.censor_rules, CensorRule.global.all]
+ applicable_rules = [self.censor_rules, CensorRule.global.all]
+ unless is_batch_request_template?
+ applicable_rules << self.public_body.censor_rules
+ end
if self.user && !self.user.censor_rules.empty?
applicable_rules << self.user.censor_rules
end
diff --git a/app/models/info_request_batch.rb b/app/models/info_request_batch.rb
new file mode 100644
index 000000000..498ab4951
--- /dev/null
+++ b/app/models/info_request_batch.rb
@@ -0,0 +1,73 @@
+# == Schema Information
+# Schema version: 20131024114346
+#
+# Table name: info_request_batches
+#
+# id :integer not null, primary key
+# title :text not null
+# user_id :integer not null
+# created_at :datetime
+# updated_at :datetime
+#
+
+class InfoRequestBatch < ActiveRecord::Base
+ has_many :info_requests
+ belongs_to :user
+ has_and_belongs_to_many :public_bodies
+
+ validates_presence_of :user
+ validates_presence_of :title
+ validates_presence_of :body
+
+ # When constructing a new batch, use this to check user hasn't double submitted.
+ def InfoRequestBatch.find_existing(user, title, body, public_body_ids)
+ find(:first, :conditions => ['user_id = ?
+ AND title = ?
+ AND body = ?
+ AND info_request_batches_public_bodies.public_body_id in (?)',
+ user, title, body, public_body_ids],
+ :include => :public_bodies)
+ end
+
+ # Create a batch of information requests, returning a list of public bodies
+ # that are unrequestable from the initial list of public body ids passed.
+ def create_batch!
+ unrequestable = []
+ created = []
+ ActiveRecord::Base.transaction do
+ public_bodies.each do |public_body|
+ if public_body.is_requestable?
+ created << create_request!(public_body)
+ else
+ unrequestable << public_body
+ end
+ end
+ self.sent_at = Time.now
+ self.save!
+ end
+ created.each{ |info_request| info_request.outgoing_messages.first.send_message }
+
+ return unrequestable
+ end
+
+ # Create and send an FOI request to a public body
+ def create_request!(public_body)
+ body = OutgoingMessage.fill_in_salutation(self.body, public_body)
+ info_request = InfoRequest.create_from_attributes({:title => self.title},
+ {:body => body},
+ self.user)
+ info_request.public_body_id = public_body.id
+ info_request.info_request_batch = self
+ info_request.save!
+ info_request
+ end
+
+ def InfoRequestBatch.send_batches()
+ find_each(:conditions => "sent_at IS NULL") do |info_request_batch|
+ unrequestable = info_request_batch.create_batch!
+ mail_message = InfoRequestBatchMailer.batch_sent(info_request_batch,
+ unrequestable,
+ info_request_batch.user).deliver
+ end
+ end
+end
diff --git a/app/models/outgoing_message.rb b/app/models/outgoing_message.rb
index 6efc1d2ba..a435511d3 100644
--- a/app/models/outgoing_message.rb
+++ b/app/models/outgoing_message.rb
@@ -1,4 +1,5 @@
# == Schema Information
+# Schema version: 20131024114346
#
# Table name: outgoing_messages
#
@@ -67,15 +68,30 @@ class OutgoingMessage < ActiveRecord::Base
# How the default letter starts and ends
def get_salutation
+ if self.info_request.is_batch_request_template?
+ return OutgoingMessage.placeholder_salutation
+ end
ret = ""
if self.message_type == 'followup' && !self.incoming_message_followup.nil? && !self.incoming_message_followup.safe_mail_from.nil? && self.incoming_message_followup.valid_to_reply_to?
ret = ret + OutgoingMailer.name_for_followup(self.info_request, self.incoming_message_followup)
else
- ret = ret + self.info_request.public_body.name
+ return OutgoingMessage.default_salutation(self.info_request.public_body)
end
salutation = _("Dear {{public_body_name}},", :public_body_name => ret)
end
+ def OutgoingMessage.default_salutation(public_body)
+ _("Dear {{public_body_name}},", :public_body_name => public_body.name)
+ end
+
+ def OutgoingMessage.placeholder_salutation
+ _("Dear [Authority name],")
+ end
+
+ def OutgoingMessage.fill_in_salutation(body, public_body)
+ body.gsub(placeholder_salutation, default_salutation(public_body))
+ end
+
def get_signoff
if self.message_type == 'followup' && !self.incoming_message_followup.nil? && !self.incoming_message_followup.safe_mail_from.nil? && self.incoming_message_followup.valid_to_reply_to?
return _("Yours sincerely,")
diff --git a/app/models/public_body.rb b/app/models/public_body.rb
index a78a6677e..7b1ded820 100644
--- a/app/models/public_body.rb
+++ b/app/models/public_body.rb
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# == Schema Information
+# Schema version: 20131024114346
#
# Table name: public_bodies
#
diff --git a/app/models/track_thing.rb b/app/models/track_thing.rb
index d5e1cdb75..d5dda7bb5 100644
--- a/app/models/track_thing.rb
+++ b/app/models/track_thing.rb
@@ -311,7 +311,7 @@ class TrackThing < ActiveRecord::Base
end
# When constructing a new track, use this to avoid duplicates / double posting
- def TrackThing.find_by_existing_track(tracking_user, track)
+ def TrackThing.find_existing(tracking_user, track)
if tracking_user.nil?
return nil
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 2c4f87944..e63ce8129 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,4 +1,5 @@
# == Schema Information
+# Schema version: 20131024114346
#
# Table name: users
#
@@ -20,6 +21,7 @@
# email_bounce_message :text default(""), not null
# no_limit :boolean default(FALSE), not null
# receive_email_alerts :boolean default(TRUE), not null
+# can_make_batch_requests :boolean default(FALSE), not null
#
require 'digest/sha1'
@@ -40,6 +42,7 @@ class User < ActiveRecord::Base
has_many :comments, :order => 'created_at desc'
has_one :profile_photo
has_many :censor_rules, :order => 'created_at desc'
+ has_many :info_request_batches, :order => 'created_at desc'
attr_accessor :password_confirmation, :no_xapian_reindex
validates_confirmation_of :password, :message => _("Please enter the same password twice")
@@ -269,6 +272,9 @@ class User < ActiveRecord::Base
# Some users have no limit
return false if self.no_limit
+ # Batch request users don't have a limit
+ return false if self.can_make_batch_requests?
+
# Has the user issued as many as MAX_REQUESTS_PER_USER_PER_DAY requests in the past 24 hours?
return false if AlaveteliConfiguration::max_requests_per_user_per_day.blank?
recent_requests = InfoRequest.count(:conditions => ["user_id = ? and created_at > now() - '1 day'::interval", self.id])
diff --git a/app/views/admin_user/_form.html.erb b/app/views/admin_user/_form.html.erb
index e7175d09c..f1edc0927 100644
--- a/app/views/admin_user/_form.html.erb
+++ b/app/views/admin_user/_form.html.erb
@@ -64,3 +64,12 @@
</div>
</div>
</div>
+<div class="control-group">
+ <label for="admin_user_can_make_batch_requests" class="control-label">Can make batch requests</label>
+ <div class="controls">
+ <%= check_box 'admin_user', 'can_make_batch_requests' %>
+ <div class="help-block">
+ allows the user to send a request to multiple authorities at once
+ </div>
+ </div>
+</div>
diff --git a/app/views/comment/_comment_form.html.erb b/app/views/comment/_comment_form.html.erb
index b78532768..6ca3f4c9f 100644
--- a/app/views/comment/_comment_form.html.erb
+++ b/app/views/comment/_comment_form.html.erb
@@ -3,7 +3,7 @@
<%= f.text_area :body, :rows => 10, :cols => 55 %>
</p>
- <% if !TrackThing.find_by_existing_track(@user, track_thing) && (!@user || @info_request.user != @user) %>
+ <% if !TrackThing.find_existing(@user, track_thing) && (!@user || @info_request.user != @user) %>
<p>
<%= check_box_tag 'subscribe_to_request', "1", params[:subscribe_to_request] ? true : false %> <label for="subscribe_to_request"><%= _('Email me future updates to this request') %></label>
</p>
diff --git a/app/views/info_request_batch/_info_request_batch.html.erb b/app/views/info_request_batch/_info_request_batch.html.erb
new file mode 100644
index 000000000..86ef90654
--- /dev/null
+++ b/app/views/info_request_batch/_info_request_batch.html.erb
@@ -0,0 +1,15 @@
+<div class="request_listing">
+ <div class="request_left">
+ <span class="head">
+ <%= link_to highlight_words(info_request_batch.title, @highlight_words), info_request_batch_path(info_request_batch) %>
+ </span>
+ <div class="requester">
+ <%= _('Batch created by {{info_request_user}} on {{date}}.', :info_request_user => user_link_absolute(info_request_batch.user),:date=>simple_date(info_request_batch.created_at)) %>
+ </div>
+ </div>
+ <div class="request_right">
+ <span class="desc">
+ <%= excerpt(info_request_batch.body, '', :radius => 150) %>
+ </span>
+ </div>
+</div>
diff --git a/app/views/info_request_batch/show.html.erb b/app/views/info_request_batch/show.html.erb
new file mode 100644
index 000000000..aaecdd45d
--- /dev/null
+++ b/app/views/info_request_batch/show.html.erb
@@ -0,0 +1,25 @@
+<% @title = _("{{title}} - a batch request", :title => @info_request_batch.title) %>
+<h1><%= @title %></h1>
+<% if @info_request_batch.sent_at %>
+ <%= n_('Sent to one authority by {{info_request_user}} on {{date}}.', 'Sent to {{authority_count}} authorities by {{info_request_user}} on {{date}}.', @info_request_batch.info_requests.size, :authority_count=> @info_request_batch.info_requests.size, :info_request_user => user_link(@info_request_batch.user), :date => simple_date(@info_request_batch.sent_at)) %>
+ <div class="results_section">
+ <div class="results_block">
+ <% @info_requests.each do |info_request| %>
+ <%= render :partial => 'request/request_listing_via_event', :locals => { :event => info_request.last_event_forming_initial_request, :info_request => info_request } %>
+ <% end %>
+ </div>
+ <%= will_paginate WillPaginate::Collection.new(@page, @per_page, @info_request_batch.info_requests.visible.count) %>
+ </div>
+
+<% else %>
+ <%= _('Created by {{info_request_user}} on {{date}}.', :info_request_user => user_link(@info_request_batch.user), :date => simple_date(@info_request_batch.created_at)) %>
+ <%= _('Requests will be sent to the following bodies:') %>
+ <div class="results_section">
+ <div class="results_block">
+ <%= render :partial => 'public_body/body_listing', :locals => { :public_bodies => @public_bodies } %>
+ </div>
+ <%= will_paginate WillPaginate::Collection.new(@page, @per_page, @info_request_batch.public_bodies.count) %>
+ </div>
+
+<% end %>
+
diff --git a/app/views/info_request_batch_mailer/batch_sent.text.erb b/app/views/info_request_batch_mailer/batch_sent.text.erb
new file mode 100644
index 000000000..25fb7d06a
--- /dev/null
+++ b/app/views/info_request_batch_mailer/batch_sent.text.erb
@@ -0,0 +1,15 @@
+<%= _('Your batch request "{{title}}" has been sent', :title => @info_request_batch.title) %>
+
+
+<%= _('Follow this link to see the requests:')%>
+
+<%= @url %>
+
+<% if !@unrequestable.empty? %>
+<%= _('Unfortunately, we do not have a working address for {{public_body_names}}.', :public_body_names => @unrequestable.map{|body| body.name}.join(",")) %>
+<%= _('You may be able to find one on their website, or by phoning them up and asking. If you manage to find one, then please send it to us:') %>
+
+<%= help_contact_url %>
+
+<% end %>
+-- <%= _('the {{site_name}} team', :site_name => site_name) %>
diff --git a/app/views/request/batch_not_allowed.html.erb b/app/views/request/batch_not_allowed.html.erb
new file mode 100644
index 000000000..156fa9ae1
--- /dev/null
+++ b/app/views/request/batch_not_allowed.html.erb
@@ -0,0 +1 @@
+<%= _('Users cannot usually make batch requests to multiple authorities at once because we don’t want public authorities to be bombarded with large numbers of inappropriate requests. Please <a href="{{url}}">contact us</a> if you think you have good reason to send the same request to multiple authorities at once.', :url => help_contact_path.html_safe) %>
diff --git a/app/views/request/new.html.erb b/app/views/request/new.html.erb
index 849a94216..7f1332464 100644
--- a/app/views/request/new.html.erb
+++ b/app/views/request/new.html.erb
@@ -1,23 +1,27 @@
-<script type="text/javascript">
- $(document).ready(function(){
- // Avoid triggering too often (on each keystroke) by using the debounce jQuery plugin:
- // http://benalman.com/projects/jquery-throttle-debounce-plugin/
- $("#typeahead_search").keypress($.debounce( 300, function() {
- $("#typeahead_response").load("<%=search_ahead_url%>?q="+encodeURI(this.value), function() {
- // When following links in typeahead results, open new tab/window
- $("#typeahead_response a").attr("target","_blank");
-
- // Update the public body site search link
- $("#body-site-search-link").attr("href", "http://www.google.com/#q="+encodeURI($("#typeahead_search").val())+
- "+site:<%= @info_request.public_body.calculated_home_page %>");
- });
- }));
-
- });
-</script>
-
-<% @title = _("Make an {{law_used_short}} request to '{{public_body_name}}'",:law_used_short=>h(@info_request.law_used_short),:public_body_name=>h(@info_request.public_body.name)) %>
-
+<% unless @batch %>
+ <script type="text/javascript">
+ $(document).ready(function(){
+ // Avoid triggering too often (on each keystroke) by using the debounce jQuery plugin:
+ // http://benalman.com/projects/jquery-throttle-debounce-plugin/
+ $("#typeahead_search").keypress($.debounce( 300, function() {
+ $("#typeahead_response").load("<%=search_ahead_url%>?q="+encodeURI(this.value), function() {
+ // When following links in typeahead results, open new tab/window
+ $("#typeahead_response a").attr("target","_blank");
+
+ // Update the public body site search link
+ $("#body-site-search-link").attr("href", "http://www.google.com/#q="+encodeURI($("#typeahead_search").val())+
+ "+site:<%= @info_request.public_body.calculated_home_page %>");
+ });
+ }));
+
+ });
+ </script>
+<% end %>
+<% if @batch %>
+ <% @title = _("Make an {{law_used_short}} request", :law_used_short=>h(@info_request.law_used_short)) %>
+<% else %>
+ <% @title = _("Make an {{law_used_short}} request to '{{public_body_name}}'",:law_used_short=>h(@info_request.law_used_short),:public_body_name=>h(@info_request.public_body.name)) %>
+<% end %>
<h1><%= _('2. Ask for Information') %></h1>
<% if @existing_request %>
@@ -29,53 +33,82 @@
</li>
</ul></div>
<% end %>
+ <% if @existing_batch %>
+ <div class="errorExplanation" id="errorExplanation"><ul>
+ <li>
+ <%= _('You already created the same batch of requests on {{date}}. You can either view the <a href="{{existing_batch}}">existing batch</a>, or edit the details below to make a new but similar batch of requests.', :date=>simple_date(@existing_batch.created_at), :existing_batch=>info_request_batch_path(@existing_batch)) %>
+ </li>
+ </ul></div>
+ <% end %>
<%= foi_error_messages_for :info_request, :outgoing_message %>
- <%= form_for(@info_request, :url => new_request_path, :html => { :id => 'write_form' } ) do |f| %>
+ <%= form_for(@info_request, :url => (@batch ? new_batch_path : new_request_path), :html => { :id => 'write_form' } ) do |f| %>
<div id="request_header">
<div id="request_header_body">
<label class="form_label"><%= _('To:') %></label>
- <span id="to_public_body"><%=h(@info_request.public_body.name)%></span>
- <div class="form_item_note">
- <% if @info_request.public_body.info_requests.size > 0 %>
- <%= _("Browse <a href='{{url}}'>other requests</a> to '{{public_body_name}}' for examples of how to word your request.", :public_body_name=>h(@info_request.public_body.name), :url=>public_body_path(@info_request.public_body)) %>
- <% else %>
- <%= _("Browse <a href='{{url}}'>other requests</a> for examples of how to word your request.", :url=>request_list_url) %>
- <% end %>
- </div>
- <% if @info_request.public_body.has_notes? %>
- <div id="request_header_text">
- <h3><%= _('Special note for this authority!') %></h3>
- <p><%= @info_request.public_body.notes_as_html.html_safe %></p>
- </div>
+ <% if @batch %>
+ <span id="to_public_body">
+ <%= _("Your selected authorities") %>
+ <span class="batch_public_body_toggle" data-hidetext="<%= _("(hide)") %>" data-showtext="<%= _("(show)") %>"><a class="toggle-message"></a></span>
+ </span>
+
+ <div class="batch_public_body_list">
+ <ul>
+ <% @public_bodies.each do |public_body| %>
+ <li><%= public_body.name %></li>
+ <% end %>
+ </ul>
+ </div>
+
+ <% else %>
+ <span id="to_public_body">
+ <%=h(@info_request.public_body.name)%>
+ </span>
<% end %>
- <% if @info_request.public_body.eir_only? %>
- <h3><%= _('Please ask for environmental information only') %></h3>
+ <% unless @batch %>
+ <div class="form_item_note">
+ <% if @info_request.public_body.info_requests.size > 0 %>
+ <%= _("Browse <a href='{{url}}'>other requests</a> to '{{public_body_name}}' for examples of how to word your request.", :public_body_name=>h(@info_request.public_body.name), :url=>public_body_path(@info_request.public_body)) %>
+ <% else %>
+ <%= _("Browse <a href='{{url}}'>other requests</a> for examples of how to word your request.", :url=>request_list_url) %>
+ <% end %>
+ </div>
+
+ <% if @info_request.public_body.has_notes? %>
+ <div id="request_header_text">
+ <h3><%= _('Special note for this authority!') %></h3>
+ <p><%= @info_request.public_body.notes_as_html.html_safe %></p>
+ </div>
+ <% end %>
+
+ <% if @info_request.public_body.eir_only? %>
+ <h3><%= _('Please ask for environmental information only') %></h3>
- <p><%= _('The Freedom of Information Act <strong>does not apply</strong> to') %> <%=h(@info_request.public_body.name)%>.
- <%= _('However, you have the right to request environmental
+ <p><%= _('The Freedom of Information Act <strong>does not apply</strong> to') %> <%=h(@info_request.public_body.name)%>.
+ <%= _('However, you have the right to request environmental
information under a different law') %> (<a href="/help/requesting#eir">explanation</a>).
- <%= _('This covers a very wide spectrum of information about the state of
+ <%= _('This covers a very wide spectrum of information about the state of
the <strong>natural and built environment</strong>, such as:') %>
- <ul>
- <li><%= _('Air, water, soil, land, flora and fauna (including how these effect
+ <ul>
+ <li><%= _('Air, water, soil, land, flora and fauna (including how these effect
human beings)') %></li>
- <li><%= _('Information on emissions and discharges (e.g. noise, energy,
+ <li><%= _('Information on emissions and discharges (e.g. noise, energy,
radiation, waste materials)') %></li>
- <li><%= _('Human health and safety') %></li>
- <li><%= _('Cultural sites and built structures (as they may be affected by the
+ <li><%= _('Human health and safety') %></li>
+ <li><%= _('Cultural sites and built structures (as they may be affected by the
environmental factors listed above)') %></li>
- <li><%= _('Plans and administrative measures that affect these matters') %></li>
- </ul>
+ <li><%= _('Plans and administrative measures that affect these matters') %></li>
+ </ul>
- <p><%= _('Please only request information that comes under those categories, <strong>do not waste your
+ <p><%= _('Please only request information that comes under those categories, <strong>do not waste your
time</strong> or the time of the public authority by requesting unrelated information.') %></p>
- <% end %>
+ <% end %>
+ <% end %>
</div>
<div id="request_header_subject">
@@ -132,7 +165,13 @@
</p>
<div class="form_button">
- <%= f.hidden_field(:public_body_id, { :value => @info_request.public_body_id } ) %>
+ <% if @batch %>
+ <% params[:public_body_ids].each do |public_body_id| %>
+ <%= hidden_field_tag("public_body_ids[]", public_body_id)%>
+ <% end %>
+ <% else %>
+ <%= f.hidden_field(:public_body_id, { :value => @info_request.public_body_id } ) %>
+ <% end %>
<%= hidden_field_tag(:submitted_new_request, 1 ) %>
<%= hidden_field_tag(:preview, 1 ) %>
<%= submit_tag _("Preview your public request") %>
@@ -150,5 +189,6 @@
</div>
<% end %>
-
-
+<% if @batch %>
+ <%= javascript_include_tag 'new-request.js' %>
+<% end %>
diff --git a/app/views/request/preview.html.erb b/app/views/request/preview.html.erb
index 243dc90a9..0265d0328 100644
--- a/app/views/request/preview.html.erb
+++ b/app/views/request/preview.html.erb
@@ -1,6 +1,9 @@
-<% @title = "Preview new " + h(@info_request.law_used_short) + " request to '" + h(@info_request.public_body.name) + "'" %>
-
-<%= form_for(@info_request, :url => new_request_path, :html => { :id => 'preview_form' } ) do |f| %>
+<% if @batch %>
+ <% @title = _("Preview new {{law_used_short}} request", :law_used_short => h(@info_request.law_used_short)) %>
+<% else %>
+ <% @title = _("Preview new {{law_used_short}} request to '{{public_body_name}}", :law_used_short => h(@info_request.law_used_short), :public_body_name => h(@info_request.public_body.name)) %>
+<% end %>
+<%= form_for(@info_request, :url => (@batch ? new_batch_path : new_request_path), :html => { :id => 'preview_form' } ) do |f| %>
<h1><%= _('3. Now check your request') %></h1>
<ul>
@@ -14,7 +17,12 @@
<div class="correspondence" id="outgoing-0">
<p class="preview_subject">
- <strong><%= _('To:') %></strong> <%=h @info_request.public_body.name %>
+ <strong><%= _('To:') %></strong>
+ <% if @batch %>
+ <%= _("Your selected authorities")%>
+ <% else %>
+ <%=h(@info_request.public_body.name)%>
+ <% end %>
<br><strong><%= _('Subject:') %></strong> <%=h @info_request.email_subject_request %>
</p>
@@ -33,7 +41,13 @@
<p>
<%= f.hidden_field(:title) %>
- <%= f.hidden_field(:public_body_id, { :value => @info_request.public_body_id } ) %>
+ <% if @batch %>
+ <% params[:public_body_ids].each do |public_body_id| %>
+ <%= hidden_field_tag("public_body_ids[]", public_body_id)%>
+ <% end %>
+ <% else %>
+ <%= f.hidden_field(:public_body_id, { :value => @info_request.public_body_id } ) %>
+ <% end %>
<%= f.hidden_field(:tag_string) %>
<%= hidden_field_tag(:submitted_new_request, 1) %>
<%= hidden_field_tag(:preview, 0 ) %>
diff --git a/app/views/request/select_authorities.html.erb b/app/views/request/select_authorities.html.erb
new file mode 100644
index 000000000..e16bcc191
--- /dev/null
+++ b/app/views/request/select_authorities.html.erb
@@ -0,0 +1,77 @@
+<% @title = _("Select the authorities to write to") %>
+<h1><%= _('1. Select authorities') %></h1>
+
+<p>
+ <%= _("Search for the authorities you'd like information from:") %>
+</p>
+
+<div>
+ <%= form_tag(select_authorities_path, {:method => 'get', :id => 'body_search_form', :remote => true, "data-type" => 'json'}) do %>
+ <%= text_field_tag 'public_body_query', params[:public_body_query], { :size => 30, :title => "type your search term here" } %>
+ <% if !@public_bodies.blank? %>
+ <%- @public_bodies.each do |public_body| %>
+ <%= hidden_field_tag "public_body_ids[]", public_body.id, {:id => nil} %>
+ <%- end %>
+ <% end %>
+ <% end %>
+</div>
+
+<div id="body_selection">
+ <div id="body_lists">
+ <div id="body_candidates" class="body_list">
+ <%= form_tag(select_authorities_path, {:id => "body_select_form"}) do %>
+ <%= submit_tag _(' >> '), :id => 'body_select_all_button', :class => 'select_all_button' %>
+ <%= submit_tag _(' > '), :id => 'body_select_button' %>
+ <%= hidden_field_tag "public_body_query", params[:public_body_query], { :id => 'public_body_select_query' } %>
+ <% if !@public_bodies.blank? %>
+ <% @public_bodies.each do |public_body| %>
+ <%= hidden_field_tag "public_body_ids[]", public_body.id, {:id => nil} %>
+ <% end %>
+ <% end %>
+ <select multiple name="public_body_ids[]" id="select_body_candidates" class="body_select" size="15">
+ <% if @search_bodies %>
+ <% @search_bodies.results.each do |result| %>
+ <% unless (@public_bodies && @public_bodies.include?(result[:model])) %>
+ <option value="<%= result[:model].id %>"><%= result[:model].name %></option>
+ <% end %>
+ <% end %>
+ <% end %>
+ </select>
+ <% end %>
+ </div>
+
+ <div id="body_selections" class="body_list">
+ <%= form_tag(select_authorities_path, {:id => "body_deselect_form"}) do %>
+
+ <%= submit_tag _(' < '), :id => 'body_deselect_button' %>
+ <%= submit_tag _(' << '), :id => 'body_deselect_all_button', :class => 'select_all_button' %>
+ <%= hidden_field_tag "public_body_query", params[:public_body_query], { :id => 'public_body_deselect_query' } %>
+ <% if @public_bodies %>
+ <% @public_bodies.each do |public_body| %>
+ <%= hidden_field_tag "public_body_ids[]", public_body.id, {:id => nil} %>
+ <% end %>
+ <% end %>
+ <select multiple name="remove_public_body_ids[]" id="select_body_selections" class="body_select" size="15">
+ <% if @public_bodies %>
+ <% @public_bodies.each do |public_body| %>
+ <option value="<%= public_body.id %>"><%= public_body.name %></option>
+ <% end %>
+ <% end %>
+ </select>
+ <% end %>
+
+ <div id="body_submission">
+ <%= form_tag(new_batch_path, {:id => "body_submit_form"}) do %>
+ <% if @public_bodies %>
+ <% @public_bodies.each do |public_body| %>
+ <%= hidden_field_tag "public_body_ids[]", public_body.id , {:id => nil} %>
+ <% end %>
+ <% end %>
+ <%= submit_tag _('Make a request to these authorities'), :id => 'body_submit_button' %>
+ <% end %>
+ </div>
+
+ </div>
+ </div>
+</div>
+<%= javascript_include_tag 'jquery_ujs.js', 'select-authorities.js' %>
diff --git a/app/views/request/select_authority.html.erb b/app/views/request/select_authority.html.erb
index 4f117ee75..83abdb184 100644
--- a/app/views/request/select_authority.html.erb
+++ b/app/views/request/select_authority.html.erb
@@ -40,6 +40,13 @@
<%= hidden_field_tag 'bodies', 1 %>
<%= submit_tag _('Search') %>
</div>
+ <% if AlaveteliConfiguration.allow_batch_requests && @user && @user.can_make_batch_requests? %>
+ <div id="batch_request_link">
+ <p>
+ <%= _('Or make a <a href="{{url}}">batch request</a> to <strong>multiple authorities</strong> at once.', :url => select_authorities_path) %>
+ </p>
+ </div>
+ <% end %>
<% end %>
<div id="typeahead_response">
diff --git a/app/views/track/_tracking_links.html.erb b/app/views/track/_tracking_links.html.erb
index a3cd8fc60..5419ec605 100644
--- a/app/views/track/_tracking_links.html.erb
+++ b/app/views/track/_tracking_links.html.erb
@@ -1,6 +1,6 @@
<%
if @user
- existing_track = TrackThing.find_by_existing_track(@user, track_thing)
+ existing_track = TrackThing.find_existing(@user, track_thing)
end
%>
diff --git a/app/views/user/show.html.erb b/app/views/user/show.html.erb
index c9862effe..76ecdeda0 100644
--- a/app/views/user/show.html.erb
+++ b/app/views/user/show.html.erb
@@ -105,6 +105,17 @@
<div style="clear:both"></div>
<% end %>
+<% if @show_batches %>
+
+ <% if @is_you && !@display_user.info_request_batches.empty? %>
+ <h2 class="batch_results" id="batch_requests">
+ <%= n_('Your {{count}} batch requests', 'Your {{count}} batch requests', @display_user.info_request_batches.size, :count => @display_user.info_request_batches.size) %>
+ </h2>
+ <%= render :partial => 'info_request_batch/info_request_batch', :collection => @display_user.info_request_batches %>
+ <% end %>
+
+<% end %>
+
<% if @show_requests %>
<div id="user_profile_search">
<%= form_tag(show_user_url, :method => "get", :id=>"search_form") do %>