diff options
-rw-r--r-- | Gemfile | 1 | ||||
-rw-r--r-- | Gemfile.lock | 1 | ||||
-rw-r--r-- | app/controllers/admin_public_body_controller.rb | 5 | ||||
-rw-r--r-- | app/controllers/public_body_controller.rb | 124 | ||||
-rw-r--r-- | app/models/info_request.rb | 6 | ||||
-rw-r--r-- | app/models/public_body.rb | 24 | ||||
-rw-r--r-- | config/crontab-example | 2 | ||||
-rw-r--r-- | config/general.yml-example | 5 | ||||
-rw-r--r-- | config/initializers/alaveteli.rb | 1 | ||||
-rw-r--r-- | doc/THEMES.md | 2 | ||||
-rw-r--r-- | lib/configuration.rb | 1 | ||||
-rw-r--r-- | lib/tasks/gettext.rake | 42 | ||||
-rw-r--r-- | lib/tasks/stats.rake | 9 | ||||
-rw-r--r-- | public/stylesheets/admin.css | 77 | ||||
-rw-r--r-- | public/stylesheets/alt.css | 232 | ||||
-rwxr-xr-x | script/generate_pot.sh | 22 | ||||
-rwxr-xr-x | script/update-public-body-stats | 4 | ||||
-rw-r--r-- | spec/controllers/public_body_controller_spec.rb | 74 | ||||
-rw-r--r-- | spec/controllers/request_controller_spec.rb | 2 | ||||
-rw-r--r-- | spec/models/info_request_spec.rb | 7 | ||||
-rw-r--r-- | spec/models/public_body_spec.rb | 46 | ||||
-rw-r--r-- | vendor/plugins/strip_attributes/lib/strip_attributes.rb | 9 |
22 files changed, 276 insertions, 420 deletions
@@ -55,6 +55,7 @@ group :test do gem 'fakeweb' gem 'coveralls', :require => false gem 'webrat' + gem 'nokogiri' end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index 8d5059d7e..15c5245ff 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -270,6 +270,7 @@ DEPENDENCIES net-http-local net-purge newrelic_rpm + nokogiri pg rack rails (= 3.1.12) diff --git a/app/controllers/admin_public_body_controller.rb b/app/controllers/admin_public_body_controller.rb index ec2a08dbc..e0da234b0 100644 --- a/app/controllers/admin_public_body_controller.rb +++ b/app/controllers/admin_public_body_controller.rb @@ -14,6 +14,7 @@ class AdminPublicBodyController < AdminController def _lookup_query_internal @locale = self.locale_from_params() + underscore_locale = @locale.gsub '-', '_' I18n.with_locale(@locale) do @query = params[:query] if @query == "" @@ -23,10 +24,10 @@ class AdminPublicBodyController < AdminController if @page == "" @page = nil end - @public_bodies = PublicBody.joins(:translations).where(@query.nil? ? "public_body_translations.locale = '#{@locale}'" : + @public_bodies = PublicBody.joins(:translations).where(@query.nil? ? "public_body_translations.locale = '#{underscore_locale}'" : ["(lower(public_body_translations.name) like lower('%'||?||'%') or lower(public_body_translations.short_name) like lower('%'||?||'%') or - lower(public_body_translations.request_email) like lower('%'||?||'%' )) AND (public_body_translations.locale = '#{@locale}')", @query, @query, @query]).paginate :order => "public_body_translations.name", :page => @page, :per_page => 100 + lower(public_body_translations.request_email) like lower('%'||?||'%' )) AND (public_body_translations.locale = '#{underscore_locale}')", @query, @query, @query]).paginate :order => "public_body_translations.name", :page => @page, :per_page => 100 end @public_bodies_by_tag = PublicBody.find_by_tag(@query) end diff --git a/app/controllers/public_body_controller.rb b/app/controllers/public_body_controller.rb index 9f692c5ba..02f0ceb19 100644 --- a/app/controllers/public_body_controller.rb +++ b/app/controllers/public_body_controller.rb @@ -86,34 +86,45 @@ class PublicBodyController < ApplicationController def list long_cache # XXX move some of these tag SQL queries into has_tag_string.rb - @query = "%#{params[:public_body_query].nil? ? "" : params[:public_body_query]}%" + + like_query = params[:public_body_query] + like_query = "" if like_query.nil? + like_query = "%#{like_query}%" + @tag = params[:tag] - @locale = self.locale_from_params() - default_locale = I18n.default_locale.to_s - locale_condition = "(upper(public_body_translations.name) LIKE upper(?) - OR upper(public_body_translations.notes) LIKE upper (?)) - AND public_body_translations.locale = ? - AND public_bodies.id <> #{PublicBody.internal_admin_body.id}" + + @locale = self.locale_from_params + underscore_locale = @locale.gsub '-', '_' + underscore_default_locale = I18n.default_locale.to_s.gsub '-', '_' + + where_condition = "public_bodies.id <> #{PublicBody.internal_admin_body.id}" + where_parameters = [] + + first_letter = false + + base_tag_condition = " AND (SELECT count(*) FROM has_tag_string_tags" \ + " WHERE has_tag_string_tags.model_id = public_bodies.id" \ + " AND has_tag_string_tags.model = 'PublicBody'" + + # Restrict the public bodies shown according to the tag + # parameter supplied in the URL: if @tag.nil? or @tag == "all" @tag = "all" - conditions = [locale_condition, @query, @query, default_locale] elsif @tag == 'other' category_list = PublicBodyCategories::get().tags().map{|c| "'"+c+"'"}.join(",") - conditions = [locale_condition + ' AND (select count(*) from has_tag_string_tags where has_tag_string_tags.model_id = public_bodies.id - and has_tag_string_tags.model = \'PublicBody\' - and has_tag_string_tags.name in (' + category_list + ')) = 0', @query, @query, default_locale] + where_condition += base_tag_condition + " AND has_tag_string_tags.name in (#{category_list})) = 0" elsif @tag.size == 1 @tag.upcase! - conditions = [locale_condition + ' AND public_body_translations.first_letter = ?', @query, @query, default_locale, @tag] + # The first letter queries have to be done on + # translations, so just indicate to add that later: + first_letter = true elsif @tag.include?(":") name, value = HasTagString::HasTagStringTag.split_tag_into_name_value(@tag) - conditions = [locale_condition + ' AND (select count(*) from has_tag_string_tags where has_tag_string_tags.model_id = public_bodies.id - and has_tag_string_tags.model = \'PublicBody\' - and has_tag_string_tags.name = ? and has_tag_string_tags.value = ?) > 0', @query, @query, default_locale, name, value] + where_condition += base_tag_condition + " AND has_tag_string_tags.name = ? AND has_tag_string_tags.value = ?) > 0" + where_parameters.concat [name, value] else - conditions = [locale_condition + ' AND (select count(*) from has_tag_string_tags where has_tag_string_tags.model_id = public_bodies.id - and has_tag_string_tags.model = \'PublicBody\' - and has_tag_string_tags.name = ?) > 0', @query, @query, default_locale, @tag] + where_condition += base_tag_condition + " AND has_tag_string_tags.name = ?) > 0" + where_parameters.concat [@tag] end if @tag == "all" @@ -128,10 +139,45 @@ class PublicBodyController < ApplicationController @description = _("in the category ‘{{category_name}}’", :category_name=>category_name) end end + I18n.with_locale(@locale) do - @public_bodies = PublicBody.where(conditions).joins(:translations).order("public_body_translations.name").paginate( - :page => params[:page], :per_page => 100 - ) + + if AlaveteliConfiguration::public_body_list_fallback_to_default_locale + # Unfortunately, when we might fall back to the + # default locale, this is a rather complex query: + query = %Q{ + SELECT public_bodies.*, COALESCE(current_locale.name, default_locale.name) AS display_name + FROM public_bodies + LEFT OUTER JOIN public_body_translations as current_locale + ON (public_bodies.id = current_locale.public_body_id + AND current_locale.locale = ? AND #{get_public_body_list_translated_condition 'current_locale', first_letter}) + LEFT OUTER JOIN public_body_translations as default_locale + ON (public_bodies.id = default_locale.public_body_id + AND default_locale.locale = ? AND #{get_public_body_list_translated_condition 'default_locale', first_letter}) + WHERE #{where_condition} AND COALESCE(current_locale.name, default_locale.name) IS NOT NULL + ORDER BY display_name} + sql = [query, underscore_locale, like_query, like_query] + sql.push @tag if first_letter + sql += [underscore_default_locale, like_query, like_query] + sql.push @tag if first_letter + sql += where_parameters + @public_bodies = PublicBody.paginate_by_sql( + sql, + :page => params[:page], + :per_page => 100) + else + # The simpler case where we're just searching in the current locale: + where_condition = get_public_body_list_translated_condition('public_body_translations', first_letter, true) + + ' AND ' + where_condition + where_sql = [where_condition, like_query, like_query] + where_sql.push @tag if first_letter + where_sql += [underscore_locale] + where_parameters + @public_bodies = PublicBody.where(where_sql) \ + .joins(:translations) \ + .order("public_body_translations.name") \ + .paginate(:page => params[:page], :per_page => 100) + end + respond_to do |format| format.html { render :template => "public_body/list" } end @@ -165,27 +211,27 @@ class PublicBodyController < ApplicationController [[total_column, [{ - :title => 'Public bodies with the most requests', - :y_axis => 'Number of requests', + :title => _('Public bodies with the most requests'), + :y_axis => _('Number of requests'), :highest => true}]], ['info_requests_successful_count', [{ - :title => 'Public bodies with the most successful requests', - :y_axis => 'Percentage of total requests', + :title => _('Public bodies with the most successful requests'), + :y_axis => _('Percentage of total requests'), :highest => true}, { - :title => 'Public bodies with the fewest successful requests', - :y_axis => 'Percentage of total requests', + :title => _('Public bodies with the fewest successful requests'), + :y_axis => _('Percentage of total requests'), :highest => false}]], ['info_requests_overdue_count', [{ - :title => 'Public bodies with most overdue requests', - :y_axis => 'Percentage of requests that are overdue', + :title => _('Public bodies with most overdue requests'), + :y_axis => _('Percentage of requests that are overdue'), :highest => true}]], ['info_requests_not_held_count', [{ - :title => 'Public bodies that most frequently replied with "Not Held"', - :y_axis => 'Percentage of total requests', + :title => _('Public bodies that most frequently replied with "Not Held"'), + :y_axis => _('Percentage of total requests'), :highest => true}]]].each do |column, graphs_properties| graphs_properties.each do |graph_properties| @@ -207,7 +253,7 @@ class PublicBodyController < ApplicationController data_to_draw = { 'id' => "#{column}-#{highest ? 'highest' : 'lowest'}", - 'x_axis' => 'Public Bodies', + 'x_axis' => _('Public Bodies'), 'y_axis' => graph_properties[:y_axis], 'errorbars' => percentages, 'title' => graph_properties[:title]} @@ -236,4 +282,18 @@ class PublicBodyController < ApplicationController @xapian_requests = perform_search_typeahead(query, PublicBody) render :partial => "public_body/search_ahead" end + + private + def get_public_body_list_translated_condition(table, first_letter=false, locale=nil) + result = "(upper(#{table}.name) LIKE upper(?)" \ + " OR upper(#{table}.notes) LIKE upper (?))" + if first_letter + result += " AND #{table}.first_letter = ?" + end + if locale + result += " AND #{table}.locale = ?" + end + result + end + end diff --git a/app/models/info_request.rb b/app/models/info_request.rb index 91bd37d9f..c0b8e2fca 100644 --- a/app/models/info_request.rb +++ b/app/models/info_request.rb @@ -1128,12 +1128,18 @@ public after_save :update_counter_cache after_destroy :update_counter_cache def update_counter_cache + PublicBody.skip_callback(:save, :after, :purge_in_cache) self.public_body.info_requests_not_held_count = InfoRequest.where( :public_body_id => self.public_body.id, :described_state => 'not_held').count self.public_body.info_requests_successful_count = InfoRequest.where( :public_body_id => self.public_body.id, :described_state => ['successful', 'partially_successful']).count + self.public_body.without_revision do + public_body.no_xapian_reindex = true + public_body.save + end + PublicBody.set_callback(:save, :after, :purge_in_cache) end def for_admin_column diff --git a/app/models/public_body.rb b/app/models/public_body.rb index 300fdb956..3154be632 100644 --- a/app/models/public_body.rb +++ b/app/models/public_body.rb @@ -40,6 +40,7 @@ class PublicBody < ActiveRecord::Base has_many :info_requests, :order => 'created_at desc' has_many :track_things, :order => 'created_at desc' has_many :censor_rules, :order => 'created_at desc' + attr_accessor :no_xapian_reindex has_tag_string before_save :set_api_key, :set_default_publication_scheme @@ -60,12 +61,23 @@ class PublicBody < ActiveRecord::Base # XXX - Don't like repeating this! def calculate_cached_fields(t) - t.first_letter = t.name.scan(/^./mu)[0].upcase unless t.name.nil? or t.name.empty? + PublicBody.set_first_letter(t) short_long_name = t.name short_long_name = t.short_name if t.short_name and !t.short_name.empty? t.url_name = MySociety::Format.simplify_url_part(short_long_name, 'body') end + # Set the first letter on a public body or translation + def PublicBody.set_first_letter(instance) + unless instance.name.nil? or instance.name.empty? + # we use a regex to ensure it works with utf-8/multi-byte + first_letter = instance.name.scan(/^./mu)[0].upcase + if first_letter != instance.first_letter + instance.first_letter = first_letter + end + end + end + def translated_versions translations end @@ -130,8 +142,7 @@ class PublicBody < ActiveRecord::Base # Set the first letter, which is used for faster queries before_save(:set_first_letter) def set_first_letter - # we use a regex to ensure it works with utf-8/multi-byte - self.first_letter = self.name.scan(/./mu)[0].upcase + PublicBody.set_first_letter(self) end # If tagged "not_apply", then FOI/EIR no longer applies to authority at all @@ -177,7 +188,11 @@ class PublicBody < ActiveRecord::Base end acts_as_versioned - self.non_versioned_columns << 'created_at' << 'updated_at' << 'first_letter' << 'api_key' << 'info_requests_count' + self.non_versioned_columns << 'created_at' << 'updated_at' << 'first_letter' << 'api_key' + self.non_versioned_columns << 'info_requests_count' << 'info_requests_successful_count' + self.non_versioned_columns << 'info_requests_not_held_count' << 'info_requests_overdue' + self.non_versioned_columns << 'info_requests_overdue_count' + class Version attr_accessor :created_at @@ -231,6 +246,7 @@ class PublicBody < ActiveRecord::Base def reindex_requested_from if self.changes.include?('url_name') for info_request in self.info_requests + for info_request_event in info_request.info_request_events info_request_event.xapian_mark_needs_index end diff --git a/config/crontab-example b/config/crontab-example index 32baff170..d2c3f6bd9 100644 --- a/config/crontab-example +++ b/config/crontab-example @@ -26,6 +26,8 @@ MAILTO=cron-!!(*= $site *)!!@mysociety.org 0 8 * * * !!(*= $user *)!! run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/alert-not-clarified-request.lock /data/vhost/!!(*= $vhost *)!!/!!(*= $vcspath *)!!/script/alert-not-clarified-request || echo "stalled?" 2 4 * * * !!(*= $user *)!! run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/check-recent-requests-sent.lock /data/vhost/!!(*= $vhost *)!!/!!(*= $vcspath *)!!/script/check-recent-requests-sent || echo "stalled?" 45 3 * * * !!(*= $user *)!! run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/stop-new-responses-on-old-requests.lock /data/vhost/!!(*= $vhost *)!!/!!(*= $vcspath *)!!/script/stop-new-responses-on-old-requests || echo "stalled?" +55 4 * * * !!(*= $user *)!! run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/update-public-body-stats.lock /data/vhost/!!(*= $vhost *)!!/!!(*= $vcspath *)!!/script/update-public-body-stats || echo "stalled?" + # Only root can restart apache 31 1 * * * root run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/change-xapian-database.lock "/data/vhost/!!(*= $vhost *)!!/!!(*= $vcspath *)!!/script/compact-xapian-database production" || echo "stalled?" diff --git a/config/general.yml-example b/config/general.yml-example index 37b0c2fc9..5f3697a36 100644 --- a/config/general.yml-example +++ b/config/general.yml-example @@ -200,3 +200,8 @@ PUBLIC_BODY_STATISTICS_PAGE: false # The page of statistics for public bodies will only consider public # bodies that have had at least this number of requests: MINIMUM_REQUESTS_FOR_STATISTICS: 50 + +# If only some of the public bodies have been translated into every +# available locale, you can allow a fallback to the default locale for +# listing of public bodies. +PUBLIC_BODY_LIST_FALLBACK_TO_DEFAULT_LOCALE: false diff --git a/config/initializers/alaveteli.rb b/config/initializers/alaveteli.rb index 2c6ee2fbc..6e0cf076c 100644 --- a/config/initializers/alaveteli.rb +++ b/config/initializers/alaveteli.rb @@ -25,7 +25,6 @@ ALAVETELI_VERSION = '0.13' # Mime::Type.register "text/richtext", :rtf # Mime::Type.register "application/x-mobile", :mobile -# The Rails cache is set up by the Interlock plugin to use memcached # Domain for URLs (so can work for scripts, not just web pages) ActionMailer::Base.default_url_options[:host] = AlaveteliConfiguration::domain diff --git a/doc/THEMES.md b/doc/THEMES.md index bae7d7665..d6109cdc5 100644 --- a/doc/THEMES.md +++ b/doc/THEMES.md @@ -64,7 +64,7 @@ add custom help pages, as described below. # Branding the site The core templates that comprise the layout and user interface of an -Alaveteli site live in `app/views/`. They are use Rails' ERB syntax. +Alaveteli site live in `app/views/`. They use Rails' ERB syntax. For example, the template for the home page lives at `app/views/general/frontpage.html.erb`, and the template for the "about us" page is at `app/views/help/about.html.erb`. diff --git a/lib/configuration.rb b/lib/configuration.rb index d6fd8765f..ab985c8bf 100644 --- a/lib/configuration.rb +++ b/lib/configuration.rb @@ -49,6 +49,7 @@ module AlaveteliConfiguration :NEW_RESPONSE_REMINDER_AFTER_DAYS => [3, 10, 24], :OVERRIDE_ALL_PUBLIC_BODY_REQUEST_EMAILS => '', :PUBLIC_BODY_STATISTICS_PAGE => false, + :PUBLIC_BODY_LIST_FALLBACK_TO_DEFAULT_LOCALE => false, :RAW_EMAILS_LOCATION => 'files/raw_emails', :READ_ONLY => '', :RECAPTCHA_PRIVATE_KEY => 'x', diff --git a/lib/tasks/gettext.rake b/lib/tasks/gettext.rake index ace7205ae..366dfbe88 100644 --- a/lib/tasks/gettext.rake +++ b/lib/tasks/gettext.rake @@ -9,27 +9,31 @@ namespace :gettext do end end - desc "Update pot file only, without fuzzy guesses (these are done by Transifex)" - task :findpot => :environment do + desc "Update pot/po files for a theme." + task :find_theme => :environment do + theme = ENV['THEME'] + unless theme + puts "Usage: Specify an Alaveteli-theme with THEME=[theme directory name]" + exit(0) + end load_gettext - $LOAD_PATH << File.join(File.dirname(__FILE__),'..','..','lib') - require 'gettext_i18n_rails/haml_parser' - files = files_to_translate + msgmerge = Rails.application.config.gettext_i18n_rails.msgmerge + msgmerge ||= %w[--sort-output --no-location --no-wrap] + GetText.update_pofiles_org( + text_domain, + theme_files_to_translate(theme), + "version 0.0.1", + :po_root => theme_locale_path(theme), + :msgmerge => msgmerge + ) + end - #write found messages to tmp.pot - temp_pot = "tmp.pot" - GetText::rgettext(files, temp_pot) + def theme_files_to_translate(theme) + Dir.glob("{vendor/plugins/#{theme}/lib}/**/*.{rb,erb}") + end - #merge tmp.pot and existing pot - FileUtils.mkdir_p('locale') - GetText::msgmerge("locale/app.pot", temp_pot, "alaveteli", :po_root => 'locale', :msgmerge=>[ :no_wrap, :sort_output ]) - Dir.glob("locale/*/app.po") do |po_file| - GetText::msgmerge(po_file, temp_pot, "alaveteli", :po_root => 'locale', :msgmerge=>[ :no_wrap, :sort_output ]) - end - File.delete(temp_pot) - end + def theme_locale_path(theme) + File.join(Rails.root, "vendor", "plugins", theme, "locale-theme") + end - def files_to_translate - Dir.glob("{app,lib,config,locale}/**/*.{rb,erb,haml,rhtml}") - end end diff --git a/lib/tasks/stats.rake b/lib/tasks/stats.rake index 1242575fe..4eda27289 100644 --- a/lib/tasks/stats.rake +++ b/lib/tasks/stats.rake @@ -93,8 +93,10 @@ namespace :stats do desc 'Update statistics in the public_bodies table' task :update_public_bodies_stats => :environment do + verbose = ENV['VERBOSE'] == '1' PublicBody.all.each do |public_body| - puts "Counting overdue requests for #{public_body.name}" + puts "Counting overdue requests for #{public_body.name}" if verbose + # Look for values of 'waiting_response_overdue' and # 'waiting_response_very_overdue' which aren't directly in the # described_state column, and instead need to be calculated: @@ -109,7 +111,10 @@ namespace :stats do end end public_body.info_requests_overdue_count = overdue_count + very_overdue_count - public_body.save! + public_body.no_xapian_reindex = true + public_body.without_revision do + public_body.save! + end end end end diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css deleted file mode 100644 index 7f8d646d3..000000000 --- a/public/stylesheets/admin.css +++ /dev/null @@ -1,77 +0,0 @@ -/* FOIFA admin CSS */ - -h2 { - margin-top: 0.2em; - margin-bottom: 0.5em; -} - -table { - border-collapse: collapse; - margin-bottom: 1em; -} - -td, th { - border: solid 1px #000000; -} -td { - vertical-align: top -} -td { - max-width: 30em; - overflow: auto; -} - -tr.odd { - background-color: #bbbbbb; -} - -tr.even { - background-color: #dddddd; -} - -.entry_changed { - font-weight: bold; -} - -form { - margin-bottom: 1em; -} - -#notice { - color: green; - border: solid 1px green; - padding: 1em; -} -#error, #errorExplanation { - color: red; - border: solid 1px red; - padding: 1em; -} -#tag_help { - float: right; - width: 25%; - margin-top: 0; -} -#public_body_form { - float: left; - width: 70%; -} - -.forms_on_one_line { - display: inline; -} - -.user_photo_on_admin { - float: right; -} - -.user_photo_on_admin img { - width: 96px; - height: 96px; - vertical-align: middle; - border: 1px solid #dddddd; - margin-right: 5px; - padding: 2px; -} - - diff --git a/public/stylesheets/alt.css b/public/stylesheets/alt.css deleted file mode 100644 index bf6ba2d16..000000000 --- a/public/stylesheets/alt.css +++ /dev/null @@ -1,232 +0,0 @@ -/*------------------------------------------------ global */ -body -{ - padding: 0px; - margin: 0px; - text-align: center; - font-family: Tahoma, Geneva, sans-serif; -} - -/*------------------------------------------------ banner */ - -#banner -{ - position: relative; - top: 0px; - left: 0px; - width: 100%; - height: 200px; - margin: 0px; - background-color: #F0F0F0; - background-image: url(../images/navimg/bnnr-ifyoudontask.png); - background-repeat: no-repeat; - background-position: center top; - border-color: #993233; - border-width: 0 0 3px 0; - border-style: solid; -} - -/*------------------------------------------------ header; not needed? */ -#header -{ display: none; } - -/*------------------------------------------------ search */ - -#navigation_search -{ - position: absolute; - width: 100%; - left: 0px; - top: 175px; - z-index: 150; - text-align: right; - -moz-opacity: 0.7!important; - filter: alpha(opacity= 70)!important; - opacity: 0.7!important; -} - #navigation_search input - { - border-color: #010101; - border-width: 1px; - border-style: solid; - background-color: #fff; - color: #000; - } - #navigation_search input#navigation_search_query - { - width: 8em; - } - -#navigation_search p { margin: 0 0.6em 0 0; } - -/*------------------------------------------------ topnav */ -#topnav -{ - position: relative; - top: 0px; - left: 0px; - width: 100%; - height: auto; - overflow: auto; - padding: 0px 0px 0px 0px; - z-index: 100; - background-color: #000; - font-size: 0.9em; -} - - #topnav ul - { - list-style: none; - margin: 0px; - padding: 0px; - } - - #topnav li - { - float: left; - } - - #topnav li a, #topnav li a:visited - { - display: block; - margin: 0px; - padding: 0.15em 0.6em 0.25em 0.8em; - color: #ADADAD; - text-decoration: none; - } - - #topnav li a:hover - { color: #fff; } - - #topnav li a:active { } - - #topnav li a.on, #topnav li a.on:visited - { - font-weight: bold; - color: #000; - } - - #topnav li a.on:hover {} - - #topnav li a.on:active {} - -/*-------------------------- login/signup */ -#logged_in_bar -{ - float: right; - clear: none; - font-size: 0.9em; - z-index: 200; - padding: 0.20em 10px 0.25em 1em; - color: #FFF; -} - #logged_in_bar a, #logged_in_bar a:visited { color: #92B3FF; } - -/*------------------------------------------------ temp stuff */ -#staging, #alpha_notice -{ display: none;} - -#staging -{ - border-color: #FF201D; - border-width: 1px; - border-style: dotted; - clear: both; - text-align: center; - color: #FF201D; - margin-top: 40px; -} - -#alpha_notice -{ - padding: 0 20px 0 20px; - border-color: #FF201D; - border-width: 1px; - border-style: dotted; - background-color: #f0f0f0; -} - -/*------------------------------------------------ wrapper*/ - -#wrapper -{ - position: relative; - clear: both; - top: 0em; - padding: 0px; - margin: 0px auto 1.2em auto; - max-width: 50em; - /* = 800px at default size? so 1em = 16px*/ - _width: 50em; - text-align: left; -} - -/*------------------------------------------------ content */ - -#content -{ - position: relative; - padding: 2em 1em 1em 1em; -} - -h1, h2, h3 -{ - font-family: Trebuchet, Trebuchet MS, Helvetica, sans-serif; - /*Arial Black, Gadget, sans-serif*/ - font-weight: bold; - line-height: 1em; - letter-spacing: 0em; - color: #555; -} - h1 { font-size: 1.8em;} - h2 { font-size: 1.4em;} - h3 { font-size: 1em;} - -h4, h5, h6 -{} - - -/*---------------- content : recent requests sidebar */ -#find_information -{ - width: 10.5em; - float: right; - clear: none; - background-color: #e0e0e0; - background-image: url(../images/navimg/sidebag-bg-wide.png); - background-repeat: no-repeat; - background-position: center top; - padding: 105px 0.25em 0.25em 0.35em; -} - #find_information h1 - { font-size: 1.2em; line-height: 0.85em; margin-top: 0px;} - - #find_information p - { font-size: 0.8em; line-height: 1em; } - - #find_information input#query - { width: 12em; } - -/*---------------- content : find body */ -#make_requests -{ - float: left; - clear: none; - width: 34em; - text-align: center; -} - -/*------------------------------------------------ footer */ - -#footer -{ - clear: both; - position: relative; - background-color: #F0F0F0; - border-color: #993233; - border-width: 3px 0 0 0; - border-style: solid; - margin: 1em 0 0 0; - padding: 0.5em 0 0.5em 0; - font-size: 0.85em; -}
\ No newline at end of file diff --git a/script/generate_pot.sh b/script/generate_pot.sh deleted file mode 100755 index c0540c3d9..000000000 --- a/script/generate_pot.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -echo "This is NOT a completed script! Just use it as reference for what to do from the command line, or fix it until it works!" -exit 1 - -cd `dirname $0` -# grab latest po files from Transifex -tx pull -a -f -git status | grep app.po | awk '{print $3}' | xargs git add -git commit -m "Backup latest po files from Transifex" - -# now regenerate POT and PO files from Alaveteli source -bundle exec rake gettext:store_model_attributes -bundle exec rake gettext:findpot - -# upload the result to Transifex -tx push -t - -# re-download (it removes the fuzzy strings and normalises it to the format last committed) -tx pull -a -f -git status | grep app.po | awk '{print $3}' | xargs git add -git commit -m "Updated POT" diff --git a/script/update-public-body-stats b/script/update-public-body-stats new file mode 100755 index 000000000..71c2d248c --- /dev/null +++ b/script/update-public-body-stats @@ -0,0 +1,4 @@ +#!/bin/bash + +cd `dirname $0` +bundle exec rake --silent stats:update_public_bodies_stats diff --git a/spec/controllers/public_body_controller_spec.rb b/spec/controllers/public_body_controller_spec.rb index 92130f3d0..2d1b1466f 100644 --- a/spec/controllers/public_body_controller_spec.rb +++ b/spec/controllers/public_body_controller_spec.rb @@ -1,6 +1,8 @@ # coding: utf-8 require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require 'nokogiri' + describe PublicBodyController, "when showing a body" do render_views @@ -78,24 +80,80 @@ describe PublicBodyController, "when listing bodies" do response.should be_success end - it "should list all bodies from default locale, even when there are no translations for selected locale" do - I18n.with_locale(:en) do - @english_only = PublicBody.new(:name => 'English only', - :short_name => 'EO', - :request_email => 'english@flourish.org', - :last_edit_editor => 'test', - :last_edit_comment => '') - @english_only.save + def make_single_language_example(locale) + result = nil + I18n.with_locale(locale) do + case locale + when :en + result = PublicBody.new(:name => 'English only', + :short_name => 'EO') + when :es + result = PublicBody.new(:name => 'Español Solamente', + :short_name => 'ES') + else + raise StandardError.new "Unknown locale #{locale}" + end + result.request_email = "#{locale}@example.org" + result.last_edit_editor = 'test' + result.last_edit_comment = '' + result.save end + result + end + + it "with no fallback, should only return bodies from the current locale" do + @english_only = make_single_language_example :en + @spanish_only = make_single_language_example :es + get :list, {:locale => 'es'} + assigns[:public_bodies].include?(@english_only).should == false + assigns[:public_bodies].include?(@spanish_only).should == true + end + + it "if fallback is requested, should list all bodies from default locale, even when there are no translations for selected locale" do + AlaveteliConfiguration.stub!(:public_body_list_fallback_to_default_locale).and_return(true) + @english_only = make_single_language_example :en get :list, {:locale => 'es'} assigns[:public_bodies].include?(@english_only).should == true end + it 'if fallback is requested, should still list public bodies only with translations in the current locale' do + AlaveteliConfiguration.stub!(:public_body_list_fallback_to_default_locale).and_return(true) + @spanish_only = make_single_language_example :es + get :list, {:locale => 'es'} + assigns[:public_bodies].include?(@spanish_only).should == true + end + + it "if fallback is requested, make sure that there are no duplicates listed" do + AlaveteliConfiguration.stub!(:public_body_list_fallback_to_default_locale).and_return(true) + get :list, {:locale => 'es'} + pb_ids = assigns[:public_bodies].map { |pb| pb.id } + unique_pb_ids = pb_ids.uniq + pb_ids.sort.should === unique_pb_ids.sort + end + it 'should show public body names in the selected locale language if present' do get :list, {:locale => 'es'} response.should contain('El Department for Humpadinking') end + it 'should not show the internal admin authority' do + PublicBody.internal_admin_body + get :list, {:locale => 'en'} + response.should_not contain('Internal admin authority') + end + + it 'should order on the translated name, even with the fallback' do + # The names of each public body is in: + # <span class="head"><a>Public Body Name</a></span> + # ... eo extract all of those, and check that they are ordered: + AlaveteliConfiguration.stub!(:public_body_list_fallback_to_default_locale).and_return(true) + get :list, {:locale => 'es'} + parsed = Nokogiri::HTML(response.body) + public_body_names = parsed.xpath '//span[@class="head"]/a/text()' + public_body_names = public_body_names.map { |pb| pb.to_s } + public_body_names.should == public_body_names.sort + end + it 'should show public body names in the selected locale language if present for a locale with underscores' do AlaveteliLocalization.set_locales('he_IL en', 'en') get :list, {:locale => 'he_IL'} diff --git a/spec/controllers/request_controller_spec.rb b/spec/controllers/request_controller_spec.rb index 2c605a139..9c4e16c67 100644 --- a/spec/controllers/request_controller_spec.rb +++ b/spec/controllers/request_controller_spec.rb @@ -174,7 +174,7 @@ describe RequestController, "when changing things that appear on the request pag ir.save! PurgeRequest.all().first.model_id.should == ir.id end - it "should not create more than one entry for any given resourcce" do + it "should not create more than one entry for any given resource" do ir = info_requests(:fancy_dog_request) ir.prominence = 'hidden' ir.save! diff --git a/spec/models/info_request_spec.rb b/spec/models/info_request_spec.rb index 3f2e02189..ab36a201c 100644 --- a/spec/models/info_request_spec.rb +++ b/spec/models/info_request_spec.rb @@ -896,8 +896,9 @@ describe InfoRequest do describe 'when changing a described_state' do - it "should change the counts on its PublicBody" do + it "should change the counts on its PublicBody without saving a new version" do pb = public_bodies(:geraldine_public_body) + old_version_count = pb.versions.count old_successful_count = pb.info_requests_successful_count old_not_held_count = pb.info_requests_not_held_count ir = InfoRequest.new(:external_url => 'http://www.example.com', @@ -909,15 +910,19 @@ describe InfoRequest do pb.info_requests_successful_count.should == (old_successful_count + 1) ir.described_state = 'not_held' ir.save! + pb.reload pb.info_requests_successful_count.should == old_successful_count pb.info_requests_not_held_count.should == (old_not_held_count + 1) ir.described_state = 'successful' ir.save! + pb.reload pb.info_requests_successful_count.should == (old_successful_count + 1) pb.info_requests_not_held_count.should == old_not_held_count ir.destroy + pb.reload pb.info_requests_successful_count.should == old_successful_count pb.info_requests_successful_count.should == old_not_held_count + pb.versions.count.should == old_version_count end end diff --git a/spec/models/public_body_spec.rb b/spec/models/public_body_spec.rb index 90affaaaa..3578c0e9c 100644 --- a/spec/models/public_body_spec.rb +++ b/spec/models/public_body_spec.rb @@ -136,36 +136,32 @@ describe PublicBody, " when saving" do @public_body = PublicBody.new end + def set_default_attributes(public_body) + public_body.name = "Testing Public Body" + public_body.short_name = "TPB" + public_body.request_email = "request@localhost" + public_body.last_edit_editor = "*test*" + public_body.last_edit_comment = "This is a test" + end + it "should not be valid without setting some parameters" do @public_body.should_not be_valid end it "should not be valid with misformatted request email" do - @public_body.name = "Testing Public Body" - @public_body.short_name = "TPB" + set_default_attributes(@public_body) @public_body.request_email = "requestBOOlocalhost" - @public_body.last_edit_editor = "*test*" - @public_body.last_edit_comment = "This is a test" @public_body.should_not be_valid @public_body.should have(1).errors_on(:request_email) end it "should save" do - @public_body.name = "Testing Public Body" - @public_body.short_name = "TPB" - @public_body.request_email = "request@localhost" - @public_body.last_edit_editor = "*test*" - @public_body.last_edit_comment = "This is a test" + set_default_attributes(@public_body) @public_body.save! end it "should update first_letter" do - @public_body.name = "Testing Public Body" - @public_body.short_name = "TPB" - @public_body.request_email = "request@localhost" - @public_body.last_edit_editor = "*test*" - @public_body.last_edit_comment = "This is a test" - + set_default_attributes(@public_body) @public_body.first_letter.should be_nil @public_body.save! @public_body.first_letter.should == 'T' @@ -178,6 +174,26 @@ describe PublicBody, " when saving" do public_body.name.should == "Mark's Public Body" end + + it 'should not create a new version when nothing has changed' do + @public_body.versions.size.should == 0 + set_default_attributes(@public_body) + @public_body.save! + @public_body.versions.size.should == 1 + @public_body.save! + @public_body.versions.size.should == 1 + end + + it 'should create a new version if something has changed' do + @public_body.versions.size.should == 0 + set_default_attributes(@public_body) + @public_body.save! + @public_body.versions.size.should == 1 + @public_body.name = 'Test' + @public_body.save! + @public_body.versions.size.should == 2 + end + end describe PublicBody, "when searching" do diff --git a/vendor/plugins/strip_attributes/lib/strip_attributes.rb b/vendor/plugins/strip_attributes/lib/strip_attributes.rb index bb93aa9a7..130d10185 100644 --- a/vendor/plugins/strip_attributes/lib/strip_attributes.rb +++ b/vendor/plugins/strip_attributes/lib/strip_attributes.rb @@ -8,12 +8,15 @@ module StripAttributes attribute_names.each do |attribute_name| value = record[attribute_name] if value.respond_to?(:strip) - record[attribute_name] = (value.nil?) ? nil : value.strip + stripped = value.strip + if stripped != value + record[attribute_name] = (value.nil?) ? nil : stripped + end end end end end - + # Necessary because Rails has removed the narrowing of attributes using :only # and :except on Base#attributes def self.narrow(attribute_names, options) @@ -28,7 +31,7 @@ module StripAttributes attribute_names & only else raise ArgumentError, "Options does not specify :except or :only (#{options.keys.inspect})" - end + end end end end |