aboutsummaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/assets/stylesheets/responsive/_global_style.scss3
-rw-r--r--app/assets/stylesheets/responsive/_new_request_layout.scss5
-rw-r--r--app/assets/stylesheets/responsive/_user_layout.scss5
-rw-r--r--app/controllers/general_controller.rb2
-rw-r--r--app/models/censor_rule.rb6
-rw-r--r--app/models/outgoing_message.rb216
-rw-r--r--app/models/public_body.rb20
-rw-r--r--app/views/admin_public_body/import_csv.html.erb18
8 files changed, 162 insertions, 113 deletions
diff --git a/app/assets/stylesheets/responsive/_global_style.scss b/app/assets/stylesheets/responsive/_global_style.scss
index 290591b5f..af25fb0b0 100644
--- a/app/assets/stylesheets/responsive/_global_style.scss
+++ b/app/assets/stylesheets/responsive/_global_style.scss
@@ -17,6 +17,9 @@ a {
&:focus {
color: #333333;
}
+ &:visited {
+ color: darken(#2688dc, 10%);
+ }
}
h1, h2, h3, h4, h5, h6 {
diff --git a/app/assets/stylesheets/responsive/_new_request_layout.scss b/app/assets/stylesheets/responsive/_new_request_layout.scss
index eec95ae77..aba4ffc29 100644
--- a/app/assets/stylesheets/responsive/_new_request_layout.scss
+++ b/app/assets/stylesheets/responsive/_new_request_layout.scss
@@ -29,6 +29,11 @@
@include lte-ie7 {
width: 26.188em;
}
+ /* Don't nest public body grid row in this context */
+ #public_body_show {
+ @include grid-row();
+ }
+
}
/* Hide some elements of the public body that aren't appropriate in this
diff --git a/app/assets/stylesheets/responsive/_user_layout.scss b/app/assets/stylesheets/responsive/_user_layout.scss
index 8087f978c..a568a5fa3 100644
--- a/app/assets/stylesheets/responsive/_user_layout.scss
+++ b/app/assets/stylesheets/responsive/_user_layout.scss
@@ -1,2 +1,7 @@
/* Layout for user pages */
+#user_profile_search {
+ #search_form {
+ margin-top: 2rem;
+ }
+}
diff --git a/app/controllers/general_controller.rb b/app/controllers/general_controller.rb
index 158492eb2..2c8abbaf4 100644
--- a/app/controllers/general_controller.rb
+++ b/app/controllers/general_controller.rb
@@ -32,7 +32,7 @@ class GeneralController < ApplicationController
if !content.empty?
@data = XmlSimple.xml_in(content)
@channel = @data['channel'][0]
- @blog_items = @channel['item']
+ @blog_items = @channel.fetch('item') { [] }
@feed_autodetect = [{:url => @feed_url, :title => "#{site_name} blog"}]
end
end
diff --git a/app/models/censor_rule.rb b/app/models/censor_rule.rb
index 3c5c77563..62cf8112f 100644
--- a/app/models/censor_rule.rb
+++ b/app/models/censor_rule.rb
@@ -30,7 +30,11 @@ class CensorRule < ActiveRecord::Base
attr_accessor :allow_global
validate :require_user_request_or_public_body, :unless => proc{ |rule| rule.allow_global == true }
validate :require_valid_regexp, :if => proc{ |rule| rule.regexp? == true }
- validates_presence_of :text
+
+ validates_presence_of :text,
+ :replacement,
+ :last_edit_comment,
+ :last_edit_editor
scope :global, {:conditions => {:info_request_id => nil,
:user_id => nil,
diff --git a/app/models/outgoing_message.rb b/app/models/outgoing_message.rb
index 160f69d0b..9424113fc 100644
--- a/app/models/outgoing_message.rb
+++ b/app/models/outgoing_message.rb
@@ -28,106 +28,115 @@ class OutgoingMessage < ActiveRecord::Base
extend MessageProminence
include Rails.application.routes.url_helpers
include LinkToHelper
- self.default_url_options[:host] = AlaveteliConfiguration::domain
- # https links in emails if forcing SSL
- if AlaveteliConfiguration::force_ssl
- self.default_url_options[:protocol] = "https"
- end
- strip_attributes!
-
- has_prominence
+ # To override the default letter
+ attr_accessor :default_letter
- belongs_to :info_request
validates_presence_of :info_request
-
validates_inclusion_of :status, :in => ['ready', 'sent', 'failed']
- validates_inclusion_of :message_type, :in => ['initial_request', 'followup' ] #, 'complaint']
+ validates_inclusion_of :message_type, :in => ['initial_request', 'followup']
validate :format_of_body
+ belongs_to :info_request
belongs_to :incoming_message_followup, :foreign_key => 'incoming_message_followup_id', :class_name => 'IncomingMessage'
# can have many events, for items which were resent by site admin e.g. if
# contact address changed
has_many :info_request_events
- # To override the default letter
- attr_accessor :default_letter
-
+ after_initialize :set_default_letter
+ after_save :purge_in_cache
# reindex if body text is edited (e.g. by admin interface)
after_update :xapian_reindex_after_update
- def xapian_reindex_after_update
- if self.changes.include?('body')
- for info_request_event in self.info_request_events
- info_request_event.xapian_mark_needs_index
- end
- end
- end
- after_initialize :set_default_letter
+ strip_attributes!
+ has_prominence
- # 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
- return OutgoingMessage.default_salutation(self.info_request.public_body)
- end
- salutation = _("Dear {{public_body_name}},", :public_body_name => ret)
+ self.default_url_options[:host] = AlaveteliConfiguration.domain
+
+ # https links in emails if forcing SSL
+ if AlaveteliConfiguration::force_ssl
+ self.default_url_options[:protocol] = "https"
end
- def OutgoingMessage.default_salutation(public_body)
+ def self.default_salutation(public_body)
_("Dear {{public_body_name}},", :public_body_name => public_body.name)
end
- def OutgoingMessage.placeholder_salutation
+ def self.placeholder_salutation
_("Dear [Authority name],")
end
- def OutgoingMessage.fill_in_salutation(body, public_body)
+ def self.fill_in_salutation(body, public_body)
body.gsub(placeholder_salutation, default_salutation(public_body))
end
+ # How the default letter starts and ends
+ def get_salutation
+ if info_request.is_batch_request_template?
+ return OutgoingMessage.placeholder_salutation
+ end
+
+ ret = ""
+ if message_type == 'followup' &&
+ !incoming_message_followup.nil? &&
+ !incoming_message_followup.safe_mail_from.nil? &&
+ incoming_message_followup.valid_to_reply_to?
+
+ ret += OutgoingMailer.name_for_followup(info_request, incoming_message_followup)
+ else
+ return OutgoingMessage.default_salutation(info_request.public_body)
+ end
+ salutation = _("Dear {{public_body_name}},", :public_body_name => ret)
+ 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,")
+ if message_type == 'followup' &&
+ !incoming_message_followup.nil? &&
+ !incoming_message_followup.safe_mail_from.nil? &&
+ incoming_message_followup.valid_to_reply_to?
+
+ _("Yours sincerely,")
else
- return _("Yours faithfully,")
+ _("Yours faithfully,")
end
end
+
def get_internal_review_insert_here_note
- return _("GIVE DETAILS ABOUT YOUR COMPLAINT HERE")
+ _("GIVE DETAILS ABOUT YOUR COMPLAINT HERE")
end
- def get_default_letter
- if self.default_letter
- return self.default_letter
- end
- if self.what_doing == 'internal_review'
- _("Please pass this on to the person who conducts Freedom of Information reviews.") +
- "\n\n" +
- _("I am writing to request an internal review of {{public_body_name}}'s handling of my FOI request '{{info_request_title}}'.",
- :public_body_name => self.info_request.public_body.name,
- :info_request_title => self.info_request.title) +
- "\n\n\n\n [ " + self.get_internal_review_insert_here_note + " ] \n\n\n\n" +
- _("A full history of my FOI request and all correspondence is available on the Internet at this address: {{url}}",
- :url => request_url(self.info_request)) +
- "\n"
+ def get_default_letter
+ return default_letter if default_letter
+
+ if what_doing == 'internal_review'
+ letter = _("Please pass this on to the person who conducts Freedom of Information reviews.")
+ letter += "\n\n"
+ letter += _("I am writing to request an internal review of {{public_body_name}}'s handling of my FOI request '{{info_request_title}}'.",
+ :public_body_name => info_request.public_body.name,
+ :info_request_title => info_request.title)
+ letter += "\n\n\n\n [ #{ get_internal_review_insert_here_note } ] \n\n\n\n"
+ letter += _("A full history of my FOI request and all correspondence is available on the Internet at this address: {{url}}",
+ :url => request_url(info_request))
+ letter += "\n"
else
""
end
end
+
def get_default_message
- get_salutation + "\n\n" + get_default_letter + "\n\n" + get_signoff + "\n\n"
+ msg = get_salutation
+ msg += "\n\n"
+ msg += get_default_letter
+ msg += "\n\n"
+ msg += get_signoff
+ msg += "\n\n"
end
+
def set_signature_name(name)
# TODO: We use raw_body here to get unstripped one
- if self.raw_body == self.get_default_message
- self.body = self.raw_body + name
+ if raw_body == get_default_message
+ self.body = raw_body + name
end
end
@@ -142,84 +151,88 @@ class OutgoingMessage < ActiveRecord::Base
ret.gsub!(/(?:\n\s*){2,}/, "\n\n") # remove excess linebreaks that unnecessarily space it out
# Remove things from censor rules
- if !self.info_request.nil?
+ unless info_request.nil?
self.info_request.apply_censor_rules_to_text!(ret)
end
ret
end
+
def raw_body
read_attribute(:body)
end
# Used to give warnings when writing new messages
def contains_email?
- MySociety::Validate.email_find_regexp.match(self.body)
+ MySociety::Validate.email_find_regexp.match(body)
end
+
def contains_postcode?
- MySociety::Validate.contains_postcode?(self.body)
+ MySociety::Validate.contains_postcode?(body)
end
# Deliver outgoing message
# Note: You can test this from script/console with, say:
# InfoRequest.find(1).outgoing_messages[0].send_message
def send_message(log_event_type = 'sent')
- if self.status == 'ready'
- if self.message_type == 'initial_request'
+ if status == 'ready'
+ if message_type == 'initial_request'
self.last_sent_at = Time.now
self.status = 'sent'
self.save!
- mail_message = OutgoingMailer.initial_request(self.info_request, self).deliver
+ mail_message = OutgoingMailer.initial_request(info_request, self).deliver
self.info_request.log_event(log_event_type, {
:email => mail_message.to_addrs.join(", "),
:outgoing_message_id => self.id,
:smtp_message_id => mail_message.message_id
})
self.info_request.set_described_state('waiting_response')
- elsif self.message_type == 'followup'
+ elsif message_type == 'followup'
self.last_sent_at = Time.now
self.status = 'sent'
self.save!
- mail_message = OutgoingMailer.followup(self.info_request, self, self.incoming_message_followup).deliver
+ mail_message = OutgoingMailer.followup(info_request, self, incoming_message_followup).deliver
self.info_request.log_event('followup_' + log_event_type, {
:email => mail_message.to_addrs.join(", "),
:outgoing_message_id => self.id,
:smtp_message_id => mail_message.message_id
})
- if self.info_request.described_state == 'waiting_clarification'
+ if info_request.described_state == 'waiting_clarification'
self.info_request.set_described_state('waiting_response')
end
- if self.what_doing == 'internal_review'
+ if what_doing == 'internal_review'
self.info_request.set_described_state('internal_review')
end
else
- raise "Message id #{self.id} has type '#{self.message_type}' which send_message can't handle"
+ raise "Message id #{id} has type '#{message_type}' which send_message can't handle"
end
- elsif self.status == 'sent'
- raise "Message id #{self.id} has already been sent"
+ elsif status == 'sent'
+ raise "Message id #{id} has already been sent"
else
- raise "Message id #{self.id} not in state for send_message"
+ raise "Message id #{id} not in state for send_message"
end
end
# An admin function
def resend_message
- if ['initial_request', 'followup'].include?(self.message_type) and self.status == 'sent'
+ if ['initial_request', 'followup'].include?(message_type) and status == 'sent'
self.status = 'ready'
send_message('resent')
else
- raise "Message id #{self.id} has type '#{self.message_type}' status '#{self.status}' which resend_message can't handle"
+ raise "Message id #{id} has type '#{message_type}' status '#{status}' which resend_message can't handle"
end
end
# Returns the text to quote the original message when sending this one
def quoted_part_to_append_to_email
- if self.message_type == 'followup' && !self.incoming_message_followup.nil?
- return "\n\n-----Original Message-----\n\n" + self.incoming_message_followup.get_body_for_quoting + "\n"
+ if message_type == 'followup' && !incoming_message_followup.nil?
+ quoted = "\n\n-----Original Message-----\n\n"
+ quoted += incoming_message_followup.get_body_for_quoting
+ quoted += "\n"
else
- return ""
+ ""
end
end
@@ -229,8 +242,8 @@ class OutgoingMessage < ActiveRecord::Base
end
# Returns text for indexing / text display
- def get_text_for_indexing(strip_salutation=true)
- text = self.body.strip
+ def get_text_for_indexing(strip_salutation = true)
+ text = body.strip
# Remove salutation
text.sub!(/Dear .+,/, "") if strip_salutation
@@ -238,19 +251,20 @@ class OutgoingMessage < ActiveRecord::Base
# Remove email addresses from display/index etc.
self.remove_privacy_sensitive_things!(text)
- return text
+ text
end
# Return body for display as HTML
def get_body_for_html_display
- text = self.body.strip
+ text = body.strip
self.remove_privacy_sensitive_things!(text)
- text = MySociety::Format.wrap_email_body_by_lines(text) # reparagraph and wrap it so is good preview of emails
+ # reparagraph and wrap it so is good preview of emails
+ text = MySociety::Format.wrap_email_body_by_lines(text)
text = CGI.escapeHTML(text)
text = MySociety::Format.make_clickable(text, :contract => 1)
text.gsub!(/\[(email address|mobile number)\]/, '[<a href="/help/officers#mobiles">\1</a>]')
text = text.gsub(/\n/, '<br>')
- return text.html_safe
+ text.html_safe
end
# Return body for display as text
@@ -261,17 +275,16 @@ class OutgoingMessage < ActiveRecord::Base
def fully_destroy
ActiveRecord::Base.transaction do
- info_request_event = InfoRequestEvent.find_by_outgoing_message_id(self.id)
+ info_request_event = InfoRequestEvent.find_by_outgoing_message_id(id)
info_request_event.track_things_sent_emails.each { |a| a.destroy }
info_request_event.user_info_request_sent_alerts.each { |a| a.destroy }
info_request_event.destroy
- self.destroy
+ destroy
end
end
- after_save(:purge_in_cache)
def purge_in_cache
- self.info_request.purge_in_cache
+ info_request.purge_in_cache
end
def for_admin_column
@@ -280,18 +293,24 @@ class OutgoingMessage < ActiveRecord::Base
end
end
+ def xapian_reindex_after_update
+ if changes.include?('body')
+ info_request_events.each do |event|
+ event.xapian_mark_needs_index
+ end
+ end
+ end
+
private
def set_default_letter
- if self.body.nil?
- self.body = get_default_message
- end
+ self.body = get_default_message if body.nil?
end
def format_of_body
- if self.body.empty? || self.body =~ /\A#{Regexp.escape(get_salutation)}\s+#{Regexp.escape(get_signoff)}/ || self.body =~ /#{Regexp.escape(get_internal_review_insert_here_note)}/
- if self.message_type == 'followup'
- if self.what_doing == 'internal_review'
+ if body.empty? || body =~ /\A#{Regexp.escape(get_salutation)}\s+#{Regexp.escape(get_signoff)}/ || body =~ /#{Regexp.escape(get_internal_review_insert_here_note)}/
+ if message_type == 'followup'
+ if what_doing == 'internal_review'
errors.add(:body, _("Please give details explaining why you want a review"))
else
errors.add(:body, _("Please enter your follow up message"))
@@ -299,16 +318,19 @@ class OutgoingMessage < ActiveRecord::Base
elsif
errors.add(:body, _("Please enter your letter requesting information"))
else
- raise "Message id #{self.id} has type '#{self.message_type}' which validate can't handle"
+ raise "Message id #{id} has type '#{message_type}' which validate can't handle"
end
end
- if self.body =~ /#{get_signoff}\s*\Z/m
+
+ if body =~ /#{get_signoff}\s*\Z/m
errors.add(:body, _("Please sign at the bottom with your name, or alter the \"{{signoff}}\" signature", :signoff => get_signoff))
end
- if !MySociety::Validate.uses_mixed_capitals(self.body)
+
+ unless MySociety::Validate.uses_mixed_capitals(body)
errors.add(:body, _('Please write your message using a mixture of capital and lower case letters. This makes it easier for others to read.'))
end
- if self.what_doing.nil? || !['new_information', 'internal_review', 'normal_sort'].include?(self.what_doing)
+
+ if what_doing.nil? || !['new_information', 'internal_review', 'normal_sort'].include?(what_doing)
errors.add(:what_doing_dummy, _('Please choose what sort of reply you are making.'))
end
end
diff --git a/app/models/public_body.rb b/app/models/public_body.rb
index b22482541..87b5c2227 100644
--- a/app/models/public_body.rb
+++ b/app/models/public_body.rb
@@ -60,6 +60,21 @@ class PublicBody < ActiveRecord::Base
translates :name, :short_name, :request_email, :url_name, :notes, :first_letter, :publication_scheme
+ # Default fields available for importing from CSV, in the format
+ # [field_name, 'short description of field (basic html allowed)']
+ cattr_accessor :csv_import_fields do
+ [
+ ['name', '(i18n)<strong>Existing records cannot be renamed</strong>'],
+ ['short_name', '(i18n)'],
+ ['request_email', '(i18n)'],
+ ['notes', '(i18n)'],
+ ['publication_scheme', '(i18n)'],
+ ['disclosure_log', '(i18n)'],
+ ['home_page', ''],
+ ['tag_string', '(tags separated by spaces)'],
+ ]
+ end
+
# Public: Search for Public Bodies whose name, short_name, request_email or
# tags contain the given query
#
@@ -477,7 +492,10 @@ class PublicBody < ActiveRecord::Base
next
end
- field_list = ['name', 'short_name', 'request_email', 'notes', 'publication_scheme', 'disclosure_log', 'home_page', 'tag_string']
+ field_list = []
+ self.csv_import_fields.each do |field_name, field_notes|
+ field_list.push field_name
+ end
if public_body = bodies_by_name[name] # Existing public body
available_locales.each do |locale|
diff --git a/app/views/admin_public_body/import_csv.html.erb b/app/views/admin_public_body/import_csv.html.erb
index d15ef1791..c690f0fc2 100644
--- a/app/views/admin_public_body/import_csv.html.erb
+++ b/app/views/admin_public_body/import_csv.html.erb
@@ -51,19 +51,11 @@ Another One,another@example.com,Otro organismo,a_tag
</pre>
<p><strong>Supported fields:</strong>
- <ul>
- <li>
- <code>name</code> (i18n)
- <strong>Existing records cannot be renamed</strong>
- </li>
- <li><code>short_name</code> (i18n)</li>
- <li><code>request_email</code> (i18n)</li>
- <li><code>notes</code> (i18n)</li>
- <li><code>publication_scheme</code> (i18n)</li>
- <li><code>disclosure_log</code> (i18n)</li>
- <li><code>home_page</code></li>
- <li><code>tag_string</code> (tags separated by spaces)</li>
- </ul>
+ <ul>
+ <% PublicBody.csv_import_fields.each do |field, notes| %>
+ <li><code><%= field %></code> <%= sanitize(notes) %></li>
+ <% end %>
+ </ul>
</p>
<p><strong>Note:</strong> Choose <strong>dry run</strong> to test, without