diff options
174 files changed, 3469 insertions, 6056 deletions
@@ -2,56 +2,60 @@ source 'https://rubygems.org' gem 'rails', '3.2.21' -gem 'pg' +gem 'pg', '~> 0.17.1' # New gem releases aren't being done. master is newer and supports Rails > 3.0 -gem 'acts_as_versioned', :git => 'git://github.com/technoweenie/acts_as_versioned.git' -gem 'charlock_holmes' -gem 'dynamic_form' -gem 'exception_notification' -gem 'fancybox-rails' -gem 'foundation-rails' +gem 'acts_as_versioned', :git => 'git://github.com/technoweenie/acts_as_versioned.git', :ref => '63b1fc8529d028' +gem 'charlock_holmes', '~> 0.6.9.4' +gem 'dynamic_form', '~> 1.1.4' +gem 'exception_notification', '~> 3.0.1' +gem 'fancybox-rails', '~> 0.2.1' +gem 'foundation-rails', '~> 5.2.1.0' +gem 'icalendar', '1.4.3' gem 'jquery-rails', '~> 3.0.4' -gem 'jquery-ui-rails' -gem 'json' -gem 'mahoro' -gem 'memcache-client' -gem 'net-http-local', :platforms => [:ruby_18, :ruby_19] -gem 'net-purge' -gem 'rack' +gem 'jquery-ui-rails', '~> 4.1.0' +gem 'json', '~> 1.8.1' +gem 'holidays', '~> 1.0.8' +gem 'iso_country_codes', '~> 0.6.1' +gem 'mahoro', '~> 0.4' +gem 'memcache-client', '~> 1.8.5' +gem 'net-http-local', '~> 0.1.2', :platforms => [:ruby_18, :ruby_19] +gem 'net-purge', '~> 0.1.0' +gem 'rack', '~> 1.4.5' gem 'rake', '0.9.2.2' -gem 'rails-i18n' +gem 'rails-i18n', '~> 0.7.3' gem 'recaptcha', '~> 0.3.1', :require => 'recaptcha/rails' # :require avoids "already initialized constant" warnings -gem 'rmagick', :require => 'RMagick' +gem 'rmagick', '~> 2.13.2', :require => 'RMagick' gem 'ruby-msg', '~> 1.5.0', :git => 'git://github.com/mysociety/ruby-msg.git' -gem "statistics2", "~> 0.54" -gem 'syslog_protocol' -gem 'thin' -gem 'vpim' -gem 'will_paginate' +gem 'secure_headers', '~> 1.3.4' +gem 'statistics2', '~> 0.54' +gem 'syslog_protocol', '~> 0.9.2' +gem 'thin', '~> 1.5.1' +gem 'vpim', '~> 13.11.11' +gem 'will_paginate', '~> 3.0.5' # when 1.2.9 is released by the maintainer, we can stop using this fork: gem 'xapian-full-alaveteli', '~> 1.2.9.5' -gem 'xml-simple', :require => 'xmlsimple' -gem 'zip' +gem 'xml-simple', '~> 1.1.2', :require => 'xmlsimple' +gem 'zip', '~> 2.0.2' # Gems related to internationalisation -gem 'fast_gettext' -gem 'gettext_i18n_rails' -gem 'gettext' +gem 'fast_gettext', '~> 0.7.0' +gem 'gettext_i18n_rails', '~> 0.9.4' +gem 'gettext', '~> 2.3.9' gem 'globalize3', :git => 'git://github.com/globalize/globalize.git', :ref => '5fd95f2389dff1' -gem 'locale' -gem 'routing-filter' -gem 'unicode' -gem 'unidecoder' +gem 'locale', '~> 2.0.8' +gem 'routing-filter', '~> 0.3.1' +gem 'unicode', '~> 0.4.4' +gem 'unidecoder', '~> 1.1.2' group :assets do - gem 'bootstrap-sass' + gem 'bootstrap-sass', '~> 2.3.1.2' gem 'sass-rails', '~> 3.2.3' gem 'compass-rails', '2.0.0' - gem 'coffee-rails', "~> 3.2.1" + gem 'coffee-rails', '~> 3.2.1' gem 'uglifier', '>= 1.0.3' - gem 'therubyracer' + gem 'therubyracer', '~> 0.12.0' end group :production do @@ -59,28 +63,27 @@ group :production do end group :test do - gem 'fakeweb' + gem 'fakeweb', '~> 1.3.0' gem 'coveralls', :require => false - gem 'webrat' - gem 'nokogiri' + gem 'webrat', '~> 0.7.3' + gem 'nokogiri', '~> 1.5.9' end group :test, :development do gem 'factory_girl_rails', '~> 1.7' - gem 'rspec-rails' - gem 'spork-rails' + gem 'rspec-rails', '~> 2.13.2' + gem 'spork-rails', '~> 3.2.1' end group :development do - gem 'capistrano' - gem 'mailcatcher' - gem 'quiet_assets' - gem 'rdoc' + gem 'capistrano', '~> 2.15.4' + gem 'mailcatcher', '~> 0.5.11' + gem 'quiet_assets', '~> 1.0.2' + gem 'rdoc', '~> 3.12.2' end group :debug do - gem 'ruby-debug', :platforms => :ruby_18 - gem 'debugger', :platforms => :ruby_19 - gem 'annotate' + gem 'ruby-debug', '~> 0.10.4', :platforms => :ruby_18 + gem 'debugger', '~> 1.6.0', :platforms => :ruby_19 + gem 'annotate', '~> 2.5.0' end - diff --git a/Gemfile.lock b/Gemfile.lock index b5f5671f3..3af06fc8d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -19,6 +19,7 @@ GIT GIT remote: git://github.com/technoweenie/acts_as_versioned.git revision: 63b1fc8529d028fae632fe80ec0cb25df56cd76b + ref: 63b1fc8529d028 specs: acts_as_versioned (0.6.0) activerecord (>= 3.0.9) @@ -125,14 +126,17 @@ GEM tilt highline (1.6.19) hike (1.2.3) + holidays (1.0.8) i18n (0.6.11) + icalendar (1.4.3) + iso_country_codes (0.6.1) journey (1.0.4) jquery-rails (3.0.4) railties (>= 3.0, < 5.0) thor (>= 0.14, < 2.0) jquery-ui-rails (4.1.0) railties (>= 3.1.0) - json (1.8.1) + json (1.8.2) libv8 (3.16.14.3) linecache (0.46) rbx-require-relative (> 0.0.4) @@ -167,7 +171,7 @@ GEM paper_trail (2.7.2) activerecord (~> 3.0) railties (~> 3.0) - pg (0.15.1) + pg (0.17.1) polyglot (0.3.5) quiet_assets (1.0.2) railties (>= 3.1, < 5.0) @@ -201,7 +205,7 @@ GEM rbx-require-relative (0.0.9) rdoc (3.12.2) json (~> 1.4) - recaptcha (0.3.5) + recaptcha (0.3.6) ref (1.0.5) rest-client (1.6.7) mime-types (>= 1.16) @@ -230,6 +234,7 @@ GEM railties (~> 3.2.0) sass (>= 3.1.10) tilt (~> 1.3) + secure_headers (1.3.4) simplecov (0.7.1) multi_json (~> 1.0) simplecov-html (~> 0.7.1) @@ -287,60 +292,64 @@ PLATFORMS DEPENDENCIES acts_as_versioned! - annotate - bootstrap-sass - capistrano - charlock_holmes + annotate (~> 2.5.0) + bootstrap-sass (~> 2.3.1.2) + capistrano (~> 2.15.4) + charlock_holmes (~> 0.6.9.4) coffee-rails (~> 3.2.1) compass-rails (= 2.0.0) coveralls - debugger - dynamic_form - exception_notification + debugger (~> 1.6.0) + dynamic_form (~> 1.1.4) + exception_notification (~> 3.0.1) factory_girl_rails (~> 1.7) - fakeweb - fancybox-rails - fast_gettext - foundation-rails - gettext - gettext_i18n_rails + fakeweb (~> 1.3.0) + fancybox-rails (~> 0.2.1) + fast_gettext (~> 0.7.0) + foundation-rails (~> 5.2.1.0) + gettext (~> 2.3.9) + gettext_i18n_rails (~> 0.9.4) globalize3! + holidays (~> 1.0.8) + icalendar (= 1.4.3) + iso_country_codes (~> 0.6.1) jquery-rails (~> 3.0.4) - jquery-ui-rails - json - locale - mahoro - mailcatcher - memcache-client - net-http-local - net-purge + jquery-ui-rails (~> 4.1.0) + json (~> 1.8.1) + locale (~> 2.0.8) + mahoro (~> 0.4) + mailcatcher (~> 0.5.11) + memcache-client (~> 1.8.5) + net-http-local (~> 0.1.2) + net-purge (~> 0.1.0) newrelic_rpm - nokogiri - pg - quiet_assets - rack + nokogiri (~> 1.5.9) + pg (~> 0.17.1) + quiet_assets (~> 1.0.2) + rack (~> 1.4.5) rails (= 3.2.21) - rails-i18n + rails-i18n (~> 0.7.3) rake (= 0.9.2.2) - rdoc + rdoc (~> 3.12.2) recaptcha (~> 0.3.1) - rmagick - routing-filter - rspec-rails - ruby-debug + rmagick (~> 2.13.2) + routing-filter (~> 0.3.1) + rspec-rails (~> 2.13.2) + ruby-debug (~> 0.10.4) ruby-msg (~> 1.5.0)! sass-rails (~> 3.2.3) - spork-rails + secure_headers (~> 1.3.4) + spork-rails (~> 3.2.1) statistics2 (~> 0.54) - syslog_protocol - therubyracer - thin + syslog_protocol (~> 0.9.2) + therubyracer (~> 0.12.0) + thin (~> 1.5.1) uglifier (>= 1.0.3) - unicode - unidecoder - vpim - webrat - will_paginate + unicode (~> 0.4.4) + unidecoder (~> 1.1.2) + vpim (~> 13.11.11) + webrat (~> 0.7.3) + will_paginate (~> 3.0.5) xapian-full-alaveteli (~> 1.2.9.5) - xml-simple - zip + xml-simple (~> 1.1.2) + zip (~> 2.0.2) diff --git a/app/assets/images/next-step-facebook.png b/app/assets/images/next-step-facebook.png Binary files differnew file mode 100644 index 000000000..c01fa6ced --- /dev/null +++ b/app/assets/images/next-step-facebook.png diff --git a/app/assets/images/next-step-twitter.png b/app/assets/images/next-step-twitter.png Binary files differnew file mode 100644 index 000000000..e79255bd6 --- /dev/null +++ b/app/assets/images/next-step-twitter.png diff --git a/app/assets/javascripts/admin.js b/app/assets/javascripts/admin.js index 4925a65a4..9402f7f6c 100644 --- a/app/assets/javascripts/admin.js +++ b/app/assets/javascripts/admin.js @@ -3,8 +3,10 @@ //= require jquery.ui.tabs //= require jquery.ui.sortable //= require jquery.ui.effect-highlight -//= require admin/bootstrap-collapse -//= require admin/bootstrap-tab +//= require bootstrap-collapse +//= require bootstrap-tab +//= require bootstrap-dropdown //= require admin/admin //= require admin/category-order +//= require admin/holidays //= require jquery_ujs diff --git a/app/assets/javascripts/admin/bootstrap-collapse.js b/app/assets/javascripts/admin/bootstrap-collapse.js deleted file mode 100644 index 9a364468b..000000000 --- a/app/assets/javascripts/admin/bootstrap-collapse.js +++ /dev/null @@ -1,138 +0,0 @@ -/* ============================================================= - * bootstrap-collapse.js v2.0.2 - * http://twitter.github.com/bootstrap/javascript.html#collapse - * ============================================================= - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================ */ - -!function( $ ){ - - "use strict" - - var Collapse = function ( element, options ) { - this.$element = $(element) - this.options = $.extend({}, $.fn.collapse.defaults, options) - - if (this.options["parent"]) { - this.$parent = $(this.options["parent"]) - } - - this.options.toggle && this.toggle() - } - - Collapse.prototype = { - - constructor: Collapse - - , dimension: function () { - var hasWidth = this.$element.hasClass('width') - return hasWidth ? 'width' : 'height' - } - - , show: function () { - var dimension = this.dimension() - , scroll = $.camelCase(['scroll', dimension].join('-')) - , actives = this.$parent && this.$parent.find('.in') - , hasData - - if (actives && actives.length) { - hasData = actives.data('collapse') - actives.collapse('hide') - hasData || actives.data('collapse', null) - } - - this.$element[dimension](0) - this.transition('addClass', 'show', 'shown') - this.$element[dimension](this.$element[0][scroll]) - - } - - , hide: function () { - var dimension = this.dimension() - this.reset(this.$element[dimension]()) - this.transition('removeClass', 'hide', 'hidden') - this.$element[dimension](0) - } - - , reset: function ( size ) { - var dimension = this.dimension() - - this.$element - .removeClass('collapse') - [dimension](size || 'auto') - [0].offsetWidth - - this.$element[size ? 'addClass' : 'removeClass']('collapse') - - return this - } - - , transition: function ( method, startEvent, completeEvent ) { - var that = this - , complete = function () { - if (startEvent == 'show') that.reset() - that.$element.trigger(completeEvent) - } - - this.$element - .trigger(startEvent) - [method]('in') - - $.support.transition && this.$element.hasClass('collapse') ? - this.$element.one($.support.transition.end, complete) : - complete() - } - - , toggle: function () { - this[this.$element.hasClass('in') ? 'hide' : 'show']() - } - - } - - /* COLLAPSIBLE PLUGIN DEFINITION - * ============================== */ - - $.fn.collapse = function ( option ) { - return this.each(function () { - var $this = $(this) - , data = $this.data('collapse') - , options = typeof option == 'object' && option - if (!data) $this.data('collapse', (data = new Collapse(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.collapse.defaults = { - toggle: true - } - - $.fn.collapse.Constructor = Collapse - - - /* COLLAPSIBLE DATA-API - * ==================== */ - - $(function () { - $('body').on('click.collapse.data-api', '[data-toggle=collapse]', function ( e ) { - var $this = $(this), href - , target = $this.attr('data-target') - || e.preventDefault() - || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 - , option = $(target).data('collapse') ? 'toggle' : $this.data() - $(target).collapse(option) - }) - }) - -}( window.jQuery );
\ No newline at end of file diff --git a/app/assets/javascripts/admin/bootstrap-tab.js b/app/assets/javascripts/admin/bootstrap-tab.js deleted file mode 100644 index 26c9ece75..000000000 --- a/app/assets/javascripts/admin/bootstrap-tab.js +++ /dev/null @@ -1,130 +0,0 @@ -/* ======================================================== - * bootstrap-tab.js v2.0.1 - * http://twitter.github.com/bootstrap/javascript.html#tabs - * ======================================================== - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ======================================================== */ - - -!function( $ ){ - - "use strict" - - /* TAB CLASS DEFINITION - * ==================== */ - - var Tab = function ( element ) { - this.element = $(element) - } - - Tab.prototype = { - - constructor: Tab - - , show: function () { - var $this = this.element - , $ul = $this.closest('ul:not(.dropdown-menu)') - , selector = $this.attr('data-target') - , previous - , $target - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 - } - - if ( $this.parent('li').hasClass('active') ) return - - previous = $ul.find('.active a').last()[0] - - $this.trigger({ - type: 'show' - , relatedTarget: previous - }) - - $target = $(selector) - - this.activate($this.parent('li'), $ul) - this.activate($target, $target.parent(), function () { - $this.trigger({ - type: 'shown' - , relatedTarget: previous - }) - }) - } - - , activate: function ( element, container, callback) { - var $active = container.find('> .active') - , transition = callback - && $.support.transition - && $active.hasClass('fade') - - function next() { - $active - .removeClass('active') - .find('> .dropdown-menu > .active') - .removeClass('active') - - element.addClass('active') - - if (transition) { - element[0].offsetWidth // reflow for transition - element.addClass('in') - } else { - element.removeClass('fade') - } - - if ( element.parent('.dropdown-menu') ) { - element.closest('li.dropdown').addClass('active') - } - - callback && callback() - } - - transition ? - $active.one($.support.transition.end, next) : - next() - - $active.removeClass('in') - } - } - - - /* TAB PLUGIN DEFINITION - * ===================== */ - - $.fn.tab = function ( option ) { - return this.each(function () { - var $this = $(this) - , data = $this.data('tab') - if (!data) $this.data('tab', (data = new Tab(this))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.tab.Constructor = Tab - - - /* TAB DATA-API - * ============ */ - - $(function () { - $('body').on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { - e.preventDefault() - $(this).tab('show') - }) - }) - -}( window.jQuery );
\ No newline at end of file diff --git a/app/assets/javascripts/admin/holidays.js b/app/assets/javascripts/admin/holidays.js new file mode 100644 index 000000000..55eae9e2a --- /dev/null +++ b/app/assets/javascripts/admin/holidays.js @@ -0,0 +1,46 @@ +$(function() { + + // New button loads the 'new' form via AJAX + $('#new-holiday-button').click(function(){ + var new_call = $.ajax({ type: 'GET', url: $(this).attr('href')}); + new_call.done(function(response) { + $('#existing-holidays').before(response); + }); + return false; + + }); + + // Each edit button loads the 'edit' form for that holiday via AJAX + $('.holiday').each(function(index){ + var holiday_row = $(this); + var edit_button = holiday_row.find('.edit-button'); + edit_button.click(function(){ + var edit_call = $.ajax({ type: 'GET', url: holiday_row.data('target') }); + edit_call.done(function(response) { + holiday_row.html(response); + }); + return false; + }); + }); + + // Remove button removes form div for holiday from an import set + $('.remove-holiday').each(function(index){ + $(this).click(function(){ + $(this).parents('.import-holiday-info').remove(); + return false; + }); + }); + + if ($('#holiday_import_source_suggestions').is(':checked')){ + $('#holiday_import_ical_feed_url').attr("disabled", "disabled"); + } + // Enable and disable the feed element when that is selected as the import source + $('#holiday_import_source_feed').click(function(){ + $('#holiday_import_ical_feed_url').removeAttr("disabled"); + }); + + $('#holiday_import_source_suggestions').click(function(){ + $('#holiday_import_ical_feed_url').attr("disabled", "disabled"); + }); + +}); diff --git a/app/assets/javascripts/bootstrap-collapse.js b/app/assets/javascripts/bootstrap-collapse.js deleted file mode 100644 index 9a364468b..000000000 --- a/app/assets/javascripts/bootstrap-collapse.js +++ /dev/null @@ -1,138 +0,0 @@ -/* ============================================================= - * bootstrap-collapse.js v2.0.2 - * http://twitter.github.com/bootstrap/javascript.html#collapse - * ============================================================= - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================ */ - -!function( $ ){ - - "use strict" - - var Collapse = function ( element, options ) { - this.$element = $(element) - this.options = $.extend({}, $.fn.collapse.defaults, options) - - if (this.options["parent"]) { - this.$parent = $(this.options["parent"]) - } - - this.options.toggle && this.toggle() - } - - Collapse.prototype = { - - constructor: Collapse - - , dimension: function () { - var hasWidth = this.$element.hasClass('width') - return hasWidth ? 'width' : 'height' - } - - , show: function () { - var dimension = this.dimension() - , scroll = $.camelCase(['scroll', dimension].join('-')) - , actives = this.$parent && this.$parent.find('.in') - , hasData - - if (actives && actives.length) { - hasData = actives.data('collapse') - actives.collapse('hide') - hasData || actives.data('collapse', null) - } - - this.$element[dimension](0) - this.transition('addClass', 'show', 'shown') - this.$element[dimension](this.$element[0][scroll]) - - } - - , hide: function () { - var dimension = this.dimension() - this.reset(this.$element[dimension]()) - this.transition('removeClass', 'hide', 'hidden') - this.$element[dimension](0) - } - - , reset: function ( size ) { - var dimension = this.dimension() - - this.$element - .removeClass('collapse') - [dimension](size || 'auto') - [0].offsetWidth - - this.$element[size ? 'addClass' : 'removeClass']('collapse') - - return this - } - - , transition: function ( method, startEvent, completeEvent ) { - var that = this - , complete = function () { - if (startEvent == 'show') that.reset() - that.$element.trigger(completeEvent) - } - - this.$element - .trigger(startEvent) - [method]('in') - - $.support.transition && this.$element.hasClass('collapse') ? - this.$element.one($.support.transition.end, complete) : - complete() - } - - , toggle: function () { - this[this.$element.hasClass('in') ? 'hide' : 'show']() - } - - } - - /* COLLAPSIBLE PLUGIN DEFINITION - * ============================== */ - - $.fn.collapse = function ( option ) { - return this.each(function () { - var $this = $(this) - , data = $this.data('collapse') - , options = typeof option == 'object' && option - if (!data) $this.data('collapse', (data = new Collapse(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.collapse.defaults = { - toggle: true - } - - $.fn.collapse.Constructor = Collapse - - - /* COLLAPSIBLE DATA-API - * ==================== */ - - $(function () { - $('body').on('click.collapse.data-api', '[data-toggle=collapse]', function ( e ) { - var $this = $(this), href - , target = $this.attr('data-target') - || e.preventDefault() - || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 - , option = $(target).data('collapse') ? 'toggle' : $this.data() - $(target).collapse(option) - }) - }) - -}( window.jQuery );
\ No newline at end of file diff --git a/app/assets/javascripts/bootstrap-tab.js b/app/assets/javascripts/bootstrap-tab.js deleted file mode 100644 index 26c9ece75..000000000 --- a/app/assets/javascripts/bootstrap-tab.js +++ /dev/null @@ -1,130 +0,0 @@ -/* ======================================================== - * bootstrap-tab.js v2.0.1 - * http://twitter.github.com/bootstrap/javascript.html#tabs - * ======================================================== - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ======================================================== */ - - -!function( $ ){ - - "use strict" - - /* TAB CLASS DEFINITION - * ==================== */ - - var Tab = function ( element ) { - this.element = $(element) - } - - Tab.prototype = { - - constructor: Tab - - , show: function () { - var $this = this.element - , $ul = $this.closest('ul:not(.dropdown-menu)') - , selector = $this.attr('data-target') - , previous - , $target - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 - } - - if ( $this.parent('li').hasClass('active') ) return - - previous = $ul.find('.active a').last()[0] - - $this.trigger({ - type: 'show' - , relatedTarget: previous - }) - - $target = $(selector) - - this.activate($this.parent('li'), $ul) - this.activate($target, $target.parent(), function () { - $this.trigger({ - type: 'shown' - , relatedTarget: previous - }) - }) - } - - , activate: function ( element, container, callback) { - var $active = container.find('> .active') - , transition = callback - && $.support.transition - && $active.hasClass('fade') - - function next() { - $active - .removeClass('active') - .find('> .dropdown-menu > .active') - .removeClass('active') - - element.addClass('active') - - if (transition) { - element[0].offsetWidth // reflow for transition - element.addClass('in') - } else { - element.removeClass('fade') - } - - if ( element.parent('.dropdown-menu') ) { - element.closest('li.dropdown').addClass('active') - } - - callback && callback() - } - - transition ? - $active.one($.support.transition.end, next) : - next() - - $active.removeClass('in') - } - } - - - /* TAB PLUGIN DEFINITION - * ===================== */ - - $.fn.tab = function ( option ) { - return this.each(function () { - var $this = $(this) - , data = $this.data('tab') - if (!data) $this.data('tab', (data = new Tab(this))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.tab.Constructor = Tab - - - /* TAB DATA-API - * ============ */ - - $(function () { - $('body').on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { - e.preventDefault() - $(this).tab('show') - }) - }) - -}( window.jQuery );
\ No newline at end of file diff --git a/app/assets/stylesheets/admin.scss b/app/assets/stylesheets/admin.scss index 104f10c75..31fe7e95a 100644 --- a/app/assets/stylesheets/admin.scss +++ b/app/assets/stylesheets/admin.scss @@ -80,6 +80,10 @@ body.admin { } } + .fieldWithErrors input{ + border: 1px solid #ff0c11; + } + body.admin blockquote p { font-size: 13px; display: inline; @@ -119,5 +123,34 @@ body.admin { padding: 3px 0; } + /* Holidays */ + .day_select { + width: 75px; + } + + .holiday-description, .holiday-day, .holiday-buttons, .holiday-destroy { + padding: 6px 4px; + } + + .holiday-description, .holiday-day, .holiday-buttons{ + display: inline-block; + } + + .holiday-description { + width: 300px; + } + .holiday-day { + width: 240px; + text-align: center; + } + .holiday-buttons{ + width: 200px; + text-align: right; + } + + #import_start_year, #import_end_year { + width: 75px; + } + } diff --git a/app/assets/stylesheets/responsive/_global_style.scss b/app/assets/stylesheets/responsive/_global_style.scss index af25fb0b0..0ffa875ab 100644 --- a/app/assets/stylesheets/responsive/_global_style.scss +++ b/app/assets/stylesheets/responsive/_global_style.scss @@ -225,6 +225,11 @@ div.pagination { } +.pretitle { + margin-bottom: -0.5em; + color: #666; +} + /* Search result highlighting */ .highlight { background:#FF0; diff --git a/app/assets/stylesheets/responsive/_new_request_layout.scss b/app/assets/stylesheets/responsive/_new_request_layout.scss index a2ab23060..55c72b8e3 100644 --- a/app/assets/stylesheets/responsive/_new_request_layout.scss +++ b/app/assets/stylesheets/responsive/_new_request_layout.scss @@ -58,6 +58,10 @@ } } +#typeahead_response .close-button { + float: right; +} + /* Advice sits on right hand side */ #request_advice { @@ -161,5 +165,40 @@ div.batch_public_body_toggle { } +/* Request sent page */ +.request-sent-message { + margin-top: 1em; + h1 { + margin-bottom: 1em; + } +} +.request-sent-message__row { + @include grid-row($behavior: nest); +} +.request-sent-message__column-1 { + @include grid-column(12); + @include respond-min( $main_menu-mobile_menu_cutoff ){ + @include grid-column($columns:8); + @include ie8{ + padding-right: 0.9375em; + } + @include lte-ie7 { + width: 36.813em; + } + } +} + +.request-sent-message__column-2 { + @include grid-column(12); + @include respond-min( $main_menu-mobile_menu_cutoff ){ + @include grid-column($columns:4); + @include ie8{ + padding-left: 0.9375em; + } + @include lte-ie7 { + width: 17.438em; + } + } +} diff --git a/app/assets/stylesheets/responsive/_new_request_style.scss b/app/assets/stylesheets/responsive/_new_request_style.scss index 86e17cbfe..e07ecb55c 100644 --- a/app/assets/stylesheets/responsive/_new_request_style.scss +++ b/app/assets/stylesheets/responsive/_new_request_style.scss @@ -61,3 +61,32 @@ color: #0000EE; font-size: 0.9em; } + +/* Request sent page */ +.request-sent-message { + border-bottom: 1px solid #e9e9e9; + font-size: 1em; + h1 { + } +} + +.request-sent-message__column-1 { + h2 { + font-size: 1em; + } +} + +.what-next { + background-color: #e6e8d6; + background-color: rgba(255,255,255, 0.4); + padding: 0.5em 1.5em 1.5em; + margin-bottom: 1.5em; +} + +.what-next__list { + list-style: none outside none; + padding-left: 0; + li { + margin-bottom: 0.5em; + } +} diff --git a/app/assets/stylesheets/responsive/_public_body_layout.scss b/app/assets/stylesheets/responsive/_public_body_layout.scss index ac02b1c10..39d42e213 100644 --- a/app/assets/stylesheets/responsive/_public_body_layout.scss +++ b/app/assets/stylesheets/responsive/_public_body_layout.scss @@ -3,3 +3,8 @@ #foi_results_section { @include grid-column(12); } + +.back-to-results { + @include grid-column(12); + margin-top: 0.5em; +} diff --git a/app/assets/stylesheets/responsive/_public_body_style.scss b/app/assets/stylesheets/responsive/_public_body_style.scss index 240d92618..4040198b3 100644 --- a/app/assets/stylesheets/responsive/_public_body_style.scss +++ b/app/assets/stylesheets/responsive/_public_body_style.scss @@ -1,4 +1,14 @@ /* Style for public body pages */ + +.back-to-results { + .message { + margin-top: 0.5em; + padding: 0.5em 0.8em; + background-color: #fff; + background-color: rgba(0,0,0,0.1); + } +} + .public-body-name-prefix { color:#888; font-size: 1.3em; diff --git a/app/assets/stylesheets/responsive/_signin_layout.scss b/app/assets/stylesheets/responsive/_signin_layout.scss index 44999d31b..5a0e0057f 100644 --- a/app/assets/stylesheets/responsive/_signin_layout.scss +++ b/app/assets/stylesheets/responsive/_signin_layout.scss @@ -6,7 +6,7 @@ #left_half { @include grid-column(12); @include respond-min( $main_menu-mobile_menu_cutoff ){ - @include grid-column($columns:5,$float:left); + @include grid-column($columns:7,$float:left); @include ie8{ padding-right: 0.9375em; } @@ -19,7 +19,7 @@ #right_half { @include grid-column(12); @include respond-min( $main_menu-mobile_menu_cutoff ){ - @include grid-column($columns:5,$float:right); + @include grid-column($columns:4,$float:right); @include ie8{ padding-left: 0.9375em; } @@ -29,20 +29,6 @@ } } -#middle_strip { - @include grid-column(12); - @include respond-min( $main_menu-mobile_menu_cutoff ){ - @include grid-column($columns:2,$float:left); - @include ie8{ - padding-left: 0.9375em; - padding-right: 0.9375em; - } - @include lte-ie7 { - width: 7.438em; - } - } -} - #sign_together{ @include grid-row($behavior: nest); } diff --git a/app/assets/stylesheets/responsive/_signin_style.scss b/app/assets/stylesheets/responsive/_signin_style.scss index 2bd2802b4..918392365 100644 --- a/app/assets/stylesheets/responsive/_signin_style.scss +++ b/app/assets/stylesheets/responsive/_signin_style.scss @@ -15,14 +15,19 @@ font-size:1.2em; } -p#sign_in_reason, p#superuser_message { +#sign_in_reason, #superuser_message { font-size:2em; font-weight:bold; line-height:1em; } -p#superuser_message { +#superuser_message { font-size:1.2em; } - +.sign-in-wrapper { + margin-top: 1.5em; + @include respond-min( $main_menu-mobile_menu_cutoff ){ + margin-top: 0; + } +} diff --git a/app/controllers/admin_censor_rule_controller.rb b/app/controllers/admin_censor_rule_controller.rb index 68ca57510..3387fd832 100644 --- a/app/controllers/admin_censor_rule_controller.rb +++ b/app/controllers/admin_censor_rule_controller.rb @@ -5,11 +5,15 @@ # Email: hello@mysociety.org; WWW: http://www.mysociety.org/ class AdminCensorRuleController < AdminController + + before_filter :set_editor, :only => [:create, :update] + before_filter :find_and_check_rule, :only => [:edit, :update, :destroy] + def new - if params[:info_request_id] - @info_request = InfoRequest.find(params[:info_request_id]) + if params[:request_id] + @info_request = InfoRequest.find(params[:request_id]) @censor_rule = @info_request.censor_rules.build - @form_url = admin_info_request_censor_rules_path(@info_request) + @form_url = admin_request_censor_rules_path(@info_request) end if params[:user_id] @@ -17,18 +21,13 @@ class AdminCensorRuleController < AdminController @censor_rule = @censor_user.censor_rules.build @form_url = admin_user_censor_rules_path(@censor_user) end - - @censor_rule ||= CensorRule.new - @form_url ||= admin_rule_create_path end def create - params[:censor_rule][:last_edit_editor] = admin_current_user - - if params[:info_request_id] - @info_request = InfoRequest.find(params[:info_request_id]) + if params[:request_id] + @info_request = InfoRequest.find(params[:request_id]) @censor_rule = @info_request.censor_rules.build(params[:censor_rule]) - @form_url = admin_info_request_censor_rules_path(@info_request) + @form_url = admin_request_censor_rules_path(@info_request) end if params[:user_id] @@ -37,26 +36,16 @@ class AdminCensorRuleController < AdminController @form_url = admin_user_censor_rules_path(@censor_user) end - @censor_rule ||= CensorRule.new(params[:censor_rule]) - @form_url ||= admin_rule_create_path - if @censor_rule.save - if !@censor_rule.info_request.nil? - expire_for_request(@censor_rule.info_request) - end - - if !@censor_rule.user.nil? - expire_requests_for_user(@censor_rule.user) - end flash[:notice] = 'CensorRule was successfully created.' - if !@censor_rule.info_request.nil? - redirect_to admin_request_show_url(@censor_rule.info_request) - elsif !@censor_rule.user.nil? - redirect_to admin_user_show_url(@censor_rule.user) - else - raise "internal error" + if @censor_rule.info_request + expire_for_request(@censor_rule.info_request) + redirect_to admin_request_url(@censor_rule.info_request) + elsif @censor_rule.user + expire_requests_for_user(@censor_rule.user) + redirect_to admin_user_url(@censor_rule.user) end else render :action => 'new' @@ -64,63 +53,55 @@ class AdminCensorRuleController < AdminController end def edit - @censor_rule = CensorRule.find(params[:id]) end def update - params[:censor_rule][:last_edit_editor] = admin_current_user - @censor_rule = CensorRule.find(params[:id]) - if @censor_rule.update_attributes(params[:censor_rule]) - unless @censor_rule.info_request.nil? - expire_for_request(@censor_rule.info_request) - end - - unless @censor_rule.user.nil? - expire_requests_for_user(@censor_rule.user) - end flash[:notice] = 'CensorRule was successfully updated.' - if !@censor_rule.info_request.nil? - redirect_to admin_request_show_url(@censor_rule.info_request) - elsif !@censor_rule.user.nil? - redirect_to admin_user_show_url(@censor_rule.user) - else - raise "internal error" + if @censor_rule.info_request + expire_for_request(@censor_rule.info_request) + redirect_to admin_request_url(@censor_rule.info_request) + elsif @censor_rule.user + expire_requests_for_user(@censor_rule.user) + redirect_to admin_user_url(@censor_rule.user) end + else render :action => 'edit' end end def destroy - @censor_rule = CensorRule.find(params[:censor_rule_id]) info_request = @censor_rule.info_request user = @censor_rule.user - @censor_rule.destroy - unless info_request.nil? - expire_for_request(info_request) - end - - unless user.nil? - expire_requests_for_user(user) - end - flash[:notice] = "CensorRule was successfully destroyed." - if !info_request.nil? - redirect_to admin_request_show_url(info_request) - elsif !user.nil? - redirect_to admin_user_show_url(user) - else - raise "internal error" + if info_request + expire_for_request(info_request) + redirect_to admin_request_url(info_request) + elsif user + expire_requests_for_user(user) if user + redirect_to admin_user_url(user) end + end private + def set_editor + params[:censor_rule][:last_edit_editor] = admin_current_user + end + + def find_and_check_rule + @censor_rule = CensorRule.find(params[:id]) + unless (@censor_rule.user || @censor_rule.info_request) + flash[:notice] = 'Only user and request censor rules can be edited' + redirect_to admin_general_index_path + end + end end diff --git a/app/controllers/admin_comment_controller.rb b/app/controllers/admin_comment_controller.rb new file mode 100644 index 000000000..0aafb122a --- /dev/null +++ b/app/controllers/admin_comment_controller.rb @@ -0,0 +1,36 @@ +# app/controllers/admin_comment_controller.rb: +# Controller for editing comments from the admin interface. +# +# Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. +# Email: hello@mysociety.org; WWW: http://www.mysociety.org/ + +class AdminCommentController < AdminController + + def edit + @comment = Comment.find(params[:id]) + end + + def update + @comment = Comment.find(params[:id]) + + old_body = @comment.body + old_visible = @comment.visible + @comment.visible = params[:comment][:visible] == "true" ? true : false + + if @comment.update_attributes(params[:comment]) + @comment.info_request.log_event("edit_comment", + { :comment_id => @comment.id, + :editor => admin_current_user(), + :old_body => old_body, + :body => @comment.body, + :old_visible => old_visible, + :visible => @comment.visible, + }) + flash[:notice] = 'Comment successfully updated.' + redirect_to admin_request_url(@comment.info_request) + else + render :action => 'edit' + end + end + +end diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb index 3bf40b8f9..7760c372b 100644 --- a/app/controllers/admin_controller.rb +++ b/app/controllers/admin_controller.rb @@ -9,7 +9,6 @@ require 'fileutils' class AdminController < ApplicationController layout "admin" before_filter :authenticate - protect_from_forgery # See ActionController::RequestForgeryProtection for details # action to take if expecting an authenticity token and one isn't received def handle_unverified_request diff --git a/app/controllers/admin_holiday_imports_controller.rb b/app/controllers/admin_holiday_imports_controller.rb new file mode 100644 index 000000000..8596936f0 --- /dev/null +++ b/app/controllers/admin_holiday_imports_controller.rb @@ -0,0 +1,28 @@ +class AdminHolidayImportsController < AdminController + + def new + @holiday_import = HolidayImport.new(holiday_import_params) + @holiday_import.populate if @holiday_import.valid? + end + + def create + @holiday_import = HolidayImport.new(holiday_import_params) + if @holiday_import.save + notice = "Holidays successfully imported" + redirect_to admin_holidays_path, :notice => notice + else + render :new + end + end + + private + + def holiday_import_params(key = :holiday_import) + if params[key] + params[key].slice(:holidays_attributes, :start_year, :end_year, :source, :ical_feed_url) + else + {} + end + end + +end diff --git a/app/controllers/admin_holidays_controller.rb b/app/controllers/admin_holidays_controller.rb new file mode 100644 index 000000000..9177ebd44 --- /dev/null +++ b/app/controllers/admin_holidays_controller.rb @@ -0,0 +1,67 @@ +class AdminHolidaysController < AdminController + + def index + get_all_holidays + end + + def new + @holiday = Holiday.new + if request.xhr? + render :partial => 'new_form', :locals => { :holiday => @holiday } + else + render :action => 'new' + end + end + + def create + @holiday = Holiday.new(holiday_params) + if @holiday.save + notice = "Holiday successfully created." + redirect_to admin_holidays_path, :notice => notice + else + render :new + end + end + + def edit + @holiday = Holiday.find(params[:id]) + if request.xhr? + render :partial => 'edit_form' + else + render :action => 'edit' + end + end + + def update + @holiday = Holiday.find(params[:id]) + if @holiday.update_attributes(holiday_params) + flash[:notice] = 'Holiday successfully updated.' + redirect_to admin_holidays_path + else + render :edit + end + end + + def destroy + @holiday = Holiday.find(params[:id]) + @holiday.destroy + notice = "Holiday successfully destroyed" + redirect_to admin_holidays_path, :notice => notice + end + + private + + def get_all_holidays + @holidays_by_year = Holiday.all.group_by { |holiday| holiday.day.year } + @years = @holidays_by_year.keys.sort.reverse + end + + def holiday_params(key = :holiday) + if params[key] + params[key].slice(:description, 'day(1i)', 'day(2i)', 'day(3i)') + else + {} + end + end + +end diff --git a/app/controllers/admin_incoming_message_controller.rb b/app/controllers/admin_incoming_message_controller.rb index 6b50d0e36..bc653bf53 100644 --- a/app/controllers/admin_incoming_message_controller.rb +++ b/app/controllers/admin_incoming_message_controller.rb @@ -20,14 +20,14 @@ class AdminIncomingMessageController < AdminController :prominence_reason => @incoming_message.prominence_reason) expire_for_request(@incoming_message.info_request) flash[:notice] = 'Incoming message successfully updated.' - redirect_to admin_request_show_url(@incoming_message.info_request) + redirect_to admin_request_url(@incoming_message.info_request) else render :action => 'edit' end end def destroy - @incoming_message = IncomingMessage.find(params[:incoming_message_id]) + @incoming_message = IncomingMessage.find(params[:id]) @info_request = @incoming_message.info_request incoming_message_id = @incoming_message.id @@ -37,11 +37,11 @@ class AdminIncomingMessageController < AdminController # expire cached files expire_for_request(@info_request) flash[:notice] = 'Incoming message successfully destroyed.' - redirect_to admin_request_show_url(@info_request) + redirect_to admin_request_url(@info_request) end def redeliver - incoming_message = IncomingMessage.find(params[:redeliver_incoming_message_id]) + incoming_message = IncomingMessage.find(params[:id]) message_ids = params[:url_title].split(",").each {|x| x.strip} previous_request = incoming_message.info_request destination_request = nil @@ -54,7 +54,7 @@ class AdminIncomingMessageController < AdminController end if destination_request.nil? flash[:error] = "Failed to find destination request '" + m + "'" - return redirect_to admin_request_show_url(previous_request) + return redirect_to admin_request_url(previous_request) end raw_email_data = incoming_message.raw_email.data @@ -74,7 +74,7 @@ class AdminIncomingMessageController < AdminController expire_for_request(previous_request) incoming_message.fully_destroy end - redirect_to admin_request_show_url(destination_request) + redirect_to admin_request_url(destination_request) end end diff --git a/app/controllers/admin_info_request_event_controller.rb b/app/controllers/admin_info_request_event_controller.rb new file mode 100644 index 000000000..17d147582 --- /dev/null +++ b/app/controllers/admin_info_request_event_controller.rb @@ -0,0 +1,24 @@ +# app/controllers/admin_info_request_event_controller.rb: +# Controller for FOI request event manipulation from the admin interface. +# +# Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. +# Email: hello@mysociety.org; WWW: http://www.mysociety.org/ + +class AdminInfoRequestEventController < AdminController + + # used so due dates get fixed + def update + @info_request_event = InfoRequestEvent.find(params[:id]) + if @info_request_event.event_type != 'response' + raise Exception("can only mark responses as requires clarification") + end + @info_request_event.described_state = 'waiting_clarification' + @info_request_event.calculated_state = 'waiting_clarification' + # TODO: deliberately don't update described_at so doesn't reenter search? + @info_request_event.save! + + flash[:notice] = "Old response marked as having been a clarification" + redirect_to admin_request_url(@info_request_event.info_request) + end + +end diff --git a/app/controllers/admin_outgoing_message_controller.rb b/app/controllers/admin_outgoing_message_controller.rb index ec0981677..2ee811dc0 100644 --- a/app/controllers/admin_outgoing_message_controller.rb +++ b/app/controllers/admin_outgoing_message_controller.rb @@ -5,7 +5,7 @@ class AdminOutgoingMessageController < AdminController end def destroy - @outgoing_message = OutgoingMessage.find(params[:outgoing_message_id]) + @outgoing_message = OutgoingMessage.find(params[:id]) @info_request = @outgoing_message.info_request outgoing_message_id = @outgoing_message.id @@ -14,7 +14,7 @@ class AdminOutgoingMessageController < AdminController { :editor => admin_current_user(), :deleted_outgoing_message_id => outgoing_message_id }) flash[:notice] = 'Outgoing message successfully destroyed.' - redirect_to admin_request_show_url(@info_request) + redirect_to admin_request_url(@info_request) end def update @@ -38,10 +38,41 @@ class AdminOutgoingMessageController < AdminController :prominence_reason => @outgoing_message.prominence_reason }) flash[:notice] = 'Outgoing message successfully updated.' expire_for_request(@outgoing_message.info_request) - redirect_to admin_request_show_url(@outgoing_message.info_request) + redirect_to admin_request_url(@outgoing_message.info_request) else render :action => 'edit' end end + def resend + @outgoing_message = OutgoingMessage.find(params[:id]) + @outgoing_message.prepare_message_for_resend + + mail_message = case @outgoing_message.message_type + when 'initial_request' + OutgoingMailer.initial_request( + @outgoing_message.info_request, + @outgoing_message + ).deliver + when 'followup' + OutgoingMailer.followup( + @outgoing_message.info_request, + @outgoing_message, + @outgoing_message.incoming_message_followup + ).deliver + else + raise "Message id #{id} has type '#{message_type}' which cannot be resent" + end + + @outgoing_message.record_email_delivery( + mail_message.to_addrs.join(', '), + mail_message.message_id, + 'resent' + ) + + flash[:notice] = "Outgoing message resent" + redirect_to admin_request_url(@outgoing_message.info_request) + end + + end diff --git a/app/controllers/admin_public_body_controller.rb b/app/controllers/admin_public_body_controller.rb index baa5a1d22..d188f109d 100644 --- a/app/controllers/admin_public_body_controller.rb +++ b/app/controllers/admin_public_body_controller.rb @@ -5,69 +5,9 @@ # Email: hello@mysociety.org; WWW: http://www.mysociety.org/ class AdminPublicBodyController < AdminController - def index - list - render :action => 'list' - end - - def _lookup_query_internal - @locale = self.locale_from_params() - underscore_locale = @locale.gsub '-', '_' - I18n.with_locale(@locale) do - @query = params[:query] - if @query == "" - @query = nil - end - @page = params[:page] - if @page == "" - @page = nil - end - @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 = '#{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 - def list - self._lookup_query_internal - end - - def mass_tag_add - self._lookup_query_internal - - if params[:new_tag] and params[:new_tag] != "" - if params[:table_name] == 'exact' - bodies = @public_bodies_by_tag - elsif params[:table_name] == 'substring' - bodies = @public_bodies - else - raise "Unknown table_name " + params[:table_name] - end - for body in bodies - body.add_tag_if_not_already_present(params[:new_tag]) - end - flash[:notice] = "Added tag to table of bodies." - end - - redirect_to admin_body_list_url(:query => @query, :page => @page) - end - - def missing_scheme - # There might be a way to do this in ActiveRecord, but I can't find it - @public_bodies = PublicBody.find_by_sql(" - SELECT a.id, a.name, a.url_name, COUNT(*) AS howmany - FROM public_bodies a JOIN info_requests r ON a.id = r.public_body_id - WHERE a.publication_scheme = '' - GROUP BY a.id, a.name, a.url_name - ORDER BY howmany DESC - LIMIT 20 - ") - @stats = { - "total" => PublicBody.count, - "entered" => PublicBody.count(:conditions => "publication_scheme != ''") - } + def index + lookup_query end def show @@ -116,7 +56,7 @@ class AdminPublicBodyController < AdminController @change_request.send_response(params[:subject], response_text) end flash[:notice] = 'PublicBody was successfully created.' - redirect_to admin_body_show_url(@public_body) + redirect_to admin_body_url(@public_body) else render :action => 'new' end @@ -157,7 +97,7 @@ class AdminPublicBodyController < AdminController @change_request.send_response(params[:subject], params[:response]) end flash[:notice] = 'PublicBody was successfully updated.' - redirect_to admin_body_show_url(@public_body) + redirect_to admin_body_url(@public_body) else render :action => 'edit' end @@ -171,17 +111,53 @@ class AdminPublicBodyController < AdminController if public_body.info_requests.size > 0 flash[:notice] = "There are requests associated with the authority, so can't destroy it" - redirect_to admin_body_show_url(public_body) + redirect_to admin_body_url(public_body) return end public_body.tag_string = "" public_body.destroy flash[:notice] = "PublicBody was successfully destroyed." - redirect_to admin_body_list_url + redirect_to admin_bodies_url end end + def mass_tag_add + lookup_query + + if params[:new_tag] and params[:new_tag] != "" + if params[:table_name] == 'exact' + bodies = @public_bodies_by_tag + elsif params[:table_name] == 'substring' + bodies = @public_bodies + else + raise "Unknown table_name " + params[:table_name] + end + for body in bodies + body.add_tag_if_not_already_present(params[:new_tag]) + end + flash[:notice] = "Added tag to table of bodies." + end + + redirect_to admin_bodies_url(:query => @query, :page => @page) + end + + def missing_scheme + # There might be a way to do this in ActiveRecord, but I can't find it + @public_bodies = PublicBody.find_by_sql(" + SELECT a.id, a.name, a.url_name, COUNT(*) AS howmany + FROM public_bodies a JOIN info_requests r ON a.id = r.public_body_id + WHERE a.publication_scheme = '' + GROUP BY a.id, a.name, a.url_name + ORDER BY howmany DESC + LIMIT 20 + ") + @stats = { + "total" => PublicBody.count, + "entered" => PublicBody.count(:conditions => "publication_scheme != ''") + } + end + def import_csv @notes = "" @errors = "" @@ -261,4 +237,24 @@ class AdminPublicBodyController < AdminController return csv_contents end + def lookup_query + @locale = self.locale_from_params() + underscore_locale = @locale.gsub '-', '_' + I18n.with_locale(@locale) do + @query = params[:query] + if @query == "" + @query = nil + end + @page = params[:page] + if @page == "" + @page = nil + end + @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 = '#{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 + end diff --git a/app/controllers/admin_raw_email_controller.rb b/app/controllers/admin_raw_email_controller.rb new file mode 100644 index 000000000..1b3ee2871 --- /dev/null +++ b/app/controllers/admin_raw_email_controller.rb @@ -0,0 +1,45 @@ +# app/controllers/admin_raw_email_controller.rb: +# Controller for managing raw emails from the admin interface. +# +# Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. +# Email: hello@mysociety.org; WWW: http://www.mysociety.org/ + +class AdminRawEmailController < AdminController + + def show + @raw_email = RawEmail.find(params[:id]) + respond_to do |format| + format.html do + # For the holding pen, try to guess where it should be ... + @holding_pen = false + if (@raw_email.incoming_message.info_request == InfoRequest.holding_pen_request && !@raw_email.incoming_message.empty_from_field?) + @holding_pen = true + + # 1. Use domain of email to try and guess which public body it + # is associated with, so we can display that. + email = @raw_email.incoming_message.from_email + domain = PublicBody.extract_domain_from_email(email) + + if domain.nil? + @public_bodies = [] + else + @public_bodies = PublicBody.find(:all, :order => "name", + :conditions => [ "lower(request_email) like lower('%'||?||'%')", domain ]) + end + + # 2. Match the email address in the message without matching the hash + @info_requests = InfoRequest.guess_by_incoming_email(@raw_email.incoming_message) + + # 3. Give a reason why it's in the holding pen + last_event = InfoRequestEvent.find_by_incoming_message_id(@raw_email.incoming_message.id) + @rejected_reason = last_event.params[:rejected_reason] || "unknown reason" + end + end + format.text do + response.content_type = 'message/rfc822' + render :text => @raw_email.data + end + end + end + +end diff --git a/app/controllers/admin_request_controller.rb b/app/controllers/admin_request_controller.rb index 8f023bf12..1e083f57e 100644 --- a/app/controllers/admin_request_controller.rb +++ b/app/controllers/admin_request_controller.rb @@ -4,15 +4,9 @@ # Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. # Email: hello@mysociety.org; WWW: http://www.mysociety.org/ -require 'ostruct' - class AdminRequestController < AdminController - def index - list - render :action => 'list' - end - def list + def index @query = params[:query] if @query info_requests = InfoRequest.where(["lower(title) like lower('%'||?||'%')", @query]) @@ -35,36 +29,6 @@ class AdminRequestController < AdminController :locals => vars_for_explanation) end - def resend - @outgoing_message = OutgoingMessage.find(params[:outgoing_message_id]) - @outgoing_message.prepare_message_for_resend - - mail_message = case @outgoing_message.message_type - when 'initial_request' - OutgoingMailer.initial_request( - @outgoing_message.info_request, - @outgoing_message - ).deliver - when 'followup' - OutgoingMailer.followup( - @outgoing_message.info_request, - @outgoing_message, - @outgoing_message.incoming_message_followup - ).deliver - else - raise "Message id #{id} has type '#{message_type}' which cannot be resent" - end - - @outgoing_message.record_email_delivery( - mail_message.to_addrs.join(', '), - mail_message.message_id, - 'resent' - ) - - flash[:notice] = "Outgoing message resent" - redirect_to admin_request_show_url(@outgoing_message.info_request) - end - def edit @info_request = InfoRequest.find(params[:id]) end @@ -108,13 +72,13 @@ class AdminRequestController < AdminController # expire cached files expire_for_request(@info_request) flash[:notice] = 'Request successfully updated.' - redirect_to admin_request_show_url(@info_request) + redirect_to admin_request_url(@info_request) else render :action => 'edit' end end - def fully_destroy + def destroy @info_request = InfoRequest.find(params[:id]) user = @info_request.user @@ -125,36 +89,12 @@ class AdminRequestController < AdminController expire_for_request(@info_request) email = user.try(:email) ? user.email : 'This request is external so has no associated user' flash[:notice] = "Request #{ url_title } has been completely destroyed. Email of user who made request: #{ email }" - redirect_to admin_request_list_url - end - - def edit_comment - @comment = Comment.find(params[:id]) - end - - def update_comment - @comment = Comment.find(params[:id]) - - old_body = @comment.body - old_visible = @comment.visible - @comment.visible = params[:comment][:visible] == "true" ? true : false - - if @comment.update_attributes(params[:comment]) - @comment.info_request.log_event("edit_comment", - { :comment_id => @comment.id, :editor => admin_current_user(), - :old_body => old_body, :body => @comment.body, - :old_visible => old_visible, :visible => @comment.visible, - }) - flash[:notice] = 'Comment successfully updated.' - redirect_to admin_request_show_url(@comment.info_request) - else - render :action => 'edit_comment' - end + redirect_to admin_requests_url end # change user or public body of a request magically - def move_request - info_request = InfoRequest.find(params[:info_request_id]) + def move + info_request = InfoRequest.find(params[:id]) if params[:commit] == 'Move request to user' && !params[:user_url_name].blank? old_user = info_request.user destination_user = User.find_by_url_name(params[:user_url_name]) @@ -172,7 +112,7 @@ class AdminRequestController < AdminController info_request.reindex_request_events flash[:notice] = "Message has been moved to new user" end - redirect_to admin_request_show_url(info_request) + redirect_to admin_request_url(info_request) elsif params[:commit] == 'Move request to authority' && !params[:public_body_url_name].blank? old_public_body = info_request.public_body destination_public_body = PublicBody.find_by_url_name(params[:public_body_url_name]) @@ -191,10 +131,10 @@ class AdminRequestController < AdminController flash[:notice] = "Request has been moved to new body" end - redirect_to admin_request_show_url(info_request) + redirect_to admin_request_url(info_request) else flash[:error] = "Please enter the user or authority to move the request to" - redirect_to admin_request_show_url(info_request) + redirect_to admin_request_url(info_request) end end @@ -218,7 +158,7 @@ class AdminRequestController < AdminController if !info_request.public_body.is_foi_officer?(user) flash[:notice] = user.email + " is not an email at the domain @" + info_request.public_body.foi_officer_domain_required + ", so won't be able to upload." - redirect_to admin_request_show_url(info_request) + redirect_to admin_request_url(info_request) return end @@ -230,61 +170,11 @@ class AdminRequestController < AdminController post_redirect.save! url = confirm_url(:email_token => post_redirect.email_token) - flash[:notice] = ("Send \"#{name}\" <<a href=\"mailto:#{email}\">#{email}</a>> this URL: <a href=\"#{url}\">#{url}</a> - it will log them in and let them upload a response to this request.").html_safe - redirect_to admin_request_show_url(info_request) - end - - def show_raw_email - @raw_email = RawEmail.find(params[:id]) - # For the holding pen, try to guess where it should be ... - @holding_pen = false - if (@raw_email.incoming_message.info_request == InfoRequest.holding_pen_request && !@raw_email.incoming_message.empty_from_field?) - @holding_pen = true - - # 1. Use domain of email to try and guess which public body it - # is associated with, so we can display that. - email = @raw_email.incoming_message.from_email - domain = PublicBody.extract_domain_from_email(email) - - if domain.nil? - @public_bodies = [] - else - @public_bodies = PublicBody.find(:all, :order => "name", - :conditions => [ "lower(request_email) like lower('%'||?||'%')", domain ]) - end - - # 2. Match the email address in the message without matching the hash - @info_requests = InfoRequest.guess_by_incoming_email(@raw_email.incoming_message) - - # 3. Give a reason why it's in the holding pen - last_event = InfoRequestEvent.find_by_incoming_message_id(@raw_email.incoming_message.id) - @rejected_reason = last_event.params[:rejected_reason] || "unknown reason" - end - end - - def download_raw_email - @raw_email = RawEmail.find(params[:id]) - - response.content_type = 'message/rfc822' - render :text => @raw_email.data - end - - # used so due dates get fixed - def mark_event_as_clarification - info_request_event = InfoRequestEvent.find(params[:info_request_event_id]) - if info_request_event.event_type != 'response' - raise Exception("can only mark responses as requires clarification") - end - info_request_event.described_state = 'waiting_clarification' - info_request_event.calculated_state = 'waiting_clarification' - # TODO: deliberately don't update described_at so doesn't reenter search? - info_request_event.save! - - flash[:notice] = "Old response marked as having been a clarification" - redirect_to admin_request_show_url(info_request_event.info_request) + flash[:notice] = ("Send \"#{CGI.escapeHTML(name)}\" <<a href=\"mailto:#{email}\">#{email}</a>> this URL: <a href=\"#{url}\">#{url}</a> - it will log them in and let them upload a response to this request.").html_safe + redirect_to admin_request_url(info_request) end - def hide_request + def hide ActiveRecord::Base.transaction do subject = params[:subject] explanation = params[:explanation] @@ -314,7 +204,7 @@ class AdminRequestController < AdminController end # expire cached files expire_for_request(info_request) - redirect_to admin_request_show_url(info_request) + redirect_to admin_request_url(info_request) end end diff --git a/app/controllers/admin_track_controller.rb b/app/controllers/admin_track_controller.rb index 085c9c6cc..63ee5c12e 100644 --- a/app/controllers/admin_track_controller.rb +++ b/app/controllers/admin_track_controller.rb @@ -5,7 +5,8 @@ # Email: hello@mysociety.org; WWW: http://www.mysociety.org/ class AdminTrackController < AdminController - def list + + def index @query = params[:query] if @query track_things = TrackThing.where(["lower(track_query) like lower('%'||?||'%')", @query]) @@ -13,7 +14,14 @@ class AdminTrackController < AdminController track_things = TrackThing end @admin_tracks = track_things.paginate :order => "created_at desc", :page => params[:page], :per_page => 100 - @popular = ActiveRecord::Base.connection.select_all("select count(*) as count, title, info_request_id from track_things join info_requests on info_request_id = info_requests.id where info_request_id is not null group by info_request_id, title order by count desc limit 10;") + @popular = ActiveRecord::Base.connection.select_all("select count(*) as count, title, info_request_id from track_things join info_requests on info_request_id = info_requests.id where info_request_id is not null group by info_request_id, title order by count desc limit 10;") + end + + def destroy + track_thing = TrackThing.find(params[:id].to_i) + track_thing.destroy + flash[:notice] = 'Track destroyed' + redirect_to admin_user_url(track_thing.tracking_user) end private diff --git a/app/controllers/admin_user_controller.rb b/app/controllers/admin_user_controller.rb index a6438e151..7ef461594 100644 --- a/app/controllers/admin_user_controller.rb +++ b/app/controllers/admin_user_controller.rb @@ -5,12 +5,8 @@ # Email: hello@mysociety.org; WWW: http://www.mysociety.org/ class AdminUserController < AdminController - def index - list - render :action => 'list' - end - def list + def index @query = params[:query] if @query users = User.where(["lower(name) like lower('%'||?||'%') or @@ -21,20 +17,11 @@ class AdminUserController < AdminController @admin_users = users.paginate :order => "name", :page => params[:page], :per_page => 100 end - def list_banned - @banned_users = User.paginate :order => "name", :page => params[:page], :per_page => 100, - :conditions => ["ban_text <> ''"] - end - def show # Don't use @user as that is any logged in user @admin_user = User.find(params[:id]) end - def show_bounce_message - @admin_user = User.find(params[:id]) - end - def edit @admin_user = User.find(params[:id]) end @@ -53,17 +40,19 @@ class AdminUserController < AdminController if @admin_user.valid? @admin_user.save! flash[:notice] = 'User successfully updated.' - redirect_to admin_user_show_url(@admin_user) + redirect_to admin_user_url(@admin_user) else render :action => 'edit' end end - def destroy_track - track_thing = TrackThing.find(params[:track_id].to_i) - track_thing.destroy - flash[:notice] = 'Track destroyed' - redirect_to admin_user_show_url(track_thing.tracking_user) + def banned + @banned_users = User.paginate :order => "name", :page => params[:page], :per_page => 100, + :conditions => ["ban_text <> ''"] + end + + def show_bounce_message + @admin_user = User.find(params[:id]) end def clear_bounce @@ -71,7 +60,7 @@ class AdminUserController < AdminController user.email_bounced_at = nil user.email_bounce_message = "" user.save! - redirect_to admin_user_show_url(user) + redirect_to admin_user_url(user) end def login_as @@ -87,16 +76,12 @@ class AdminUserController < AdminController def clear_profile_photo @admin_user = User.find(params[:id]) - if !request.post? - raise "Can only clear profile photo from POST request" - end - if @admin_user.profile_photo @admin_user.profile_photo.destroy end flash[:notice] = "Profile photo cleared" - redirect_to admin_user_show_url(@admin_user) + redirect_to admin_user_url(@admin_user) end def modify_comment_visibility diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 4d3f40d40..dbd879a1c 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -14,9 +14,14 @@ class ApplicationController < ActionController::Base end class RouteNotFound < StandardError end + protect_from_forgery + # assign our own handler method for non-local exceptions rescue_from Exception, :with => :render_exception + # Add some security-related headers (see config/initializers/secure_headers.rb) + ensure_security_headers + # Standard headers, footers and navigation for whole site layout "default" include FastGettext::Translation # make functions like _, n_, N_ etc available) @@ -27,6 +32,8 @@ class ApplicationController < ActionController::Base before_filter :check_in_post_redirect before_filter :session_remember_me before_filter :set_vary_header + before_filter :validate_session_timestamp + after_filter :persist_session_timestamp def set_vary_header response.headers['Vary'] = 'Cookie' @@ -118,6 +125,29 @@ class ApplicationController < ActionController::Base end end + # Set a TTL for non "remember me" sessions so that the cookie + # is not replayable forever + SESSION_TTL = 3.hours + def validate_session_timestamp + if session[:user_id] && session.key?(:ttl) && session[:ttl] < SESSION_TTL.ago + clear_session_credentials + redirect_to signin_path + end + end + + def persist_session_timestamp + session[:ttl] = Time.now if session[:user_id] && !session[:remember_me] + end + + # Logout form + def clear_session_credentials + session[:user_id] = nil + session[:user_circumstance] = nil + session[:remember_me] = false + session[:using_admin] = nil + session[:admin_name] = nil + end + def render_exception(exception) # In development or the admin interface let Rails handle the exception # with its stack trace templates diff --git a/app/controllers/comment_controller.rb b/app/controllers/comment_controller.rb index 2c0037577..890e9faaa 100644 --- a/app/controllers/comment_controller.rb +++ b/app/controllers/comment_controller.rb @@ -10,7 +10,6 @@ class CommentController < ApplicationController before_filter :create_track_thing, :only => [ :new ] before_filter :reject_unless_comments_allowed, :only => [ :new ] before_filter :reject_if_user_banned, :only => [ :new ] - protect_from_forgery :only => [ :new ] def new if params[:comment] diff --git a/app/controllers/public_body_controller.rb b/app/controllers/public_body_controller.rb index e64644a1b..2e540d198 100644 --- a/app/controllers/public_body_controller.rb +++ b/app/controllers/public_body_controller.rb @@ -55,6 +55,8 @@ class PublicBodyController < ApplicationController @xapian_requests = nil end + flash.keep(:search_params) + @track_thing = TrackThing.create_track_for_public_body(@public_body) @feed_autodetect = [ { :url => do_track_url(@track_thing, 'feed'), :title => @track_thing.params[:title_in_rss], :has_json => true } ] @@ -349,6 +351,7 @@ class PublicBodyController < ApplicationController # Since acts_as_xapian doesn't support the Partial match flag, we work around it # by making the last work a wildcard, which is quite the same query = params[:query] + flash[:search_params] = params.slice(:query, :bodies, :page) @xapian_requests = perform_search_typeahead(query, PublicBody) render :partial => "public_body/search_ahead" end diff --git a/app/controllers/request_controller.rb b/app/controllers/request_controller.rb index a334abcb7..081c14d7f 100644 --- a/app/controllers/request_controller.rb +++ b/app/controllers/request_controller.rb @@ -10,7 +10,6 @@ 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 @@ -38,6 +37,7 @@ class RequestController < ApplicationController end if !params[:query].nil? query = params[:query] + flash[:search_params] = params.slice(:query, :bodies, :page) @xapian_requests = perform_search_typeahead(query, PublicBody) end medium_cache @@ -124,7 +124,6 @@ class RequestController < ApplicationController @track_thing = TrackThing.create_track_for_request(@info_request) @feed_autodetect = [ { :url => do_track_url(@track_thing, 'feed'), :title => @track_thing.params[:title_in_rss], :has_json => true } ] - respond_to do |format| format.html { @has_json = true; render :template => 'request/show'} format.json { render :json => @info_request.json_for_api(true) } @@ -246,13 +245,8 @@ class RequestController < ApplicationController :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) + + flash[:batch_sent] = true redirect_to info_request_batch_path(@info_request_batch) end @@ -380,12 +374,7 @@ class RequestController < ApplicationController ) end - flash[:notice] = _("<p>Your {{law_used_full}} request has been <strong>sent on its way</strong>!</p> - <p><strong>We will email you</strong> when there is a response, or after {{late_number_of_days}} working days if the authority still hasn't - replied by then.</p> - <p>If you write about this request (for example in a forum or a blog) please link to this page, and add an - annotation below telling people about your writing.</p>",:law_used_full=>@info_request.law_used_full, - :late_number_of_days => AlaveteliConfiguration::reply_late_after_days) + flash[:request_sent] = true redirect_to show_new_request_path(:url_title => @info_request.url_title) end @@ -770,13 +759,13 @@ class RequestController < ApplicationController get_attachment_internal(false) return unless @attachment - # Prevent spam to magic request address. Note that the binary - # subsitution method used depends on the content type - @incoming_message.binary_mask_stuff!(@attachment.body, @attachment.content_type) # we don't use @attachment.content_type here, as we want same mime type when cached in cache_attachments above response.content_type = AlaveteliFileTypes.filename_to_mimetype(params[:file_name]) || 'application/octet-stream' + # Prevent spam to magic request address. Note that the binary + # subsitution method used depends on the content type + @incoming_message.apply_masks!(@attachment.body, @attachment.content_type) if response.content_type == 'text/html' @attachment.body = ActionController::Base.helpers.sanitize(@attachment.body) end @@ -808,10 +797,9 @@ class RequestController < ApplicationController :body_prefix => render_to_string(:partial => "request/view_html_prefix") } ) - - @incoming_message.html_mask_stuff!(html) - response.content_type = 'text/html' + @incoming_message.apply_masks!(html, response.content_type) + render :text => html end @@ -845,7 +833,15 @@ class RequestController < ApplicationController end # check filename in URL matches that in database (use a censor rule if you want to change a filename) - raise ActiveRecord::RecordNotFound.new("please use same filename as original file has, display: '" + @attachment.display_filename + "' old_display: '" + @attachment.old_display_filename + "' original: '" + @original_filename + "'") if @attachment.display_filename != @original_filename && @attachment.old_display_filename != @original_filename + if @attachment.display_filename != @original_filename && @attachment.old_display_filename != @original_filename + msg = 'please use same filename as original file has, display: ' + msg += "'#{ @attachment.display_filename }' " + msg += 'old_display: ' + msg += "'#{ @attachment.old_display_filename }' " + msg += 'original: ' + msg += "'#{ @original_filename }'" + raise ActiveRecord::RecordNotFound.new(msg) + end @attachment_url = get_attachment_url(:id => @incoming_message.info_request_id, :incoming_message_id => @incoming_message.id, :part => @part_number, @@ -904,10 +900,18 @@ class RequestController < ApplicationController # Type ahead search def search_typeahead - # Since acts_as_xapian doesn't support the Partial match flag, we work around it - # by making the last work a wildcard, which is quite the same - query = params[:q] - @xapian_requests = perform_search_typeahead(query, InfoRequestEvent) + # Since acts_as_xapian doesn't support the Partial match flag, we work + # around it by making the last word a wildcard, which is quite the same + @query = '' + + if params.key?(:requested_from) + @query << "requested_from:#{ params[:requested_from] } " + end + + @per_page = (params.fetch(:per_page) { 25 }).to_i + + @query << params[:q] + @xapian_requests = perform_search_typeahead(@query, InfoRequestEvent, @per_page) render :partial => "request/search_ahead" end diff --git a/app/controllers/services_controller.rb b/app/controllers/services_controller.rb index dc4f783a6..9b3a3396f 100644 --- a/app/controllers/services_controller.rb +++ b/app/controllers/services_controller.rb @@ -5,6 +5,8 @@ require 'open-uri' class ServicesController < ApplicationController def other_country_message + flash.keep + text = "" iso_country_code = AlaveteliConfiguration::iso_country_code.downcase if country_from_ip.downcase != iso_country_code diff --git a/app/controllers/track_controller.rb b/app/controllers/track_controller.rb index 144f4d55a..4b272797f 100644 --- a/app/controllers/track_controller.rb +++ b/app/controllers/track_controller.rb @@ -6,9 +6,6 @@ # Email: hello@mysociety.org; WWW: http://www.mysociety.org/ class TrackController < ApplicationController - - protect_from_forgery # See ActionController::RequestForgeryProtection for details - before_filter :medium_cache # Track all updates to a particular request diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index 43eb99c58..56f42891d 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -7,15 +7,8 @@ require 'set' class UserController < ApplicationController - layout :select_layout - protect_from_forgery :only => [ :contact, - :set_profile_photo, - :signchangeemail, - :clear_profile_photo, - :set_profile_about_me ] # See ActionController::RequestForgeryProtection for details - # Show page about a user def show long_cache @@ -260,16 +253,8 @@ class UserController < ApplicationController do_post_redirect post_redirect end - # Logout form - def _do_signout - session[:user_id] = nil - session[:user_circumstance] = nil - session[:remember_me] = false - session[:using_admin] = nil - session[:admin_name] = nil - end def signout - self._do_signout + clear_session_credentials if params[:r] redirect_to URI.parse(params[:r]).path else diff --git a/app/helpers/admin_helper.rb b/app/helpers/admin_helper.rb index 151e53758..d13fea79b 100644 --- a/app/helpers/admin_helper.rb +++ b/app/helpers/admin_helper.rb @@ -21,17 +21,17 @@ module AdminHelper def request_both_links(info_request) link_to(eye, request_path(info_request), :title => "view request on public website") + " " + - link_to(info_request.title, admin_request_show_path(info_request), :title => "view full details") + link_to(info_request.title, admin_request_path(info_request), :title => "view full details") end def public_body_both_links(public_body) link_to(eye, public_body_path(public_body), :title => "view authority on public website") + " " + - link_to(h(public_body.name), admin_body_show_path(public_body), :title => "view full details") + link_to(h(public_body.name), admin_body_path(public_body), :title => "view full details") end def user_both_links(user) link_to(eye, user_path(user), :title => "view user's page on public website") + " " + - link_to(h(user.name), admin_user_show_path(user), :title => "view full details") + link_to(h(user.name), admin_user_path(user), :title => "view full details") end def comment_visibility(comment) diff --git a/app/helpers/link_to_helper.rb b/app/helpers/link_to_helper.rb index 3709469cf..44d6c6f5f 100755 --- a/app/helpers/link_to_helper.rb +++ b/app/helpers/link_to_helper.rb @@ -116,7 +116,7 @@ module LinkToHelper if request.is_external? external_text || (request.external_user_name || _("Anonymous user")) + " (external)" else - link_to(internal_text || request.user.name, admin_user_show_url(request.user)) + link_to(internal_text || request.user.name, admin_user_url(request.user)) end end @@ -178,7 +178,7 @@ module LinkToHelper end def user_admin_link(user, name="admin", cls=nil) - link_to name, admin_user_show_url(user), :class => cls + link_to name, admin_user_url(user), :class => cls end # Tracks. feed can be 'track' or 'feed' diff --git a/app/mailers/outgoing_mailer.rb b/app/mailers/outgoing_mailer.rb index 797bf9fdd..19054b4e2 100644 --- a/app/mailers/outgoing_mailer.rb +++ b/app/mailers/outgoing_mailer.rb @@ -21,7 +21,7 @@ class OutgoingMailer < ApplicationMailer mail(:from => info_request.incoming_name_and_email, :to => info_request.recipient_name_and_email, - :subject => info_request.email_subject_request) + :subject => info_request.email_subject_request(:html => false)) end # Later message to public body regarding existing request @@ -32,7 +32,7 @@ class OutgoingMailer < ApplicationMailer mail(:from => info_request.incoming_name_and_email, :to => OutgoingMailer.name_and_email_for_followup(info_request, incoming_message_followup), - :subject => OutgoingMailer.subject_for_followup(info_request, outgoing_message)) + :subject => OutgoingMailer.subject_for_followup(info_request, outgoing_message, :html => false)) end # TODO: the condition checking valid_to_reply_to? also appears in views/request/_followup.html.erb, @@ -67,11 +67,12 @@ class OutgoingMailer < ApplicationMailer end end # Subject to use for followup - def OutgoingMailer.subject_for_followup(info_request, outgoing_message) + def OutgoingMailer.subject_for_followup(info_request, outgoing_message, options = {}) if outgoing_message.what_doing == 'internal_review' - return "Internal review of " + info_request.email_subject_request + return "Internal review of " + info_request.email_subject_request(:html => options[:html]) else - return info_request.email_subject_followup(outgoing_message.incoming_message_followup) + return info_request.email_subject_followup(:incoming_message => outgoing_message.incoming_message_followup, + :html => options[:html]) end end # Whether we have a valid email address for a followup diff --git a/app/mailers/request_mailer.rb b/app/mailers/request_mailer.rb index 768257ba8..c9decc6db 100644 --- a/app/mailers/request_mailer.rb +++ b/app/mailers/request_mailer.rb @@ -20,7 +20,7 @@ class RequestMailer < ApplicationMailer mail(:from => from_user.name_and_email, :to => info_request.incoming_name_and_email, - :subject => info_request.email_subject_followup) + :subject => info_request.email_subject_followup(:html => false)) end # Used when a response is uploaded using the API @@ -58,7 +58,7 @@ class RequestMailer < ApplicationMailer user = set_by || info_request.user @reported_by = user @url = request_url(info_request) - @admin_url = admin_request_show_url(info_request) + @admin_url = admin_request_url(info_request) @info_request = info_request @message = message diff --git a/app/models/holiday.rb b/app/models/holiday.rb index 4c4941589..34044683a 100644 --- a/app/models/holiday.rb +++ b/app/models/holiday.rb @@ -22,6 +22,8 @@ class Holiday < ActiveRecord::Base + validates_presence_of :day + def self.holidays @@holidays ||= all.collect { |h| h.day }.to_set end diff --git a/app/models/holiday_import.rb b/app/models/holiday_import.rb new file mode 100644 index 000000000..c6019fac0 --- /dev/null +++ b/app/models/holiday_import.rb @@ -0,0 +1,93 @@ +class HolidayImport + + include ActiveModel::Validations + + attr_accessor :holidays, + :ical_feed_url, + :start_year, + :end_year, + :start_date, + :end_date, + :source, + :populated + + validate :all_holidays_valid + validates_inclusion_of :source, :in => %w( suggestions feed ) + validates_presence_of :ical_feed_url, + :if => proc { |holiday_import| holiday_import.source == 'feed' } + + def initialize(opts = {}) + @populated = false + @start_year = opts.fetch(:start_year, Time.now.year).to_i + @end_year = opts.fetch(:end_year, Time.now.year).to_i + @start_date = Date.civil(start_year, 1, 1) + @end_date = Date.civil(end_year, 12, 31) + @source = opts.fetch(:source, 'suggestions') + @ical_feed_url = opts.fetch(:ical_feed_url, nil) + @country_code = AlaveteliConfiguration::iso_country_code.downcase + self.holidays_attributes = opts.fetch(:holidays_attributes, []) + end + + def populate + source == 'suggestions' ? populate_from_suggestions : populate_from_ical_feed + @populated = true + end + + def suggestions_country_name + IsoCountryCodes.find(@country_code).name if @country_code + end + + def period + start_year == end_year ? "#{start_year}" : "#{start_year}-#{end_year}" + end + + def save + holidays.all?(&:save) + end + + def holidays_attributes=(incoming_data) + incoming_data.each{ |offset, incoming| self.holidays << Holiday.new(incoming) } + end + + def holidays + @holidays ||= [] + end + + private + + def all_holidays_valid + errors.add(:base, 'These holidays could not be imported') unless holidays.all?(&:valid?) + end + + def populate_from_ical_feed + begin + cal_file = open(ical_feed_url) + cals = Icalendar.parse(cal_file, strict=false) + cal = cals.first + cal.events.each{ |cal_event| populate_from_ical_event(cal_event) } + rescue Errno::ENOENT, Exception => e + if e.message == 'Invalid line in calendar string!' + errors.add(:ical_feed_url, "Sorry, there's a problem with the format of that feed.") + elsif e.message.starts_with 'No such file or directory' + errors.add(:ical_feed_url, "Sorry we couldn't find that feed.") + else + raise e + end + end + end + + def populate_from_ical_event(cal_event) + if cal_event.dtstart >= start_date and cal_event.dtstart <= end_date + holidays << Holiday.new(:description => cal_event.summary, + :day => cal_event.dtstart) + end + end + + def populate_from_suggestions + holiday_info = Holidays.between(start_date, end_date, @country_code.to_sym, :observed) + holiday_info.each do |holiday_info_hash| + holidays << Holiday.new(:description => holiday_info_hash[:name], + :day => holiday_info_hash[:date]) + end + end +end diff --git a/app/models/incoming_message.rb b/app/models/incoming_message.rb index db6722976..658ee969a 100644 --- a/app/models/incoming_message.rb +++ b/app/models/incoming_message.rb @@ -52,17 +52,6 @@ class IncomingMessage < ActiveRecord::Base has_prominence - # See binary_mask_stuff function below. It just test for inclusion - # in this hash, not the value of the right hand side. - DoNotBinaryMask = { - 'image/tiff' => 1, - 'image/gif' => 1, - 'image/jpeg' => 1, - 'image/png' => 1, - 'image/bmp' => 1, - 'application/zip' => 1, - } - # Given that there are in theory many info request events, a convenience method for # getting the response event def response_event @@ -218,111 +207,10 @@ class IncomingMessage < ActiveRecord::Base end end - # Converts email addresses we know about into textual descriptions of them - def mask_special_emails!(text) - # TODO: can later display some of these special emails as actual emails, - # if they are public anyway. For now just be precautionary and only - # put in descriptions of them in square brackets. - if self.info_request.public_body.is_followupable? - text.gsub!(self.info_request.public_body.request_email, _("[{{public_body}} request email]", :public_body => self.info_request.public_body.short_or_long_name)) - end - text.gsub!(self.info_request.incoming_email, _('[FOI #{{request}} email]', :request => self.info_request.id.to_s) ) - text.gsub!(AlaveteliConfiguration::contact_email, _("[{{site_name}} contact email]", :site_name => AlaveteliConfiguration::site_name) ) - end - - # Replaces all email addresses in (possibly binary data) with equal length alternative ones. - # Also replaces censor items - def binary_mask_stuff!(text, content_type) - # See if content type is one that we mask - things like zip files and - # images may get broken if we try to. We err on the side of masking too - # much, as many unknown types will really be text. - if DoNotBinaryMask.include?(content_type) - return - end - - # Special cases for some content types - if content_type == 'application/pdf' - uncompressed_text = nil - uncompressed_text = AlaveteliExternalCommand.run("pdftk", "-", "output", "-", "uncompress", :stdin_string => text) - # if we managed to uncompress the PDF... - if !uncompressed_text.nil? && !uncompressed_text.empty? - # then censor stuff (making a copy so can compare again in a bit) - censored_uncompressed_text = uncompressed_text.dup - self._binary_mask_stuff_internal!(censored_uncompressed_text) - # if the censor rule removed something... - if censored_uncompressed_text != uncompressed_text - # then use the altered file (recompressed) - recompressed_text = nil - if AlaveteliConfiguration::use_ghostscript_compression == true - command = ["gs", "-sDEVICE=pdfwrite", "-dCompatibilityLevel=1.4", "-dPDFSETTINGS=/screen", "-dNOPAUSE", "-dQUIET", "-dBATCH", "-sOutputFile=-", "-"] - else - command = ["pdftk", "-", "output", "-", "compress"] - end - recompressed_text = AlaveteliExternalCommand.run(*(command + [{:stdin_string=>censored_uncompressed_text}])) - if recompressed_text.nil? || recompressed_text.empty? - # buggy versions of pdftk sometimes fail on - # compression, I don't see it's a disaster in - # these cases to save an uncompressed version? - recompressed_text = censored_uncompressed_text - logger.warn "Unable to compress PDF; problem with your pdftk version?" - end - if !recompressed_text.nil? && !recompressed_text.empty? - text.replace recompressed_text - end - end - end - return - end - - self._binary_mask_stuff_internal!(text) - end - - # Used by binary_mask_stuff - replace text in place - def _binary_mask_stuff_internal!(text) - # Keep original size, so can check haven't resized it - orig_size = text.mb_chars.size - - # Replace ASCII email addresses... - text.gsub!(MySociety::Validate.email_find_regexp) do |email| - email.gsub(/[^@.]/, 'x') - end - - # And replace UCS-2 ones (for Microsoft Office documents)... - # Find emails, by finding them in parts of text that have ASCII - # equivalents to the UCS-2 - ascii_chars = text.gsub(/\0/, "") - emails = ascii_chars.scan(MySociety::Validate.email_find_regexp) - - # Convert back to UCS-2, making a mask at the same time - if String.method_defined?(:encode) - emails.map! do |email| - # We want the ASCII representation of UCS-2 - [email[0].encode('UTF-16LE').force_encoding('US-ASCII'), - email[0].gsub(/[^@.]/, 'x').encode('UTF-16LE').force_encoding('US-ASCII')] - end - else - emails.map! {|email| [ - Iconv.conv('ucs-2le', 'ascii', email[0]), - Iconv.conv('ucs-2le', 'ascii', email[0].gsub(/[^@.]/, 'x')) - ] } - end - - # Now search and replace the UCS-2 email with the UCS-2 mask - for email, mask in emails - text.gsub!(email, mask) - end - - # Replace censor items - self.info_request.apply_censor_rules_to_binary!(text) - - raise "internal error in binary_mask_stuff" if text.mb_chars.size != orig_size - return text - end - - # Removes censored stuff from from HTML conversion of downloaded binaries - def html_mask_stuff!(html) - self.mask_special_emails!(html) - self.remove_privacy_sensitive_things!(html) + def apply_masks!(text, content_type) + mask_options = { :censor_rules => info_request.applicable_censor_rules, + :masks => info_request.masks } + AlaveteliTextMasker.apply_masks!(text, content_type, mask_options) end # Lotus notes quoting yeuch! @@ -346,26 +234,6 @@ class IncomingMessage < ActiveRecord::Base end - # Remove emails, mobile phones and other details FOI officers ask us to remove. - def remove_privacy_sensitive_things!(text) - # Remove any email addresses - we don't want bounce messages to leak out - # either the requestor's email address or the request's response email - # address out onto the internet - text.gsub!(MySociety::Validate.email_find_regexp, "[email address]") - - # Mobile phone numbers - # http://www.whatdotheyknow.com/request/failed_test_purchases_off_licenc#incoming-1013 - # http://www.whatdotheyknow.com/request/selective_licensing_statistics_i#incoming-550 - # http://www.whatdotheyknow.com/request/common_purpose_training_graduate#incoming-774 - text.gsub!(/(Mobile|Mob)([\s\/]*(Fax|Tel))*\s*:?[\s\d]*\d/, "[mobile number]") - - # Remove WhatDoTheyKnow signup links - text.gsub!(/http:\/\/#{AlaveteliConfiguration::domain}\/c\/[^\s]+/, "[WDTK login link]") - - # Remove things from censor rules - self.info_request.apply_censor_rules_to_text!(text) - end - # Remove quoted sections from emails (eventually the aim would be for this # to do as good a job as GMail does) TODO: bet it needs a proper parser @@ -465,9 +333,8 @@ class IncomingMessage < ActiveRecord::Base raise "main body text more than 1 MB, need to implement clipping like for attachment text, or there is some other MIME decoding problem or similar" end - # remove emails for privacy/anti-spam reasons - self.mask_special_emails!(text) - self.remove_privacy_sensitive_things!(text) + # apply masks for this message + apply_masks!(text, 'text/html') # Remove existing quoted sections folded_quoted_text = self.remove_lotus_quoting(text, 'FOLDED_QUOTED_SECTION') @@ -735,7 +602,14 @@ class IncomingMessage < ActiveRecord::Base text = MySociety::Format.simplify_angle_bracketed_urls(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>]') + + # add a helpful link to email addresses and mobile numbers removed + # by apply_masks! + email_pattern = Regexp.escape(_("email address")) + mobile_pattern = Regexp.escape(_("mobile number")) + text.gsub!(/\[(#{email_pattern}|#{mobile_pattern})\]/, + '[<a href="/help/officers#mobiles">\1</a>]') + if collapse_quoted_sections text = text.gsub(/(\s*FOLDED_QUOTED_SECTION\s*)+/m, "FOLDED_QUOTED_SECTION") text.strip! @@ -773,8 +647,8 @@ class IncomingMessage < ActiveRecord::Base # Returns text version of attachment text def get_attachment_text_full text = self._get_attachment_text_internal - self.mask_special_emails!(text) - self.remove_privacy_sensitive_things!(text) + apply_masks!(text, 'text/html') + # This can be useful for memory debugging #STDOUT.puts 'xxx '+ MySociety::DebugHelpers::allocated_string_size_around_gc diff --git a/app/models/info_request.rb b/app/models/info_request.rb index d0052603a..814057ef4 100644 --- a/app/models/info_request.rb +++ b/app/models/info_request.rb @@ -210,16 +210,6 @@ class InfoRequest < ActiveRecord::Base OLD_AGE_IN_DAYS = 21.days - def after_initialize - if self.described_state.nil? - self.described_state = 'waiting_response' - end - # FOI or EIR? - if !self.public_body.nil? && self.public_body.eir_only? - self.law_used = 'eir' - end - end - def visible_comments self.comments.find(:all, :conditions => 'visible') end @@ -292,13 +282,18 @@ public end # Subject lines for emails about the request - def email_subject_request - _('{{law_used_full}} request - {{title}}',:law_used_full=>self.law_used_full,:title=>self.title.html_safe) + def email_subject_request(opts = {}) + html = opts.fetch(:html, true) + _('{{law_used_full}} request - {{title}}', + :law_used_full => self.law_used_full, + :title => (html ? title : title.html_safe)) end - def email_subject_followup(incoming_message = nil) + def email_subject_followup(opts = {}) + incoming_message = opts.fetch(:incoming_message, nil) + html = opts.fetch(:html, true) if incoming_message.nil? || !incoming_message.valid_to_reply_to? || !incoming_message.subject - 'Re: ' + self.email_subject_request + 'Re: ' + self.email_subject_request(:html => html) else if incoming_message.subject.match(/^Re:/i) incoming_message.subject @@ -753,7 +748,6 @@ public # This is a long stop - even with UK public interest test extensions, 40 # days is a very long time. def date_very_overdue_after - last_sent = last_event_forming_initial_request if self.public_body.is_school? # schools have 60 working days maximum (even over a long holiday) Holiday.due_date_from(self.date_initial_request_last_sent_at, AlaveteliConfiguration::special_reply_very_late_after_days, AlaveteliConfiguration::working_or_calendar_days) @@ -1148,6 +1142,22 @@ public return binary end + # Masks we apply to text associated with this request convert email addresses + # we know about into textual descriptions of them + def masks + masks = [{ :to_replace => incoming_email, + :replacement => _('[FOI #{{request}} email]', + :request => id.to_s) }, + { :to_replace => AlaveteliConfiguration::contact_email, + :replacement => _("[{{site_name}} contact email]", + :site_name => AlaveteliConfiguration::site_name)} ] + if public_body.is_followupable? + masks << { :to_replace => public_body.request_email, + :replacement => _("[{{public_body}} request email]", + :public_body => public_body.short_or_long_name) } + end + end + def is_owning_user?(user) !user.nil? && (user.id == user_id || user.owns_every_request?) end @@ -1345,9 +1355,9 @@ public end def InfoRequest.find_in_state(state) - find(:all, :select => '*, ' + last_event_time_clause + ' as last_event_time', - :conditions => ["described_state = ?", state], - :order => "last_event_time") + select("*, #{ last_event_time_clause } as last_event_time"). + where(:described_state => state). + order('last_event_time') end private diff --git a/app/models/info_request_event.rb b/app/models/info_request_event.rb index 9dde3ba80..635ba8f58 100644 --- a/app/models/info_request_event.rb +++ b/app/models/info_request_event.rb @@ -161,11 +161,10 @@ class InfoRequestEvent < ActiveRecord::Base end def incoming_message_selective_columns(fields) - message = IncomingMessage.find(:all, - :select => fields + ", incoming_messages.info_request_id", - :joins => "INNER JOIN info_request_events ON incoming_messages.id = incoming_message_id ", - :conditions => "info_request_events.id = #{self.id}" - ) + message = IncomingMessage.select("#{ fields }, incoming_messages.info_request_id"). + joins('INNER JOIN info_request_events ON incoming_messages.id = incoming_message_id'). + where('info_request_events.id = ?', id) + message = message[0] if !message.nil? message.info_request = InfoRequest.find(message.info_request_id) diff --git a/app/models/public_body.rb b/app/models/public_body.rb index 829625cac..b8163b07d 100644 --- a/app/models/public_body.rb +++ b/app/models/public_body.rb @@ -349,33 +349,29 @@ class PublicBody < ActiveRecord::Base # Use tags to describe what type of thing this is def type_of_authority(html = false) - types = [] - first = true - for tag in self.tags + types = tags.each_with_index.map do |tag, index| if PublicBodyCategory.get().by_tag().include?(tag.name) desc = PublicBodyCategory.get().singular_by_tag()[tag.name] - if first - # terrible that Ruby/Rails doesn't have an equivalent of ucfirst - # (capitalize shockingly converts later characters to lowercase) - desc = desc[0,1].capitalize + desc[1,desc.size] - first = false + + if index.zero? + desc = desc.sub(/\S/) { |m| Unicode.upcase(m) } end + if html # TODO: this should call proper route helpers, but is in model sigh desc = '<a href="/body/list/' + tag.name + '">' + desc + '</a>' end - types.push(desc) + + desc end end - if types.size > 0 - ret = types[0, types.size - 1].join(", ") - if types.size > 1 - ret = ret + " and " - end - ret = ret + types[-1] - return ret.html_safe + + types.compact! + + if types.any? + types.to_sentence(:last_word_connector => ' and ').html_safe else - return _("A public authority") + _("A public authority") end end diff --git a/app/models/public_body_category.rb b/app/models/public_body_category.rb index bb83c4c82..c313e5734 100644 --- a/app/models/public_body_category.rb +++ b/app/models/public_body_category.rb @@ -2,11 +2,8 @@ # # Table name: public_body_categories # -# id :integer not null, primary key -# title :text not null -# category_tag :text not null -# description :text not null -# display_order :integer +# id :integer not null, primary key +# category_tag :text not null # require 'forwardable' diff --git a/app/models/public_body_category_link.rb b/app/models/public_body_category_link.rb index ba3ff1f95..8c3eb8060 100644 --- a/app/models/public_body_category_link.rb +++ b/app/models/public_body_category_link.rb @@ -1,10 +1,11 @@ # == Schema Information # -# Table name: public_body_category_link +# Table name: public_body_category_links # -# public_body_category_id :integer not null -# public_body_heading_id :integer not null -# category_display_order :integer +# public_body_category_id :integer not null +# public_body_heading_id :integer not null +# category_display_order :integer +# id :integer not null, primary key # class PublicBodyCategoryLink < ActiveRecord::Base diff --git a/app/models/public_body_heading.rb b/app/models/public_body_heading.rb index f1916d233..f394c37c6 100644 --- a/app/models/public_body_heading.rb +++ b/app/models/public_body_heading.rb @@ -2,8 +2,7 @@ # # Table name: public_body_headings # -# id :integer not null, primary key -# name :text not null +# id :integer not null, primary key # display_order :integer # diff --git a/app/models/user.rb b/app/models/user.rb index 1c6dc0eb0..c953e52f2 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -264,11 +264,9 @@ class User < ActiveRecord::Base # Returns list of requests which the user hasn't described (and last # changed more than a day ago) def get_undescribed_requests - info_requests.find( - :all, - :conditions => [ 'awaiting_description = ? and ' + InfoRequest.last_event_time_clause + ' < ?', - true, Time.now() - 1.day - ] + info_requests.where( + "awaiting_description = ? and #{ InfoRequest.last_event_time_clause } < ?", + true, 1.day.ago ) end diff --git a/app/views/admin_censor_rule/_show.html.erb b/app/views/admin_censor_rule/_show.html.erb index 46904b3b9..4b37d0cc9 100644 --- a/app/views/admin_censor_rule/_show.html.erb +++ b/app/views/admin_censor_rule/_show.html.erb @@ -15,7 +15,7 @@ <td><%=h censor_rule.send(column) %></td> <% end %> <td> - <%= link_to "Edit", admin_rule_edit_path(censor_rule) %> + <%= link_to "Edit", edit_admin_censor_rule_path(censor_rule) %> </td> </tr> <% end %> @@ -25,7 +25,7 @@ <% end %> <% if defined? info_request %> - <%= link_to "New censor rule", new_admin_info_request_censor_rule_path(info_request), :class => "btn btn-info" %> + <%= link_to "New censor rule", new_admin_request_censor_rule_path(info_request), :class => "btn btn-info" %> <span class="label label-info">for this request only</span> <% end %> diff --git a/app/views/admin_censor_rule/edit.html.erb b/app/views/admin_censor_rule/edit.html.erb index 230446ed3..ff07987f2 100644 --- a/app/views/admin_censor_rule/edit.html.erb +++ b/app/views/admin_censor_rule/edit.html.erb @@ -2,15 +2,14 @@ <h1><%=@title%></h1> -<%= form_tag admin_rule_update_path(@censor_rule), :class => "form form-horizontal" do %> +<%= form_tag admin_censor_rule_path(@censor_rule), :method => 'put', :class => "form form-horizontal" do %> <%= render :partial => 'form', :locals => { :info_request => @censor_rule.info_request, :user => @censor_rule.user } %> <div class="form-actions"> <%= submit_tag 'Save', :accesskey => 's', :class => "btn btn-primary" %> </div> <% end %> -<%= form_tag admin_rule_destroy_path(@censor_rule), :class => "form form-horizontal" do %> - <%= hidden_field_tag(:censor_rule_id, @censor_rule.id) %> +<%= form_tag admin_censor_rule_path(@censor_rule), :method => 'delete', :class => "form form-horizontal" do %> <div class="form-actions"> Permanent! --> <%= submit_tag "Destroy rule", :class => "btn btn-primary" %> </div> diff --git a/app/views/admin_censor_rule/new.html.erb b/app/views/admin_censor_rule/new.html.erb index 26b3212be..ded31cff2 100644 --- a/app/views/admin_censor_rule/new.html.erb +++ b/app/views/admin_censor_rule/new.html.erb @@ -4,7 +4,6 @@ <%= form_for @censor_rule, :url => @form_url, :class => "form form-horizontal" do %> <%= render :partial => 'form', :locals => { :info_request => @info_request, :user => @censor_user } %> - <div class="form-actions"> <%= submit_tag "Create", :class => "btn btn-primary" %> </div> diff --git a/app/views/admin_request/edit_comment.html.erb b/app/views/admin_comment/edit.html.erb index 2cf49a4a8..e3cbd7472 100644 --- a/app/views/admin_request/edit_comment.html.erb +++ b/app/views/admin_comment/edit.html.erb @@ -2,12 +2,12 @@ <%= error_messages_for 'comment' %> -<%= form_tag admin_request_update_comment_path(@comment) do %> +<%= form_tag admin_comment_path(@comment), :method => 'put' do %> <p><label for="comment_body">Body of annotation</label><br/> <%= text_area 'comment', 'body', :rows => 10, :cols => 60 %></p> - <p><label for="comment_visible">Visible</label> + <p><label for="comment_visible">Visible</label> <%= select('comment', "visible", [["Yes – show comment",true],["No – hide comment",false]]) %> </p> @@ -16,7 +16,7 @@ <% end %> <p> -<%= link_to 'Show', admin_request_show_path(@comment.info_request) %> | -<%= link_to 'List all', admin_request_list_path %> +<%= link_to 'Show request', admin_request_path(@comment.info_request) %> | +<%= link_to 'List all requests', admin_requests_path %> </p> diff --git a/app/views/admin_general/_admin_navbar.html.erb b/app/views/admin_general/_admin_navbar.html.erb index 14fc06092..b6e01f049 100644 --- a/app/views/admin_general/_admin_navbar.html.erb +++ b/app/views/admin_general/_admin_navbar.html.erb @@ -9,11 +9,17 @@ <li><%= link_to 'Timeline', admin_timeline_path %></li> <li><%= link_to 'Stats', admin_stats_path %></li> <li><%= link_to 'Debug', admin_debug_path %></li> - <li><%= link_to 'Authorities', admin_body_list_path %></li> - <li><%= link_to 'Categories', admin_categories_path %></li> - <li><%= link_to 'Requests', admin_request_list_path %></li> - <li><%= link_to 'Users', admin_user_list_path %></li> - <li><%= link_to 'Tracks', admin_track_list_path %></li> + <li class="dropdown"> + <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Authorities<span class="caret"></span></a> + <ul class="dropdown-menu" role="menu"> + <li><%= link_to 'Authorities', admin_bodies_path %></li> + <li><%= link_to 'Categories', admin_categories_path %></li> + </ul> + </li> + <li><%= link_to 'Requests', admin_requests_path %></li> + <li><%= link_to 'Users', admin_users_path %></li> + <li><%= link_to 'Tracks', admin_tracks_path %></li> + <li><%= link_to 'Holidays', admin_holidays_path %></li> <li><%= link_to 'Log out', signout_path %></li> </ul> </div> diff --git a/app/views/admin_general/index.html.erb b/app/views/admin_general/index.html.erb index ba9396ceb..ba0563bb6 100644 --- a/app/views/admin_general/index.html.erb +++ b/app/views/admin_general/index.html.erb @@ -37,9 +37,9 @@ <tr> <td> <% if message.get_body_for_quoting.strip.size == 0 %> - <%= link_to "(no body)", admin_request_show_raw_email_path(message.raw_email_id) %> + <%= link_to "(no body)", admin_raw_email_path(message.raw_email_id) %> <% else %> - <%= link_to excerpt(message.get_body_for_quoting, "", :radius => 60), admin_request_show_raw_email_path(message.raw_email_id) %> + <%= link_to excerpt(message.get_body_for_quoting, "", :radius => 60), admin_raw_email_path(message.raw_email_id) %> <% end %> </td> <td class="span2"> @@ -183,10 +183,10 @@ <div id="new-authorities" class="accordion-body collapse"> <% for @change_request in @new_body_requests %> <%= render :partial => 'change_request_summary'%> - <%= form_tag admin_change_request_update_path(@change_request), :class => "form form-horizontal" do %> + <%= form_tag admin_change_request_path(@change_request), :method => 'put', :class => "form form-horizontal" do %> <%= submit_tag 'Close', :class => "btn btn-danger" %> - <%= link_to("Close and respond", admin_change_request_edit_path(@change_request), :class => 'btn') %> - <%= link_to("Add authority", admin_body_new_path(:change_request_id => @change_request.id), :class => 'btn btn-primary') %> + <%= link_to("Close and respond", edit_admin_change_request_path(@change_request), :class => 'btn') %> + <%= link_to("Add authority", new_admin_body_path(:change_request_id => @change_request.id), :class => 'btn btn-primary') %> <% end %> <% end %> @@ -202,10 +202,10 @@ <div id="update-authorities" class="accordion-body collapse"> <% for @change_request in @body_update_requests %> <%= render :partial => 'change_request_summary' %> - <%= form_tag admin_change_request_update_path(@change_request), :class => "form form-horizontal" do %> + <%= form_tag admin_change_request_path(@change_request), :class => "form form-horizontal", :method => 'put' do %> <%= submit_tag 'Close', :class => "btn btn-danger" %> - <%= link_to("Close and respond", admin_change_request_edit_path(@change_request), :class => 'btn') %> - <%= link_to("Make update", admin_body_edit_path(@change_request.public_body, :change_request_id => @change_request.id), :class => 'btn btn-primary') %> + <%= link_to("Close and respond", edit_admin_change_request_path(@change_request), :class => 'btn') %> + <%= link_to("Make update", edit_admin_body_path(@change_request.public_body, :change_request_id => @change_request.id), :class => 'btn btn-primary') %> <% end %> <% end %> </div> diff --git a/app/views/admin_general/stats.html.erb b/app/views/admin_general/stats.html.erb index 27dc25ee0..03268cc14 100644 --- a/app/views/admin_general/stats.html.erb +++ b/app/views/admin_general/stats.html.erb @@ -53,8 +53,3 @@ </div> </div> </div> -<div class="row"> - <div class="span12"> - <h2>Web analytics</h2> - </div> -</div> diff --git a/app/views/admin_holiday_imports/new.html.erb b/app/views/admin_holiday_imports/new.html.erb new file mode 100644 index 000000000..047f321f9 --- /dev/null +++ b/app/views/admin_holiday_imports/new.html.erb @@ -0,0 +1,81 @@ +<% @title = "Create holidays from suggestions or iCal feed" %> +<h1><%= @title %></h1> + +<%= form_for( @holiday_import, :as => 'holiday_import', :url => '', :method => 'get', :html => { :class => 'form-horizontal form-inline' }) do |f| %> + <% if @holiday_import.holidays.empty? %> + <%= error_messages_for 'holiday_import', :header_message => 'There was a problem with these import settings' %> + <% end %> + <legend>Import settings</legend> + <div> + <div class="control-group"> + <label class="control-label">Choose the years to import holidays for</label> + <div class="controls"> + <label for="import_start_year" class="inline">Start year:</label> + <%= f.select :start_year, (Time.now.year)..(Time.now.year + 5) %> + <label for="import_end_year" class="inline">End year:</label> + <%= f.select :end_year, (Time.now.year)..(Time.now.year + 5) %> + </div> + </div> + + <div class="control-group"> + <label class="control-label">Import from built-in suggestions or iCal feed</label> + <div class="controls"> + <label class="radio inline"> + <%= f.radio_button :source, "suggestions" %>Built-in suggestions + </label> + <label class="radio inline"> + <%= f.radio_button :source, "feed" %>iCal feed + </label> + </div> + </div> + + <div class="control-group"> + <label class="control-label">iCal feed URL:</label> + <div class="controls"> + <%= f.text_field 'ical_feed_url' %> + </div> + </div> + + <div class="control-group"> + <input type="submit" value="Show holidays" class="btn btn-primary"> + </div> + + </div> +<% end %> + +<% if @holiday_import.populated %> + <h2>Holidays to import</h2> + + <table class="table table-striped table-condensed"> + <tbody> + <tr> + <td> + <% if @holiday_import.holidays.empty? %> + <% if @holiday_import.source == 'suggestions' %> + Sorry, we don't have any built-in suggestions for holiday days in <%= @holiday_import.suggestions_country_name %>. + <% else %> + Sorry, we couldn't find any holidays in that iCal feed. + <% end %> + <% else %> + <%= form_for( @holiday_import, :as => 'holiday_import', :url => admin_holiday_imports_path, :html => { :class => 'form-inline' } ) do |f| -%> + <%= error_messages_for 'holiday_import' %> + <legend> + <% if @holiday_import.source == 'suggestions' %> + Suggested holidays for <%= @holiday_import.suggestions_country_name %> (<%= @holiday_import.period %>) + <% else %> + Holidays from feed (<%= @holiday_import.period %>) + <% end %> + </legend> + <%= f.fields_for :holidays do |holiday_fields| %> + <div class="import-holiday-info"> + <%= render :partial => 'admin_holidays/form', :locals => {:f => holiday_fields, :context => :import, :holiday => holiday_fields.object } %> + </div> + <% end%> + <%= f.submit "Import", :class => 'btn btn-warning' %> + <% end %> + <% end %> + </td> + </tr> + </tbody> + </table> +<% end %> diff --git a/app/views/admin_holidays/_edit_form.html.erb b/app/views/admin_holidays/_edit_form.html.erb new file mode 100644 index 000000000..b750dbf4c --- /dev/null +++ b/app/views/admin_holidays/_edit_form.html.erb @@ -0,0 +1,14 @@ +<td> + <%= form_for(@holiday, :url => admin_holiday_path(@holiday), :html => { :class => 'form-inline edit-holiday-form'}) do |f| -%> + <%= render :partial => 'form', :locals => { :f => f, :holiday => @holiday, :context => :edit } %> + <% end %> + + <div class="holiday-destroy "> + <%= form_for @holiday, :url => admin_holiday_path(@holiday), :method => 'delete', :html => { :class => "form form-inline delete-holiday-form" } do |f| %> + <%= f.submit "Destroy", + :class => "btn btn-danger", + :confirm => 'Are you sure you want to destroy this public holiday?' %> + <% end %> + </div> + +</td> diff --git a/app/views/admin_holidays/_form.html.erb b/app/views/admin_holidays/_form.html.erb new file mode 100644 index 000000000..35370e5fc --- /dev/null +++ b/app/views/admin_holidays/_form.html.erb @@ -0,0 +1,22 @@ +<%= error_messages_for 'holiday' %> + +<div class="holiday-description"> + <% if holiday.new_record? %> + <%= f.text_field :description, :class => 'input', :placeholder => 'Enter description here' %> + <% else %> + <%= f.text_field :description, :class => 'input' %> + <% end %> +</div> + +<div class="holiday-day"> + <%= f.date_select :day, { :use_month_numbers => true }, { :class => "day_select" } %> +</div> +<div class="holiday-buttons"> + <% if context == :import %> + <%= f.submit "Remove", :class => 'btn remove-holiday' %> + <% else %> + <%= link_to("Cancel", admin_holidays_path, :class => 'btn') %> + <%= f.submit "Save", :class => 'btn btn-warning' %> +<% end %> +</div> + diff --git a/app/views/admin_holidays/_holiday.html.erb b/app/views/admin_holidays/_holiday.html.erb new file mode 100644 index 000000000..78818f411 --- /dev/null +++ b/app/views/admin_holidays/_holiday.html.erb @@ -0,0 +1,7 @@ +<td> + <div class="holiday-description"><%= holiday.description %></div> + <div class="holiday-day"><%= holiday.day %></div> + <div class="holiday-buttons"> + <%= link_to 'Edit', edit_admin_holiday_path(holiday), :class => "btn edit-button" %> + </div> +</td> diff --git a/app/views/admin_holidays/_new_form.html.erb b/app/views/admin_holidays/_new_form.html.erb new file mode 100644 index 000000000..aee73f426 --- /dev/null +++ b/app/views/admin_holidays/_new_form.html.erb @@ -0,0 +1,10 @@ +<table class="table table-striped table-condensed"> + <tbody> + <tr> + <td><%= form_for(@holiday, :url => admin_holidays_path, :html => { :class => 'form-inline new-holiday-form'}) do |f| -%> + <%= render :partial => 'form', :locals => { :f => f, :holiday => @holiday, :context => :new } %> + <% end %> + </td> + </tr> + </tbody> +</table> diff --git a/app/views/admin_holidays/edit.html.erb b/app/views/admin_holidays/edit.html.erb new file mode 100644 index 000000000..8f29c9a44 --- /dev/null +++ b/app/views/admin_holidays/edit.html.erb @@ -0,0 +1,9 @@ +<% @title = 'Edit public holiday' %> +<h1><%= @title %></h1> +<table class="table table-striped table-condensed"> + <tbody> + <tr> + <%= render :partial => 'edit_form' %> + </tr> + </tbody> +</table> diff --git a/app/views/admin_holidays/index.html.erb b/app/views/admin_holidays/index.html.erb new file mode 100644 index 000000000..d4ee8706b --- /dev/null +++ b/app/views/admin_holidays/index.html.erb @@ -0,0 +1,41 @@ +<% @title = 'Public Holidays' %> +<h1><%= @title %></h1> +<p> + + Alaveteli calculates the due dates of requests taking account of the + public holidays shown here. If you have set the + <code>WORKING_OR_CALENDAR_DAYS</code><a + href="http://alaveteli.org/docs/customising/config/#working_or_calendar_days" + target="_blank">(docs)</a> setting for Alaveteli to + <code>working</code>, the date when a response to a request is + officially overdue will be calculated in days that are not weekends + or public holidays. If you have set + <code>WORKING_OR_CALENDAR_DAYS</code> to <code>calendar</code>, the + date will be calculated in calendar days, but if the due date falls + on a public holiday or weekend day, then the due date is considered + to be the next week day that isn't a holiday. + +</p> +<div class="btn-toolbar"> + <div class="btn-group"> + <%= link_to 'New holiday', new_admin_holiday_path, :class => "btn btn-primary", :id => 'new-holiday-button' %> + </div> + <div class="btn-group"> + <%= link_to 'Create holidays from suggestions or iCal feed', new_admin_holiday_import_path, :class => "btn btn-warning" %> + </div> +</div> + +<div id="existing-holidays"> + <% @years.each do |year| %> + <h2><%= year %></h2> + <table class="table table-striped table-condensed"> + <tbody> + <% @holidays_by_year[year].sort_by(&:day).each do |holiday| %> + <%= content_tag_for(:tr, holiday, prefix=nil, 'data-target' => edit_admin_holiday_path(holiday)) do %> + <%= render :partial => 'holiday', :locals => { :holiday => holiday }%> + <% end %> + <% end %> + </tbody> + </table> + <% end %> +</div> diff --git a/app/views/admin_holidays/new.html.erb b/app/views/admin_holidays/new.html.erb new file mode 100644 index 000000000..792c32f52 --- /dev/null +++ b/app/views/admin_holidays/new.html.erb @@ -0,0 +1,4 @@ +<% @title = 'New public holiday' %> +<h1><%= @title %></h1> + +<%= render :partial => 'new_form' %> diff --git a/app/views/admin_request/_incoming_message_actions.html.erb b/app/views/admin_incoming_message/_actions.html.erb index 22effcce5..4780ad910 100644 --- a/app/views/admin_request/_incoming_message_actions.html.erb +++ b/app/views/admin_incoming_message/_actions.html.erb @@ -1,6 +1,6 @@ <fieldset class="form-horizontal"> <legend>Actions</legend> - <%= form_tag admin_incoming_redeliver_path, :class => "form form-inline" do %> + <%= form_tag redeliver_admin_incoming_message_path(incoming_message), :class => "form form-inline" do %> <div class="control-group"> <label class="control-label" for="url_title_<%= incoming_message.id %>">Redeliver message to one or more other requests</label> <div class="controls"> @@ -9,7 +9,6 @@ <% else %> <%= text_field_tag 'url_title', "", { :size => 20, :id => "url_title_#{incoming_message.id}" } %> <% end %> - <%= hidden_field_tag 'redeliver_incoming_message_id', incoming_message.id, :id => nil %> <%= submit_tag "Redeliver to another request", :class => "btn" %> <p class="help-block"><code>id</code> or <code>url_title</code>; you can supply more than one, separated by commas</p> </div> @@ -18,7 +17,10 @@ <div class="control-group"> <label class="control-label">Generate FOI officer upload URL</label> <div class="controls"> - <%= link_to 'Generate and take me there', admin_request_generate_upload_url_path(incoming_message.info_request, :incoming_message_id => incoming_message.id), :class => "btn" %> + <%= form_tag generate_upload_url_admin_request_path(incoming_message.info_request), :class => "form form-inline" do %> + <%= hidden_field_tag 'incoming_message_id', incoming_message.id, :id => nil %> + <%= submit_tag "Generate and take me there", :class => "btn" %> + <% end %> </div> </div> @@ -29,7 +31,7 @@ </div> </div> - <%= form_tag admin_incoming_destroy_path, :class => "form form-inline" do %> + <%= form_tag admin_incoming_message_path(incoming_message), :method => 'delete', :class => "form form-inline" do %> <div class="control-group"> <label class="control-label" for="destroy_message_<%= incoming_message.id %>">Destroy message</label> <div class="controls"> @@ -44,7 +46,7 @@ <div class="control-group"> <label class="control-label">Inspect email</label> <div class="controls"> - <%= link_to "View raw email", admin_request_show_raw_email_path(incoming_message.raw_email_id), :class => "btn" %> + <%= link_to "View raw email", admin_raw_email_path(incoming_message.raw_email_id), :class => "btn" %> </div> </div> <% end %> diff --git a/app/views/admin_incoming_message/edit.html.erb b/app/views/admin_incoming_message/edit.html.erb index 1088edcab..5e172af76 100644 --- a/app/views/admin_incoming_message/edit.html.erb +++ b/app/views/admin_incoming_message/edit.html.erb @@ -1,8 +1,8 @@ <%= render :partial => 'intro', :locals => {:incoming_message => @incoming_message } %> -<%= render :partial => 'admin_request/incoming_message_actions', :locals => { :incoming_message => @incoming_message } %> +<%= render :partial => 'actions', :locals => { :incoming_message => @incoming_message } %> <fieldset class="form-horizontal"> <legend>Prominence</legend> - <%= form_tag admin_incoming_update_path(@incoming_message), :class => "form form-inline" do %> + <%= form_tag admin_incoming_message_path(@incoming_message), :method => 'put', :class => "form form-inline" do %> <div class="control-group"> <label class="control-label" for="incoming_message_prominence"> Prominence</label> diff --git a/app/views/admin_outgoing_message/edit.html.erb b/app/views/admin_outgoing_message/edit.html.erb index d5f5f43bf..d84a5ba66 100644 --- a/app/views/admin_outgoing_message/edit.html.erb +++ b/app/views/admin_outgoing_message/edit.html.erb @@ -2,7 +2,7 @@ <%= error_messages_for 'outgoing_message' %> -<%= form_tag admin_outgoing_update_path(@outgoing_message) do %> +<%= form_tag admin_outgoing_message_path(@outgoing_message), :method => 'put' do %> <div class="control-group"> <label class="control-label" for="outgoing_message_prominence"> Prominence</label> <div class="controls"> @@ -36,13 +36,12 @@ <% end %> <p> -<%= link_to 'Show', admin_request_show_path(@outgoing_message.info_request) %> | -<%= link_to 'List all', admin_request_list_path %> +<%= link_to 'Show', admin_request_path(@outgoing_message.info_request) %> | +<%= link_to 'List all', admin_requests_path %> </p> -<%= form_tag admin_outgoing_destroy_path do %> +<%= form_tag admin_outgoing_message_path(@outgoing_message), :method => 'delete' do %> <div> - <%= hidden_field_tag 'outgoing_message_id', @outgoing_message.id %> <%= submit_tag "Destroy outgoing message", :class => "btn btn-danger", :confirm => "This is permanent! Are you sure?" %> </div> <% end %> diff --git a/app/views/admin_public_body/_one_list.html.erb b/app/views/admin_public_body/_one_list.html.erb index 8f1d719ec..8d891d16c 100644 --- a/app/views/admin_public_body/_one_list.html.erb +++ b/app/views/admin_public_body/_one_list.html.erb @@ -4,7 +4,7 @@ <div class="accordion-heading accordion-toggle row"> <span class="item-title span6"> <a href="#body_<%=public_body.id%>" data-toggle="collapse" data-parent="requests"><%= chevron_right %></a> - <%= link_to(public_body.name, admin_body_show_path(public_body), :title => "view full details")%> + <%= link_to(public_body.name, admin_body_path(public_body), :title => "view full details")%> </span> <span class="item-metadata span6"> <%= render :partial => 'tags', :locals => { :body => public_body} %> @@ -31,7 +31,7 @@ <% end %> </div> -<%= form_tag(admin_body_mass_tag_add_url, :method => "post", :class => "form form-inline" ) do %> +<%= form_tag(mass_tag_add_admin_bodies_path, :method => "post", :class => "form form-inline" ) do %> <p> <%= text_field_tag 'new_tag', params[:new_tag], { :size => 15, :id => "mass_add_tag_new_tag_" + table_name } %> <%= hidden_field_tag(:query, params[:query], { :id => "mass_add_tag_query_" + table_name } ) %> diff --git a/app/views/admin_public_body/edit.html.erb b/app/views/admin_public_body/edit.html.erb index 11b7eec22..dcafbd270 100644 --- a/app/views/admin_public_body/edit.html.erb +++ b/app/views/admin_public_body/edit.html.erb @@ -3,7 +3,7 @@ <div class="row"> <div class="span8"> <div id="public_body_form"> - <%= form_for @public_body, :url => admin_body_update_path(@public_body), :html => { :class => "form form-horizontal" } do |f| %> + <%= form_for @public_body, :url => admin_body_path(@public_body), :method => 'put', :html => { :class => "form form-horizontal" } do |f| %> <%= render :partial => 'form', :locals => {:f => f} %> <div class="form-actions"> <%= f.submit 'Save', :accesskey => 's', :class => "btn btn-success" %></p> @@ -13,15 +13,14 @@ <div class="row"> <div class="span8"> <div class="well"> - <%= link_to 'Show', admin_body_show_path(@public_body), :class => "btn" %> - <%= link_to 'List all', admin_body_list_path, :class => "btn" %> + <%= link_to 'Show', admin_bodies_path(@public_body), :class => "btn" %> + <%= link_to 'List all', admin_bodies_path, :class => "btn" %> </div> </div> </div> <% if @public_body.info_requests.empty? %> - <%= form_tag(admin_body_destroy_path(@public_body), :class => "form form-inline") do %> - <%= hidden_field_tag(:public_body_id, { :value => @public_body.id } ) %> + <%= form_tag(admin_body_path(@public_body), :class => "form form-inline", :method => 'delete') do %> <%= submit_tag _("Destroy {{name}}", :name => @public_body.name), :class => "btn btn-danger" %> (this is permanent!) <% end %> <% end %> diff --git a/app/views/admin_public_body/import_csv.html.erb b/app/views/admin_public_body/import_csv.html.erb index 4b14226d1..4b481e895 100644 --- a/app/views/admin_public_body/import_csv.html.erb +++ b/app/views/admin_public_body/import_csv.html.erb @@ -70,16 +70,25 @@ Another One,another@example.com,Otro organismo,a_tag "Add new tags to existing ones". </p> - <p><%= submit_tag 'Dry run' %> <%= submit_tag 'Upload' %></p> + <div class="form-actions"> + <p> + <%= submit_tag 'Dry run', :class => 'btn btn-success' %> + <%= submit_tag 'Upload', :class => 'btn btn-warning' %> + </p> + </div> <% end %> <hr> -<p>Standard tags: - <% for category, description in PublicBodyCategory.get().by_tag() %> - <% if category != "other" %> - <strong><%= category %></strong>=<%= description %>; - <% end %> +<div id="standard-tags"> + <h2>Standard tags:</h2> + + <ul> + <% PublicBodyCategory.get().by_tag().each do |category, description| %> + <% if category != "other" %> + <li><strong><%= category %></strong>=<%= description %></li> + <% end %> <% end %> - </p> + </ul> +</div> diff --git a/app/views/admin_public_body/list.html.erb b/app/views/admin_public_body/index.html.erb index 3d7d9c4cd..861593bee 100644 --- a/app/views/admin_public_body/list.html.erb +++ b/app/views/admin_public_body/index.html.erb @@ -8,10 +8,10 @@ <div class="btn-toolbar"> <div class="btn-group"> - <%= link_to 'New public authority', admin_body_new_path, :class => "btn btn-primary" %> + <%= link_to 'New public authority', new_admin_body_path, :class => "btn btn-primary" %> </div> <div class="btn-group"> - <%= link_to 'Import from CSV file', admin_body_import_csv_path, :class => "btn btn-warning" %> + <%= link_to 'Import from CSV file', import_csv_admin_bodies_path, :class => "btn btn-warning" %> </div> </div> @@ -19,7 +19,7 @@ <%= text_field_tag 'query', params[:query], { :size => 30, :class => "input-large search-query" } %> <%= submit_tag "Search", :class => "btn" %> <% if !@query.nil? %> - <%= link_to 'Show all', admin_body_list_path, :class => "btn" %> + <%= link_to 'Show all', admin_bodies_path, :class => "btn" %> <% end %><br> (substring search in names and emails; exact match of tags) <% end %> diff --git a/app/views/admin_public_body/new.html.erb b/app/views/admin_public_body/new.html.erb index 24b27d7af..69b1f8503 100644 --- a/app/views/admin_public_body/new.html.erb +++ b/app/views/admin_public_body/new.html.erb @@ -4,7 +4,7 @@ <div class="row"> <div class="span8"> <div id="public_body_form"> - <%= form_for @public_body, :as => :public_body, :url => admin_body_create_path, :html => {:class => "form form-horizontal"} do |f| %> + <%= form_for @public_body, :as => :public_body, :url => admin_bodies_path, :html => {:class => "form form-horizontal"} do |f| %> <%= render :partial => 'form', :locals => {:f => f} %> @@ -14,7 +14,7 @@ <% end %> <div class="row"> <div class="span8 well"> - <%= link_to 'List all', admin_body_list_path, :class => "btn" %> + <%= link_to 'List all', admin_bodies_path, :class => "btn" %> </div> </div> </div> diff --git a/app/views/admin_public_body/show.html.erb b/app/views/admin_public_body/show.html.erb index f8161db26..40f341a22 100644 --- a/app/views/admin_public_body/show.html.erb +++ b/app/views/admin_public_body/show.html.erb @@ -45,7 +45,7 @@ </tr> </tbody> </table> -<%= link_to _("Edit"), admin_body_edit_path(@public_body), :class => "btn btn-primary" %> +<%= link_to _("Edit"), edit_admin_body_path(@public_body), :class => "btn btn-primary" %> <% unless @public_body.url_name.nil? %> <%=link_to _("Public page"), public_body_path(@public_body), :class => "btn" %> <% else %> diff --git a/app/views/admin_public_body_change_requests/edit.html.erb b/app/views/admin_public_body_change_requests/edit.html.erb index cc9c5b5d9..aaf457084 100644 --- a/app/views/admin_public_body_change_requests/edit.html.erb +++ b/app/views/admin_public_body_change_requests/edit.html.erb @@ -1,6 +1,6 @@ <h1><%=@title%></h1> -<%= form_tag admin_change_request_update_path(@change_request), :class => "form form-horizontal" do %> +<%= form_tag admin_change_request_path(@change_request), :method => 'put', :class => "form form-horizontal" do %> <%= render :partial => 'admin_public_body_change_requests/response'%> <div class="form-actions"> <%= submit_tag 'Close', :accesskey => 'c', :class => "btn btn-primary" %> diff --git a/app/views/admin_request/show_raw_email.html.erb b/app/views/admin_raw_email/show.html.erb index da22b6069..f88b00ef0 100644 --- a/app/views/admin_request/show_raw_email.html.erb +++ b/app/views/admin_raw_email/show.html.erb @@ -31,7 +31,7 @@ <tr> <td><strong>Authority:</strong></td> <td> - <%= link_to(info_request.public_body.name, admin_body_show_path(info_request.public_body)) %> + <%= link_to(info_request.public_body.name, admin_body_path(info_request.public_body)) %> </td> </tr> <tr> @@ -52,12 +52,12 @@ </p> <div> - <%= render :partial => 'incoming_message_actions', :locals => { :incoming_message => @raw_email.incoming_message } %> + <%= render :partial => 'admin_incoming_message/actions', :locals => { :incoming_message => @raw_email.incoming_message } %> </div> <h2>Raw email</h2> -<p><%= link_to "Download", admin_request_download_raw_email_path(@raw_email) %></p> +<p><%= link_to "Download", admin_raw_email_path(@raw_email, :format => 'txt') %></p> <pre><%=h(@raw_email.data).gsub(/\n/, '<br>').html_safe %></pre> diff --git a/app/views/admin_request/_some_annotations.html.erb b/app/views/admin_request/_some_annotations.html.erb index 7adcdc5bb..de470d26b 100644 --- a/app/views/admin_request/_some_annotations.html.erb +++ b/app/views/admin_request/_some_annotations.html.erb @@ -1,20 +1,20 @@ <% if comments.any? %> - <%= form_tag admin_user_modify_comment_visibility_path do %> + <%= form_tag modify_comment_visibility_admin_users_path do %> <div class="accordion" id="comments"> <% comments.each do |comment| %> <div class="accordion-group"> <div class="accordion-heading"> <%= check_box_tag 'comment_ids[]', comment.id %> - + <a href="#comment_<%= comment.id %>" data-toggle="collapse" data-parent="#comments"><%= chevron_right %></a> - - <%= link_to admin_request_edit_comment_path(comment) do %> + + <%= link_to edit_admin_comment_path(comment) do %> #<%= comment.id %> -- <%= h(comment.user.name) %> <%= admin_value(comment.created_at) %> <% end %> - + <%= comment_visibility(comment) %> <blockquote class="incoming-message"> @@ -58,4 +58,4 @@ <% end %> <% else %> <p>None yet.</p> -<% end %> +<% end %> diff --git a/app/views/admin_request/_some_requests.html.erb b/app/views/admin_request/_some_requests.html.erb index cff94956d..9a39cd0c0 100644 --- a/app/views/admin_request/_some_requests.html.erb +++ b/app/views/admin_request/_some_requests.html.erb @@ -4,10 +4,10 @@ <div class="accordion-heading accordion-toggle row"> <span class="item-title span6"> <a href="#request_<%=info_request.id%>" data-toggle="collapse" data-parent="requests"><%= chevron_right %></a> - <%= link_to(info_request.title, admin_request_show_path(info_request), :title => "view full details") %> + <%= link_to(info_request.title, admin_request_path(info_request), :title => "view full details") %> </span> <span class="item-metadata span6"> - <%= user_admin_link_for_request(info_request) %> <%= arrow_right %> <%= link_to("#{info_request.public_body.name}", admin_body_show_path(info_request.public_body)) %>, <%= time_ago_in_words(info_request.updated_at) %> ago + <%= user_admin_link_for_request(info_request) %> <%= arrow_right %> <%= link_to("#{info_request.public_body.name}", admin_body_path(info_request.public_body)) %>, <%= time_ago_in_words(info_request.updated_at) %> ago </span> </div> <div id="request_<%=info_request.id%>" class="item-detail accordion-body collapse row"> diff --git a/app/views/admin_request/edit.html.erb b/app/views/admin_request/edit.html.erb index 552b31bbb..db0b54655 100644 --- a/app/views/admin_request/edit.html.erb +++ b/app/views/admin_request/edit.html.erb @@ -2,7 +2,7 @@ <%= error_messages_for 'info_request' %> -<%= form_tag admin_request_update_path(@info_request) do %> +<%= form_tag admin_request_path(@info_request), :method => :put do %> <p><label for="info_request_title"><strong>Title</strong></label> (warning: editing this will break URLs right now)<br/> <%= text_field 'info_request', 'title', :size => 50 %></p> @@ -43,15 +43,15 @@ <% end %> <p> -<%= link_to 'Show', admin_request_show_path(@info_request) %> | -<%= link_to 'List all', admin_request_list_path %> +<%= link_to 'Show', admin_request_path(@info_request) %> | +<%= link_to 'List all', admin_requests_path %> </p> <hr> <div class="well"> -<%= form_tag admin_request_destroy_path(@info_request) do %> +<%= form_tag admin_request_path(@info_request), :method => :delete do %> <p> <strong>This is permanent and irreversible!</strong> <%= submit_tag 'Destroy request entirely', :class => 'btn btn-danger' %> <br>Use it mainly if someone posts private information, e.g. made a Data Protection request. It diff --git a/app/views/admin_request/list.html.erb b/app/views/admin_request/index.html.erb index 2bd3e3326..2bd3e3326 100644 --- a/app/views/admin_request/list.html.erb +++ b/app/views/admin_request/index.html.erb diff --git a/app/views/admin_request/show.html.erb b/app/views/admin_request/show.html.erb index 9c04badeb..dfb911ea7 100644 --- a/app/views/admin_request/show.html.erb +++ b/app/views/admin_request/show.html.erb @@ -2,8 +2,7 @@ <h1><%=@title%></h1> -<%= form_tag admin_request_move_request_path, { :class => "form form-horizontal" } do %> - <%= hidden_field_tag 'info_request_id', @info_request.id %> +<%= form_tag move_admin_request_path(@info_request), { :class => "form form-horizontal" } do %> <div class="accordion" id="info_request"> <div class="accordion-group"> <div class="accordion-heading"> @@ -16,7 +15,7 @@ <thead> <tr> <td colspan="2"> - <%= link_to 'Edit metadata', admin_request_edit_path(@info_request), :class => "btn" %> + <%= link_to 'Edit metadata', edit_admin_request_path(@info_request), :class => "btn" %> </td> </tr> </thead> @@ -101,7 +100,7 @@ <tfoot> <tr> <td colspan="2"> - <%= link_to 'Edit metadata', admin_request_edit_path(@info_request), :class => "btn" %> + <%= link_to 'Edit metadata', edit_admin_request_path(@info_request), :class => "btn" %> </td> </tr> </tfoot> @@ -117,11 +116,13 @@ FOI officer upload URL </label> <div class="controls"> - <%= link_to 'Generate URL', admin_request_generate_upload_url_path(@info_request), :class => "btn" %> + <%= form_tag generate_upload_url_admin_request_path(@info_request), :class => "form form-inline" do %> + <%= submit_tag "Generate URL", :class => "btn" %> + <% end %> <p class="help-block">(see also option to generate URLs for individual incoming messages below)</p> </div> </div> - <%= form_tag admin_request_hide_path(@info_request), :class => "form form-inline", :id => "hide_request_form", 'data-info-request-id' => @info_request.id.to_s do %> + <%= form_tag hide_admin_request_path(@info_request), :class => "form form-inline", :id => "hide_request_form", 'data-info-request-id' => @info_request.id.to_s do %> <div class="control-group"> <% if @info_request.is_external? %> <label class="control-label">Hide the request:</label> @@ -191,8 +192,7 @@ <tr> <td> <% if info_request_event.described_state != 'waiting_clarification' and info_request_event.event_type == 'response' %> - <%= form_tag admin_request_clarification_path, :class => "form form-inline admin-table-form admin-inline-form" do %> - <%= hidden_field_tag 'info_request_event_id', info_request_event.id, :id => nil %> + <%= form_tag admin_info_request_event_path(info_request_event), :method => 'put', :class => "form form-inline admin-table-form admin-inline-form" do %> <%= submit_tag "Was clarification request", :class => "btn btn-mini btn-primary" %> <% end %> <% end %> @@ -233,7 +233,7 @@ <div class="accordion-group"> <div class="accordion-heading"> <a href="#outgoing_<%=outgoing_message.id%>" data-toggle="collapse" data-parent="#outgoing_messages"><%= chevron_right %></a> - <%= link_to admin_outgoing_edit_path(outgoing_message) do %> + <%= link_to edit_admin_outgoing_message_path(outgoing_message) do %> #<%= outgoing_message.id %> -- <%= outgoing_message.status.humanize %> <%= outgoing_message.message_type.humanize %> <% end %> <blockquote> @@ -245,8 +245,7 @@ <tbody> <tr> <td colspan="2"> - <%= form_tag admin_request_resend_path, :class => "admin-table-form" do %> - <%= hidden_field_tag 'outgoing_message_id', outgoing_message.id %> + <%= form_tag resend_admin_outgoing_message_path(outgoing_message), :class => "admin-table-form" do %> <%= submit_tag "Resend", :class => "btn" %> <% end %> </td> @@ -279,7 +278,7 @@ <div class="accordion-group"> <div class="accordion-heading"> <a href="#incoming_<%=incoming_message.id%>" data-toggle="collapse" data-parent="#incoming_messages"><%= chevron_right %></a> - <%= link_to admin_incoming_edit_path(incoming_message) do %> + <%= link_to edit_admin_incoming_message_path(incoming_message) do %> <%=incoming_message.id%> -- <%= h(incoming_message.mail_from) %> @@ -296,7 +295,7 @@ <thead> <tr> <td colspan="2" class="well"> - <%= render :partial => 'incoming_message_actions', :locals => { :incoming_message => incoming_message } %> + <%= render :partial => 'admin_incoming_message/actions', :locals => { :incoming_message => incoming_message } %> </td> </tr> </thead> diff --git a/app/views/admin_track/_some_tracks.html.erb b/app/views/admin_track/_some_tracks.html.erb index e9facfb5d..c17350e4b 100644 --- a/app/views/admin_track/_some_tracks.html.erb +++ b/app/views/admin_track/_some_tracks.html.erb @@ -32,9 +32,8 @@ <% if include_destroy %> <tr> <td colspan="2"> - <%= form_tag admin_user_destroy_track_path, :class => "form form-inline admin-table-form" do %> + <%= form_tag admin_track_path(track_thing), :method => 'delete', :class => "form form-inline admin-table-form" do %> <div> - <%= hidden_field_tag 'track_id', track_thing.id %> <%= submit_tag "Destroy track", :class => "btn btn-warning" %> </div> <% end %> diff --git a/app/views/admin_track/list.html.erb b/app/views/admin_track/index.html.erb index 5e967a926..2b1dc5737 100644 --- a/app/views/admin_track/list.html.erb +++ b/app/views/admin_track/index.html.erb @@ -14,7 +14,7 @@ <h2>Current top tracks:</h2> <ol> <% for row in @popular %> - <li><%= link_to row['title'], admin_request_show_path(row['info_request_id']) %> (<%= row['count'] %> people following)</li> + <li><%= link_to row['title'], admin_request_path(row['info_request_id']) %> (<%= row['count'] %> people following)</li> <% end %> </ol> diff --git a/app/views/admin_user/_form.html.erb b/app/views/admin_user/_form.html.erb index f1edc0927..01273a657 100644 --- a/app/views/admin_user/_form.html.erb +++ b/app/views/admin_user/_form.html.erb @@ -41,7 +41,7 @@ user from filing new requests, making annotations or messaging other users; the text is shown in public on the user's page and when they try to do a forbidden action; write in the second person (you); see - <%= link_to 'banned users', admin_user_list_banned_path %> for examples</small> + <%= link_to 'banned users', banned_admin_users_path %> for examples</small> </div> </div> </div> diff --git a/app/views/admin_user/_user_table.html.erb b/app/views/admin_user/_user_table.html.erb index 57066bf3f..4fd90d5c6 100644 --- a/app/views/admin_user/_user_table.html.erb +++ b/app/views/admin_user/_user_table.html.erb @@ -7,7 +7,7 @@ <% if user.admin_level == "super" %> <span class="label">superuser</span> <% end %> - <%= link_to("#{h(user.name)}", admin_user_show_path(user))%> + <%= link_to("#{h(user.name)}", admin_user_path(user))%> <%= link_to("(#{h(user.email)})", "mailto:#{h(user.email)}")%> </span> <span class="item-metadata"> diff --git a/app/views/admin_user/list_banned.html.erb b/app/views/admin_user/banned.html.erb index e535415e6..ee17d9899 100644 --- a/app/views/admin_user/list_banned.html.erb +++ b/app/views/admin_user/banned.html.erb @@ -2,7 +2,7 @@ <h1><%=@title%></h1> -<p><%= link_to 'List all', admin_user_list_path %></p> +<p><%= link_to 'List all', admin_users_path %></p> <%= render :partial => 'user_table', :locals => { :users => @banned_users, :banned_column => true } %> diff --git a/app/views/admin_user/edit.html.erb b/app/views/admin_user/edit.html.erb index e641a13d6..ed1fb6e08 100644 --- a/app/views/admin_user/edit.html.erb +++ b/app/views/admin_user/edit.html.erb @@ -1,11 +1,11 @@ <h1><%=@title%></h1> -<%= form_tag admin_user_update_path(@admin_user), :class => "form form-horizontal" do %> +<%= form_tag admin_user_path(@admin_user), :method => 'put', :class => "form form-horizontal" do %> <%= render :partial => 'form' %> <div class="form-actions"> <%= submit_tag 'Save', :accesskey => 's', :class => "btn btn-primary" %> </div> <% end %> -<%= link_to 'Show', admin_user_show_path(@admin_user), :class => "btn" %> -<%= link_to 'List all', admin_user_list_path, :class => "btn" %> +<%= link_to 'Show', admin_user_path(@admin_user), :class => "btn" %> +<%= link_to 'List all', admin_users_path, :class => "btn" %> diff --git a/app/views/admin_user/list.html.erb b/app/views/admin_user/index.html.erb index b1238f87a..cfb34fd7b 100644 --- a/app/views/admin_user/list.html.erb +++ b/app/views/admin_user/index.html.erb @@ -5,7 +5,7 @@ <%= form_tag({}, :method => "get", :class => "form form-search") do %> <%= text_field_tag 'query', params[:query], { :size => 30, :class => "input-large search-query"} %> <%= submit_tag "Search", :class => "btn" %> (substring search, names and emails) - <%= link_to 'Banned users', admin_user_list_banned_path, :class => "btn btn-info" %> + <%= link_to 'Banned users', banned_admin_users_path, :class => "btn btn-info" %> <% end %> <%= render :partial => 'user_table', :locals => { :users => @admin_users, :banned_column => false } %> diff --git a/app/views/admin_user/show.html.erb b/app/views/admin_user/show.html.erb index 6d12aeff5..1e7d885c5 100644 --- a/app/views/admin_user/show.html.erb +++ b/app/views/admin_user/show.html.erb @@ -4,7 +4,7 @@ <% if @admin_user.profile_photo %> <div class="user_photo_on_admin"> - <%= form_tag admin_clear_profile_photo_path(@admin_user), :multipart => true, :class => "form" do %> + <%= form_tag clear_profile_photo_admin_user_path(@admin_user), :multipart => true, :class => "form" do %> <img src="<%= get_profile_photo_url(:url_name => @admin_user.url_name) %>"> <br> <%= submit_tag "Clear photo", :class => "btn btn-info" %> @@ -32,13 +32,13 @@ <%=link_to @admin_user.email, "mailto:#{h @admin_user.email}"%> <% elsif column_name == 'email_bounce_message' %> <% unless @admin_user.email_bounce_message.empty? %> - <%= link_to _("See bounce message"), admin_user_show_bounce_path(@admin_user.id) %> + <%= link_to _("See bounce message"), show_bounce_message_admin_user_path(@admin_user) %> <% end %> <% else %> <%=h admin_value(value)%> <% end %> <% if column_name == 'email_bounced_at' && !@admin_user.email_bounced_at.nil? %> - <%= form_tag admin_user_clear_bounce_path(@admin_user), :class => "form form-inline" do %> + <%= form_tag clear_bounce_admin_user_path(@admin_user), :class => "form form-inline" do %> <input type="submit" name="action" value="Clear bounce" class="btn btn-info"> <% end %> <% end %> @@ -48,11 +48,13 @@ </tbody> </table> - -<%= link_to 'Edit', admin_user_edit_path(@admin_user), :class => "btn btn-primary" %> +<div class="btn-toolbar"> +<%= link_to 'Edit', edit_admin_user_path(@admin_user), :class => "btn btn-primary" %> <%= link_to 'Public page', user_path(@admin_user), :class => "btn" %> -<%= link_to "Log in as #{@admin_user.name} (also confirms their email)", admin_user_login_as_path(@admin_user), :class => "btn btn-info" %> - +</div> +<%= form_tag login_as_admin_user_path(@admin_user), :class => "form form-horizontal" do %> + <%= submit_tag "Log in as #{@admin_user.name} (also confirms their email)", :class => "btn btn-info" %> +<% end %> <hr> <h2>Track things</h2> diff --git a/app/views/comment/_single_comment.html.erb b/app/views/comment/_single_comment.html.erb index cdcb3b85f..07017dabf 100644 --- a/app/views/comment/_single_comment.html.erb +++ b/app/views/comment/_single_comment.html.erb @@ -17,7 +17,7 @@ <p class="event_actions"> <% if !comment.id.nil? %> <% if !@user.nil? && @user.admin_page_links? %> - <%= link_to "Admin", admin_request_edit_comment_path(comment) %> | + <%= link_to "Admin", edit_admin_comment_path(comment) %> | <% end %> <%= link_to "Link to this", comment_path(comment), :class => "link_to_this" %> <!-- | <%= link_to _('Report abuse'), comment_path(comment) %> --> diff --git a/app/views/comment/new.html.erb b/app/views/comment/new.html.erb index 578732cdb..48fe055ac 100644 --- a/app/views/comment/new.html.erb +++ b/app/views/comment/new.html.erb @@ -1,4 +1,5 @@ -<% @title = "Make an annotation on '" + h(@info_request.title) + "'" %> +<% @title = _("Add an annotation to “{{request_title}}”", + :request_title => h(@info_request.title)) %> <% if @existing_comment %> <div class="errorExplanation" id="errorExplanation"><ul> @@ -11,8 +12,10 @@ <%= foi_error_messages_for :comment %> -<h1><%= _('Add an annotation')%></h1> -<h2>to “<%=request_link(@info_request)%>”</h2> +<h1> + <%= _("Add an annotation to “{{request_title}}”", + :request_title => request_link(@info_request)) %> +</h1> <p> <%= _('Annotations are so anyone, including you, can help the requester with their request. For example:')%> diff --git a/app/views/contact_mailer/add_public_body.text.erb b/app/views/contact_mailer/add_public_body.text.erb index 5baa1fa1a..306a70432 100644 --- a/app/views/contact_mailer/add_public_body.text.erb +++ b/app/views/contact_mailer/add_public_body.text.erb @@ -13,7 +13,7 @@ <%= @change_request.notes %> <%= _('Add the authority:') %> -<%= admin_body_new_url(:change_request_id => @change_request.id, :only_path => false ) %> +<%= new_admin_body_url(:change_request_id => @change_request.id, :only_path => false ) %> <%= _('Close the request and respond:') %> -<%= admin_change_request_edit_url(:id => @change_request.id, :only_path => false ) %> +<%= edit_admin_change_request_url(@change_request, :only_path => false ) %> diff --git a/app/views/contact_mailer/update_public_body_email.text.erb b/app/views/contact_mailer/update_public_body_email.text.erb index 7d5a3dae0..e849463d0 100644 --- a/app/views/contact_mailer/update_public_body_email.text.erb +++ b/app/views/contact_mailer/update_public_body_email.text.erb @@ -10,7 +10,7 @@ <%= @change_request.notes %> <%= _('Update the address:') %> -<%= admin_body_edit_path(@change_request.public_body, :change_request_id => @change_request.id, :only_path => false) %> +<%= edit_admin_body_path(@change_request.public_body, :change_request_id => @change_request.id, :only_path => false) %> <%= _('Close the request and respond:') %> -<%= admin_change_request_edit_url(:id => @change_request.id, :only_path => false ) %> +<%= edit_admin_change_request_url(@change_request, :only_path => false ) %> diff --git a/app/views/general/exception_caught.html.erb b/app/views/general/exception_caught.html.erb index 8d78e2e92..21223dc1e 100644 --- a/app/views/general/exception_caught.html.erb +++ b/app/views/general/exception_caught.html.erb @@ -12,13 +12,10 @@ <%= submit_tag _("Search") %> <% end %> </li> - </ul> + </ul> <% else %> <h1><%= _("Sorry, there was a problem processing this page") %></h1> <p><%= _('You have found a bug. Please <a href="{{contact_url}}">contact us</a> to tell us about the problem', :contact_url => help_contact_path) %></p> <% end %> - <h2><%= _('Technical details') %></h2> - <p><strong><%= h(@exception_class ? @exception_class : _("Unknown")) %></strong></p> - <p><strong><%= h(@exception_message) %></strong></p> </div> diff --git a/app/views/general/search.html.erb b/app/views/general/search.html.erb index 0a04f544e..4f9ef5b68 100644 --- a/app/views/general/search.html.erb +++ b/app/views/general/search.html.erb @@ -131,6 +131,7 @@ <div id="header_right"> <h2><%= _('Track this search')%></h2> <%= render :partial => 'track/tracking_links', :locals => { :track_thing => @track_thing, :own_request => false, :location => 'main' } %> + <%= render :partial => 'track/rss_feed', :locals => { :track_thing => @track_thing, :location => 'main' } %> </div> <% end %> diff --git a/app/views/info_request_batch/_batch_sent.html.erb b/app/views/info_request_batch/_batch_sent.html.erb new file mode 100644 index 000000000..1bf51962f --- /dev/null +++ b/app/views/info_request_batch/_batch_sent.html.erb @@ -0,0 +1,18 @@ +<div id="notice"> + <p> + <%= _("Your 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.", + :late_number_of_days => AlaveteliConfiguration::reply_late_after_days) %> + </p> + + <p> + <%= _("If you write about these requests (for example in a forum or a blog) " \ + "please link to this page.") %> + </p> +</div> diff --git a/app/views/info_request_batch/show.html.erb b/app/views/info_request_batch/show.html.erb index 8bb834b3c..9f94306d9 100644 --- a/app/views/info_request_batch/show.html.erb +++ b/app/views/info_request_batch/show.html.erb @@ -1,4 +1,9 @@ <% @title = _("{{title}} - a batch request", :title => @info_request_batch.title) %> + +<% if flash[:batch_sent] %> + <%= render :partial => 'batch_sent' %> +<% end %> + <div class="info_request_batch_intro"> <h1><%= @title %></h1> <% if @info_request_batch.sent_at %> diff --git a/app/views/layouts/default.html.erb b/app/views/layouts/default.html.erb index 50abc59c3..56e6b3362 100644 --- a/app/views/layouts/default.html.erb +++ b/app/views/layouts/default.html.erb @@ -20,10 +20,14 @@ <% end %> <%= javascript_include_tag "application" %> + <% if @profile_photo_javascript %> <%= javascript_include_tag "profile-photos" %> <%= stylesheet_link_tag "jquery.Jcrop.css" %> <% end %> + <% if is_admin? %> + <%= javascript_include_tag "bootstrap-dropdown" %> + <% end %> <% if @feed_autodetect %> <% for feed in @feed_autodetect %> diff --git a/app/views/public_body/show.html.erb b/app/views/public_body/show.html.erb index 011aea535..403216c6c 100644 --- a/app/views/public_body/show.html.erb +++ b/app/views/public_body/show.html.erb @@ -1,5 +1,16 @@ <% @title = h(@public_body.name) + _(" - view and make Freedom of Information requests") %> <div id="main_content"> + + <% if flash[:search_params] %> + <div class="back-to-results"> + <div class="message"> + <%= link_to select_authority_path(flash[:search_params]) do %> + <%= _('« Back to search results') %> + <% end %> + </div> + </div> + <% end %> + <div id="header_right"> <h2><%= _('Follow this authority')%></h2> @@ -12,6 +23,7 @@ </p> <%= render :partial => 'track/tracking_links', :locals => { :track_thing => @track_thing, :own_request => false, :location => 'sidebar' } %> + <%= render :partial => 'track/rss_feed', :locals => { :track_thing => @track_thing, :location => 'sidebar' } %> <%= render :partial => 'more_info', :locals => { :public_body => @public_body } %> </div> @@ -23,7 +35,7 @@ <%=@public_body.type_of_authority(true)%><% if not @public_body.short_name.empty? %>, <%= _('also called {{public_body_short_name}}', :public_body_short_name => h(@public_body.short_name))%><% end %> <% if !@user.nil? && @user.admin_page_links? %> - (<%= link_to _("admin"), admin_body_show_path(@public_body) %>) + (<%= link_to _("admin"), admin_body_path(@public_body) %>) <% end %> </p> @@ -91,7 +103,8 @@ <a name="results"></a> <% if @public_body.info_requests.size > 4 %> - <%= render :partial => 'request/request_filter_form' %> + <%= render :partial => 'request/request_search_form', + :locals => { :after_form_fields => render(:partial => 'request/request_filter_form') } %> <% end %> <% end %> diff --git a/app/views/request/_act.html.erb b/app/views/request/_act.html.erb index 1199cb4a2..878cdf4ff 100644 --- a/app/views/request/_act.html.erb +++ b/app/views/request/_act.html.erb @@ -1,7 +1,14 @@ <h2><%= _("Act on what you've learnt") %></h2> <div class="act_link"> - <% tweet_link = "https://twitter.com/share?" + {:url => request.url, :via => AlaveteliConfiguration::twitter_username, :text => "'#{@info_request.title}'", :related => _('alaveteli_foi:The software that runs {{site_name}}', :site_name => site_name)}.to_query %> + <% tweet_link = "https://twitter.com/share?" << { + :url => request.url, + :via => AlaveteliConfiguration.twitter_username, + :text => "'#{ @info_request.title }'", + :related => _('alaveteli_foi:The software that runs {{site_name}}', :site_name => site_name) + }.to_query + %> + <% link_to tweet_link do %> <%= image_tag "twitter-16.png", :alt => "twitter icon" %> <% end %> diff --git a/app/views/request/_incoming_correspondence.html.erb b/app/views/request/_incoming_correspondence.html.erb index f39d650d8..70bd25c7f 100644 --- a/app/views/request/_incoming_correspondence.html.erb +++ b/app/views/request/_incoming_correspondence.html.erb @@ -17,7 +17,7 @@ <p class="event_actions"> <% if !@user.nil? && @user.admin_page_links? %> - <%= link_to "Admin", admin_incoming_edit_path(incoming_message.id) %> | + <%= link_to "Admin", edit_admin_incoming_message_path(incoming_message.id) %> | <% end %> <%= link_to _("Link to this"), incoming_message_path(incoming_message), :class => "link_to_this" %> </p> diff --git a/app/views/request/_request_filter_form.html.erb b/app/views/request/_request_filter_form.html.erb index 090db01df..0983c8c57 100644 --- a/app/views/request/_request_filter_form.html.erb +++ b/app/views/request/_request_filter_form.html.erb @@ -1,41 +1,14 @@ -<%= render :partial => 'general/localised_datepicker' %> - -<div id="list-filter"> - <%= form_tag(request.path, :method => "get", :id=>"filter_requests_form") do %> - <div class="list-filter-item"> - <%= label_tag(:query, _("Keywords"), :class=>"form_label title") %> - <%= text_field_tag(:query, params[:query]) %> - </div> -<% if false # don't think we want this, but leaving as an example %> - <div class="list-filter-item"> - <%= _("Search for words in:") %> <br/> - <% [["sent", _("messages from users")], - ["response", _("messages from authorities")], - ["comment", _("comments")]].each_with_index do |item, index| - variety, title = item %> - - <%= check_box_tag "request_variety[]", variety, params[:request_variety].nil? ? true : params[:request_variety].include?(variety), :id => "request_variety_#{index}" %> - <%= label_tag("request_variety_#{index}", title) %> <br/> - <% end %> - </div> -<% end %> - <div class="list-filter-item"> - <%= label_tag(:query, _("Made between"), :class=>"form_label title") %> - <%= text_field_tag(:request_date_after, params[:request_date_after], {:class => "use-datepicker", :size => 10}) %> - <%= label_tag(:query, _("and"), :class=>"form_label") %> - <%= text_field_tag(:request_date_before, params[:request_date_before], {:class => "use-datepicker", :size => 10}) %> - </div> - <div class="list-filter-item"> - <h3 class="title"><%= _("Showing") %></h3> - <div class="filter-request-types"> - <% statuses = [["all", _("all requests")], - ["successful", _("successful requests")], - ["unsuccessful", _("unsuccessful requests")], - ["awaiting", _("unresolved requests")]] %> - <% for status, label in statuses %> - <% if params[:view] != status %> - <% if params[:controller] == "public_body" %> - <%= link_to label, url_for(:controller => "public_body", :action => "show", :view => status, :url_name => @public_body.url_name) + "?" + request.query_string + '#results' %> +<div class="list-filter-item"> + <h3 class="title"><%= _("Showing") %></h3> + <div class="filter-request-types"> + <% statuses = [["all", _("all requests")], + ["successful", _("successful requests")], + ["unsuccessful", _("unsuccessful requests")], + ["awaiting", _("unresolved requests")]] %> + <% statuses.each do |status, label| %> + <% if params[:view] != status %> + <% if params[:controller] == "public_body" %> + <%= link_to label, url_for(:controller => "public_body", :action => "show", :view => status, :url_name => @public_body.url_name) + "?" + request.query_string + '#results' %> <% else %> <%= link_to label, url_for(:controller => "request", :action => "list", :view => status) + "?" + request.query_string + '#results' %> <% end %> @@ -43,12 +16,6 @@ <%= label %> <% end %> <%= "|" unless statuses.last[0] == status %> - <% end %> - </div> - </div> - - <div class="list-filter-item"> - <%= submit_tag(_("Search")) %> - </div> -<% end %> + <% end %> + </div> </div> diff --git a/app/views/request/_request_search_form.html.erb b/app/views/request/_request_search_form.html.erb new file mode 100644 index 000000000..3f2f66950 --- /dev/null +++ b/app/views/request/_request_search_form.html.erb @@ -0,0 +1,35 @@ +<%= render :partial => 'general/localised_datepicker' %> + +<div id="list-filter"> + <%= form_tag(request.path, :method => "get", :id=>"filter_requests_form") do %> + <div class="list-filter-item"> + <%= label_tag(:query, _("Keywords"), :class=>"form_label title") %> + <%= text_field_tag(:query, params[:query]) %> + </div> +<% if false # don't think we want this, but leaving as an example %> + <div class="list-filter-item"> + <%= _("Search for words in:") %> <br/> + <% [["sent", _("messages from users")], + ["response", _("messages from authorities")], + ["comment", _("comments")]].each_with_index do |item, index| + variety, title = item %> + + <%= check_box_tag "request_variety[]", variety, params[:request_variety].nil? ? true : params[:request_variety].include?(variety), :id => "request_variety_#{index}" %> + <%= label_tag("request_variety_#{index}", title) %> <br/> + <% end %> + </div> +<% end %> + <div class="list-filter-item"> + <%= label_tag(:query, _("Made between"), :class=>"form_label title") %> + <%= text_field_tag(:request_date_after, params[:request_date_after], {:class => "use-datepicker", :size => 10}) %> + <%= label_tag(:query, _("and"), :class=>"form_label") %> + <%= text_field_tag(:request_date_before, params[:request_date_before], {:class => "use-datepicker", :size => 10}) %> + </div> + + <%= after_form_fields if defined?(after_form_fields) -%> + + <div class="list-filter-item"> + <%= submit_tag(_("Search")) %> + </div> +<% end %> +</div> diff --git a/app/views/request/_request_sent.html.erb b/app/views/request/_request_sent.html.erb new file mode 100644 index 000000000..70fa18712 --- /dev/null +++ b/app/views/request/_request_sent.html.erb @@ -0,0 +1,66 @@ +<div id="content"> + <div class="request-sent-message" id="notice"> + <h1> + <%= _("Your {{law_used_full}} request has been sent", + :law_used_full => @info_request.law_used_full) %> + </h1> + <div class="request-sent-message__row"> + <div class="request-sent-message__column-1"> + <p class="subtitle"> + <%= _("<strong>We will email you</strong> when there is a response, or after " \ + "{{late_number_of_days}} working days if the authority still hasn't " \ + "replied by then.", + :late_number_of_days => AlaveteliConfiguration.reply_late_after_days) %> + </p> + + <h2><%= _("Share your request") %></h2> + + <%= link_to image_tag("next-step-twitter.png", + :alt => _("Tweet it"), + :width => "120", + :height => "37"), + "https://twitter.com/intent/tweet?" << { + :url => request.url, + :via => AlaveteliConfiguration.twitter_username, + :text => "'#{ @info_request.title }'", + :related => _('alaveteli_foi:The software that runs {{site_name}}', :site_name => site_name) + }.to_query %> + + <%= link_to image_tag("next-step-facebook.png", + :alt => _("Share on Facebook"), + :width => "120", + :height => "37"), + "https://www.facebook.com/sharer/sharer.php?" << { + :u => request.url + }.to_query %> + + <h2><%= _("Keep your request up to date") %></h2> + <p> + <%= _('If you write about this request ' \ + '(for example in a forum or a blog) ' \ + 'please link to this page, and <a href="{{url}}">add an ' \ + 'annotation</a> below telling people ' \ + 'about your writing.', :url => new_comment_url(:url_title => @info_request.url_title).html_safe) %> + </p> + </div> + <div class="request-sent-message__column-2"> + <div class="what-next"> + <h2><%= _("What next?") %></h2> + <ul class="what-next__list"> + <li> + <a href="#"><%= _("Change how you'd like to be notified of changes " \ + "to your request") %></a> + </li> + <li> + <%= link_to _("View other requests to {{public_body}}", :public_body => @info_request.public_body.name), public_body_path(@info_request.public_body) %> + </li> + <li> + <%= link_to _("Help us classify requests that haven't " \ + "been updated"), categorise_play_path %> + </li> + </ul> + </div> + </div> + </div> + </div> +</div> diff --git a/app/views/request/_search_ahead.html.erb b/app/views/request/_search_ahead.html.erb index 1e65a5458..4fbe06ebc 100644 --- a/app/views/request/_search_ahead.html.erb +++ b/app/views/request/_search_ahead.html.erb @@ -1,14 +1,20 @@ -<div id="request_search_ahead_results"> - <% if !@xapian_requests.nil? %> - <% if @xapian_requests.results.size > 0 %> +<% unless @xapian_requests.nil? %> + <div id="request_search_ahead_results"> + <% if @xapian_requests.results.any? %> + <span class="close-button">X</span> <h3><%= _("Possibly related requests:") %></h3> - <% end %> - <% for result in @xapian_requests.results %> - <%= render :partial => 'request/request_listing_short_via_event', :locals => { :event => result[:model], :info_request => result[:model].info_request } %> - <% end %> - <p> - <a id="body-site-search-link"><%= _("Or search in their website for this information.") %></a> - </p> - <% end %> -</div> + <% @xapian_requests.results.each do |result| %> + <%= render :partial => 'request/request_listing_short_via_event', + :locals => { :event => result[:model], + :info_request => result[:model].info_request } %> + <% end %> + + <p> + <a id="body-site-search-link"> + <%= _("Search in their website for this information →") %> + </a> + </p> + <% end %> + </div> +<% end %> diff --git a/app/views/request/_sidebar.html.erb b/app/views/request/_sidebar.html.erb index 0f7965ffa..0d81ef111 100644 --- a/app/views/request/_sidebar.html.erb +++ b/app/views/request/_sidebar.html.erb @@ -10,6 +10,7 @@ :count => follower_count) %> </p> <%= render :partial => 'track/tracking_links', :locals => { :track_thing => @track_thing, :own_request => @info_request.user && @info_request.user == @user, :location => 'sidebar' } %> + <%= render :partial => 'track/rss_feed', :locals => { :track_thing => @track_thing, :location => 'sidebar' } %> </div> <% if @info_request.described_state != "attention_requested" %> <h2><%= _('Offensive? Unsuitable?') %></h2> diff --git a/app/views/request/details.html.erb b/app/views/request/details.html.erb index 3cb2f5afe..194820da6 100644 --- a/app/views/request/details.html.erb +++ b/app/views/request/details.html.erb @@ -1,5 +1,10 @@ -<% @title = _("Details of request '") + h(@info_request.title) + "'" %> -<h1><%= _("Details of request '") + request_link(@info_request) + "'" %></h1> +<% @title = _("Details of request “{{request_title}}”", + :request_title => h(@info_request.title)) %> + +<h1> + <%= _("Details of request “{{request_title}}”", + :request_title => request_link(@info_request)) %> +</h1> <h2><%= _('Event history') %></h2> diff --git a/app/views/request/followup_bad.html.erb b/app/views/request/followup_bad.html.erb index ea2400c5d..38a7549b2 100644 --- a/app/views/request/followup_bad.html.erb +++ b/app/views/request/followup_bad.html.erb @@ -1,32 +1,31 @@ <% if @incoming_message.nil? || !@incoming_message.valid_to_reply_to? %> - <% @title = _("Unable to send follow up message to {{username}}",:username=>OutgoingMailer.name_for_followup(@info_request, nil)) %> + <% @title = _("Unable to send follow up message to {{username}}", :username => OutgoingMailer.name_for_followup(@info_request, nil)) %> <% else %> - <% @title = _("Unable to send a reply to {{username}}",:username=>OutgoingMailer.name_for_followup(@info_request, @incoming_message)) %> + <% @title = _("Unable to send a reply to {{username}}", :username => OutgoingMailer.name_for_followup(@info_request, @incoming_message)) %> <% end %> -<h1><%=@title%></h1> +<h1><%= @title %></h1> <% if @reason == 'not_apply' %> <!-- we should never get here, but just in case give a sensible message --> - <p><%= _('Freedom of Information law no longer applies to') %> <%=h @info_request.public_body.name %>. + <p><%= _('Freedom of Information law no longer applies to {{public_body_name}}.', :public_body_name => @info_request.public_body.name) %> <%= _('From the request page, try replying to a particular message, rather than sending a general followup. If you need to make a general followup, and know an email which will go to the right place, please <a href="{{url}}">send it to us</a>.', :url => help_contact_path.html_safe) %> </p> <% elsif @reason == 'defunct' %> <!-- we should never get here, but just in case give a sensible message --> - <p><%=h @info_request.public_body.name %> <%= _('no longer exists. If you are trying to make - From the request page, try replying to a particular message, rather than sending + <p><%= _('{{public_body_name}} no longer exists. From the request page, try replying to a particular message, rather than sending a general followup. If you need to make a general followup, and know - an email which will go to the right place, please <a href="{{url}}">send it to us</a>.', :url => help_contact_path.html_safe) %> + an email which will go to the right place, please <a href="{{url}}">send it to us</a>.', :url => help_contact_path.html_safe, :public_body_name => @info_request.public_body.name) %> </p> <% elsif @reason == 'bad_contact' %> - <p><%= _('We do not have a working {{law_used_full}} address for {{public_body_name}}.',:law_used_full=>h(@info_request.law_used_full),:public_body_name=>h(@info_request.public_body.name)) %> <%= _('You may be able to find + <p><%= _('We do not have a working {{law_used_full}} address for {{public_body_name}}.', :law_used_full => @info_request.law_used_full, :public_body_name => @info_request.public_body.name) %> <%= _('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 <a href="{{url}}">send it to us</a>.', :url => help_contact_path.html_safe) %> </p> <% elsif @reason == 'external' %> - <p><%= _("Followups cannot be sent for this request, as it was made externally, and published here by {{public_body_name}} on the requester's behalf.", :public_body_name => h(@info_request.public_body.name)) %> + <p><%= _("Followups cannot be sent for this request, as it was made externally, and published here by {{public_body_name}} on the requester's behalf.", :public_body_name => @info_request.public_body.name) %> </p> <% else %> <% raise _("unknown reason ") + @reason %> diff --git a/app/views/request/followup_preview.html.erb b/app/views/request/followup_preview.html.erb index 55afc0245..83978a2f5 100644 --- a/app/views/request/followup_preview.html.erb +++ b/app/views/request/followup_preview.html.erb @@ -3,7 +3,7 @@ <div id="followup"> <%= form_for(@outgoing_message, :html => { :id => 'preview_form' }, :url => (@incoming_message.nil? ? show_response_no_followup_url(:id => @info_request.id) : show_response_url(:id => @info_request.id, :incoming_message_id => @incoming_message.id)) + "#followup" ) do |o| %> - + <% if @internal_review %> <h1><%= _('Now preview your message asking for an internal review') %></h1> <% else %> @@ -20,7 +20,7 @@ <div class="correspondence" id="outgoing-0"> <p class="preview_subject"> <strong><%= _('To:') %></strong> <%=h OutgoingMailer.name_for_followup(@info_request, @incoming_message) %> - <br><strong><%= _('Subject:') %></strong> <%=h OutgoingMailer.subject_for_followup(@info_request, @outgoing_message) %> + <br><strong><%= _('Subject:') %></strong> <%= OutgoingMailer.subject_for_followup(@info_request, @outgoing_message, :html => true) %> </p> <div class="correspondence_text"> diff --git a/app/views/request/list.html.erb b/app/views/request/list.html.erb index a465f03ba..75cb463ef 100644 --- a/app/views/request/list.html.erb +++ b/app/views/request/list.html.erb @@ -1,13 +1,14 @@ - <div id="header_left"> - <h1><%=@title%></h1> - <%= render :partial => 'request/request_filter_form' %> + <h1><%= @title %></h1> + <%= render :partial => 'request/request_search_form', + :locals => { :after_form_fields => render(:partial => 'request/request_filter_form') } %> </div> <div id="header_right"> <h2><%= _("Follow these requests") %></h2> <% if @track_thing %> <%= render :partial => 'track/tracking_links', :locals => { :track_thing => @track_thing, :own_request => false, :location => 'main' } %> + <%= render :partial => 'track/rss_feed', :locals => { :track_thing => @track_thing, :location => 'main' } %> <% end %> </div> diff --git a/app/views/request/new.html.erb b/app/views/request/new.html.erb index 7f1332464..51224129e 100644 --- a/app/views/request/new.html.erb +++ b/app/views/request/new.html.erb @@ -1,19 +1,33 @@ <% unless @batch %> <script type="text/javascript"> $(document).ready(function(){ - // Avoid triggering too often (on each keystroke) by using the debounce jQuery plugin: + // 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 %>"); + if ( $('#request_search_ahead_results').text().trim().length > 0) { + $('#typeahead_response').slideUp('fast'); + } + + $("#typeahead_response").load("<%= search_ahead_url %>?q="+encodeURI(this.value)+ + "&requested_from=<%= @info_request.public_body.url_name %>"+ + "&per_page=3", function() { + + if ( $('#request_search_ahead_results').text().trim().length > 0) { + $('#typeahead_response').hide().slideDown('fast'); + + // 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 %>"); + + $('.close-button').click(function() { $(this).parent().hide() }); + } }); })); - }); </script> <% end %> diff --git a/app/views/request/preview.html.erb b/app/views/request/preview.html.erb index 0265d0328..ddd5ab30c 100644 --- a/app/views/request/preview.html.erb +++ b/app/views/request/preview.html.erb @@ -23,7 +23,7 @@ <% else %> <%=h(@info_request.public_body.name)%> <% end %> - <br><strong><%= _('Subject:') %></strong> <%=h @info_request.email_subject_request %> + <br><strong><%= _('Subject:') %></strong> <%= @info_request.email_subject_request %> </p> <div class="correspondence_text"> diff --git a/app/views/request/show.html.erb b/app/views/request/show.html.erb index 153b0b861..78e022aa9 100644 --- a/app/views/request/show.html.erb +++ b/app/views/request/show.html.erb @@ -2,6 +2,11 @@ :title => h(@info_request.title), :public_body => (@info_request.public_body.name)) %> +<% if flash[:request_sent] %> + <%= render :partial => 'request_sent', + :locals => { :info_request => @info_request } %> +<% end %> + <% if @info_request.prominence == 'hidden' %> <p id="hidden_request"> <%= _('This request has prominence \'hidden\'. You can only see it because you are logged @@ -37,9 +42,9 @@ :user => request_user_link(@info_request, _('An anonymous user')), :law_used_full => h(@info_request.law_used_full), :user_admin_link => user_admin_link_for_request(@info_request, _('external'), _('admin')), - :request_admin_url => admin_request_show_url(@info_request), + :request_admin_url => admin_request_url(@info_request), :public_body_link => public_body_link(@info_request.public_body), - :public_body_admin_url => admin_body_show_url(@info_request.public_body)) %> + :public_body_admin_url => admin_body_url(@info_request.public_body)) %> <% else %> <%= _('{{user}} made this {{law_used_full}} request', :user=>request_user_link(@info_request, _('An anonymous user')), @@ -51,19 +56,20 @@ <p id="request_status" class="request_icon_line icon_<%= @info_request.calculate_status %>"> <% if @info_request.awaiting_description %> <% if @is_owning_user && !@info_request.is_external? && !@render_to_file %> - <%= _('Please <strong>answer the question above</strong> so we know whether the ')%> - <%= MySociety::Format.fancy_pluralize(@new_responses_count, 'recent response contains', 'recent responses contain') %> <%= _('useful information.') %> + <%= n_('Please <strong>answer the question above</strong> so we know whether the recent response contains useful information.', + 'Please <strong>answer the question above</strong> so we know whether the recent responses contain useful information.', + @new_responses_count) %> <% else %> <%= _('This request has an <strong>unknown status</strong>.') %> <% if @old_unclassified %> - <%= _('We\'re waiting for someone to read') %> - <%= MySociety::Format.fancy_pluralize(@new_responses_count, 'a recent response', 'recent responses') %> - <%= _('and update the status accordingly. Perhaps <strong>you</strong> might like to help out by doing that?') %> + <%= n_("We're waiting for someone to read a recent response and update the status accordingly. Perhaps <strong>you</strong> might like to help out by doing that?", + "We're waiting for someone to read recent responses and update the status accordingly. Perhaps <strong>you</strong> might like to help out by doing that?", + @new_responses_count) %> <% else %> - <%= _('We\'re waiting for') %> - <%= user_link_for_request(@info_request) %> <%= _('to read') %> - <%= MySociety::Format.fancy_pluralize(@new_responses_count, 'a recent response', 'recent responses') %> - <%= _('and update the status.') %> + <%= n_("We're waiting for {{user}} to read a recent response and update the status.", + "We're waiting for {{user}} to read recent responses and update the status.", + @new_responses_count, + :user => user_link_for_request(@info_request)) %> <% end %> <% end %> <% elsif @status == 'waiting_response' %> diff --git a/app/views/request/show_response.html.erb b/app/views/request/show_response.html.erb index ace86cf4c..7571f147b 100644 --- a/app/views/request/show_response.html.erb +++ b/app/views/request/show_response.html.erb @@ -35,7 +35,7 @@ </dt> <dd> <%= _('To do that please send a private email to ') %><%=h(@postal_email_name)%> - <<%=link_to h(@postal_email), "mailto:" + @postal_email%>> + <<%=mail_to h(@postal_email) %>> <%= _('containing your postal address, and asking them to reply to this request. Or you could phone them.') %> diff --git a/app/views/track/_rss_feed.html.erb b/app/views/track/_rss_feed.html.erb new file mode 100644 index 000000000..4be46ffa9 --- /dev/null +++ b/app/views/track/_rss_feed.html.erb @@ -0,0 +1,4 @@ +<div class="feed_link feed_link_<%= location %>"> + <%= link_to image_tag('feed-16.png', :alt => "RSS icon"), do_track_path(track_thing, 'feed') %> + <%= link_to (location == 'sidebar' ? _('RSS feed of updates') : _('RSS feed')), do_track_path(track_thing, 'feed') %> +</div> diff --git a/app/views/track/_tracking_links.html.erb b/app/views/track/_tracking_links.html.erb index 5419ec605..c027e9732 100644 --- a/app/views/track/_tracking_links.html.erb +++ b/app/views/track/_tracking_links.html.erb @@ -13,17 +13,12 @@ </div> <% elsif track_thing %> <div class="feed_link feed_link_<%=location%>"> - <% if defined? follower_count && follower_count > 0 %> + <% if defined?(follower_count) && follower_count > 0 %> <%= link_to _("I like this request"), do_track_path(track_thing), :class => "link_button_green" %> <% else %> <%= link_to _("Follow"), do_track_path(track_thing), :class => "link_button_green" %> <% end %> </div> - - <div class="feed_link feed_link_<%=location%>"> - <%= link_to image_tag('feed-16.png', :alt => "RSS icon"), do_track_path(track_thing, 'feed') %> - <%= link_to (location == 'sidebar' ? _('RSS feed of updates') : _('RSS feed')), do_track_path(track_thing, 'feed') %> - </div> <% end %> diff --git a/app/views/user/_signin.html.erb b/app/views/user/_signin.html.erb index afc55d249..7428082d3 100644 --- a/app/views/user/_signin.html.erb +++ b/app/views/user/_signin.html.erb @@ -9,27 +9,27 @@ <p> <label class="form_label" for="user_signin_email"><%= _('Your e-mail:')%></label> - <%= text_field 'user_signin', 'email', { :size => 20, :tabindex => 10 } %> + <%= text_field 'user_signin', 'email', { :size => 20, :tabindex => 60 } %> </p> <p> <label class="form_label" for="user_signin_password"><%= _('Password:')%></label> - <%= password_field 'user_signin', 'password', { :size => 15, :tabindex => 20 } %> + <%= password_field 'user_signin', 'password', { :size => 15, :tabindex => 70, :autocomplete => 'off' } %> </p> <p class="form_note"> - <%= link_to _('Forgotten your password?'), signchangepassword_path + "?pretoken=" + h(params[:token]), :tabindex => 30 %> + <%= link_to _('Forgotten your password?'), signchangepassword_path(:pretoken => h(params[:token])), :tabindex => 80 %> </p> <p class="form_checkbox"> - <%= check_box_tag 'remember_me', "1", false, :tabindex => 40 %> + <%= check_box_tag 'remember_me', "1", false, :tabindex => 90 %> <label for="remember_me"><%= _('Remember me</label> (keeps you signed in longer; do not use on a public computer) ')%></p> <div class="form_button"> <%= hidden_field_tag 'token', params[:token], {:id => 'signin_token' } %> <%= hidden_field_tag :modal, params[:modal], {:id => 'signin_modal' } %> - <%= submit_tag _('Sign in'), :tabindex => 50 %> + <%= submit_tag _('Sign in'), :tabindex => 100 %> </div> <% end %> diff --git a/app/views/user/_signup.html.erb b/app/views/user/_signup.html.erb index ec6541881..801d2abe0 100644 --- a/app/views/user/_signup.html.erb +++ b/app/views/user/_signup.html.erb @@ -5,35 +5,36 @@ <!--<h2><%= _('If you\'re new to {{site_name}}', :site_name=>site_name)%></h2>--> + + <p> - <label class="form_label" for="user_signup_email"><%= _('Your e-mail:')%></label> - <%= text_field 'user_signup', 'email', { :size => 20, :tabindex => 60 } %> + <label class="form_label" for="user_signup_name"> <%= _('Your name:')%></label> + <%= text_field 'user_signup', 'name', { :size => 20, :tabindex => 10, :autocomplete => "off" } %> </p> <div class="form_item_note"> - <%= _('We will not reveal your email address to anybody unless you or - the law tell us to (<a href="{{url}}">details</a>). ', :url => help_privacy_path) %> + <%= _('Your <strong>name will appear publicly</strong> + (<a href="{{why_url}}">why?</a>) + on this website and in search engines. + <a href="{{help_url}}">Thinking of using a pseudonym?</a>', :why_url => (help_privacy_path+"#public_request").html_safe, :help_url => (help_privacy_path+"#real_name").html_safe) %> </div> <p> - <label class="form_label" for="user_signup_name"> <%= _('Your name:')%></label> - <%= text_field 'user_signup', 'name', { :size => 20, :tabindex => 70, :autocomplete => "off" } %> + <label class="form_label" for="user_signup_email"><%= _('Your e-mail:')%></label> + <%= text_field 'user_signup', 'email', { :size => 20, :tabindex => 20 } %> </p> <div class="form_item_note"> - <%= _('Your <strong>name will appear publicly</strong> - (<a href="{{why_url}}">why?</a>) - on this website and in search engines. If you - are thinking of using a pseudonym, please - <a href="{{help_url}}">read this first</a>.', :why_url => (help_privacy_path+"#public_request").html_safe, :help_url => (help_privacy_path+"#real_name").html_safe) %> + <%= _('We will not reveal your email address to anybody unless <a href="{{url}}">you or + the law tell us to</a>. ', :url => help_privacy_path) %> </div> <p> <label class="form_label" for="user_signup_password"> <%= _('Password:')%></label> - <%= password_field 'user_signup', 'password', { :size => 15, :tabindex => 80, :autocomplete => "off" } %> + <%= password_field 'user_signup', 'password', { :size => 15, :tabindex => 30, :autocomplete => "off" } %> </p> <p> - <label class="form_label" for="user_signup_password_confirmation"> <%= _('Password: (again)')%></label> - <%= password_field 'user_signup', 'password_confirmation', { :size => 15, :tabindex => 90, :autocomplete => "off" } %> + <label class="form_label" for="user_signup_password_confirmation"> <%= _('Confirm password:')%></label> + <%= password_field 'user_signup', 'password_confirmation', { :size => 15, :tabindex => 40, :autocomplete => "off" } %> </p> <% if @request_from_foreign_country %> @@ -43,7 +44,7 @@ <div class="form_button"> <%= hidden_field_tag 'token', params[:token], {:id => 'signup_token' } %> <%= hidden_field_tag :modal, params[:modal], {:id => 'signup_modal' } %> - <%= submit_tag _('Sign up'), :tabindex => 100 %> + <%= submit_tag _('Sign up'), :tabindex => 50 %> </div> <% end %> diff --git a/app/views/user/show.html.erb b/app/views/user/show.html.erb index b23f74326..7c8d52568 100644 --- a/app/views/user/show.html.erb +++ b/app/views/user/show.html.erb @@ -34,6 +34,7 @@ <% if !@track_thing.nil? %> <h2><%= _('Track this person')%></h2> <%= render :partial => 'track/tracking_links', :locals => { :track_thing => @track_thing, :own_request => false, :location => 'sidebar' } %> + <%= render :partial => 'track/rss_feed', :locals => { :track_thing => @track_thing, :location => 'sidebar' } %> <% end %> <% if !@xapian_requests.nil? %> <h2><%= _('On this page')%></h2> @@ -66,7 +67,7 @@ <p class="subtitle"> <%= _('Joined {{site_name}} in', :site_name=>site_name) %> <%= @display_user.created_at.year %> <% if !@user.nil? && @user.admin_page_links? %> - (<%= link_to "admin", admin_user_show_path(@display_user) %>) + (<%= link_to "admin", admin_user_path(@display_user) %>) <% end %> </p> diff --git a/app/views/user/sign.html.erb b/app/views/user/sign.html.erb index e8c5d5a58..394c42a47 100644 --- a/app/views/user/sign.html.erb +++ b/app/views/user/sign.html.erb @@ -1,52 +1,50 @@ - <% if !@post_redirect.nil? && @post_redirect.reason_params[:user_name] %> <% @title = _("Sign in") %> <div id="sign_alone"> - <p id="sign_in_reason"> - <% if @post_redirect.reason_params[:web].empty? %> - <%= _('Please sign in as ')%><%= link_to h(@post_redirect.reason_params[:user_name]), @post_redirect.reason_params[:user_url] %>. - <% else %> - <%= @post_redirect.reason_params[:web] %>, - <%= _('please sign in as ')%><%= link_to h(@post_redirect.reason_params[:user_name]), @post_redirect.reason_params[:user_url] %>. - <% end %> - </p> - <% if @post_redirect.post_params["controller"] == "admin_general" %> - <% unless AlaveteliConfiguration::disable_emergency_user %> - <p id="superuser_message"><%= _("Don't have a superuser account yet?") %> <%= link_to _("Sign in as the emergency user"), @post_redirect.uri + "?emergency=1" %></p> + <p id="sign_in_reason"> + <% if @post_redirect.reason_params[:web].empty? %> + <%= _('Please sign in as ')%><%= link_to h(@post_redirect.reason_params[:user_name]), @post_redirect.reason_params[:user_url] %>. + <% else %> + <%= @post_redirect.reason_params[:web] %>, + <%= _('please sign in as ')%><%= link_to h(@post_redirect.reason_params[:user_name]), @post_redirect.reason_params[:user_url] %>. <% end %> - <% end %> + </p> - <%= render :partial => 'signin', :locals => { :sign_in_as_existing_user => true } %> + <% if @post_redirect.post_params["controller"] == "admin_general" %> + <% unless AlaveteliConfiguration::disable_emergency_user %> + <p id="superuser_message"><%= _("Don't have a superuser account yet?") %> <%= link_to _("Sign in as the emergency user"), @post_redirect.uri + "?emergency=1" %></p> + <% end %> + <% end %> + <%= render :partial => 'signin', :locals => { :sign_in_as_existing_user => true } %> </div> - <% else %> <% @title = _('Sign in or make a new account') %> <div id="sign_together"> - <% if !@post_redirect.nil? %> - <p id="sign_in_reason"> - <% if @post_redirect.reason_params[:web].empty? %> - <%= _('Please sign in or make a new account.') %> - <% else %> - <%= _('{{reason}}, please sign in or make a new account.', :reason => @post_redirect.reason_params[:web]) %> - <% end %> - </p> - <% end %> + <% if !@post_redirect.nil? %> + <h1 id="sign_in_reason"> + <% if @post_redirect.reason_params[:web].empty? %> + <%= _('Please create an account or sign in') %> + <% else %> + <%= _('{{reason}}, create an account or sign in', :reason => @post_redirect.reason_params[:web]) %> + <% end %> + </h1> + <% end %> <div id="left_half"> - <h1><%= _('Sign in') %></h1> - <%= render :partial => 'signin', :locals => { :sign_in_as_existing_user => false } %> - </div> - <div id="middle_strip"> - <%= _('- or -') %> + <h2><%= _('Create a new account') %></h2> + <%= render :partial => 'signup' %> </div> + <div id="right_half"> - <h1><%= _('Sign up') %></h1> - <%= render :partial => 'signup' %> + <div class="sign-in-wrapper"> + <p class="pretitle"><%= _('Got an account?') %></p> + <h2><%= _('Sign in') %></h2> + <%= render :partial => 'signin', :locals => { :sign_in_as_existing_user => false } %> + </div> </div> + <div style="clear:both"></div> </div> - <% end %> - diff --git a/app/views/user/signchangeemail.html.erb b/app/views/user/signchangeemail.html.erb index 7308179f4..a99bcb785 100644 --- a/app/views/user/signchangeemail.html.erb +++ b/app/views/user/signchangeemail.html.erb @@ -23,7 +23,7 @@ <p> <label class="form_label" for="signchangeemail_password"> <%= _('Your password:')%></label> - <%= password_field 'signchangeemail', 'password', { :size => 15 } %> + <%= password_field 'signchangeemail', 'password', { :size => 15, :autocomplete => 'off' } %> </p> <p class="form_note"> diff --git a/app/views/user/signchangepassword.html.erb b/app/views/user/signchangepassword.html.erb index 51bcb466d..60f5d2c62 100644 --- a/app/views/user/signchangepassword.html.erb +++ b/app/views/user/signchangepassword.html.erb @@ -13,12 +13,12 @@ <p> <label class="form_label" for="user_password"><%= _('New password:')%></label> - <%= password_field 'user', 'password', { :size => 15 } %> + <%= password_field 'user', 'password', { :size => 15, :autocomplete => 'off' } %> </p> <p> <label class="form_label" for="user_password_confirmation"><%= _('New password: (again)')%></label> - <%= password_field 'user', 'password_confirmation', { :size => 15 } %> + <%= password_field 'user', 'password_confirmation', { :size => 15, :autocomplete => 'off' } %> </p> <div class="form_button"> diff --git a/config/brakeman.ignore b/config/brakeman.ignore new file mode 100644 index 000000000..391013a5a --- /dev/null +++ b/config/brakeman.ignore @@ -0,0 +1,63 @@ +{ + "ignored_warnings": [ + { + "location": { + "type": "method", + "method": "list_all_csv", + "class": "PublicBodyController" + }, + "file": "app/controllers/public_body_controller.rb", + "warning_code": 16, + "render_path": null, + "link": "http://brakemanscanner.org/docs/warning_types/file_access/", + "warning_type": "File Access", + "code": "File.open(Tempfile.new(\"all-authorities.csv\", File.join(InfoRequest.download_zip_dir, \"download\")).path, \"w\")", + "line": 211, + "confidence": "Weak", + "user_input": "InfoRequest.download_zip_dir", + "message": "Model attribute used in file name", + "fingerprint": "00ce9cdd1d2c3f220bae94cb854393b5072ee1da064ca7a3af693fe2867d51c8", + "note": "InfoRequest.download_zip_dir does not contain user input" + }, + { + "location": { + "type": "method", + "method": "list_all_csv", + "class": "PublicBodyController" + }, + "file": "app/controllers/public_body_controller.rb", + "warning_code": 16, + "render_path": null, + "link": "http://brakemanscanner.org/docs/warning_types/file_access/", + "warning_type": "File Access", + "code": "File.rename(Tempfile.new(\"all-authorities.csv\", File.join(InfoRequest.download_zip_dir, \"download\")).path, File.join(File.join(InfoRequest.download_zip_dir, \"download\"), \"all-authorities.csv\"))", + "line": 213, + "confidence": "Weak", + "user_input": "InfoRequest.download_zip_dir", + "message": "Model attribute used in file name", + "fingerprint": "6078628aa47451d597e211629d80dcea0fdc7600dc066cabf2c0a4b9e07a75cc", + "note": "InfoRequest.download_zip_dir does not contain user input" + }, + { + "location": { + "type": "method", + "method": "list_all_csv", + "class": "PublicBodyController" + }, + "file": "app/controllers/public_body_controller.rb", + "warning_code": 16, + "render_path": null, + "link": "http://brakemanscanner.org/docs/warning_types/file_access/", + "warning_type": "File Access", + "code": "FileUtils.mkdir_p(File.join(InfoRequest.download_zip_dir, \"download\"))", + "line": 194, + "confidence": "Weak", + "user_input": "InfoRequest.download_zip_dir", + "message": "Model attribute used in file name", + "fingerprint": "5ed20f867c17c814cfe117906161a26f37b986d694996c9fd0089d4f971dc1d0", + "note": "InfoRequest.download_zip_dir does not contain user input" + } + ], + "updated": "Thu Oct 02 10:43:19 +0000 2014", + "brakeman_version": "2.6.2" +} diff --git a/config/brakeman.yml b/config/brakeman.yml new file mode 100644 index 000000000..1f95903fd --- /dev/null +++ b/config/brakeman.yml @@ -0,0 +1,4 @@ +--- +:output_files: +- tmp/brakeman.html +- tmp/brakeman.json diff --git a/config/httpd.conf-example b/config/httpd.conf-example index e010ac22f..00722fbdf 100644 --- a/config/httpd.conf-example +++ b/config/httpd.conf-example @@ -34,7 +34,7 @@ # Passenger's default MaxPoolSize is 6. At the time of writing # normal instances of Alaveteli seem to take 150-200MB per # process, so we've set this conservatively at 3. Read the guides - # above to tune this for your system + # above to tune this for your system PassengerMaxPoolSize 3 # The RAILS_ENV that the app is running in. This can be any of @@ -97,6 +97,11 @@ # # The condition means that the rule will fire only if the cached # file exists. + # + # The second condition-rule pair handles the same transformation for + # files served from a non-default locale, 'cy'. You will need one + # set of rules for each non-default locale. + RewriteMap escape int:escape RewriteCond %{DOCUMENT_ROOT}/views_cache/request/$2/$1/${escape:$3} -f RewriteRule ^/request/((\d{1,3})\d*)/(response/\d+/attach/(html/)?\d+/.+) /views_cache/request/$2/$1/${escape:$3} [L] diff --git a/config/initializers/alaveteli.rb b/config/initializers/alaveteli.rb index a08496d67..5094e3ac6 100644 --- a/config/initializers/alaveteli.rb +++ b/config/initializers/alaveteli.rb @@ -56,6 +56,7 @@ require 'public_body_csv' require 'category_and_heading_migrator' require 'public_body_categories' require 'routing_filters' +require 'alaveteli_text_masker' AlaveteliLocalization.set_locales(AlaveteliConfiguration::available_locales, AlaveteliConfiguration::default_locale) diff --git a/config/initializers/secure_headers.rb b/config/initializers/secure_headers.rb new file mode 100644 index 000000000..99730e6b2 --- /dev/null +++ b/config/initializers/secure_headers.rb @@ -0,0 +1,24 @@ +::SecureHeaders::Configuration.configure do |config| + + # https://tools.ietf.org/html/rfc6797 + if AlaveteliConfiguration::force_ssl + config.hsts = { :max_age => 20.years.to_i, :include_subdomains => true } + else + config.hsts = false + end + # https://tools.ietf.org/html/draft-ietf-websec-x-frame-options-02 + config.x_frame_options = "sameorigin" + + # http://msdn.microsoft.com/en-us/library/ie/gg622941%28v=vs.85%29.aspx + config.x_content_type_options = "nosniff" + + # http://msdn.microsoft.com/en-us/library/dd565647%28v=vs.85%29.aspx + config.x_xss_protection = { :value => 1 } + + # https://w3c.github.io/webappsec/specs/content-security-policy/ + config.csp = false + + # https://www.nwebsec.com/HttpHeaders/SecurityHeaders/XDownloadOptions + config.x_download_options = false +end + diff --git a/config/routes.rb b/config/routes.rb index 4b2eb5695..c975d6007 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -169,17 +169,15 @@ Alaveteli::Application.routes.draw do #### #### AdminPublicBody controller - match '/admin/missing_scheme' => 'admin_public_body#missing_scheme', :as => :admin_body_missing - match '/admin/body' => 'admin_public_body#index', :as => :admin_body_index - match '/admin/body/list' => 'admin_public_body#list', :as => :admin_body_list - match '/admin/body/show/:id' => 'admin_public_body#show', :as => :admin_body_show - match '/admin/body/new' => 'admin_public_body#new', :as => :admin_body_new - match '/admin/body/edit/:id' => 'admin_public_body#edit', :as => :admin_body_edit - match '/admin/body/update/:id' => 'admin_public_body#update', :as => :admin_body_update - match '/admin/body/create' => 'admin_public_body#create', :as => :admin_body_create - match '/admin/body/destroy/:id' => 'admin_public_body#destroy', :as => :admin_body_destroy - match '/admin/body/import_csv' => 'admin_public_body#import_csv', :as => :admin_body_import_csv - match '/admin/body/mass_tag_add' => 'admin_public_body#mass_tag_add', :as => :admin_body_mass_tag_add + scope '/admin', :as => 'admin' do + resources :bodies, + :controller => 'admin_public_body' do + get 'missing_scheme', :on => :collection + post 'mass_tag_add', :on => :collection + get 'import_csv', :on => :collection + post 'import_csv', :on => :collection + end + end #### #### AdminPublicBodyCategory controller @@ -200,9 +198,27 @@ Alaveteli::Application.routes.draw do end #### + #### AdminHoliday controller + scope '/admin', :as => 'admin' do + resources :holidays, + :controller => 'admin_holidays' + end + #### + + #### AdminHolidayImports controller + scope '/admin', :as => 'admin' do + resources :holiday_imports, + :controller => 'admin_holiday_imports', + :only => [:new, :create] + end + #### + #### AdminPublicBodyChangeRequest controller - match '/admin/change_request/edit/:id' => 'admin_public_body_change_requests#edit', :as => :admin_change_request_edit - match '/admin/change_request/update/:id' => 'admin_public_body_change_requests#update', :as => :admin_change_request_update + scope '/admin', :as => 'admin' do + resources :change_requests, + :controller => 'admin_public_body_change_requests', + :only => [:edit, :update] + end #### #### AdminGeneral controller @@ -213,81 +229,99 @@ Alaveteli::Application.routes.draw do #### #### AdminRequest controller - match '/admin/request' => 'admin_request#index', :as => :admin_request_index - match '/admin/request/list' => 'admin_request#list', :as => :admin_request_list - match '/admin/request/show/:id' => 'admin_request#show', :as => :admin_request_show - match '/admin/request/resend' => 'admin_request#resend', :as => :admin_request_resend - match '/admin/request/edit/:id' => 'admin_request#edit', :as => :admin_request_edit - match '/admin/request/update/:id' => 'admin_request#update', :as => :admin_request_update - match '/admin/request/destroy/:id' => 'admin_request#fully_destroy', :as => :admin_request_destroy - match '/admin/request/edit_comment/:id' => 'admin_request#edit_comment', :as => :admin_request_edit_comment - match '/admin/request/update_comment/:id' => 'admin_request#update_comment', :as => :admin_request_update_comment - match '/admin/request/move_request' => 'admin_request#move_request', :as => :admin_request_move_request - match '/admin/request/generate_upload_url/:id' => 'admin_request#generate_upload_url', :as => :admin_request_generate_upload_url - match '/admin/request/show_raw_email/:id' => 'admin_request#show_raw_email', :as => :admin_request_show_raw_email - match '/admin/request/download_raw_email/:id' => 'admin_request#download_raw_email', :as => :admin_request_download_raw_email - match '/admin/request/mark_event_as_clarification' => 'admin_request#mark_event_as_clarification', :as => :admin_request_clarification - match '/admin/request/hide/:id' => 'admin_request#hide_request', :as => :admin_request_hide - #### + scope '/admin', :as => 'admin' do + resources :requests, + :controller => 'admin_request', + :except => [:new, :create] do + post 'move', :on => :member + post 'generate_upload_url', :on => :member + post 'hide', :on => :member + resources :censor_rules, + :controller => 'admin_censor_rule', + :only => [:new, :create], + :name_prefix => 'request_' - #### AdminIncomingMessage controller - match '/admin/incoming/destroy' => 'admin_incoming_message#destroy', :as => :admin_incoming_destroy - match '/admin/incoming/redeliver' => 'admin_incoming_message#redeliver', :as => :admin_incoming_redeliver - match '/admin/incoming/edit/:id' => 'admin_incoming_message#edit', :as => :admin_incoming_edit - match '/admin/incoming/update/:id' => 'admin_incoming_message#update', :as => :admin_incoming_update + end + end #### - #### AdminOutgoingMessage controller - match '/admin/outgoing/edit/:id' => 'admin_outgoing_message#edit', :as => :admin_outgoing_edit - match '/admin/outgoing/destroy/:id' => 'admin_outgoing_message#destroy', :as => :admin_outgoing_destroy - match '/admin/outgoing/update/:id' => 'admin_outgoing_message#update', :as => :admin_outgoing_update + #### AdminComment controller + scope '/admin', :as => 'admin' do + resources :comments, + :controller => 'admin_comment', + :only => [:edit, :update] + end #### - #### AdminUser controller - match '/admin/user' => 'admin_user#index', :as => :admin_user_index - match '/admin/user/list' => 'admin_user#list', :as => :admin_user_list - match '/admin/user/banned' => 'admin_user#list_banned', :as => :admin_user_list_banned - match '/admin/user/show/:id' => 'admin_user#show', :as => :admin_user_show - match '/admin/user/edit/:id' => 'admin_user#edit', :as => :admin_user_edit - match '/admin/user/show_bounce_message/:id' => 'admin_user#show_bounce_message', :as => :admin_user_show_bounce - match '/admin/user/update/:id' => 'admin_user#update', :as => :admin_user_update - match '/admin/user/clear_bounce/:id' => 'admin_user#clear_bounce', :as => :admin_user_clear_bounce - match '/admin/user/destroy_track' => 'admin_user#destroy_track', :as => :admin_user_destroy_track - match '/admin/user/login_as/:id' => 'admin_user#login_as', :as => :admin_user_login_as - match '/admin/user/clear_profile_photo/:id' => 'admin_user#clear_profile_photo', :as => :admin_clear_profile_photo - match '/admin/user/modify_comment_visibility/:id' => 'admin_user#modify_comment_visibility', :as => 'admin_user_modify_comment_visibility' + #### AdminRawEmail controller + scope '/admin', :as => 'admin' do + resources :raw_emails, + :controller => 'admin_raw_email', + :only => [:show] + end #### - #### AdminTrack controller - match '/admin/track/list' => 'admin_track#list', :as => :admin_track_list - #### + #### AdminInfoRequestEvent controller + scope '/admin', :as => 'admin' do + resources :info_request_events, + :controller => 'admin_info_request_event', + :only => [:update] + end - #### AdminCensorRule controller - match '/admin/censor/new' => 'admin_censor_rule#new', :as => :admin_rule_new - match '/admin/censor/create' => 'admin_censor_rule#create', :as => :admin_rule_create - match '/admin/censor/edit/:id' => 'admin_censor_rule#edit', :as => :admin_rule_edit - match '/admin/censor/update/:id' => 'admin_censor_rule#update', :as => :admin_rule_update - match '/admin/censor/destroy/:censor_rule_id' => 'admin_censor_rule#destroy', :as => :admin_rule_destroy + #### AdminIncomingMessage controller + scope '/admin', :as => 'admin' do + resources :incoming_messages, + :controller => 'admin_incoming_message', + :only => [:edit, :update, :destroy] do + post 'redeliver', :on => :member + end + end + #### + #### AdminOutgoingMessage controller scope '/admin', :as => 'admin' do - resources :info_requests, :only => [] do - resources :censor_rules, - :controller => 'admin_censor_rule', - :only => [:new, :create], - :name_prefix => 'info_request_' + resources :outgoing_messages, + :controller => 'admin_outgoing_message', + :only => [:edit, :update, :destroy] do + post 'resend', :on => :member end end + #### + #### AdminUser controller scope '/admin', :as => 'admin' do - resources :users, :only => [] do - resources :censor_rules, - :controller => 'admin_censor_rule', - :only => [:new, :create], - :name_prefix => 'user_' + resources :users, + :controller => 'admin_user', + :except => [:new, :create, :destroy] do + get 'banned', :on => :collection + get 'show_bounce_message', :on => :member + post 'clear_bounce', :on => :member + post 'login_as', :on => :member + post 'clear_profile_photo', :on => :member + post 'modify_comment_visibility', :on => :collection + resources :censor_rules, + :controller => 'admin_censor_rule', + :only => [:new, :create], + :name_prefix => 'user_' end end #### + #### AdminTrack controller + scope '/admin', :as => 'admin' do + resources :tracks, + :controller => 'admin_track', + :only => [:index, :destroy] + end + #### + + #### AdminCensorRule controller + scope '/admin', :as => 'admin' do + resources :censor_rules, + :controller => 'admin_censor_rule', + :except => [:index, :new, :create] + end + #### AdminSpamAddresses controller scope '/admin', :as => 'admin' do resources :spam_addresses, diff --git a/doc/CHANGES.md b/doc/CHANGES.md index 8ee29a9f6..421099604 100644 --- a/doc/CHANGES.md +++ b/doc/CHANGES.md @@ -1,3 +1,29 @@ +# rails-3-develop + +## Highlighted Features + +* State changing admin actions are now restricted to PUT or POST methods + to protect against CSRF attacks, and now use more standard RESTful + routing. +* Global request forgery protection is now used +* The dynamic list of possibly related requests for a new request is now + limited to requests to the same authority and capped at three requests +* Some standard security headers are added by default +* New rake task for cleaning theme translations - `rake + gettext:clean_theme` +* A TTL is enforced on session cookies +* There's a new admin interface for adding public holidays for the site, + to be used in calculating request due dates. +* Autocomplete has been turned off on password fields +* Some interface phrases have been grouped together for easier + translation + +## Upgrade notes + +* Admin route names have been standardised so if you have overridden + templates that refer to admin routes, check the original templates to + see if these need to be changed. + # Version 0.20 ## Highlighted Features diff --git a/lib/alaveteli_text_masker.rb b/lib/alaveteli_text_masker.rb new file mode 100644 index 000000000..68ff0d318 --- /dev/null +++ b/lib/alaveteli_text_masker.rb @@ -0,0 +1,127 @@ +module AlaveteliTextMasker + extend self + DoNotBinaryMask = [ 'image/tiff', + 'image/gif', + 'image/jpeg', + 'image/png', + 'image/bmp', + 'application/zip' ] + + # Replaces all email addresses in (possibly binary) data + # Also applies custom masks and censor items + def apply_masks!(text, content_type, options = {}) + # See if content type is one that we mask - things like zip files and + # images may get broken if we try to. We err on the side of masking too + # much, as many unknown types will really be text. + + # Special cases for some content types + case content_type + when *DoNotBinaryMask + # do nothing + when 'text/html' + apply_text_masks!(text, options) + when 'application/pdf' + apply_pdf_masks!(text, options) + else + apply_binary_masks!(text, options) + end + end + + def apply_pdf_masks!(text, options = {}) + uncompressed_text = nil + uncompressed_text = AlaveteliExternalCommand.run("pdftk", "-", "output", "-", "uncompress", + :stdin_string => text) + # if we managed to uncompress the PDF... + if !uncompressed_text.blank? + # then censor stuff (making a copy so can compare again in a bit) + censored_uncompressed_text = uncompressed_text.dup + apply_binary_masks!(censored_uncompressed_text, options) + # if the censor rule removed something... + if censored_uncompressed_text != uncompressed_text + # then use the altered file (recompressed) + recompressed_text = nil + if AlaveteliConfiguration::use_ghostscript_compression == true + command = ["gs", "-sDEVICE=pdfwrite", "-dCompatibilityLevel=1.4", "-dPDFSETTINGS=/screen", "-dNOPAUSE", "-dQUIET", "-dBATCH", "-sOutputFile=-", "-"] + else + command = ["pdftk", "-", "output", "-", "compress"] + end + recompressed_text = AlaveteliExternalCommand.run(*(command + [{:stdin_string=>censored_uncompressed_text}])) + if recompressed_text.blank? + # buggy versions of pdftk sometimes fail on + # compression, I don't see it's a disaster in + # these cases to save an uncompressed version? + recompressed_text = censored_uncompressed_text + logger.warn "Unable to compress PDF; problem with your pdftk version?" + end + if !recompressed_text.blank? + text.replace recompressed_text + end + end + end + end + + private + + # Replace text in place + def apply_binary_masks!(text, options = {}) + # Keep original size, so can check haven't resized it + orig_size = text.mb_chars.size + + # Replace ASCII email addresses... + text.gsub!(MySociety::Validate.email_find_regexp) do |email| + email.gsub(/[^@.]/, 'x') + end + + # And replace UCS-2 ones (for Microsoft Office documents)... + # Find emails, by finding them in parts of text that have ASCII + # equivalents to the UCS-2 + ascii_chars = text.gsub(/\0/, "") + emails = ascii_chars.scan(MySociety::Validate.email_find_regexp) + + # Convert back to UCS-2, making a mask at the same time + if String.method_defined?(:encode) + emails.map! do |email| + # We want the ASCII representation of UCS-2 + [email[0].encode('UTF-16LE').force_encoding('US-ASCII'), + email[0].gsub(/[^@.]/, 'x').encode('UTF-16LE').force_encoding('US-ASCII')] + end + else + emails.map! {|email| [ + Iconv.conv('ucs-2le', 'ascii', email[0]), + Iconv.conv('ucs-2le', 'ascii', email[0].gsub(/[^@.]/, 'x')) + ] } + end + + # Now search and replace the UCS-2 email with the UCS-2 mask + for email, mask in emails + text.gsub!(email, mask) + end + + # Replace censor items + censor_rules = options[:censor_rules] || [] + censor_rules.each{ |censor_rule| censor_rule.apply_to_binary!(text) } + raise "internal error in apply_binary_masks!" if text.mb_chars.size != orig_size + return text + end + + # Remove any email addresses, login links and mobile phone numbers + def default_text_masks + [{ :to_replace => MySociety::Validate.email_find_regexp, + :replacement => "[#{_("email address")}]" }, + { :to_replace => /(Mobile|Mob)([\s\/]*(Fax|Tel))*\s*:?[\s\d]*\d/, + :replacement => "[#{_("mobile number")}]" }, + { :to_replace => /https?:\/\/#{AlaveteliConfiguration::domain}\/c\/[^\s]+/, + :replacement => "[#{_("{{site_name}} login link", + :site_name => AlaveteliConfiguration::site_name)}]" }] + end + + def apply_text_masks!(text, options = {}) + masks = options[:masks] || [] + masks += default_text_masks + censor_rules = options[:censor_rules] || [] + masks.each{ |mask| text.gsub!(mask[:to_replace], mask[:replacement]) } + censor_rules.each{ |censor_rule| censor_rule.apply_to_text!(text) } + text + end + +end diff --git a/lib/languages.rb b/lib/languages.rb index 42231ef56..85d2d5950 100644 --- a/lib/languages.rb +++ b/lib/languages.rb @@ -111,11 +111,11 @@ class LanguageNames 'mn' => 'монгол', 'na' => 'Ekakairũ Naoero', 'nv' => 'Diné bizaad', - 'nb' => 'Norsk bokmål', + 'nb' => 'Bokmål', 'nd' => 'isiNdebele', 'ne' => 'नेपाली', 'ng' => 'Owambo', - 'nn' => 'Norsk nynorsk', + 'nn' => 'Nynorsk', 'no' => 'Norsk', 'ii' => 'ꆈꌠ꒿ Nuosuhxop', 'nr' => 'isiNdebele', diff --git a/lib/quiet_opener.rb b/lib/quiet_opener.rb index 16ea27b8e..c6e259b93 100644 --- a/lib/quiet_opener.rb +++ b/lib/quiet_opener.rb @@ -7,8 +7,19 @@ end def quietly_try_to_open(url) begin result = open(url).read.strip - rescue OpenURI::HTTPError, SocketError, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ECONNRESET - Rails.logger.warn("Unable to open third-party URL #{url}") + rescue OpenURI::HTTPError, + SocketError, + Errno::ETIMEDOUT, + Errno::ECONNREFUSED, + Errno::EHOSTUNREACH, + Errno::ECONNRESET, + Timeout::Error => exception + e = Exception.new("Unable to open third-party URL #{url}: #{exception.message}") + e.set_backtrace(exception.backtrace) + if !AlaveteliConfiguration.exception_notifications_from.blank? && !AlaveteliConfiguration.exception_notifications_to.blank? + ExceptionNotifier::Notifier.exception_notification(request.env, e).deliver + end + Rails.logger.warn(e.message) result = "" end return result diff --git a/lib/tasks/gettext.rake b/lib/tasks/gettext.rake index 3f357213f..9bdb6169b 100644 --- a/lib/tasks/gettext.rake +++ b/lib/tasks/gettext.rake @@ -11,11 +11,7 @@ namespace :gettext 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 + theme = find_theme(ENV['THEME']) load_gettext msgmerge = Rails.application.config.gettext_i18n_rails.msgmerge msgmerge ||= %w[--sort-output --no-location --no-wrap] @@ -28,6 +24,25 @@ namespace :gettext do ) end + desc 'Rewrite theme .po files into a consistent msgmerge format' + task :clean_theme do + theme = find_theme(ENV['THEME']) + load_gettext + + Dir.glob("#{ theme_locale_path(theme) }/*/app.po") do |po_file| + GetText::msgmerge(po_file, po_file, 'alaveteli', + :msgmerge => [:sort_output, :no_location, :no_wrap]) + end + end + + def find_theme(theme) + unless theme + puts "Usage: Specify an Alaveteli-theme with THEME=[theme directory name]" + exit(0) + end + theme + end + def theme_files_to_translate(theme) Dir.glob("{lib/themes/#{theme}/lib}/**/*.{rb,erb}") end diff --git a/locale/nb_NO/app.po b/locale/nb_NO/app.po deleted file mode 100644 index e99bb35d7..000000000 --- a/locale/nb_NO/app.po +++ /dev/null @@ -1,3948 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# andreli <andre@lindhjem.net>, 2013 -# andreli <andre@lindhjem.net>, 2013 -# atluxity <atluxity@1kb.no>, 2014 -# atluxity <atluxity@1kb.no>, 2014 -# gorm <gormer@gmail.com>, 2013-2014 -# gorm <gormer@gmail.com>, 2013 -# atluxity <atluxity@1kb.no>, 2014 -# Kjetil Torgrim Homme <kjetilho@ifi.uio.no>, 2015 -# louisecrow <louise@mysociety.org>, 2014 -# oeyrvin <oeyrvin@hagan.no>, 2014 -# oeyrvin <oeyrvin@hagan.no>, 2014 -# pere <pere-transifex@hungry.com>, 2013 -# pere <pere-transifex@hungry.com>, 2013-2015 -msgid "" -msgstr "" -"Project-Id-Version: alaveteli\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-12-02 13:14+0000\n" -"PO-Revision-Date: 2015-01-06 11:39+0000\n" -"Last-Translator: pere <pere-transifex@hungry.com>\n" -"Language-Team: Norwegian Bokmål (Norway) (http://www.transifex.com/projects/p/alaveteli/language/nb_NO/)\n" -"Language: nb_NO\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgid " This will appear on your {{site_name}} profile, to make it\\n easier for others to get involved with what you're doing." -msgstr "Dette vil vises i din profil på {{site_name}}, for å gjøre det enklere\\n for andre å delta i hva du holder på med." - -msgid " (<strong>no ranty</strong> politics, read our <a href=\"{{url}}\">moderation policy</a>)" -msgstr " (<strong>ikke noe</strong> tåkeprat, les våre <a href=\"{{url}}\">retningslinjer for moderering</a>)" - -msgid " (<strong>patience</strong>, especially for large files, it may take a while!)" -msgstr " (<strong>ha tålmodighet</strong>, spesielt for store filer, dette kan ta litt tid!)" - -msgid " (you)" -msgstr " (deg)" - -msgid " - view and make Freedom of Information requests" -msgstr " - se og lag innsynsbegjæringer" - -msgid " - wall" -msgstr " - vegg" - -msgid " < " -msgstr "<" - -msgid " << " -msgstr "<<" - -msgid " <strong>Note:</strong>\\n We will send you an email. Follow the instructions in it to change\\n your password." -msgstr " <strong>Merk:</strong>\\n Vi kommer til å sende deg en e-post. Følg instruksjonene i den for å bytte\\n passordet ditt." - -msgid " <strong>Privacy note:</strong> Your email address will be given to" -msgstr "<strong>Personvernvarsel:</strong>E-postadressen din vil bli gitt til" - -msgid " <strong>Summarise</strong> the content of any information returned. " -msgstr "<stong>Oppsummer</strong> innholdet av utlevert informasjon." - -msgid " > " -msgstr ">" - -msgid " >> " -msgstr ">>" - -msgid " Advise on how to <strong>best clarify</strong> the request." -msgstr "Råd om hvordan <strong>best klargjøre</strong> henvendelsen." - -msgid " Ideas on what <strong>other documents to request</strong> which the authority may hold. " -msgstr "Ideer om hvilke <strong>andre dokumenter å be om</strong> som etaten kan ha." - -msgid " If you know the address to use, then please <a href=\"{{url}}\">send it to us</a>.\\n You may be able to find the address on their website, or by phoning them up and asking." -msgstr "Hvis du vet adressen som kan brukes, vær så snill å <a href=\"{{url}}\">send den til oss</a>. Du finner kanskje adressen på deres nettsted eller ved å ringe dem opp og spørre." - -msgid " Include relevant links, such as to a campaign page, your blog or a\\n twitter account. They will be made clickable. \\n e.g." -msgstr "Inkluder relevante lenker, som f.eks. din kampanjeside, blogg, Twitter-konto o.l. De vil vises som lenker her. \\n f.eks." - -msgid " Link to the information requested, if it is <strong>already available</strong> on the Internet. " -msgstr " Lenke til informasjonen som det ble spurt om, om den <strong>allerede var tilgjengelig</strong> på Internettet." - -msgid " Offer better ways of <strong>wording the request</strong> to get the information. " -msgstr "Tilby bedre måter å <strong>ordlegge henvendelsen</strong> for å få informasjonen." - -msgid " Say how you've <strong>used the information</strong>, with links if possible." -msgstr "Fortell hvordan du <strong>brukte informasjonen</strong>, gjerne med lenker hvis det er mulig." - -msgid " Suggest <strong>where else</strong> the requester might find the information. " -msgstr "Foreslå <strong>hvor ellers</strong> innsenderen kan finne informasjonen." - -msgid " What are you investigating using Freedom of Information? " -msgstr " Hva er det du undersøker med innsynsbegjæringene dine? " - -msgid " You are already being emailed updates about the request." -msgstr "Du mottar allerede oppdateringer om denne henvendelsen på e-post." - -msgid " You will also be emailed updates about the request." -msgstr "Du vil også motta oppdateringer om denne henvendelsen på e-post." - -msgid " filtered by status: '{{status}}'" -msgstr "filtrert etter status: '{{status}}'" - -msgid " when you send this message." -msgstr " når du sender denne meldingen." - -msgid "'Crime statistics by ward level for Wales'" -msgstr "'Kriminalitetsstatistikk på bydelsnivå for Oslo'" - -msgid "'Pollution levels over time for the River Tyne'" -msgstr "'Forurensningsnivå over tid i Akerselva'" - -msgid "'{{link_to_authority}}', a public authority" -msgstr "'{{link_to_authority}}', en offentlig myndighet" - -msgid "'{{link_to_request}}', a request" -msgstr "'{{link_to_request}}', en henvendelse" - -msgid "'{{link_to_user}}', a person" -msgstr "'{{link_to_user}}', en person" - -msgid "(hide)" -msgstr "(skjul)" - -msgid "(or <a href=\"{{url}}\">sign in</a>)" -msgstr "(eller <a href=\"{{url}}\">logg på</a>)" - -msgid "(show)" -msgstr "(vis)" - -msgid "*unknown*" -msgstr "*ukjent*" - -msgid ",\\n\\n\\n\\nYours,\\n\\n{{user_name}}" -msgstr ",\\n\\n\\n\\nMed vennlig hilsen,\\n\\n{{user_name}}" - -msgid "- or -" -msgstr "- eller -" - -msgid "1. Select an authority" -msgstr "1. Velg en myndighet" - -msgid "1. Select authorities" -msgstr "1. Velg myndigheter" - -msgid "2. Ask for Information" -msgstr "2. Be om innsyn" - -msgid "3. Now check your request" -msgstr "3. Se over henvendelsen din nå" - -msgid "<a href=\"{{browse_url}}\">Browse all</a> or <a href=\"{{add_url}}\">ask us to add one</a>." -msgstr "<a href=\"{{browse_url}}\">Bla i gjennom alle</a> eller <a href=\"{{add_url}}\">be oss om å legge til en ny</a>." - -msgid "<a href=\"{{url}}\">Add an annotation</a> (to help the requester or others)" -msgstr "<a href=\"{{url}}\">Legg til merknad</a> (for å hjelpe innsender eller andre)" - -msgid "<a href=\"{{url}}\">Sign in</a> to change password, subscriptions and more ({{user_name}} only)" -msgstr "<a href=\"{{url}}\">Logg inn</a> for å endre passord, abonnementer og mer (kun {{user_name}})" - -msgid "<p>All done! Thank you very much for your help.</p><p>There are <a href=\"{{helpus_url}}\">more things you can do</a> to help {{site_name}}.</p>" -msgstr "<p>Alt er ferdig! Tusen takk for hjelpen.</p><p>Det er <a href=\"{{helpus_url}}\">flere ting du kan gjøre</a> for å hjelpe {{site_name}}.</p>" - -msgid "<p>Thank you! Here are some ideas on what to do next:</p>\\n <ul>\\n <li>To send your request to another authority, first copy the text of your request below, then <a href=\"{{find_authority_url}}\">find the other authority</a>.</li>\\n <li>If you would like to contest the authority's claim that they do not hold the information, here is\\n <a href=\"{{complain_url}}\">how to complain</a>.\\n </li>\\n <li>We have <a href=\"{{other_means_url}}\">suggestions</a>\\n on other means to answer your question.\\n </li>\\n </ul>" -msgstr "<p>Tusen takk! Her er noen ideer om hva som kan gjøres videre:</p>\\n <ul>\\n <li>For å sende henvendelsen til en annen myndighet, må du først kopiere teksten i din henvendelse nedenfor, deretter <a href=\"{{find_authority_url}}\">finne den andre myndigheten</a>.</li>\\n <li>Hvis du gjerne vil gå videre med å undersøke om de faktisk ikke har informasjonen, se her for å lære\\n <a href=\"{{complain_url}}\">hvordan man klager</a>.\\n </li>\\n <li>Vi har <a href=\"{{other_means_url}}\">forslag</a>\\n til andre muligheter til å få svar på ditt spørsmål.\\n </li>\\n </ul>" - -msgid "<p>Thank you! Hope you don't have to wait much longer.</p> <p>By law, you should have got a response promptly, and normally before the end of <strong>{{date_response_required_by}}</strong>.</p>" -msgstr "<p>Takk! Vi håper du slipper å vente mye lenger.</p> <p>I følge loven så bør du få svar innen rimelig tid, og normalt før slutten av <strong>{{date_response_required_by}}</strong>.</p>" - -msgid "<p>Thank you! Hopefully your wait isn't too long.</p> <p>By law, you should get a response promptly, and normally before the end of <strong>\\n{{date_response_required_by}}</strong>.</p>" -msgstr "<p>Tusen takk! Forhåpentligvis må du ikke vente for lenge.</p> <p>Etter loven skal du få svar uten opphold, og normalt før utgangen av <strong>\\n{{date_response_required_by}}</strong>.</p>" - -msgid "<p>Thank you! Hopefully your wait isn't too long.</p><p>You should get a response within {{late_number_of_days}} days, or be told if it will take longer (<a href=\"{{review_url}}\">details</a>).</p>" -msgstr "<p>Takk! Vi håper du slipper å vente for lenge.</p><p>Du bør få et svar iløpet av {{late_number_of_days}} dager, eller få beskjed dersom det vil ta lenger tid (<a href=\"{{review_url}}\">detaljer</a>).</p>" - -msgid "<p>Thank you! Your request is long overdue, by more than {{very_late_number_of_days}} working days. Most requests should be answered within {{late_number_of_days}} working days. You might like to complain about this, see below.</p>" -msgstr "Takk! Din henvendelse har gått over svarfristen med mer enn {{very_late_number_of_days}} arbeidsdager. De fleste henvendelser bør få svar innen {{late_number_of_days}} arbeidsdager. Se under dersom du vil klage på dette.</p>" - -msgid "<p>Thanks for changing the text about you on your profile.</p>\\n <p><strong>Next...</strong> You can upload a profile photograph too.</p>" -msgstr "<p>Takk for at du endret teksten om deg på din profil.</p>\\n <p><strong>Som neste steg...</strong>kan du laste opp et profilbilde.</p>" - -msgid "<p>Thanks for updating your profile photo.</p>\\n <p><strong>Next...</strong> You can put some text about you and your research on your profile.</p>" -msgstr "<p>Takk for at du oppdaterte ditt profilbilde.</p>\\n <p><strong>Som neste steg...</strong> kan du legge ut litt tekst om deg og din forskning på din profil.</p>" - -msgid "<p>We recommend that you edit your request and remove the email address.\\n If you leave it, the email address will be sent to the authority, but will not be displayed on the site.</p>" -msgstr "<p>Vi anbefaler at du redigerer din henvendelsen og fjerner e-postadressen.\\n Hvis du lar den være, vil e-postadressen bli sendt til etaten, men vil ikke bli vist frem på nettstedet.</p>" - -msgid "<p>We're glad you got all the information that you wanted. If you write about or make use of the information, please come back and add an annotation below saying what you did.</p>" -msgstr "<p>Vi er glad du fikk all informasjonen du ønsket. Hvis du skriver om det eller gjør bruk av informasjonen, vær så snill å kom tilbake hit og legg inn en bemerkning under som forteller hva du gjorde.</p>" - -msgid "<p>We're glad you got all the information that you wanted. If you write about or make use of the information, please come back and add an annotation below saying what you did.</p><p>If you found {{site_name}} useful, <a href=\"{{donation_url}}\">make a donation</a> to the charity which runs it.</p>" -msgstr "<p>Vi er glad for at du fikk den informasjonen du var ute etter. Hvis du skriver om, eller bruker informasjonen, vennligst kom tilbake hit og legg til et notat under og del med andre hva du har gjort.</p><p>Dersom du synes {{site_name}} er nyttig, så kan du <a href=\"{{donation_url}}\">gi et bidrag</a> til organisasjonen drifter denne siden.</p>" - -msgid "<p>We're glad you got some of the information that you wanted. If you found {{site_name}} useful, <a href=\"{{donation_url}}\">make a donation</a> to the charity which runs it.</p><p>If you want to try and get the rest of the information, here's what to do now.</p>" -msgstr "<p>Vi er glad for at du fikk noe av informasjonen du var ute etter. Dersom du synes at {{site_name}} er nyttig, så kan du <a href=\"{{donation_url}}\">gi et bidrag</a> til organisasjonen som drifter denne siden.</p><p>Hvis du vil forsøke å få tak i resten av informasjonen, så forklarer vi hva du bør gjøre videre.</p>" - -msgid "<p>We're glad you got some of the information that you wanted.</p><p>If you want to try and get the rest of the information, here's what to do now.</p>" -msgstr "<p>Vi er glade for at du fikk noe av informasjonen du ønsket.</p><p>Hvis du ønsker å forsøke å få tak i resten av informasjonen, så kan du gjøre følgende.</p>" - -msgid "<p>You do not need to include your email in the request in order to get a reply (<a href=\"{{url}}\">details</a>).</p>" -msgstr "<p>Du trenger ikke ta med e-postadressen i henvendelsen for å få et svar (<a href=\"{{url}}\">detaljer</a>).</p>" - -msgid "<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>" -msgstr "<p>Du trenger ikke ta med e-postadressen i henvendelsen for å få et svar, da vi vil spørre om den i det neste skjermbildet (<a href=\"{{url}}\">detaljer</a>).</p>" - -msgid "<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>" -msgstr "<p>Din henvendelse inneholder et <strong>postnummer</strong>. Med mindre det er direkte relevant for temaet i din henvendelse, vær så snill å fjern enhver adresse da den vil <strong>være offentlig tilgjengelig på Internettet</strong>.</p>" - -msgid "<p>Your {{law_used_full}} request has been <strong>sent on its way</strong>!</p>\\n <p><strong>We will email you</strong> when there is a response, or after {{late_number_of_days}} working days if the authority still hasn't\\n replied by then.</p>\\n <p>If you write about this request (for example in a forum or a blog) please link to this page, and add an\\n annotation below telling people about your writing.</p>" -msgstr "" -"<p>Din {{law_used_full}}-henvendelsen har blitt <strong>sendt avgårde</strong>!</p>\\n\n" -"<p><strong>Vi vil kontakte deg med e-post</strong> når det kommer et svar, eller etter {{late_number_of_days}} arbeidsdager, om myndigheten ikke har svart innen da.</p>\\n\n" -"<p>Hvis du skriver om denne henvendelsen (for eksempel i et forum eller en blogg), så er det fint om du lenker til denne siden, og legger til en kommentar under som forteller folk om det du har skrevet." - -msgid "<p>Your {{law_used_full}} requests will be <strong>sent</strong> shortly!</p>\\n <p><strong>We will email you</strong> when they have been sent.\\n 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\\n replied by then.</p>\\n <p>If you write about these requests (for example in a forum or a blog) please link to this page.</p>" -msgstr "<p>Dine {{law_used_full}}-henvendelser vil bli <strong>sent</strong> straks!</p>\\n<p><strong>Vi vil send deg e-post</strong> når de er sendt.\\n Vi vil også sende deg e-post når det kommer svar for en av dem, eller etter {{late_number_of_days}} arbeidsdager hvis myndighetene fortsatt ikke har svart innen da.</p>\\n<p>Hvis du skriver om disse henvendelsene (for eksempel i et forum eller en blogg), vær så snill å lenk til denne siden.</p>" - -msgid "<p>{{site_name}} is currently in maintenance. You can only view existing requests. You cannot make new ones, add followups or annotations, or otherwise change the database.</p> <p>{{read_only}}</p>" -msgstr "<p>Det utføres vedlikehold på {{site_name}}. Du kan bare se på eksisterende henvendelser. Du kan ikke opprette nye, legge til oppfølgingshenvendelser, notater eller endre på data.</p> <p>{{read_only}}</p>" - -msgid "<small>If you use web-based email or have \"junk mail\" filters, also check your\\nbulk/spam mail folders. Sometimes, our messages are marked that way.</small>\\n</p>" -msgstr "<small>Bruker du web-basert e-post eller har \"spam-filter\", sjekk også din\\nsøppel/spam-e-postfolder. Det hender at meldingene våre blir behandlet som spam.</small>\\n</p>" - -msgid "<strong> Can I request information about myself?</strong>\\n\t\t\t<a href=\"{{url}}\">No! (Click here for details)</a>" -msgstr "<strong> Kan jeg be om informasjon om meg personlig?</strong>\\n\t\t\t<a href=\"{{url}}\">NEI! (klikk her for detaljer)</a>" - -msgid "<strong><code>commented_by:tony_bowden</code></strong> to search annotations made by Tony Bowden, typing the name as in the URL." -msgstr "<strong><code>commented_by:tony_bowden</code></strong> for å søke etter annoteringer fra Tony Bowden. Navnet skrives slik det kommer frem i URL." - -msgid "<strong><code>filetype:pdf</code></strong> to find all responses with PDF attachments. Or try these: <code>{{list_of_file_extensions}}</code>" -msgstr "<strong><code>filetype:pdf</code></strong> for å finne alle svar som har PDF-vedlegg. Eller, forsøk med disse: <code>{{list_of_file_extensions}}</code>" - -msgid "<strong><code>request:</code></strong> to restrict to a specific request, typing the title as in the URL." -msgstr "<strong><code>request:</code></strong> for å begrense til én henvendelse. Tittel skrives som den kommer frem i URL." - -msgid "<strong><code>requested_by:julian_todd</code></strong> to search requests made by Julian Todd, typing the name as in the URL." -msgstr "<strong><code>requested_by:julian_todd</code></strong> for å søke etter henvendelser gjort av Julian Todd. Navnet skrives slik det kommer frem i URL." - -msgid "<strong><code>requested_from:home_office</code></strong> to search requests from the Home Office, typing the name as in the URL." -msgstr "<strong><code>requested_from:home_office</code></strong> for å søke i henvendelser mot statsministerens kontor, skriv navnet inn som URL-en." - -msgid "<strong><code>status:</code></strong> to select based on the status or historical status of the request, see the <a href=\"{{statuses_url}}\">table of statuses</a> below." -msgstr "<strong><code>status:</code></strong> for å velge ut fra nåværende eller tidligere status til en henvendelse. Se <a href=\"{{statuses_url}}\">tabell over statuser</a> under." - -msgid "<strong><code>tag:charity</code></strong> to find all public authorities or requests with a given tag. You can include multiple tags, \\n and tag values, e.g. <code>tag:openlylocal AND tag:financial_transaction:335633</code>. Note that by default any of the tags\\n can be present, you have to put <code>AND</code> explicitly if you only want results them all present." -msgstr "<strong><code>tag:charity</code></strong> for å finne alle offentlige myndigheter eller med en gitt merkelapp. Man kan ha med flere merkelapper, \\n og -innhold, for eksempel <code>tag:openlylocal AND tag:financial_transaction:335633</code>. Merk at som standard kan hver av merkelappene \\n være med. Da må du sette <code>AND</code> tydelig hvis du ønsker å ha alle med. " - -msgid "<strong><code>variety:</code></strong> to select type of thing to search for, see the <a href=\"{{varieties_url}}\">table of varieties</a> below." -msgstr "<strong><code>variety:</code></strong> for å velge typen ting du skal søke etter. Se <a href=\"{{varieties_url}}\">tabell over typer</a> under." - -msgid "<strong>Advice</strong> on how to get a response that will satisfy the requester. </li>" -msgstr "<strong>Råd</strong> for å få et svar som er tilfredsstillende til den som spør. </li>" - -msgid "<strong>All the information</strong> has been sent" -msgstr "<strong>All informasjonen</strong> har blitt sendt" - -msgid "<strong>Anything else</strong>, such as clarifying, prompting, thanking" -msgstr "<strong>Noe annet</strong>, som for eksempel oppklaringer, spørsmål, takk" - -msgid "<strong>Caveat emptor!</strong> To use this data in an honourable way, you will need \\na good internal knowledge of user behaviour on {{site_name}}. How, \\nwhy and by whom requests are categorised is not straightforward, and there will\\nbe user error and ambiguity. You will also need to understand FOI law, and the\\nway authorities use it. Plus you'll need to be an elite statistician. Please\\n<a href=\"{{contact_path}}\">contact us</a> with questions." -msgstr "<strong>Advarsel!</strong> For å bruke disse dataene ordentlig, vil du trenge \\n god kunnskap om brukeradferd på {{site_name}}. Hvordan,\\n hvorfor, og av hvem henvendelser er kategorisert er ikke bare enkelt, og det vil \\n være brukerfeil og uklarheter. Du vil også ha behov for å forstå offentlighetslovgivningen og måten\\n myndighetene bruker den. Og du må være en dyktig statistiker. <a href=\"{{contact_path}}\">Kontakt oss</a> gjerne med spørsmål." - -msgid "<strong>Clarification</strong> has been requested" -msgstr "<strong>Klargjøring</strong> har blitt forespurt" - -msgid "<strong>No response</strong> has been received\\n <small>(maybe there's just an acknowledgement)</small>" -msgstr "<strong>Intet svar</strong>er mottatt\\n <small>(kanskje bare en bekreftelse på at henvendelsen er mottatt)</small>" - -msgid "<strong>Note:</strong> Because we're testing, requests are being sent to {{email}} rather than to the actual authority." -msgstr "<strong>Merk:</strong> Fordi vi holder på å teste, så vil begjæringer bli sendt til {{email}} istedet for den faktiske myndigheten." - -msgid "<strong>Note:</strong> You're sending a message to yourself, presumably\\n to try out how it works." -msgstr "<strong>Merk:</strong> Du sender en beskjed til deg selv, vi anter at det er\\n for å teste hvordan det fungerer." - -msgid "<strong>Note:</strong>\\n We will send an email to your new email address. Follow the\\n instructions in it to confirm changing your email." -msgstr "<strong>Merk:</strong>\\n Vi kommer til å sende en e-post til din nye e-postadresse. Følg\\n instruksjonene i den e-posten for å bekrefte at du ønsker å bytte e-postadresse." - -msgid "<strong>Privacy note:</strong> If you want to request private information about\\n yourself then <a href=\"{{url}}\">click here</a>." -msgstr "<strong>Personverns OBS</strong> Om du ønsker å spørre om personlig informasjon om\\n deg selv <a href=\"{{url}}\">klikk her</a>." - -msgid "<strong>Privacy note:</strong> Your photo will be shown in public on the Internet,\\n wherever you do something on {{site_name}}." -msgstr "<strong>Personverns OBS:</strong> Ditt bilde vil være offentlig tlgjengelig på hele Internettet.\\n uavhengig om du gjør noe på {{site_name}}." - -msgid "<strong>Privacy warning:</strong> Your message, and any response\\n to it, will be displayed publicly on this website." -msgstr "<strong>Personverns OBS:</strong> Meldingen din og alle svar\\n\\n vil vises offentlig på denne tjenesten." - -msgid "<strong>Some of the information</strong> has been sent " -msgstr "<strong>Noe av informasjonen</strong> ble sendt" - -msgid "<strong>Thank</strong> the public authority or " -msgstr "<strong>Takk</strong> myndigheten eller " - -msgid "<strong>did not have</strong> the information requested." -msgstr "<strong>hadde ikke</strong> informasjonen du ba om." - -msgid "?" -msgstr "?" - -msgid "A <a href=\"{{request_url}}\">follow up</a> to <em>{{request_title}}</em> was sent to {{public_body_name}} by {{info_request_user}} on {{date}}." -msgstr "En <a href=\"{{request_url}}\">oppfølging</a> til <em>{{request_title}}</em> ble sendt til {{public_body_name}} fra {{info_request_user}} den {{date}}." - -msgid "A <a href=\"{{request_url}}\">response</a> to <em>{{request_title}}</em> was sent by {{public_body_name}} to {{info_request_user}} on {{date}}. The request status is: {{request_status}}" -msgstr "Et <a href=\"{{request_url}}\">svar</a> til <em>{{request_title}}</em> var sendt av {{public_body_name}} til {{info_request_user}} den {{date}}. Begjæringen sin status er: {{request_status}}" - -msgid "A <strong>summary</strong> of the response if you have received it by post. " -msgstr "En <strong>oppsummering</strong> av svaret dersom du har mottat det i posten. " - -msgid "A Freedom of Information request" -msgstr "En innsynsbegjæring" - -msgid "A full history of my FOI request and all correspondence is available on the Internet at this address: {{url}}" -msgstr "Komplett historie for min innsynshenvendelse og all korrespondanse er tilgjengelig på Internettet fra denne adressen: {{url}}" - -msgid "A new request, <em><a href=\"{{request_url}}\">{{request_title}}</a></em>, was sent to {{public_body_name}} by {{info_request_user}} on {{date}}." -msgstr "En ny henvendelse, <em><a href=\"{{request_url}}\">{{request_title}}</a></em>, ble sendt til {{public_body_name}} av {{info_request_user}} den {{date}}." - -msgid "A public authority" -msgstr "En offentlig myndighet" - -msgid "A response will be sent <strong>by post</strong>" -msgstr "Et svar vil bli sendt <strong>per brev</strong>" - -msgid "A strange reponse, required attention by the {{site_name}} team" -msgstr "Et merkelig svar krevde oppfølging fra {{site_name}}-gruppen" - -msgid "A vexatious request" -msgstr "En sjikanøs henvendelse" - -msgid "A {{site_name}} user" -msgstr "En {{site_name}} bruker" - -msgid "About you:" -msgstr "Om deg:" - -msgid "Act on what you've learnt" -msgstr "Gjør noe med det du har lært" - -msgid "Acts as xapian/acts as xapian job" -msgstr "Acts as xapian/acts as xapian job" - -msgid "ActsAsXapian::ActsAsXapianJob|Action" -msgstr "ActsAsXapian::ActsAsXapianJob|Action" - -msgid "ActsAsXapian::ActsAsXapianJob|Model" -msgstr "ActsAsXapian::ActsAsXapianJob|Model" - -msgid "Add an annotation" -msgstr "Legg til en merknad" - -msgid "Add an annotation to your request with choice quotes, or\\n a <strong>summary of the response</strong>." -msgstr "Legg til en kommentar til henvendelsen med utvalgte sitater, eller\\n <strong> gi en oppsummering av svaret.</strong>" - -msgid "Add authority - {{public_body_name}}" -msgstr "Legg til myndighet - {{public_body_name}}" - -msgid "Add the authority:" -msgstr "Legg til myndigheten:" - -msgid "Added on {{date}}" -msgstr "Lagt til {{date}}" - -msgid "Admin level is not included in list" -msgstr "Administrasjonsnivå er ikke med i listen" - -msgid "Administration URL:" -msgstr "Administrasjons-URL:" - -msgid "Advanced search" -msgstr "Avansert søk" - -msgid "Advanced search tips" -msgstr "Avansert søketips" - -msgid "Advise on whether the <strong>refusal is legal</strong>, and how to complain about it if not." -msgstr "Råd om hvorvidt <strong>avvisningen er lovlig</strong>, og hvordan du eventuelt kan klage." - -msgid "Air, water, soil, land, flora and fauna (including how these effect\\n human beings)" -msgstr "Luft, vann, jord, flora og fauna (inkludert hvordan disse påvirker\\n mennesker)" - -msgid "All of the information requested has been received" -msgstr "All forespurt informasjon er blitt mottatt" - -msgid "All the options below can use <strong>status</strong> or <strong>latest_status</strong> before the colon. For example, <strong>status:not_held</strong> will match requests which have <em>ever</em> been marked as not held; <strong>latest_status:not_held</strong> will match only requests that are <em>currently</em> marked as not held." -msgstr "Alle valgene under kan bruke <strong>status</strong> eller <strong>latest_status</strong> før kolon. For eksempel, <strong>status:not_held</strong> vil få treff i henvendelser som <em>nå eller tidligere</em> har vært merket som not held; <strong>latest_status:not_held</strong> vil kun treffe henvendelser som er <em>nå</em> er markert som not held." - -msgid "All the options below can use <strong>variety</strong> or <strong>latest_variety</strong> before the colon. For example, <strong>variety:sent</strong> will match requests which have <em>ever</em> been sent; <strong>latest_variety:sent</strong> will match only requests that are <em>currently</em> marked as sent." -msgstr "Alle alternativene nedenfor kan bruke <strong>variety</strong> eller <strong>latest_variety</strong> foran kolon. For eksempel, <strong>variety:sent</strong> vil svare til henvendelser som har <em>noen gang</em> blitt sent; <strong>latest_variety:sent</strong> vil bare svare til henvendelser <em>som for tiden</em> er merket som sendt." - -msgid "Also called {{other_name}}." -msgstr "Også kalt {{other_name}}." - -msgid "Also send me alerts by email" -msgstr "Send meg også varsel via e-post" - -msgid "Alter your subscription" -msgstr "Endre ditt abonnement" - -msgid "Although all responses are automatically published, we depend on\\nyou, the original requester, to evaluate them." -msgstr "Selv om alle svar blir automatisk publisert så er vi avhengig av deg,\\nden opprinnelige innsenderen, til å vurdere dem." - -msgid "An <a href=\"{{request_url}}\">annotation</a> to <em>{{request_title}}</em> was made by {{event_comment_user}} on {{date}}" -msgstr "En <a href=\"{{request_url}}\">annotering</a> til <em>{{request_title}}</em> ble laget av {{event_comment_user}} på {{date}}" - -msgid "An <strong>error message</strong> has been received" -msgstr "En <strong>feilmelding</strong> har blitt mottatt" - -msgid "An Environmental Information Regulations request" -msgstr "En miljøinformasjonslov-henvendelse" - -msgid "An anonymous user" -msgstr "En anonym bruker" - -msgid "Annotation added to request" -msgstr "Merknad lagt til henvendelse" - -msgid "Annotations" -msgstr "Merknader" - -msgid "Annotations are so anyone, including you, can help the requester with their request. For example:" -msgstr "Merknader gjør at enhver, også du, kan hjelpe innsender med deres henvendelse. For eksempel:" - -msgid "Annotations will be posted publicly here, and are\\n <strong>not</strong> sent to {{public_body_name}}." -msgstr "Merknader gjøres offentlig tilgjengelig her og er <strong>ikke</strong> sendt til {{public_body_name}}." - -msgid "Anonymous user" -msgstr "Anonym bruker" - -msgid "Anyone:" -msgstr "Alle" - -msgid "Applies to" -msgstr "Gjelder for" - -msgid "Are we missing a public authority?" -msgstr "Skal vi legge til flere myndigheter?" - -msgid "Are you the owner of any commercial copyright on this page?" -msgstr "Er du eier av kommersielle åndsverksrettigheter på denne siden?" - -msgid "Ask for <strong>specific</strong> documents or information, this site is not suitable for general enquiries." -msgstr "Spør om <strong>spesifikke</strong> dokumenter, informasjon eller veiledning om noe som angår deg." - -msgid "Ask us to add an authority" -msgstr "Be oss legge til en myndighet" - -msgid "Ask us to update FOI email" -msgstr "Be oss om å oppdatere e-postadresse brukt ved innsynshenvendelser" - -msgid "Ask us to update the email address for {{public_body_name}}" -msgstr "Spør oss om å oppdatere e-postadressen til {{public_body_name}}" - -msgid "At the bottom of this page, write a reply to them trying to persuade them to scan it in\\n (<a href=\"{{url}}\">more details</a>)." -msgstr "Skriv et svar til dem nederst på denne siden, og forsøk å overtale dem til å scanne det inn\\n (<a href=\"{{url}}\">flere detaljer</a>)." - -msgid "Attachment (optional):" -msgstr "Vedlegg (valgfritt):" - -msgid "Attachment:" -msgstr "Vedlegg:" - -msgid "Authority email:" -msgstr "Myndighet e-post:" - -msgid "Authority:" -msgstr "Myndighet:" - -msgid "Awaiting classification." -msgstr "Venter på kategorisering." - -msgid "Awaiting internal review." -msgstr "Vemter på behandling av klage." - -msgid "Awaiting response." -msgstr "Venter på svar." - -msgid "Batch created by {{info_request_user}} on {{date}}." -msgstr "Bunt opprettet av {{info_request_user}} den {{date}}." - -msgid "Beginning with" -msgstr "Begynner med" - -msgid "Browse <a href='{{url}}'>other requests</a> for examples of how to word your request." -msgstr "Se på <a href='{{url}}'>andre henvendelser</a> for eksempler på hvordan du bør ordlegge henvendelsen." - -msgid "Browse <a href='{{url}}'>other requests</a> to '{{public_body_name}}' for examples of how to word your request." -msgstr "Se på <a href='{{url}}'>andre henvendelser</a> til '{{public_body_name}}' for eksempler på hvordan du kan ordlegge deg." - -msgid "Browse all authorities..." -msgstr "Vis alle myndighetene..." - -msgid "Browse and search requests" -msgstr "Vis og søk i henvendelser" - -msgid "Browse requests" -msgstr "Vis henvendelser" - -msgid "By law, under all circumstances, {{public_body_link}} should have responded by now" -msgstr "I følge loven så burde {{public_body_link}}, under enhver omstendighet ha svart på dette tidspunkt" - -msgid "By law, {{public_body_link}} should normally have responded <strong>promptly</strong> and" -msgstr "I følge loven, så burde {{public_body_link}} normal ha svart <strong>raskt</strong> og" - -msgid "Calculated home page" -msgstr "Beregnet hjemmeside" - -msgid "Can't find the one you want?" -msgstr "Vil du kontakte en myndighet som ikke er her?" - -msgid "Cancel a {{site_name}} alert" -msgstr "Avbryt et {{site_name}}-varsel" - -msgid "Cancel some {{site_name}} alerts" -msgstr "Avbryt noen {{site_name}}-varsler" - -msgid "Cancel, return to your profile page" -msgstr "Kanselerer, returner til profil-bildet ditt" - -msgid "Censor rule" -msgstr "Sensurregel" - -msgid "CensorRule|Last edit comment" -msgstr "SensurRegel|Siste redigeringskommentar" - -msgid "CensorRule|Last edit editor" -msgstr "SensurRegel|Siste endring av" - -msgid "CensorRule|Regexp" -msgstr "SensurRegel|Regexp" - -msgid "CensorRule|Replacement" -msgstr "SensurRegel|Erstatning" - -msgid "CensorRule|Text" -msgstr "SensurRegel|Tekst" - -msgid "Change email on {{site_name}}" -msgstr "Bytt e-post-adresse på {{site_name}}" - -msgid "Change password on {{site_name}}" -msgstr "Bytt passord på {{site_name}}" - -msgid "Change profile photo" -msgstr "Bytt profil-bildet" - -msgid "Change the text about you on your profile at {{site_name}}" -msgstr "Bytt teksten på din profil hos {{site_name}}" - -msgid "Change your email" -msgstr "Bytt e-postadresse" - -msgid "Change your email address used on {{site_name}}" -msgstr "Endre din e-postadresse brukt på {{site_name}}" - -msgid "Change your password" -msgstr "Bytt passordet ditt" - -msgid "Change your password on {{site_name}}" -msgstr "Bytt passordet ditt på {{site_name}}" - -msgid "Check for mistakes if you typed or copied the address." -msgstr "Sjekk at det ikke er skrivefeil dersom du skrev inn eller kopierte adressen" - -msgid "Check you haven't included any <strong>personal information</strong>." -msgstr "Sjekk at du ikke har inkludert noe <strong>personlig informasjon</strong>." - -msgid "Choose a reason" -msgstr "Velg en grunn" - -msgid "Choose your profile photo" -msgstr "Velg ditt profil-bilde" - -msgid "Clarification" -msgstr "Klargjøring" - -msgid "Clarification sent to {{public_body_name}} by {{info_request_user}} on {{date}}." -msgstr "Klargjøring sendt til {{public_body_name}} av {{info_request_user}} den {{date}}." - -msgid "Clarify your FOI request - " -msgstr "Klargjør din innsynshenvendelse - " - -msgid "Classify an FOI response from " -msgstr "Klassifiser ett innsynsvar fra" - -msgid "Clear photo" -msgstr "Slett bilde" - -msgid "Click on the link below to send a message to {{public_body_name}} telling them to reply to your request. You might like to ask for an internal\\nreview, asking them to find out why response to the request has been so slow." -msgstr "Trykk på linken nedenfor for å sende en melding til {{public_body_name}} for å be om svar på henvendelsen. Du kan vurdere å be dem om en gjennomgang av hvorfor det tar så lang tid å få svar på henvendelsen." - -msgid "Click on the link below to send a message to {{public_body}} reminding them to reply to your request." -msgstr "Klikk på lenken under for å sende en melding til {{public_body}} og minne dem på å besvare henvendelsen din." - -msgid "Close" -msgstr "Lukk" - -msgid "Close the request and respond:" -msgstr "Lukk henvendelsen og svar:" - -msgid "Comment" -msgstr "Kommenter" - -msgid "Comment|Body" -msgstr "Kommentar|Brødtekst" - -msgid "Comment|Comment type" -msgstr "Kommentar|Kommentartype" - -msgid "Comment|Locale" -msgstr "Kommentar|Lokalisering" - -msgid "Comment|Visible" -msgstr "Kommentar|Synlig" - -msgid "Confirm you want to follow all successful FOI requests" -msgstr "Bekreft at du ønsker å følge alle innsynsbegjæringer som lykkes" - -msgid "Confirm you want to follow new requests" -msgstr "Bekreft at du ønsker å følge nye begjæringer" - -msgid "Confirm you want to follow new requests or responses matching your search" -msgstr "Bekreft at du ønsker å følge nye begjæringer eller svar som treffer ditt søk" - -msgid "Confirm you want to follow requests by '{{user_name}}'" -msgstr "Bekreft at du ønsker å følge begjæringer fra '{{user_name}}'" - -msgid "Confirm you want to follow requests to '{{public_body_name}}'" -msgstr "Bekreft at du ønsker å følge begjæringer til '{{public_body_name}}'" - -msgid "Confirm you want to follow the request '{{request_title}}'" -msgstr "Bekreft at du ønsker å følge begjæringen '{{request_title}}'" - -msgid "Confirm your FOI request to {{public_body_name}}" -msgstr "Bekreft din innsynshenvendelse til {{public_body_name}}" - -msgid "Confirm your account on {{site_name}}" -msgstr "Bekreft din konto på {{site_name}}" - -msgid "Confirm your annotation to {{info_request_title}}" -msgstr "Bekreft din merknad til {{info_request_title}}" - -msgid "Confirm your email address" -msgstr "Bekreft din e-postadresse" - -msgid "Confirm your new email address on {{site_name}}" -msgstr "Bekreft din nye e-postadresse på {{site_name}}" - -msgid "Considered by administrators as not an FOI request and hidden from site." -msgstr "Administratorene ser ikke på dette som en innsynsbegjæring, og den vil være skjult." - -msgid "Considered by administrators as vexatious and hidden from site." -msgstr "Ansett av administratorer som sjikanøs og skjult fra nettstedet." - -msgid "Contact {{recipient}}" -msgstr "Kontakt " - -msgid "Contact {{site_name}}" -msgstr "Kontakt " - -msgid "Contains defamatory material" -msgstr "Inneholder ærekrenkende materiale" - -msgid "Contains personal information" -msgstr "Inneholder personlig informasjon" - -msgid "Could not identify the request from the email address" -msgstr "Kunne ikke finne henvendelsen ut fra e-post-adressen" - -msgid "Couldn't understand the image file that you uploaded. PNG, JPEG, GIF and many other common image file formats are supported." -msgstr "Klarer ikke å lese inn bilde-filen du lastet opp. Vi støtter PNG, JPEG, GIF og mange andre vanlige bilde-formater." - -msgid "Created by {{info_request_user}} on {{date}}." -msgstr "Opprettet av {{info_request_user}} den {{date}}." - -msgid "Crop your profile photo" -msgstr "Beskjær ditt profilbilde" - -msgid "Cultural sites and built structures (as they may be affected by the\\n environmental factors listed above)" -msgstr "Vern av kulturminner og rett til miljøinformasjon " - -msgid "Currently <strong>waiting for a response</strong> from {{public_body_link}}, they must respond promptly and" -msgstr "<strong>Venter på svar</strong> fra {{public_body_link}}, de må svare uten ugrunnet opphold og" - -msgid "Date:" -msgstr "Dato:" - -msgid "Dear [Authority name]," -msgstr "Kjære [Authority name]," - -msgid "Dear {{name}}," -msgstr "Kjære {{name}}," - -msgid "Dear {{public_body_name}}," -msgstr "Kjære {{public_body_name}}," - -msgid "Dear {{user_name}}," -msgstr "Kjære {{user_name}}," - -msgid "Default locale" -msgstr "Forvalgt locale" - -msgid "Defunct." -msgstr "Nedlagt." - -msgid "Delayed response to your FOI request - " -msgstr "Forsinket svar på din innsynshenvendelse - " - -msgid "Delayed." -msgstr "Forsinket." - -msgid "Delivery error" -msgstr "Leveringsfeil" - -msgid "Destroy {{name}}" -msgstr "Fjern {{name}}" - -msgid "Details of request '" -msgstr "Detaljer for henvendelse '" - -msgid "Did you mean: {{correction}}" -msgstr "Mente du: " - -msgid "Disclaimer: This message and any reply that you make will be published on the internet. Our privacy and copyright policies:" -msgstr "Til orientering: Denne meldingen og alle dine svar vil offentliggjort på Internett. Våre regler for personvern og åndsverk:" - -msgid "Disclosure log" -msgstr "Utleveringslogg" - -msgid "Disclosure log URL" -msgstr "" - -msgid "Do not fill in this field" -msgstr "Ikke fyll inn dette feltet" - -msgid "Don't have a superuser account yet?" -msgstr "Ingen superuser-konto ennå?" - -msgid "Don't want to address your message to {{person_or_body}}? You can also write to:" -msgstr "Om du vil sette mottaker til en annen person enn {{person_or_body}}, kan du også skrive til:" - -msgid "Done" -msgstr "Ferdig" - -msgid "Done >>" -msgstr "Ferdig " - -msgid "Download a zip file of all correspondence" -msgstr "Last ned en zip-fil med all korrespondanse" - -msgid "Download original attachment" -msgstr "Last ned orginalt vedlegg" - -msgid "EIR" -msgstr "miljøinformasjonslov" - -msgid "Edit" -msgstr "Rediger" - -msgid "Edit and add <strong>more details</strong> to the message above,\\n explaining why you are dissatisfied with their response." -msgstr "Rediger og legg til <strong>flere detaljer</strong> i meldingen over,\\n som forklarer hvorfor du klager." - -msgid "Edit text about you" -msgstr "Rediget teksten om deg" - -msgid "Edit this request" -msgstr "Rediger denne henvendelsen" - -msgid "Either the email or password was not recognised, please try again." -msgstr "Enten så var e-postadresse eller passord feil, forsøk igjen." - -msgid "Either the email or password was not recognised, please try again. Or create a new account using the form on the right." -msgstr "Enten så var e-postadresse eller passord feil, forsøk igjen. Eller lag deg en ny konto ved hjelp av skjemaet til høyre." - -msgid "Email doesn't look like a valid address" -msgstr "E-postadressen ser ikke gyldig ut" - -msgid "Email me future updates to this request" -msgstr "Send meg e-post om fremtidige oppdateringer på denne henvendelsen" - -msgid "Email:" -msgstr "E-post:" - -msgid "Enter words that you want to find separated by spaces, e.g. <strong>climbing lane</strong>" -msgstr "Skriv inn ord som du leter etter separert med mellomrom, f.eks. <strong>klatre linje</strong>" - -msgid "Enter your response below. You may attach one file (use email, or\\n <a href=\"{{url}}\">contact us</a> if you need more)." -msgstr "Skriv svaret ditt nedenfor. Du kan legge med et vedlegg (bruk e-post, eller\\n<a href=\"{{url}}\">kontakt oss</a> om du trengere å legge med flere)." - -msgid "Environmental Information Regulations" -msgstr "Miljøinformasjonslov" - -msgid "Environmental Information Regulations requests made" -msgstr "Miljøinformasjonslovhenvendelser gjort" - -msgid "Environmental Information Regulations requests made using this site" -msgstr "Miljøinformasjonslovhenvendelser gjort ved hjelp av dette nettstedet" - -msgid "Event history" -msgstr "Hendelseshistorikk" - -msgid "Event history details" -msgstr "Logg over hendelser" - -msgid "Event {{id}}" -msgstr "Hendelse {{id}}" - -msgid "Everything that you enter on this page, including <strong>your name</strong>,\\n will be <strong>displayed publicly</strong> on\\n this website forever (<a href=\"{{url}}\">why?</a>)." -msgstr "Alt som du skriver inn på denne tjenesten, inkludert <strong>navnet ditt</strong>,\\n vil bli <strong>vist offentlig</strong> på\\ndenne tjenesten for alltid (<a href=\"{{url}}\">hvorfor?</a>)." - -msgid "Everything that you enter on this page\\n will be <strong>displayed publicly</strong> on\\n this website forever (<a href=\"{{url}}\">why?</a>)." -msgstr "Alt du skriver inn på denne sida\\n vil bli <strong>vist offentlig</strong> på\\n denne tjenesten for all framtid (<a href=\"{{url}}\">hvorfor?</a>)." - -msgid "FOI" -msgstr "innsyn etter Offentlighetsloven" - -msgid "FOI email address for {{public_body}}" -msgstr "postmottaket hos {{public_body}}" - -msgid "FOI request – {{title}}" -msgstr "Innsynshenvendelse – {{title}}" - -msgid "FOI requests" -msgstr "Innsynshenvendelse" - -msgid "FOI requests by '{{user_name}}'" -msgstr "Innsynshenvendelse fra '{{user_name}}'" - -msgid "FOI requests {{start_count}} to {{end_count}} of {{total_count}}" -msgstr "Innsynshenvendelser {{start_count}} til {{end_count}} av {{total_count}}" - -msgid "FOI response requires admin ({{reason}}) - {{title}}" -msgstr "Innsynssvar krever administrator ({{reason}}) - {{title}}" - -msgid "Failed" -msgstr "Feilet" - -msgid "Failed to convert image to a PNG" -msgstr "Klarte ikke å konvertere bilde til PNG" - -msgid "Failed to convert image to the correct size: at {{cols}}x{{rows}}, need {{width}}x{{height}}" -msgstr "Klarte ikke konvertere bildet til korrekt størrelse: er {{cols}}x{{rows}}, trenger {{width}}x{{height}}" - -msgid "Filter" -msgstr "Filter" - -msgid "Filter by Request Status (optional)" -msgstr "Filtrer etter henvendelsestatus (valgfri)" - -msgid "First, did your other requests succeed?" -msgstr "For det første, lyktes dine andre henvendelser?" - -msgid "First, type in the <strong>name of the UK public authority</strong> you'd\\n like information from. <strong>By law, they have to respond</strong>\\n (<a href=\"{{url}}\">why?</a>)." -msgstr "Først, skriv inn <strong>navnet på en norsk offentlig myndighet</strong> som du\\n vil ha informasjon fra. <strong>Loven sier at de må svare deg</strong>\\n (<a href=\"{{url}}\">hvorfor?</a>)." - -msgid "Foi attachment" -msgstr "Innsynsbegjæring vedlegg" - -msgid "FoiAttachment|Charset" -msgstr "FoiAttachment|Charset" - -msgid "FoiAttachment|Content type" -msgstr "FoiAttachment|Content type" - -msgid "FoiAttachment|Display size" -msgstr "FoiAttachment|Display size" - -msgid "FoiAttachment|Filename" -msgstr "FoiAttachment|Filename" - -msgid "FoiAttachment|Hexdigest" -msgstr "FoiAttachment|Hexdigest" - -msgid "FoiAttachment|Url part number" -msgstr "FoiAttachment|Url part number" - -msgid "FoiAttachment|Within rfc822 subject" -msgstr "FoiAttachment|Within rfc822 subject" - -msgid "Follow" -msgstr "Følg" - -msgid "Follow all new requests" -msgstr "Følg alle nye henvendelser" - -msgid "Follow new successful responses" -msgstr "Følg ny vellykkede henvendelser" - -msgid "Follow requests to {{public_body_name}}" -msgstr "Følg begjæringer til {{public_body_name}}" - -msgid "Follow these requests" -msgstr "Følg denne typen henvendelser" - -msgid "Follow things matching this search" -msgstr "Følg ting som treffes av dette søket" - -msgid "Follow this authority" -msgstr "Følg myndighet" - -msgid "Follow this link to see the request:" -msgstr "Følg denne lenken for å se henvendelsen:" - -msgid "Follow this link to see the requests:" -msgstr "Følg denne lenken for å se henvendelsene:" - -msgid "Follow this person" -msgstr "Følg denne personen" - -msgid "Follow this request" -msgstr "Følg denne henvendelsen" - -#. "Follow up" in this context means a further -#. message sent by the requester to the authority after -#. the initial request -msgid "Follow up" -msgstr "Følg opp" - -#. "Follow up message" in this context means a -#. further message sent by the requester to the authority after -#. the initial request -msgid "Follow up message sent by requester" -msgstr "Oppfølgingsbeskjed fra innsender av henvendelsen" - -msgid "Follow up messages to existing requests are sent to " -msgstr "Oppfølgingsbeskjeder på en eksisterende henvendelse sendes til" - -msgid "Follow up sent to {{public_body_name}} by {{info_request_user}} on {{date}}." -msgstr "Oppfølging sendt til {{public_body_name}} av {{info_request_user}} den {{date}}." - -#. "Follow ups" in this context means further -#. messages sent by the requester to the authority after -#. the initial request -msgid "Follow ups and new responses to this request have been stopped to prevent spam. Please <a href=\"{{url}}\">contact us</a> if you are {{user_link}} and need to send a follow up." -msgstr "Oppfølgingsbeskjeder og nye svar på denne henvendelsen er stanset for å hindre spam. Venligst <a href=\"{{url}}\">kontakt oss</a> dersom du er {{user_link}} og trenger å sende en oppfølgingsbeskjed." - -msgid "Follow us on twitter" -msgstr "Følg oss på twitter" - -msgid "Followups cannot be sent for this request, as it was made externally, and published here by {{public_body_name}} on the requester's behalf." -msgstr "Oppfølginger kan ikke sendes for denne henvendelsen, da den ble gjort eksternt, og publisert her av {{public_body_name}} på innsenders vegne." - -msgid "For an unknown reason, it is not possible to make a request to this authority." -msgstr "Uvisst av hvilken grunn er det ikke mulig å sende en henvendelse til denne myndigheten." - -msgid "Forgotten your password?" -msgstr "Glemt passordet?" - -msgid "Found {{count}} public authority {{description}}" -msgid_plural "Found {{count}} public authorities {{description}}" -msgstr[0] "Fant {{count}} offentlig myndighet {{description}}" -msgstr[1] "Fant {{count}} offentlige myndigheter {{description}}" - -msgid "Freedom of Information" -msgstr "innsyn etter Offentlighetsloven" - -msgid "Freedom of Information Act" -msgstr "Offentlighetsloven" - -msgid "Freedom of Information law does not apply to this authority, so you cannot make\\n a request to it." -msgstr "Offentlighetsloven gjelder ikke for denne etaten, så du kan ikke sende dem en\\n innsynshenvendelse." - -msgid "Freedom of Information law no longer applies to" -msgstr "Offentlighetsloven gjelder ikke lenger for" - -msgid "Freedom of Information law no longer applies to this authority.Follow up messages to existing requests are sent to " -msgstr "Offentlighetsloven gjelder ikke lenger for denne myndigheten. Oppfølgingsbeskjeder til nåværende henvendelser blir sendt til" - -msgid "Freedom of Information requests made" -msgstr "Innsynshenvendelser utført" - -msgid "Freedom of Information requests made by this person" -msgstr "Innsynshenvendelser utført av denne personen" - -msgid "Freedom of Information requests made by you" -msgstr "Innsynshenvendelser utført av deg" - -msgid "Freedom of Information requests made using this site" -msgstr "Innsynshenvendelser utført med denne tjenesten" - -msgid "Freedom of information requests to" -msgstr "Innsynshenvendelser til" - -msgid "From" -msgstr "Fra" - -msgid "From the request page, try replying to a particular message, rather than sending\\n a general followup. If you need to make a general followup, and know\\n an email which will go to the right place, please <a href=\"{{url}}\">send it to us</a>." -msgstr "" - -msgid "From:" -msgstr "Fra:" - -msgid "GIVE DETAILS ABOUT YOUR COMPLAINT HERE" -msgstr "SKRIV GRUNNENE FOR HVORFOR DU KLAGER HER" - -msgid "Handled by post." -msgstr "Håndtert av post." - -msgid "Has tag string/has tag string tag" -msgstr "Har tag-string/har tag-string-tag" - -msgid "HasTagString::HasTagStringTag|Model" -msgstr "HasTagString::HasTagStringTag|Model" - -msgid "HasTagString::HasTagStringTag|Name" -msgstr "HasTagString::HasTagStringTag|Name" - -msgid "HasTagString::HasTagStringTag|Value" -msgstr "HasTagString::HasTagStringTag|Value" - -msgid "Hello! We have an <a href=\"{{url}}\">important message</a> for visitors outside {{country_name}}" -msgstr "Hei! Vi har en <a href=\"{{url}}\">viktig beskjed</a> til besøkende som ikke fra {{country_name}}" - -msgid "Hello! We have an <a href=\"{{url}}\">important message</a> for visitors in other countries" -msgstr "Hei! Vi har en <a href=\"{{url}}\">viktig melding</a> til besøkende i andre land" - -msgid "Hello! You can make Freedom of Information requests within {{country_name}} at {{link_to_website}}" -msgstr "Hei! Du kan lage en innsynshenvendelse for {{country_name}} på {{link_to_website}}" - -msgid "Hello, {{username}}!" -msgstr "Hei, {{username}}!" - -msgid "Help" -msgstr "Hjelp" - -msgid "Here <strong>described</strong> means when a user selected a status for the request, and\\nthe most recent event had its status updated to that value. <strong>calculated</strong> is then inferred by\\n{{site_name}} for intermediate events, which weren't given an explicit\\ndescription by a user. See the <a href=\"{{search_path}}\">search tips</a> for description of the states." -msgstr "Her betyr <strong>beskrevet</strong> når en bruker klargjør hvor i prosessen saken er kommet, og \\n hva som senest førte frem til det. <strong>Beregnet</strong> viser til forhold utledet av {{site_name}}, som ikke kom fra \\n brukerens beskrivelse. Se <a href=\"{{search_path}}\">søketips</a> for beskrivelse av dette." - -msgid "Here is the message you wrote, in case you would like to copy the text and save it for later." -msgstr "Her er beskjeden som du skrev, i tilfelle du ønsker å kopiere og ta vare på teksten." - -msgid "Hi! We need your help. The person who made the following request\\n hasn't told us whether or not it was successful. Would you mind taking\\n a moment to read it and help us keep the place tidy for everyone?\\n Thanks." -msgstr "Hei! Vi trenger din hjelp. Personen som sendte inn følgende\\n henvendelse har ikke fortalt oss hvorvidt den var vellykket eller ikke. Kunne du tenke deg å bruke et øyeblikk på å lese den og hjelpe oss å holde stedet ryddig for alle?\\n Tusen takk." - -msgid "Hide request" -msgstr "Skjul henvendelse" - -msgid "Holiday" -msgstr "Ferie" - -msgid "Holiday|Day" -msgstr "Ferie|Dag" - -msgid "Holiday|Description" -msgstr "Ferie|Beskrivelse" - -msgid "Home" -msgstr "Hjem" - -msgid "Home page" -msgstr "Hjemmeside" - -msgid "Home page of authority" -msgstr "Hjemmesida til myndigheten" - -msgid "However, you have the right to request environmental\\n information under a different law" -msgstr "Dog har du rett til å spørre om miljøinformasjon i følge en annen lov" - -msgid "Human health and safety" -msgstr "Menneskers helse og sikkerhet" - -msgid "I am asking for <strong>new information</strong>" -msgstr "Jeg spør om <strong>ny informasjon</strong>" - -msgid "I am requesting an <strong>internal review</strong>" -msgstr "Jeg ber om en <strong>intern vurdering</strong>" - -msgid "I am writing to request an internal review of {{public_body_name}}'s handling of my FOI request '{{info_request_title}}'." -msgstr "" - -msgid "I don't like these ones — give me some more!" -msgstr "Jeg liker ikke disse — gi meg flere!" - -msgid "I don't want to do any more tidying now!" -msgstr "Jeg vil ikke rydde mer nå!" - -msgid "I like this request" -msgstr "Jeg liker denne begjæringen" - -msgid "I would like to <strong>withdraw this request</strong>" -msgstr "Jeg ønsker å <strong>trekke denne henvendelsen</strong>" - -msgid "I'm still <strong>waiting</strong> for my information\\n <small>(maybe you got an acknowledgement)</small>" -msgstr "Jeg <strong>venter</strong> fortsatt på dokumentene/informasjonen min\\n <small>(du mottok kanskje bare en bekreftelse)</small>" - -msgid "I'm still <strong>waiting</strong> for the internal review" -msgstr "Jeg <strong>venter</strong> fortsatt på at klagen behandles" - -msgid "I'm waiting for an <strong>internal review</strong> response" -msgstr "Jeg venter på at <strong>klagen</strong> blir behandlet" - -msgid "I've been asked to <strong>clarify</strong> my request" -msgstr "Jeg har blitt spurt om å <strong>klargjøre</strong> henvendelsen min" - -msgid "I've received <strong>all the information" -msgstr "Jeg har fått <strong>alt av informasjonen" - -msgid "I've received <strong>some of the information</strong>" -msgstr "Jeg har mottatt <strong>en del av informasjonen</strong>" - -msgid "I've received an <strong>error message</strong>" -msgstr "Jeg har fått en <strong>feilmelding</strong>" - -msgid "I've received an error message" -msgstr "Jeg har fått en feilmelding" - -msgid "Id" -msgstr "Id" - -msgid "If the address is wrong, or you know a better address, please <a href=\"{{url}}\">contact us</a>." -msgstr "Hvis adressen er feil, eller du vet om en bedre adresse, vær så snill å <a href=\"{{url}}\">ta kontakt</a>." - -msgid "If the error was a delivery failure, and you can find an up to date FOI email address for the authority, please tell us using the form below." -msgstr "Hvis feilen var et problem med leveringen, og du kan finne en oppdatert e-postadresse som kan brukes til innsynshenvendelser for denne myndigheten, så vær så snill å fortell oss dette i skjemaet under." - -msgid "If this is incorrect, or you would like to send a late response to the request\\nor an email on another subject to {{user}}, then please\\nemail {{contact_email}} for help." -msgstr "Hvis dette ikke er korrekt, eller man ønsker å ettersende en oppfølging av henvendelsen \\n eller en e-post om et annet tema til {{user}}, send gjerne e-post til \\n {{contact_email}} for å få hjelp." - -msgid "If you are dissatisfied by the response you got from\\n the public authority, you have the right to\\n complain (<a href=\"{{url}}\">details</a>)." -msgstr "Du har rett til å klage, om du ikke er fornøyd med svaret du fikk fra\\n den offentlige myndigheten (<a href=\"{{url}}\">detaljer</a>)." - -msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." -msgstr "Hvis du fortsatt har problemer, vær så snill å <a href=\"{{url}}\">ta kontakt</a>." - -msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." -msgstr "Hvis du er innsenderen, så kan du <a href=\"{{url}}\">logge inn</a> for å se på meldingen." - -msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." -msgstr "Hvis du er innsenderen, så kan det hende du må <a href=\"{{url}}\">logge inn</a> for å se på henvendelsen." - -msgid "If you are thinking of using a pseudonym,\\n please <a href=\"{{url}}\">read this first</a>." -msgstr "" -"Hvis du vurderer å bruke et pseudonym,\\n er det fint om du\n" -"<a href=\"{{url}}\">leser dette først</a>." - -msgid "If you are {{user_link}}, please" -msgstr "Hvis du er {{user_link}}, vennligst" - -msgid "If you believe this request is not suitable, you can report it for attention by the site administrators" -msgstr "Hvis du syntes denne henvendelsen er upassende, kan du rapportere den slik at en admininstrator vil sjekke" - -msgid "If you can't click on it in the email, you'll have to <strong>select and copy\\nit</strong> from the email. Then <strong>paste it into your browser</strong>, into the place\\nyou would type the address of any other webpage." -msgstr "Hvis du ikke kan klikke på den i e-posten, så vil du måtte <strong>markere og kopiere\\nden</strong> fra e-posten. Deretter <storng>limer du den inn i din nettleser</strong>, i feltet der du ville skrevet adressen til enhver annen nettside." - -msgid "If you can, scan in or photograph the response, and <strong>send us\\n a copy to upload</strong>." -msgstr "Hvis du kan, skann eller fotografer responsen og <strong>send oss\\n en kopi for opplasting</strong>." - -msgid "If you find this service useful as an FOI officer, please ask your web manager to link to us from your organisation's FOI page." -msgstr "Hvis du som offentlig saksbehandler finner denne tjenesten nyttig, er det fint om du spør kommunikasjonsavdelingen din om de kan lenke til oss fra din organisasjons innsyns-side." - -msgid "If you got the email <strong>more than six months ago</strong>, then this login link won't work any\\nmore. Please try doing what you were doing from the beginning." -msgstr "Hvis du fikk e-posten <strong>mer enn seks måneder siden</strong>, så vil ikke denne innloggings-lenken virke lenger.\\n Forsøk igjen det du holdt på med fra starten." - -msgid "If you have not done so already, please write a message below telling the authority that you have withdrawn your request. Otherwise they will not know it has been withdrawn." -msgstr "Hvis du ikke allerede har gjort det, vær så snill å skriv en melding under som forteller myndigheten at du har trukket tilbake din henvendelse. Ellers vil de ikke vite at den er trukket tilbake." - -msgid "If you reply to this message it will go directly to {{user_name}}, who will\\nlearn your email address. Only reply if that is okay." -msgstr "Hvis du svarer på denn emeldingen, så vil svaret gå direkte til {{user_name}}, som vil få vite din e-postadresse. Svar kun hvis det er i orden." - -msgid "If you use web-based email or have \"junk mail\" filters, also check your\\nbulk/spam mail folders. Sometimes, our messages are marked that way." -msgstr "Om du bruker web-basert e-post eller har «søppel-e-post»-filtere, sjekk også din\\nsøppel/spam-e-postfolder. Det hender at meldingene våre blir behandlet som spam." - -msgid "If you would like us to lift this ban, then you may politely\\n<a href=\"/help/contact\">contact us</a> giving reasons.\\n" -msgstr "Dersom du vil ha utestegningen opphevet kan du, på høflig vis,\\n<a href=\"/help/contact\">kontakte oss</a>.\\n" - -msgid "If you're new to {{site_name}}" -msgstr "Hvis du er ny på " - -msgid "If you've used {{site_name}} before" -msgstr "Hvis du har brukt {{site_name}} tidligere" - -msgid "If your browser is set to accept cookies and you are seeing this message,\\nthen there is probably a fault with our server." -msgstr "Dersom nettleseren er satt opp til å akseptere informasjonskapsler og du ser denne meldingen,\\nså er det mest sannsynlig noe feil med vår server." - -msgid "Incoming email address" -msgstr "Inngående e-postadresse" - -msgid "Incoming message" -msgstr "Innkommende beskjed" - -msgid "IncomingMessage|Cached attachment text clipped" -msgstr "IncomingMessage|Cached attachment text clipped" - -msgid "IncomingMessage|Cached main body text folded" -msgstr "IncomingMessage|Cached main body text folded" - -msgid "IncomingMessage|Cached main body text unfolded" -msgstr "IncomingMessage|Cached main body text unfolded" - -msgid "IncomingMessage|Last parsed" -msgstr "IncomingMessage|Last parsed" - -msgid "IncomingMessage|Mail from" -msgstr "IncomingMessage|Mail from" - -msgid "IncomingMessage|Mail from domain" -msgstr "IncomingMessage|Mail from domain" - -msgid "IncomingMessage|Prominence" -msgstr "IncomingMessage|Prominence" - -msgid "IncomingMessage|Prominence reason" -msgstr "IncomingMessage|Prominence reason" - -msgid "IncomingMessage|Sent at" -msgstr "IncomingMessage|Sent at" - -msgid "IncomingMessage|Subject" -msgstr "IncomingMessage|Subject" - -msgid "IncomingMessage|Valid to reply to" -msgstr "IncomingMessage|Valid to reply to" - -msgid "Individual requests" -msgstr "Enkelte begjæringer" - -msgid "Info request" -msgstr "Informasjonshenvendelse" - -msgid "Info request batch" -msgstr "Buntinformasjonshenvendelse" - -msgid "Info request event" -msgstr "" - -msgid "InfoRequestBatch|Body" -msgstr "InfoRequestBatch|Body" - -msgid "InfoRequestBatch|Sent at" -msgstr "InfoRequestBatch|Sent at" - -msgid "InfoRequestBatch|Title" -msgstr "InfoRequestBatch|Title" - -msgid "InfoRequestEvent|Calculated state" -msgstr "InfoRequestEvent|Calculated state" - -msgid "InfoRequestEvent|Described state" -msgstr "InfoRequestEvent|Described state" - -msgid "InfoRequestEvent|Event type" -msgstr "InfoRequestEvent|Event type" - -msgid "InfoRequestEvent|Last described at" -msgstr "InfoRequestEvent|Last described at" - -msgid "InfoRequestEvent|Params yaml" -msgstr "InfoRequestEvent|Params yaml" - -msgid "InfoRequest|Allow new responses from" -msgstr "InfoRequest|Tillat nye svar fra" - -msgid "InfoRequest|Attention requested" -msgstr "InfoRequest|Attention requested" - -msgid "InfoRequest|Awaiting description" -msgstr "InfoRequest|Awaiting description" - -msgid "InfoRequest|Comments allowed" -msgstr "InfoRequest|Comments allowed" - -msgid "InfoRequest|Described state" -msgstr "InfoRequest|Described state" - -msgid "InfoRequest|External url" -msgstr "InfoRequest|External url" - -msgid "InfoRequest|External user name" -msgstr "InfoRequest|External user name" - -msgid "InfoRequest|Handle rejected responses" -msgstr "InfoRequest|Håndter avviste svar" - -msgid "InfoRequest|Idhash" -msgstr "InfoRequest|Idhash" - -msgid "InfoRequest|Law used" -msgstr "InfoRequest|Law used" - -msgid "InfoRequest|Prominence" -msgstr "InfoRequest|Prominence" - -msgid "InfoRequest|Title" -msgstr "InfoRequest|Title" - -msgid "InfoRequest|Url title" -msgstr "InfoRequest|Url title" - -msgid "Information not held." -msgstr "Har ikke informasjonen." - -msgid "Information on emissions and discharges (e.g. noise, energy,\\n radiation, waste materials)" -msgstr "Informasjon om utslipp (for eksempel støy, energi,\\n stråling, avfall)" - -msgid "Internal review request" -msgstr "Klage" - -msgid "Internal review request sent to {{public_body_name}} by {{info_request_user}} on {{date}}." -msgstr "Klage sendt til {{public_body_name}} av {{info_request_user}} den {{date}}." - -msgid "Is {{email_address}} the wrong address for {{type_of_request}} requests to {{public_body_name}}? If so, please contact us using this form:" -msgstr "Er {{email_address}} feil adresse for henvendelser om {{type_of_request}} til {{public_body_name}}? I så fall, vær så snill å ta kontakt med oss ved å bruke dette skjemaet:" - -msgid "It may be that your browser is not set to accept a thing called \"cookies\",\\nor cannot do so. If you can, please enable cookies, or try using a different\\nbrowser. Then press refresh to have another go." -msgstr "Det kan hende at din nettleser ikke er satt opp til å akseptere informasjonskapsler,\\neller ikke er i stand til det. Om du har anledning, vennligst aktiver støtte for informasjonskapsler, eller prøv en annen\\nnettleser. Deretter trykk oppdater for å forsøke på nytt." - -msgid "Items matching the following conditions are currently displayed on your wall." -msgstr "Ting som oppfyller disse kriteriene vises nå på veggen din." - -msgid "Items sent in last month" -msgstr "Oppføringer sendt siste måned" - -msgid "Joined in" -msgstr "Ble med i" - -msgid "Joined {{site_name}} in" -msgstr "Ble med {{site_name}} i" - -msgid "Just one more thing" -msgstr "Bare en ting til" - -msgid "Keep it <strong>focused</strong>, you'll be more likely to get what you want (<a href=\"{{url}}\">why?</a>)." -msgstr "Hold det <strong>fokusert</strong>, du har større sjanser for å få det du vil ha (<a href=\"{{url}}\">hvorfor?</a>)." - -msgid "Keywords" -msgstr "Nøkkelord" - -msgid "Last authority viewed: " -msgstr "Siste myndighet du så på:" - -msgid "Last request viewed: " -msgstr "Siste henvendelse du så på:" - -msgid "Let us know what you were doing when this message\\nappeared and your browser and operating system type and version." -msgstr "Fortell oss hva du gjorde da denne meldingen dukket opp, samt type og versjon for din nettleser og ditt operativsystem." - -msgid "Link to this" -msgstr "Lenke til denne" - -msgid "List of all authorities (CSV)" -msgstr "Liste over alle registrerte myndigheter (CSV)" - -msgid "Listing FOI requests" -msgstr "Lister innsynshenvendelser" - -msgid "Listing public authorities" -msgstr "Lister opp offentlige myndigheter" - -msgid "Listing public authorities matching '{{query}}'" -msgstr "Lister opp offentlige myndigheter som stemmer med '{{query}}'" - -msgid "Listing tracks" -msgstr "Lister opp spor" - -msgid "Listing users" -msgstr "Lister opp brukere" - -msgid "Log in to download a zip file of {{info_request_title}}" -msgstr "Logg inn for å laste ned en zip-fil med {{info_request_title}}" - -msgid "Log into the admin interface" -msgstr "Logg inn i administratorgrensesnittet" - -msgid "Long overdue." -msgstr "Svært forsinket" - -msgid "Made between" -msgstr "Opprettet mellom" - -msgid "Mail server log" -msgstr "E-posttjenerlogg" - -msgid "Mail server log done" -msgstr "E-posttjenerlogg ferdig" - -msgid "MailServerLogDone|Filename" -msgstr "MailServerLogDone|Filename" - -msgid "MailServerLogDone|Last stat" -msgstr "MailServerLogDone|Last stat" - -msgid "MailServerLog|Line" -msgstr "MailServerLog|Line" - -msgid "MailServerLog|Order" -msgstr "MailServerLog|Order" - -msgid "Make a batch request" -msgstr "Lag en bunthenvendelse" - -msgid "Make a new EIR request" -msgstr "Lan en ny miljøinformasjonslov-henvendelse" - -msgid "Make a new FOI request" -msgstr "Lag en ny innsynshenvendelse" - -msgid "Make a new<br/>\\n <strong>Freedom <span>of</span><br/>\\n Information<br/>\\n request</strong>" -msgstr "Lag en ny<br/>\\n <strong>henvendelse <span>om</span><br/>\\n innsyn</strong>" - -msgid "Make a request" -msgstr "Lag henvendelse" - -msgid "Make a request »" -msgstr "Lag henvendelse »" - -msgid "Make a request to these authorities" -msgstr "Lag en henvendelse til disse myndighetene" - -msgid "Make a request to this authority" -msgstr "Lag en henvendelse til denne myndigheten" - -msgid "Make an {{law_used_short}} request" -msgstr "Lag en {{law_used_short}}-henvendelse" - -msgid "Make an {{law_used_short}} request to '{{public_body_name}}'" -msgstr "Lag en {{law_used_short}} henvendelse til '{{public_body_name}}'" - -msgid "Make and browse Freedom of Information (FOI) requests" -msgstr "Lag og bla igjennom innsynsbegjæringer." - -msgid "Make your own request" -msgstr "Lag din egen henvendelse" - -msgid "Many requests" -msgstr "Mange henvendelser" - -msgid "Message" -msgstr "Melding" - -msgid "Message has been removed" -msgstr "Melding har blitt fjernet" - -msgid "Message sent using {{site_name}} contact form, " -msgstr "Melding sendt ved hjelp av kontaktskjema for {{site_name}}," - -msgid "Missing contact details for '" -msgstr "Mangler kontaktdetaljer for '" - -msgid "More about this authority" -msgstr "Mer om denne myndigheten" - -msgid "More requests..." -msgstr "Flere henvendelser..." - -msgid "More similar requests" -msgstr "Flere lignende henvendelser" - -msgid "More successful requests..." -msgstr "Flere vellykkede henvendelser..." - -msgid "My profile" -msgstr "Min profil" - -msgid "My request has been <strong>refused</strong>" -msgstr "Henvendelsen min er <strong>avslått</strong>" - -msgid "My requests" -msgstr "Mine henvendelser" - -msgid "My wall" -msgstr "Min vegg" - -msgid "Name can't be blank" -msgstr "Navn kan ikke være tomt" - -msgid "Name is already taken" -msgstr "Navn er allerede tatt" - -msgid "New Freedom of Information requests" -msgstr "Ny innsynsbegjæring" - -msgid "New censor rule" -msgstr "Ny sensurregel" - -msgid "New e-mail:" -msgstr "Ny e-post-adresse:" - -msgid "New email doesn't look like a valid address" -msgstr "Ny e-postadresse ser ikke ut til å være en gyldig adresse." - -msgid "New password:" -msgstr "Nytt passord:" - -msgid "New password: (again)" -msgstr "Nytt passord: (igjen)" - -msgid "New response to '{{title}}'" -msgstr "Nytt svar til '{{title}}'" - -msgid "New response to your FOI request - " -msgstr "Nytt svar på din innsynshenvendelse - " - -msgid "New response to your request" -msgstr "Nytt svar på henvenndelsen din" - -msgid "New response to {{law_used_short}} request" -msgstr "Nytt svar på {{law_used_short}}-henvendelse" - -msgid "New updates for the request '{{request_title}}'" -msgstr "Nye oppdateringer for henvendelsen '{{request_title}}'" - -msgid "Newest results first" -msgstr "Nyeste resultater først" - -msgid "Next" -msgstr "Neste" - -msgid "Next, crop your photo >>" -msgstr "Neste, beskjær bildet ditt >>" - -msgid "No requests of this sort yet." -msgstr "Det er ingen henvendelser av denne typen enda." - -msgid "No results found." -msgstr "Ingen resultater." - -msgid "No similar requests found." -msgstr "Ingen lignende henvendelser funnet." - -msgid "No tracked things found." -msgstr "Ingen sporede ting ble funnet." - -msgid "Nobody has made any Freedom of Information requests to {{public_body_name}} using this site yet." -msgstr "Ingen har så langt bedt om innsyn hos {{public_body_name}} ved hjelp av dette nettstedet." - -msgid "None found." -msgstr "Ingen funnet." - -msgid "None made." -msgstr "Ingen laget." - -msgid "Not a valid FOI request" -msgstr "Ikke en gyldig innsynsbegjæring" - -msgid "Not a valid request" -msgstr "Ikke en gyldig henvendelse" - -msgid "Note that the requester will not be notified about your annotation, because the request was published by {{public_body_name}} on their behalf." -msgstr "Merk at personen som står bak begjæringen ikke vil få beskjed om din annotering, fordi begjæringen var publisert av {{public_body_name}} på deres vegne." - -msgid "Notes:" -msgstr "Merknader:" - -msgid "Now check your email!" -msgstr "Sjekk e-posten din nå!" - -msgid "Now preview your annotation" -msgstr "Se nå igjennom din merknad" - -msgid "Now preview your follow up" -msgstr "Se nå igjennom din oppfølging" - -msgid "Now preview your message asking for an internal review" -msgstr "Forhåndsvis din beskjed og be om en intern gjennomgang" - -msgid "Number of requests" -msgstr "Antall henvendelser" - -msgid "OR remove the existing photo" -msgstr "ELLER fjern nåværende bilde" - -msgid "Offensive? Unsuitable?" -msgstr "Støtende? Upassende?" - -msgid "Oh no! Sorry to hear that your request was refused. Here is what to do now." -msgstr "Huff! Kjedelig å høre at innsynsbegjæringen din ble avslått. Her er det du nå kan gjøre." - -msgid "Old e-mail:" -msgstr "Gammel e-post-adresse:" - -msgid "Old email address isn't the same as the address of the account you are logged in with" -msgstr "Gammel e-postadresse er ikke samme som adressen som kontoen du er innlogget med" - -msgid "Old email doesn't look like a valid address" -msgstr "Gammel e-post ser ikke ut til å være en gyldig adresse" - -msgid "On this page" -msgstr "På denne siden" - -msgid "One FOI request found" -msgstr "En innsynsbegjæring funnet" - -msgid "One person found" -msgstr "En person funnet" - -msgid "One public authority found" -msgstr "En myndighet funnet" - -msgid "Only put in abbreviations which are really used, otherwise leave blank. Short or long name is used in the URL – don't worry about breaking URLs through renaming, as the history is used to redirect" -msgstr "Skriv kun in forkortelser som faktisk er i bruk, og la det ellers være blank. Kort eller langt navn brukes i URL-en – ikke bekymre deg om å knekke URL-er ved å bytte navn, da historien brukes til omdirigering" - -msgid "Only requests made using {{site_name}} are shown." -msgstr "Bare henvendelser som er gjort med {{site_name}} vises" - -msgid "Only the authority can reply to this request, and I don't recognise the address this reply was sent from" -msgstr "Kun myndigheten kan svare på denne henvendelsen, og jeg kjenner ikke igjen adressen dette svaret ble sendt fra" - -msgid "Only the authority can reply to this request, but there is no \"From\" address to check against" -msgstr "Kun myndigheten kan svare på denne henvendelsen, men det er ikke noen \"From\"-adresse å sjekke mot" - -msgid "Or make a <a href=\"{{url}}\">batch request</a> to <strong>multiple authorities</strong> at once." -msgstr "Eller lag en <a href=\"{{url}}\">bunthenvendelse</a> til <strong>flere myndigheter</strong> på en gang." - -msgid "Or search in their website for this information." -msgstr "Eller søk på nettsiden deres etter denne informasjonen." - -msgid "Original request sent" -msgstr "Opprinnelig henvendelse sendt" - -msgid "Other" -msgstr "Annet" - -msgid "Other:" -msgstr "Annet:" - -msgid "Outgoing message" -msgstr "Utgående melding" - -msgid "OutgoingMessage|Body" -msgstr "OutgoingMessage|Body" - -msgid "OutgoingMessage|Last sent at" -msgstr "OutgoingMessage|Last sent at" - -msgid "OutgoingMessage|Message type" -msgstr "OutgoingMessage|Message type" - -msgid "OutgoingMessage|Prominence" -msgstr "OutgoingMessage|Prominence" - -msgid "OutgoingMessage|Prominence reason" -msgstr "OutgoingMessage|Prominence reason" - -msgid "OutgoingMessage|Status" -msgstr "OutgoingMessage|Status" - -msgid "OutgoingMessage|What doing" -msgstr "OutgoingMessage|What doing" - -msgid "Partially successful." -msgstr "Delevis vellykket" - -msgid "Password is not correct" -msgstr "Passordet er ikke riktig" - -msgid "Password:" -msgstr "Passord:" - -msgid "Password: (again)" -msgstr "Passord: (igjen)" - -msgid "Paste this link into emails, tweets, and anywhere else:" -msgstr "Lim denne lenken inn i e-poster, tvitringer og andre steder:" - -msgid "People" -msgstr "Folk" - -msgid "People {{start_count}} to {{end_count}} of {{total_count}}" -msgstr "Personer {{start_count}} til {{end_count}} av {{total_count}}" - -msgid "Percentage of requests that are overdue" -msgstr "Prosent av henvendelsene som er forsinket" - -msgid "Percentage of total requests" -msgstr "Prosentandel av alle henvendelser" - -msgid "Photo of you:" -msgstr "Foto av deg:" - -msgid "Plans and administrative measures that affect these matters" -msgstr "Planer og administrative gjøremål som berører disse forholdene" - -msgid "Play the request categorisation game" -msgstr "Delta i henvendelskategoriserings-spillet" - -msgid "Play the request categorisation game!" -msgstr "Delta i henvendelseskategoriserings-spillet!" - -msgid "Please" -msgstr "Vennligst" - -msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." -msgstr "Vennligst <a href=\"{{url}}\">kontakt oss</a> dersom du har spørsmål." - -msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." -msgstr "<a href=\"{{url}}\">Ta kontakt</a> med oss slik at vi kan fikse det." - -msgid "Please <strong>answer the question above</strong> so we know whether the " -msgstr "Vennligst <strong>svar på spørsmålet ovenfor</strong> så vi vet om " - -msgid "Please <strong>go to the following requests</strong>, and let us\\n know if there was information in the recent responses to them." -msgstr "Vær så snill å <strong>besøk de følgende henvendelsene</strong>,\\n og la oss vite om det var informasjon i de siste svarene i dem." - -msgid "Please <strong>only</strong> write messages directly relating to your request {{request_link}}. If you would like to ask for information that was not in your original request, then <a href=\"{{new_request_link}}\">file a new request</a>." -msgstr "Vennligst <strong>bare</strong> skriv om ting som direkte relaterer seg til din henvendelse {{request_link}}. Om du vil spørre om informasjon som ikke var i den opprinnelige henvendelsen, <a href=\"{{new_request_link}}\">lag en ny henvendelse</a>." - -msgid "Please ask for environmental information only" -msgstr "Vær så snill å kun spørre om miljøinformasjon" - -msgid "Please check the URL (i.e. the long code of letters and numbers) is copied\\ncorrectly from your email." -msgstr "Vennligst sjekk om nettadressen (dvs. den lange koden av bokstaver og tall) er kopiert\\nriktig fra din e-post." - -msgid "Please choose a file containing your photo." -msgstr "Vennligst velg en fil som inneholder ditt bilde." - -msgid "Please choose a reason" -msgstr "Velg en begrunnelse" - -msgid "Please choose what sort of reply you are making." -msgstr "Vennligst velg hva slags svar du lager." - -msgid "Please choose whether or not you got some of the information that you wanted." -msgstr "Vennligst velg hvorvidt du fikk noe av informasjonen du etterspurte." - -msgid "Please click on the link below to cancel or alter these emails." -msgstr "Vennligst klikk på lenken under for å avbryte eller endre e-postene." - -msgid "Please click on the link below to confirm that you want to \\nchange the email address that you use for {{site_name}}\\nfrom {{old_email}} to {{new_email}}" -msgstr "Vennligst klikk på linken nedenfor for å bekrefte at du ønsker \\nå forandre e-postadressen du bruker for {{site_name}}\\nfrom {{old_email}} to {{new_email}}" - -msgid "Please click on the link below to confirm your email address." -msgstr "Vennligst klikk på lenken under for å bekrefte din e-post-adresse." - -msgid "Please describe more what the request is about in the subject. There is no need to say it is an FOI request, we add that on anyway." -msgstr "Vennligst beskriv hva henvendelsen angår i tittelfeltet. Du trenger ikke skrive at det gjelder en innsynshenvendelse, det legger vi til automatisk." - -msgid "Please don't upload offensive pictures. We will take down images\\n that we consider inappropriate." -msgstr "Vennligst ikke last opp støtende bilder. Vi vil ta ned bilder\\nsom vi finner upassende." - -msgid "Please enable \"cookies\" to carry on" -msgstr "Vennligst tillat \"cookies\" i nettleseren for å komme videre" - -msgid "Please enter a password" -msgstr "Skriv inn et passord" - -msgid "Please enter a subject" -msgstr "Skriv inn en tittel" - -msgid "Please enter a summary of your request" -msgstr "Skriv et sammendrag av henvendelsen" - -msgid "Please enter a valid email address" -msgstr "Skriv inn en gyldig e-post adresse" - -msgid "Please enter the message you want to send" -msgstr "Skriv inn meldingen du ønsker å sende" - -msgid "Please enter the name of the authority" -msgstr "Skriv inn navnet til autoriteten" - -msgid "Please enter the same password twice" -msgstr "Skriv inn det samme passordet to ganger" - -msgid "Please enter your annotation" -msgstr "Skriv inn din merknad" - -msgid "Please enter your email address" -msgstr "Skriv inn e-post adressen din" - -msgid "Please enter your follow up message" -msgstr "Skriv inn oppfølgningsmeldingen din" - -msgid "Please enter your letter requesting information" -msgstr "Vennligst skriv inn ditt brev der du ber om informasjon" - -msgid "Please enter your name" -msgstr "Skriv inn navnet ditt" - -msgid "Please enter your name, not your email address, in the name field." -msgstr "Skriv inn navnet ditt, ikke e-post adressen, i samme felt." - -msgid "Please enter your new email address" -msgstr "Skriv inn den nye e-post adressen din" - -msgid "Please enter your old email address" -msgstr "Skriv inn din gamle e-post adresse" - -msgid "Please enter your password" -msgstr "Skriv inn passordet ditt" - -msgid "Please give details explaining why you want a review" -msgstr "Du må skrive hvorfor du klager" - -msgid "Please keep it shorter than 500 characters" -msgstr "Hold det kortere enn 500 tegn" - -msgid "Please keep the summary short, like in the subject of an email. You can use a phrase, rather than a full sentence." -msgstr "Vennligst hold oppsummeringen kort, som tittelfeltet i en e-post. Du kan bruke en noen få ord i stedet for en hel setning." - -msgid "Please only request information that comes under those categories, <strong>do not waste your\\n time</strong> or the time of the public authority by requesting unrelated information." -msgstr "Vær så snill og kun spør om informasjon som hører under disse kategoriene, <strong>kast ikke\\nbort tiden din</strong> eller tiden til den offentlige myndigheten ved å spørre om urelatert informasjon." - -msgid "Please pass this on to the person who conducts Freedom of Information reviews." -msgstr "Vær så snill å send denne videre til personen som vurderer innsynsklager." - -msgid "Please select each of these requests in turn, and <strong>let everyone know</strong>\\nif they are successful yet or not." -msgstr "Velg hver av disse henvendelsene etter tur, og <strong>la alle få vite</strong>\\nom de nå er vellykket eller ikke." - -msgid "Please sign at the bottom with your name, or alter the \"{{signoff}}\" signature" -msgstr "Vær så snill å signer på slutten med ditt navn, eller endre «{{signoff}}»-signaturen." - -msgid "Please sign in as " -msgstr "Logg deg inn som " - -msgid "Please sign in or make a new account." -msgstr "Logg inn eller lag en ny konto." - -msgid "Please tell us more:" -msgstr "Fortell oss mer:" - -msgid "Please type a message and/or choose a file containing your response." -msgstr "Vennligst skriv inn en beskjed og/eller velg en fil som inneholder ditt svar." - -msgid "Please use this email address for all replies to this request:" -msgstr "Vennligst bruk denne e-post adressen for alle svar:" - -msgid "Please write a summary with some text in it" -msgstr "Vennligst fyll ut en oppsummering" - -msgid "Please write the summary using a mixture of capital and lower case letters. This makes it easier for others to read." -msgstr "Vennligst bruk små/store bokstaver i oppsummeringen. Da blir det enklere for andre å lese." - -msgid "Please write your annotation using a mixture of capital and lower case letters. This makes it easier for others to read." -msgstr "Vær så snill å skrive din merknad ved å bruke en blanding av store og små bokstaver. Dette gjør det enklere for andre å lese den." - -msgid "Please write your follow up message containing the necessary clarifications below." -msgstr "Vennligst skriv en oppfølgingsbeskjed som belyser oppklaringspunktene under" - -msgid "Please write your message using a mixture of capital and lower case letters. This makes it easier for others to read." -msgstr "Vennligst bruk store og små bokstaver i din beskjed. Da blir det enklere for andre å lese." - -msgid "Point to <strong>related information</strong>, campaigns or forums which may be useful." -msgstr "Referer til <strong>relatert informasjon</strong>, kampanjer eller forum som kan være til nytte." - -msgid "Possibly related requests:" -msgstr "Mulig relatert henvendelse:" - -msgid "Post annotation" -msgstr "Send inn merknad" - -msgid "Post redirect" -msgstr "" - -msgid "PostRedirect|Circumstance" -msgstr "PostRedirect|Circumstance" - -msgid "PostRedirect|Email token" -msgstr "PostRedirect|Email token" - -msgid "PostRedirect|Post params yaml" -msgstr "PostRedirect|Post params yaml" - -msgid "PostRedirect|Reason params yaml" -msgstr "PostRedirect|Reason params yaml" - -msgid "PostRedirect|Token" -msgstr "PostRedirect|Token" - -msgid "PostRedirect|Uri" -msgstr "PostRedirect|Uri" - -msgid "Posted on {{date}} by {{author}}" -msgstr "Innsendt {{date}} av {{author}}" - -msgid "Powered by <a href=\"http://www.alaveteli.org/\">Alaveteli</a>" -msgstr "Motoren er <a href=\"http://www.alaveteli.org/\">Alaveteli</a>" - -msgid "Prefer not to receive emails?" -msgstr "Foretrekker å ikke motta e-post?" - -msgid "Prev" -msgstr "Forrige" - -msgid "Preview follow up to '" -msgstr "Forhåndsvis oppfølging til '" - -msgid "Preview new annotation on '{{info_request_title}}'" -msgstr "Forhåndsvis ny merknad om '{{info_request_title}}'" - -msgid "Preview new {{law_used_short}} request" -msgstr "Se over ny {{law_used_short}}-henvendelse" - -msgid "Preview new {{law_used_short}} request to '{{public_body_name}}" -msgstr "Se over ny {{law_used_short}}-henvendelse til '{{public_body_name}}" - -msgid "Preview your annotation" -msgstr "Forhåndsvis din merknad" - -msgid "Preview your message" -msgstr "Forhåndsvis meldingen" - -msgid "Preview your public request" -msgstr "Forhåndsvis henvendelsen din" - -msgid "Profile photo" -msgstr "Profilbilde" - -msgid "ProfilePhoto|Data" -msgstr "ProfilePhoto|Data" - -msgid "ProfilePhoto|Draft" -msgstr "ProfilePhoto|Draft" - -msgid "Public Bodies" -msgstr "" - -msgid "Public Body" -msgstr "Offentlig instans" - -msgid "Public Body Statistics" -msgstr "Offentlig instans-statistikk" - -msgid "Public authorities" -msgstr "Offentlige myndigheter" - -msgid "Public authorities - {{description}}" -msgstr "Offentlige myndigheter - {{description}}" - -msgid "Public authorities {{start_count}} to {{end_count}} of {{total_count}}" -msgstr "Offentlige myndigheter {{start_count}} til {{end_count}} av totalt {{total_count}}" - -msgid "Public authority statistics" -msgstr "Statistikk for offentlig myndighet" - -msgid "Public authority – {{name}}" -msgstr "Offentlig myndighet – {{name}}" - -msgid "Public bodies that most frequently replied with \"Not Held\"" -msgstr "" - -msgid "Public bodies with most overdue requests" -msgstr "Offentlig etat med flest forsinkede henvendelser" - -msgid "Public bodies with the fewest successful requests" -msgstr "" - -msgid "Public bodies with the most requests" -msgstr "" - -msgid "Public bodies with the most successful requests" -msgstr "" - -msgid "Public body" -msgstr "Offentlig kropp" - -msgid "Public body category" -msgstr "Offentlig instans-kategori" - -msgid "Public body category link" -msgstr "Offentlig instans-kategorilenke" - -msgid "Public body change request" -msgstr "Offentlig instans-endringshenvendelse" - -msgid "Public body heading" -msgstr "Offentlig instans-overskrift" - -msgid "Public notes" -msgstr "Offentlige notater" - -msgid "Public page" -msgstr "Offentlig side" - -msgid "Public page not available" -msgstr "Offentlig side er ikke tilgjengelig" - -msgid "PublicBodyCategoryLink|Category display order" -msgstr "PublicBodyCategoryLink|Category display order" - -msgid "PublicBodyCategory|Category tag" -msgstr "PublicBodyCategory|Category tag" - -msgid "PublicBodyCategory|Description" -msgstr "PublicBodyCategory|Description" - -msgid "PublicBodyCategory|Title" -msgstr "PublicBodyCategory|Title" - -msgid "PublicBodyChangeRequest|Is open" -msgstr "PublicBodyChangeRequest|Is open" - -msgid "PublicBodyChangeRequest|Notes" -msgstr "PublicBodyChangeRequest|Notes" - -msgid "PublicBodyChangeRequest|Public body email" -msgstr "PublicBodyChangeRequest|Public body email" - -msgid "PublicBodyChangeRequest|Public body name" -msgstr "PublicBodyChangeRequest|Public body name" - -msgid "PublicBodyChangeRequest|Source url" -msgstr "PublicBodyChangeRequest|Source url" - -msgid "PublicBodyChangeRequest|User email" -msgstr "PublicBodyChangeRequest|User email" - -msgid "PublicBodyChangeRequest|User name" -msgstr "PublicBodyChangeRequest|User name" - -msgid "PublicBodyHeading|Display order" -msgstr "PublicBodyHeading|Display order" - -msgid "PublicBodyHeading|Name" -msgstr "PublicBodyHeading|Name" - -msgid "PublicBody|Api key" -msgstr "PublicBody|Api key" - -msgid "PublicBody|Disclosure log" -msgstr "PublicBody|Disclosure log" - -msgid "PublicBody|First letter" -msgstr "PublicBody|First letter" - -msgid "PublicBody|Home page" -msgstr "PublicBody|Home page" - -msgid "PublicBody|Info requests count" -msgstr "PublicBody|Info requests count" - -msgid "PublicBody|Info requests not held count" -msgstr "PublicBody|Info requests not held count" - -msgid "PublicBody|Info requests overdue count" -msgstr "PublicBody|Info requests overdue count" - -msgid "PublicBody|Info requests successful count" -msgstr "PublicBody|Info requests successful count" - -msgid "PublicBody|Info requests visible classified count" -msgstr "PublicBody|Info requests visible classified count" - -msgid "PublicBody|Last edit comment" -msgstr "PublicBody|Last edit comment" - -msgid "PublicBody|Last edit editor" -msgstr "PublicBody|Last edit editor" - -msgid "PublicBody|Name" -msgstr "PublicBody|Name" - -msgid "PublicBody|Notes" -msgstr "PublicBody|Notes" - -msgid "PublicBody|Publication scheme" -msgstr "PublicBody|Publication scheme" - -msgid "PublicBody|Request email" -msgstr "PublicBody|Request email" - -msgid "PublicBody|Short name" -msgstr "PublicBody|Short name" - -msgid "PublicBody|Url name" -msgstr "PublicBody|Url name" - -msgid "PublicBody|Version" -msgstr "PublicBody|Version" - -msgid "Publication scheme" -msgstr "" - -msgid "Publication scheme URL" -msgstr "" - -msgid "Purge request" -msgstr "Slett henvendelse" - -msgid "PurgeRequest|Model" -msgstr "PurgeRequest|Model" - -msgid "PurgeRequest|Url" -msgstr "PurgeRequest|Url" - -msgid "RSS feed" -msgstr "RSS-strøm" - -msgid "RSS feed of updates" -msgstr "RSS-strøm med oppdateringer" - -msgid "Re-edit this annotation" -msgstr "Skriv om igjen denne merknaden" - -msgid "Re-edit this message" -msgstr "Rediger denne meldingen på nytt" - -msgid "Read about <a href=\"{{advanced_search_url}}\">advanced search operators</a>, such as proximity and wildcards." -msgstr "Les om <a href=\"{{advanced_search_url}}\">avanserte søkefunksjoner</a>, som for eksempel nærhet og jokertegn." - -msgid "Read blog" -msgstr "Les blogg" - -msgid "Received an error message, such as delivery failure." -msgstr "Mottokk en feilmelding, slik som feil ved levering." - -msgid "Recently described results first" -msgstr "Nylige beskrevne resultater først" - -msgid "Refused." -msgstr "Avslått" - -msgid "Remember me</label> (keeps you signed in longer;\\n do not use on a public computer) " -msgstr "Husk meg</label> (holder deg innlogget lenger;\\n må ikke brukes på offentlige datamaskiner) " - -msgid "Report abuse" -msgstr "Meld misbruk" - -msgid "Report an offensive or unsuitable request" -msgstr "Meld en støtende eller upassende henvendelse" - -msgid "Report request" -msgstr "Meld henvendelse" - -msgid "Report this request" -msgstr "Rapporter henvendelsen" - -msgid "Reported for administrator attention." -msgstr "Rapportert til admininstrator" - -msgid "Reporting a request notifies the site administrators. They will respond as soon as possible." -msgstr "Når en henvendelse meldes sendes det beskjed til nettstedet administratorer. De vil svare så raskt som mulig." - -msgid "Request an internal review" -msgstr "Skriv klage" - -msgid "Request an internal review from {{person_or_body}}" -msgstr "Klag på vedtaket fra {{person_or_body}}" - -msgid "Request email" -msgstr "Forespør e-post" - -msgid "Request for personal information" -msgstr "Forespør personlig informasjon" - -msgid "Request has been removed" -msgstr "Henvendelsen er fjernet" - -msgid "Request sent to {{public_body_name}} by {{info_request_user}} on {{date}}." -msgstr "Henvendelse sendt til {{public_body_name}} av {{info_request_user}} den {{date}}." - -msgid "Request to {{public_body_name}} by {{info_request_user}}. Annotated by {{event_comment_user}} on {{date}}." -msgstr "Henvendelse til {{public_body_name}}, gjort av {{info_request_user}}. Annotert av {{event_comment_user}} den {{date}}." - -msgid "Requested from {{public_body_name}} by {{info_request_user}} on {{date}}" -msgstr "Etterspurt fra {{public_body_name}} av {{info_request_user}} den {{date}}" - -msgid "Requested on {{date}}" -msgstr "Etterspurt den {{date}}" - -msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." -msgstr "Henvendelser anses som forsinket hvis de har status 'Forsinket' eller 'Svært forsinket'." - -msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." -msgstr "Henvendelser anses vellykket hvis de er klassifisert enten som «vellykket» eller «delvis vellykket»." - -msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." -msgstr "Henvendelser om personlig informasjon og sjikanøse henvendelser er ikke tillatt (<a href=\"/help/about\">les mer</a>)." - -msgid "Requests or responses matching your saved search" -msgstr "Henvendelser eller svar som treffer ditt lagrede søk" - -msgid "Requests similar to '{{request_title}}'" -msgstr "Henvendelser som ligner '{{request_title}}'" - -msgid "Requests similar to '{{request_title}}' (page {{page}})" -msgstr "Henvendelser som ligner '{{request_title}}' (side {{page}})" - -msgid "Requests will be sent to the following bodies:" -msgstr "" - -msgid "Respond by email" -msgstr "Svar med e-post" - -msgid "Respond to request" -msgstr "Svar på henvendelsen" - -msgid "Respond to the FOI request '{{request}}' made by {{user}}" -msgstr "Svar på innsynshenvendelse '{{request}}' gjort av {{user}}" - -msgid "Respond using the web" -msgstr "Svar på nett" - -msgid "Response" -msgstr "Svar" - -msgid "Response by {{public_body_name}} to {{info_request_user}} on {{date}}." -msgstr "Svar fra {{public_body_name}} til {{info_request_user}} den {{date}}." - -msgid "Response from a public authority" -msgstr "Svar fra en offentlig myndighet" - -msgid "Response to '{{title}}'" -msgstr "Svar på " - -msgid "Response to this request is <strong>delayed</strong>." -msgstr "Svar på denne begjæringen er <strong>forsinket</strong>." - -msgid "Response to this request is <strong>long overdue</strong>." -msgstr "Svaret for denne henvendelsen er <strong>svært forsinket</strong>." - -msgid "Response to your request" -msgstr "Svar på din begjæring" - -msgid "Response:" -msgstr "Svar:" - -msgid "Restrict to" -msgstr "Begrens til" - -msgid "Results page {{page_number}}" -msgstr "Resultatside nummer {{page_number}}" - -msgid "Save" -msgstr "Lagre" - -msgid "Search" -msgstr "Søk" - -msgid "Search Freedom of Information requests, public authorities and users" -msgstr "Søk i innsynsbegjæringer, myndigheter og brukere" - -msgid "Search contributions by this person" -msgstr "Søk bidrag fra denne personen" - -msgid "Search for the authorities you'd like information from:" -msgstr "Søk etter myndighetene du kunne tenke deg informasjon fra:" - -msgid "Search for words in:" -msgstr "Søk for ord i:" - -msgid "Search in" -msgstr "Søk i" - -msgid "Search over<br/>\\n <strong>{{number_of_requests}} requests</strong> <span>and</span><br/>\\n <strong>{{number_of_authorities}} authorities</strong>" -msgstr "Søk blant <br/>\\n <strong>{{number_of_requests}} henvendelser</strong> <span>og</span><br/>\\n <strong>{{number_of_authorities}} myndigheter</strong>" - -msgid "Search queries" -msgstr "Søkespørringer" - -msgid "Search results" -msgstr "Søkeresultater" - -msgid "Search the site to find what you were looking for." -msgstr "Søk siden for å finne det du leter etter." - -msgid "Search within the {{count}} Freedom of Information requests to {{public_body_name}}" -msgid_plural "Search within the {{count}} Freedom of Information requests made to {{public_body_name}}" -msgstr[0] "Søk i {{count}} innsynshenvendelse etter offentlighetsloven sendt til {{public_body_name}}" -msgstr[1] "Søk i {{count}} innsynshenvendelser etter offentlighetsloven sendt til {{public_body_name}}" - -msgid "Search your contributions" -msgstr "Søk i dine bidrag" - -msgid "See bounce message" -msgstr "See sprett (bounce) melding" - -msgid "Select the authorities to write to" -msgstr "Velg myndighetene å skrive til" - -msgid "Select the authority to write to" -msgstr "Velg myndighet å skrive til" - -msgid "Send a followup" -msgstr "Send en oppfølgning" - -msgid "Send a message to " -msgstr "Send en melding til " - -msgid "Send a public follow up message to {{person_or_body}}" -msgstr "Send en offentlig oppfølgningsmelding til {{person_or_body}}" - -msgid "Send a public reply to {{person_or_body}}" -msgstr "Send et offentlig svar til {{person_or_body}}" - -msgid "Send follow up to '{{title}}'" -msgstr "Send oppfølgning til '{{title}}'" - -msgid "Send message" -msgstr "Send melding" - -msgid "Send message to " -msgstr "Send melding til " - -msgid "Send request" -msgstr "Send henvendelse" - -msgid "Sent to one authority by {{info_request_user}} on {{date}}." -msgid_plural "Sent to {{authority_count}} authorities by {{info_request_user}} on {{date}}." -msgstr[0] "Sendt til en myndighet av {{info_request_user}} den {{date}}." -msgstr[1] "Sent til {{authority_count}} myndigheter av {{info_request_user}} den {{date}}." - -msgid "Set your profile photo" -msgstr "Velg ditt profil-bilde" - -msgid "Short name" -msgstr "Kortnavn" - -msgid "Short name is already taken" -msgstr "Kortnavnet er allerede tatt" - -msgid "Show most relevant results first" -msgstr "Vis mest releavante resultater først" - -msgid "Show only..." -msgstr "Vis bare..." - -msgid "Showing" -msgstr "Viser" - -msgid "Sign in" -msgstr "Logg inn" - -msgid "Sign in as the emergency user" -msgstr "Logg på som nødbrukeren" - -msgid "Sign in or make a new account" -msgstr "Logg inn eller lag en ny konto" - -msgid "Sign in or sign up" -msgstr "Logg inn eller lag konto" - -msgid "Sign out" -msgstr "Logg ut" - -msgid "Sign up" -msgstr "Lag konto" - -msgid "Similar requests" -msgstr "Lignende henvendelser" - -msgid "Simple search" -msgstr "Enkelt søk" - -msgid "Some notes have been added to your FOI request - " -msgstr "Nen merknader har blitt lagt til innsynshenvendelsen din - " - -msgid "Some of the information requested has been received" -msgstr "Noe av den forespurte informasjonen er mottatt" - -msgid "Some people who've made requests haven't let us know whether they were\\nsuccessful or not. We need <strong>your</strong> help –\\nchoose one of these requests, read it, and let everyone know whether or not the\\ninformation has been provided. Everyone'll be exceedingly grateful." -msgstr "Noen som har sendt inn henvendelser har ikke fortalt oss om de var\\n vellykket eller ikke. Vi trenger <strong>din</strong>hjelp –\\nVelg en av henvendelsene, les den, og la alle få vite om\\n den forespurte information er gitt. Alle vil være svært takknemlig." - -msgid "Somebody added a note to your FOI request - " -msgstr "Noen har lagt tuil en merknad på innsynsbegjeringen din - " - -msgid "Someone has updated the status of your request" -msgstr "Noen har oppdatert status på henvendelsen din" - -msgid "Someone, perhaps you, just tried to change their email address on\\n{{site_name}} from {{old_email}} to {{new_email}}." -msgstr "Noen, kanskje deg, forsøkte å bytte e-post adressen på\\n{{site_name}} fra {{old_email}} to {{new_email}}." - -msgid "Sorry - you cannot respond to this request via {{site_name}}, because this is a copy of the request originally at {{link_to_original_request}}." -msgstr "Beklager - du kan ikke svare på denne henvendelsen via {{site_name}} fordi dette er en kopi av en begjæring fra {{link_to_original_request}}." - -msgid "Sorry, but only {{user_name}} is allowed to do that." -msgstr "Beklager, men bare {{user_name}} har lov til det." - -msgid "Sorry, there was a problem processing this page" -msgstr "Beklager, det er et problem med å klargjøre denne siden" - -msgid "Sorry, we couldn't find that page" -msgstr "Beklager, vi fant ikke den siden" - -msgid "Source URL:" -msgstr "Kilde-URL:" - -msgid "Source:" -msgstr "Kilde:" - -msgid "Spam address" -msgstr "Spam-adresse" - -msgid "SpamAddress|Email" -msgstr "SpamAddress|Email" - -msgid "Special note for this authority!" -msgstr "Spesiell merknad for denne myndigheten!" - -msgid "Start your own blog" -msgstr "Start din egen blogg" - -msgid "Stay up to date" -msgstr "Hold deg oppdatert" - -msgid "Still awaiting an <strong>internal review</strong>" -msgstr "Venter fortsatt på <strong>behandling av klage</strong>" - -msgid "Subject" -msgstr "Tittel" - -msgid "Subject:" -msgstr "Tittel:" - -msgid "Submit" -msgstr "Send inn" - -msgid "Submit request" -msgstr "Send henvendelse" - -msgid "Submit status" -msgstr "Oppdater status" - -msgid "Submit status and send message" -msgstr "Oppdater, og send melding" - -msgid "Subscribe to blog" -msgstr "Abboner på blogg" - -msgid "Success" -msgstr "Suksess" - -msgid "Successful Freedom of Information requests" -msgstr "Vellykket innsynshenvendelse" - -msgid "Successful." -msgstr "Vellykket." - -msgid "Suggest how the requester can find the <strong>rest of the information</strong>." -msgstr "Foreslår hvordan henvenderen kan få <strong>resten av informasjonen/dokumentene</strong>" - -msgid "Summary:" -msgstr "Oppsummering:" - -msgid "Table of statuses" -msgstr "Tabell over statuser" - -msgid "Table of varieties" -msgstr "Tabell over typer" - -msgid "Tags" -msgstr "Tagger" - -msgid "Tags (separated by a space):" -msgstr "Tagger (space separert):" - -msgid "Tags:" -msgstr "Tagger:" - -msgid "Technical details" -msgstr "Tekniske detaljer" - -msgid "Thank you for helping us keep the site tidy!" -msgstr "Takk for at du hjelper oss med å holde tjenesten ryddig!" - -msgid "Thank you for making an annotation!" -msgstr "Takk for at du laget en merknad!" - -msgid "Thank you for responding to this FOI request! Your response has been published below, and a link to your response has been emailed to " -msgstr "Takk for at du svarte på denne innsynsbegjæringen! Svaret ditt har nå blitt publisert under, og en lenke til svaret er sendt på e-post til " - -msgid "Thank you for updating the status of the request '<a href=\"{{url}}\">{{info_request_title}}</a>'. There are some more requests below for you to classify." -msgstr "Takk for at du oppdaterer status på innsynsbegjæringen '<a href=\"{{url}}\">{{info_request_title}}</a>'. Det er flere begjæringer under som du kan klassifisere." - -msgid "Thank you for updating this request!" -msgstr "Takk for at du oppdaterte denne henvendelsen!" - -msgid "Thank you for updating your profile photo" -msgstr "Takk for at du oppdaterte profil-bildet" - -msgid "Thank you! We'll look into what happened and try and fix it up." -msgstr "Takk! Vi skal sjekke hva som skjedde, og forsøke å fikse set." - -msgid "Thanks for helping - your work will make it easier for everyone to find successful\\nresponses, and maybe even let us make league tables..." -msgstr "Takk for at du hjelper - det vil gjøre det enklere for alle å finne vellykkede\\nsvar, og kanskje til og med la oss lage en konkurranse ut av det..." - -msgid "Thanks for your suggestion to add {{public_body_name}}. It's been added to the site here:" -msgstr "Takk for forslaget ditt om å legge til {{public_body_name}}. Den har blit lagt til nettstedet her:" - -msgid "Thanks for your suggestion to update the email address for {{public_body_name}} to {{public_body_email}}. This has now been done and any new requests will be sent to the new address." -msgstr "Tusen takk for ditt forslag om å oppdatere e-postadressen for {{public_body_name}} til {{public_body_email}}. Dette er nå gjort, og alle nye henvendelser vil bli sendt til den nye adressen." - -msgid "Thanks very much - this will help others find useful stuff. We'll\\n also, if you need it, give advice on what to do next about your\\n requests." -msgstr "Tusen takk. - Dette vil hjelpe andre å finne nyttig stoff. Vi vil\\nogså, hvis du trenger det, gi råd om hva du kan gjøre videre med dine\\nhenvendelser." - -msgid "Thanks very much for helping keep everything <strong>neat and organised</strong>.\\n We'll also, if you need it, give you advice on what to do next about each of your\\n requests." -msgstr "Tusen takk for hjelpen med holde alt <strong>ryddig og ordenlig</strong>.\\nVi vil også, hvis du trenger det, gi deg råd om hva du kan gjøre videre med hver av dine\\nhenvendelser." - -msgid "That doesn't look like a valid email address. Please check you have typed it correctly." -msgstr "Ser ikke ut som en lovlig e-post adresse. Sjekk om du har skrevet den korrekt." - -msgid "The <strong>review has finished</strong> and overall:" -msgstr "Klagen er ferdigbehandlet og:" - -msgid "The Freedom of Information Act <strong>does not apply</strong> to" -msgstr "Offentlighetsloven <strong>er ikke gjeldende</strong> for" - -msgid "The URL where you found the email address. This field is optional, but it would help us a lot if you can provide a link to a specific page on the authority's website that gives this address, as it will make it much easier for us to check." -msgstr "URL-en der du fant e-postadressen. Dette feltet er valgfritt, men det vil hjelpe oss veldig hvis du kan tilby en lenke til en spesifikk side på autoritetens nettside som oppgir denne adressen, da det vil gjøre det mye enklere for oss å sjekke den." - -msgid "The accounts have been left as they previously were." -msgstr "Kontoene er etterlatt slik de tidligere var." - -msgid "The authority do <strong>not have</strong> the information <small>(maybe they say who does)" -msgstr "Myndigheten <strong>har ikke</strong> denne informasjonen <small>(kanskje de sier hvem som har)" - -msgid "The authority email doesn't look like a valid address" -msgstr "Myndighetens e-postadresse ser ikke ut som en gyldig adresse" - -msgid "The authority only has a <strong>paper copy</strong> of the information." -msgstr "Myndigheten har kun <strong>papireksemplar</strong> av informasjonen." - -msgid "The authority say that they <strong>need a postal\\n address</strong>, not just an email, for it to be a valid FOI request" -msgstr "Myndigheten sier at de <strong> trenger en postadresse</strong>, og ikke bare en e-post, for at det skal være en gyldig innsynshenvendelse." - -msgid "The authority would like to / has <strong>responded by post</strong> to this request." -msgstr "Myndigheten ønsker å / har <strong>svart på post</strong> på denne begjæringen." - -msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." -msgstr "Klassifiseringen av henvendelser (dvs. å si om de var vellykkede eller ikke) gjøres manuelt av brukere og administratorer på nettstedet, hvilket betyr at det kan være gjort feil." - -msgid "The contact email address for FOI requests to the authority." -msgstr "Kontakt-e-postadressen for innsynshenvendelser til denne myndigheten." - -msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." -msgstr "E-posten som du, på vegne av {{public_body}}, har sendt til\\n{{user}} for å svare på en {{law_used_short}}-henvendelse, har ikke blitt levert." - -msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." -msgstr "Stolpene i diagramet viser 95% konfidensintervall for den hypotetiske underliggende størrelsen (med andre ord, den du får hvis du lager et uendelig antall henvendelser via dette nettstedet til den myndigheten). Med andre ord, populasjonen som samples er alle de nåværende og fremtidige henvendelsene til myndigheten gjennom dette nettstedet, i stedet for eksempel alle henvendelser som har blitt gjort til det offentlige myndigheten uavhengig av måte." - -msgid "The last incoming message was created in the last day" -msgstr "Den sist innkommede meldingen ble opprettet i løpet av den dagen" - -msgid "The last incoming message was created over a day ago" -msgstr "Den sist innkommede meldingen ble opprettet for mer enn en dag siden" - -msgid "The last outgoing message was created in the last day" -msgstr "Den sist utgående meldingen ble opprettet i løpet av dagen" - -msgid "The last outgoing message was created over a day ago" -msgstr "Den sist utgående meldingen ble opprettet for mer enn en dag siden" - -msgid "The last user was created in the last day" -msgstr "Den siste brukeren ble laget i løpet av dagen" - -msgid "The last user was created over a day ago" -msgstr "Den siste brukeren ble laget for mer enn en dag siden" - -msgid "The page doesn't exist. Things you can try now:" -msgstr "Siden finnes ikke. Det du kan forsøke nå:" - -msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." -msgstr "Prosentene blir beregnet ut fra det totale antall henvendelser, der ugyldige henvendelser er talt med. Dette er et kjent problem som vil bli fikset i en senere utgave." - -msgid "The public authority does not have the information requested" -msgstr "Den offentlige myndigheten har ikke informasjonen som er begjært" - -msgid "The public authority would like part of the request explained" -msgstr "Den offentlige myndigheten ønsker en forklaring på en del av henvendelsen" - -msgid "The public authority would like to / has responded by post" -msgstr "Den offentlige myndigheten ønsker å / har svart via post" - -msgid "The request has been <strong>refused</strong>" -msgstr "Begjæringen har blitt <strong>avvist</strong>" - -msgid "The request has been updated since you originally loaded this page. Please check for any new incoming messages below, and try again." -msgstr "Innsynsbegjæringen har blitt oppdatert siden du lastet denne siden. Vennligst sjekk under for nye innkomne beskjeder og forsøk igjen." - -msgid "The request is <strong>waiting for clarification</strong>." -msgstr "Innsynsbegjæringen <strong>venter på avklaring</strong>." - -msgid "The request was <strong>partially successful</strong>." -msgstr "Innsynsbegjæringen var <strong>delevis vellykket</strong>." - -msgid "The request was <strong>refused</strong> by" -msgstr "Innsynsbegjæringen ble <strong>avslått</strong> av " - -msgid "The request was <strong>successful</strong>." -msgstr "Innsynsbegjæringen var <strong>vellykket</strong>." - -msgid "The request was refused by the public authority" -msgstr "Henvendelsen ble avvist av mydnigheten" - -msgid "The request you have tried to view has been removed. There are\\nvarious reasons why we might have done this, sorry we can't be more specific here. Please <a\\n href=\"{{url}}\">contact us</a> if you have any questions." -msgstr "Henvendelsen du har forsøkt å se på er fjernet. Det er ulike\\n grunner til hvorfor vi kan ha gjort dette, beklager at vi ikke kan være mer spesifikk her.\\n <a href=\"{{url}}\">Ta kontakt med oss</a> hvis du har spørsmål." - -msgid "The requester has abandoned this request for some reason" -msgstr "Forespørrer har av en eller annen grunn gitt opp denne henvendelsen" - -msgid "The response to your request has been <strong>delayed</strong>. You can say that,\\n by law, the authority should normally have responded\\n <strong>promptly</strong> and" -msgstr "" -"Svaret på din henvendelse er <strong>forsinket</strong>. I følge lovverket\\n kan en si\n" -"at etaten normal skulle svart <strong>uten opphold</strong> og" - -msgid "The response to your request is <strong>long overdue</strong>. You can say that, by\\n law, under all circumstances, the authority should have responded\\n by now" -msgstr "Svaret på din henvendelse er <strong>svært forsinket</strong>. I følge loven\\n så burde instansen under enhver omstendighet ha svart på\\n dette tidspunkt" - -msgid "The search index is currently offline, so we can't show the Freedom of Information requests that have been made to this authority." -msgstr "Søke-indeksen er ikke tilgjengelig, så vi kan ikke vise deg innsynsbegjæringer som er sendt til denne myndigheten" - -msgid "The search index is currently offline, so we can't show the Freedom of Information requests this person has made." -msgstr "Søke-indeksen er ikke tilgjengelig, så vi kan ikke vise innsynsbegjæringen til denne personen" - -msgid "The {{site_name}} team." -msgstr "{{site_name}}-gjengen." - -msgid "Then you can cancel the alert." -msgstr "Så kan du kanselere varslingen." - -msgid "Then you can cancel the alerts." -msgstr "Så kan du kanselere varslingen." - -msgid "Then you can change your email address used on {{site_name}}" -msgstr "Så kan du endre e-post adressen brukt på {{site_name}}" - -msgid "Then you can change your password on {{site_name}}" -msgstr "Så kan du bytte passordet på {{site_name}}" - -msgid "Then you can classify the FOI response you have got from " -msgstr "Så kan du klassifisere svaret på innsynsbegjæringen som du fikk fra " - -msgid "Then you can download a zip file of {{info_request_title}}." -msgstr "Deretter kan du laste ned en zip-fil med {{info_request_title}}." - -msgid "Then you can log into the administrative interface" -msgstr "Så kan du logge deg på det admininstrative grensesnittet" - -msgid "Then you can make a batch request" -msgstr "Da kan du lage en bunthenvendelse" - -msgid "Then you can play the request categorisation game." -msgstr "Da kan du delta i henvendelseskategoriserings-spillet." - -msgid "Then you can report the request '{{title}}'" -msgstr "Så kan du rapportere begjæringen «{{title}}»" - -msgid "Then you can send a message to " -msgstr "Så kan du sende en melding til " - -msgid "Then you can sign in to {{site_name}}" -msgstr "Så kan du logge inn på {{site_name}}" - -msgid "Then you can update the status of your request to " -msgstr "Så kan du oppdater status på henvendelsen til " - -msgid "Then you can upload an FOI response. " -msgstr "Så kan du sende en innsynsbegjæring" - -msgid "Then you can write follow up message to " -msgstr "Deretter kan du skrive en oppfølgingsmelding til " - -msgid "Then you can write your reply to " -msgstr "Så kan du skrive svaret ditt til " - -msgid "Then you will be following all new FOI requests." -msgstr "Så vil du følge alle nye innsynsbegjæringer." - -msgid "Then you will be notified whenever '{{user_name}}' requests something or gets a response." -msgstr "Så vil du få beskjed når '{{user_name}}' etterspør noe eller får et svar." - -msgid "Then you will be notified whenever a new request or response matches your search." -msgstr "Så vil du få beskjed når en ny henvendelse eller et svar oppfyller ditt søk." - -msgid "Then you will be notified whenever an FOI request succeeds." -msgstr "Så vil du få beskjed når en innsynsbegjøring lykkes." - -msgid "Then you will be notified whenever someone requests something or gets a response from '{{public_body_name}}'." -msgstr "Så vil du få beskjed når noen etterspør noe eller får et svar fra '{{public_body_name}}'." - -msgid "Then you will be updated whenever the request '{{request_title}}' is updated." -msgstr "Så vil du få en oppdatering når begjæringen '{{request_title}}' blir oppdatert." - -msgid "Then you'll be allowed to send FOI requests." -msgstr "Så vil du få lov til å sende innsynsbegjæringer." - -msgid "Then your FOI request to {{public_body_name}} will be sent." -msgstr "Så vil dine innsynsbegjæringer til {{public_body_name}} bli sendt." - -msgid "Then your annotation to {{info_request_title}} will be posted." -msgstr "Så vil din annotering til {{info_request_title}} bli publisert." - -msgid "There are {{count}} new annotations on your {{info_request}} request. Follow this link to see what they wrote." -msgstr "Det er {{count}} nye annoteringer på din {{info_request}} begjæring. Følg denne lenken for å se hva de har skrevet." - -msgid "There is <strong>more than one person</strong> who uses this site and has this name.\\n One of them is shown below, you may mean a different one:" -msgstr "Det er <strong>mer enn én person</strong> som bruker dette området, og har dette navnet.\\n En av dem er vist nedenfor, men du kan mene en annen:" - -msgid "There is a limit on the number of requests you can make in a day, because we don’t want public authorities to be bombarded with large numbers of inappropriate requests. If you feel you have a good reason to ask for the limit to be lifted in your case, please <a href='{{help_contact_path}}'>get in touch</a>." -msgstr "Det er en grense på antall begjæringer du kan lage på én dag, fordi vi ikke ønsker at offentlige myndigheter skal bli oversvømt med et stort antall upassende henvendelser. Dersom du synes du har en god grunn til at grensen skal økes i ditt tilfelle, vennligst <a href='{{help_contact_path}}'>ta kontakt</a>." - -msgid "There is nothing to display yet." -msgstr "Det er ingenting å vise enda." - -msgid "There is {{count}} person following this request" -msgid_plural "There are {{count}} people following this request" -msgstr[0] "{{count}} person følger denne henvendelsen" -msgstr[1] "{{count}} personer følger denne henvendelsen" - -msgid "There was a <strong>delivery error</strong> or similar, which needs fixing by the {{site_name}} team." -msgstr "Det var en <strong>feil med leveringen</strong> eller liknende, som trenger å rettes av {{site_name}}-gruppen." - -msgid "There was an error with the words you entered, please try again." -msgstr "Det var en feil med ordene du skrev inn, vennligst forsøk på nytt." - -msgid "There was no data calculated for this graph yet." -msgstr "Det er ikke noe data beregnet for denne grafen ennå." - -msgid "There were no requests matching your query." -msgstr "Det var ingen begjæringer som tilfredsstiller ditt søk." - -msgid "There were no results matching your query." -msgstr "Det var ingen resultater som tilfredsstiller ditt søk." - -msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." -msgstr "Disse grafene er delvis inspirert av <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">endel statistikk som Mark Goodge lagde for WhatDoTheyKnow</a>, så han fortjener en takk." - -msgid "They are going to reply <strong>by post</strong>" -msgstr "De kommer til å svare <stron>per brev</strong>" - -msgid "They do <strong>not have</strong> the information <small>(maybe they say who does)</small>" -msgstr "De <strong>har ikke</strong> informasjonen <small>(vet de hvem som har den?)</small>" - -msgid "They have been given the following explanation:" -msgstr "De har fått følgende forklaring:" - -msgid "They have not replied to your {{law_used_short}} request {{title}} promptly, as normally required by law" -msgstr "De har ikke svart på din {{law_used_short}} om «{{title}}» innen kort tid, som er det som normalt kreves i følge lovverket" - -msgid "They have not replied to your {{law_used_short}} request {{title}}, \\nas required by law" -msgstr "De har ikke svart på din {{law_used_short}} om «{{title}}», slik det kreves i følge lovverket" - -msgid "Things to do with this request" -msgstr "Hva kan man gjøre med denne henvendelsen?" - -msgid "Things you're following" -msgstr "Ting du følger" - -msgid "This authority no longer exists, so you cannot make a request to it." -msgstr "Denne myndigheten er slettet, og kan ikke kontaktes." - -msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" -msgstr "Dette dekker et svært bredt spekter av informasjon om tilstanden til \\n<strong> berørt natur og bebygde områder</ strong>, som for eksempel:" - -msgid "This external request has been hidden" -msgstr "Den eksterne begjæringen har blitt skjult" - -msgid "This is <a href=\"{{profile_url}}\">{{user_name}}'s</a> wall" -msgstr "Dette er veggen til <a href=\"{{profile_url}}\">{{user_name}}</a>" - -msgid "This is a plain-text version of the Freedom of Information request \"{{request_title}}\". The latest, full version is available online at {{full_url}}" -msgstr "Det er en tekst-versjon av innsynsbegjæringen \"{{request_title}}\". Den siste, komplette versjonen er tilgjengelig på nett {{full_url}}" - -msgid "This is an HTML version of an attachment to the Freedom of Information request" -msgstr "Dette er HTML-versjonen av et vedlegg til innsynsbegjæringen" - -msgid "This is because {{title}} is an old request that has been\\nmarked to no longer receive responses." -msgstr "Dette er på grunn av at {{title}} er en gammel henvendelse\\n som har blitt markert til å ikke lenger motta svar." - -msgid "This is the first version." -msgstr "Dette er den første versjonen." - -msgid "This is your own request, so you will be automatically emailed when new responses arrive." -msgstr "Dette er din egen henvendelse, så du vil automatisk få e-post når nye svar kommer inn." - -msgid "This message has been hidden." -msgstr "Denne meldingen har blitt skjult." - -msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." -msgstr "Denne meldingen har blitt skjult. Det er ulike årsaker til at vi kan ha gjort dette, og vi beklager at vi ikke kan være mer spesifikk her." - -msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." -msgstr "Denne meldingen er fremhevet som «skjult». Du kan kun se den på grunn av at du er logget inn som superbruker." - -msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." -msgstr "Denne meldingen er fremhevet som «skjult». {{reason}} Du kan kun se den på grunn av at du er logget inn som superbruker." - -msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." -msgstr "Denne meldingen er skjult, slik at kun du, innsenderen, kan se den. <a href=\"{{url}}\">Ta kontakt</a> hvis du er usikker på hvorfor." - -msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" -msgstr "Denne meldingen er skjult slik at kun du, innsenderen, kan se den. " - -msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" -msgstr "Denne siden med statistikk over offentlige instanser er for tiden eksperimentell, så det er noen utfordringer en bør ha i bakhodet:" - -msgid "This particular request is finished:" -msgstr "Denne henvendelsen er ferdigbehandlet:" - -msgid "This person has made no Freedom of Information requests using this site." -msgstr "Denne personen har ikke opprettet noen innsynsbegjæring på denne siden." - -msgid "This person's annotations" -msgstr "Denne personens annoteringer" - -msgid "This person's {{count}} Freedom of Information request" -msgid_plural "This person's {{count}} Freedom of Information requests" -msgstr[0] "Denne personens {{count}} innsynsbegjæring" -msgstr[1] "Denne personens {{count}} innsynsbegjæringer" - -msgid "This person's {{count}} annotation" -msgid_plural "This person's {{count}} annotations" -msgstr[0] "Denne personens {{count}} merknad" -msgstr[1] "Denne personens {{count} merknader" - -msgid "This request <strong>requires administrator attention</strong>" -msgstr "Denne begjæringen trenger <strong>oppmerksomhet fra administrator</strong>" - -msgid "This request has already been reported for administrator attention" -msgstr "Denne begjæringen har allerede blitt rapportert til administrator for gjennomgang." - -msgid "This request has an <strong>unknown status</strong>." -msgstr "Denne henvendelsen har en <strong>ukjent status</strong>." - -msgid "This request has been <strong>hidden</strong> from the site, because an administrator considers it not to be an FOI request" -msgstr "Denne begjæringen er <strong>skjult</strong> fra siden fordi en administrator anser det for å ikke være en innsynsbegjæring" - -msgid "This request has been <strong>hidden</strong> from the site, because an administrator considers it vexatious" -msgstr "Denne henvendelsen er blitt <strong>skjult</strong> fra nettstedet, fordi en administrator vurderer den som sjikanøs." - -msgid "This request has been <strong>reported</strong> as needing administrator attention (perhaps because it is vexatious, or a request for personal information)" -msgstr "Denne henvendelsen er blitt <strong>rapportert</ strong> da den trenger oppmerksomhet fra administrator (kanskje fordi den er sjikanøs, eller er en henvendelse om personopplysninger)" - -msgid "This request has been <strong>withdrawn</strong> by the person who made it.\\n There may be an explanation in the correspondence below." -msgstr "Denne henvendelsen har blitt <strong>trukket tilbake</strong> av personen som laget den.\\n Det kan være forklaring i korrespondansen under." - -msgid "This request has been marked for review by the site administrators, who have not hidden it at this time. If you believe it should be hidden, please <a href=\"{{url}}\">contact us</a>." -msgstr "Denne henvendelsen har blitt markert for gjennomgang av nettstedet administrator, som ikke har skjult den akkurat nå. Hvis du tror den bør bli skjult, <a href=\"{{url}}\">ta kontakt</a>." - -msgid "This request has been reported for administrator attention" -msgstr "Denne begjæringen har blitt rapportert for gjennomgang av administrator" - -msgid "This request has been set by an administrator to \"allow new responses from nobody\"" -msgstr "Denne henvendelsen har blitt markert av en administrator til å \"ikke tillate nye svar\"" - -msgid "This request has had an unusual response, and <strong>requires attention</strong> from the {{site_name}} team." -msgstr "Denne begjæringen har et uvanlig svar, og <strong>krever oppmerksomhet</strong> fra {{site_name}}-gruppen." - -msgid "This request has prominence 'hidden'. You can only see it because you are logged\\n in as a super user." -msgstr "" - -msgid "This request is hidden, so that only you the requester can see it. Please\\n <a href=\"{{url}}\">contact us</a> if you are not sure why." -msgstr "Denne henvendelsen er skjult, slik at bare du som innsender kan se den. Vær så snill <a href=\"{{url}}\">å ta kontakt</a> hvis du er usikker på hvorfor." - -msgid "This request is still in progress:" -msgstr "Denne henvendelsen er enda ikke ferdigbehandlet:" - -msgid "This request requires administrator attention" -msgstr "En administrator må se på denne henvendelsen" - -msgid "This request was not made via {{site_name}}" -msgstr "Denne begjæringen var ikke laget av {{site_name}}" - -msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." -msgstr "Denne tabellen viser de tekniske detaljene til interne hendelser som skjedde med denne henvendelsen på {{site_name}}. Dette kan brukes til å generere informasjon om hvor raskt ulike etater svarer på henvendelser, antall henvendelser som krever papirpostsvar og mye mer." - -msgid "This user has been banned from {{site_name}} " -msgstr "Denne brukeren er sperret ute fra {{site_name}}" - -msgid "This was not possible because there is already an account using \\nthe email address {{email}}." -msgstr "Dette var ikke mulig da det allerede er en konto som bruker e-postadressen {{email}}." - -msgid "To cancel these alerts" -msgstr "For å avbryte varslingen." - -msgid "To cancel this alert" -msgstr "For å avbryte dette varselet" - -msgid "To carry on, you need to sign in or make an account. Unfortunately, there\\nwas a technical problem trying to do this." -msgstr "For å fortsette må du logge inn eller lage en konto. Beklageligvis var\\ndet et teknisk problem idet du forsøkte å gjøre dette." - -msgid "To change your email address used on {{site_name}}" -msgstr "For å endre din e-postadresse brukt på {{site_name}}" - -msgid "To classify the response to this FOI request" -msgstr "For å klassifisere svaret til denne innsynsbegjæringen" - -msgid "To do that please send a private email to " -msgstr "For å gjøre det, vennligst send en privat e-post til" - -msgid "To do this, first click on the link below." -msgstr "For å gjøre dette, klikk først på lenken nedenfor." - -msgid "To download the zip file" -msgstr "For å laste ned zip-filen" - -msgid "To follow all successful requests" -msgstr "For å følge alle vellykkede begjæringer" - -msgid "To follow new requests" -msgstr "For å følge nye begjæringer" - -msgid "To follow requests and responses matching your search" -msgstr "For å følge henvendelser og svar som treffer søket" - -msgid "To follow requests by '{{user_name}}'" -msgstr "For å følge begjæringer fra '{{user_name}}'" - -msgid "To follow requests made using {{site_name}} to the public authority '{{public_body_name}}'" -msgstr "For å følge begjæringer opprettet med {{site_name}} til den offentlige myndigheten '{{public_body_name}}'" - -msgid "To follow the request '{{request_title}}'" -msgstr "For å følge begjæringen '{{request_title}}'" - -msgid "To help us keep the site tidy, someone else has updated the status of the \\n{{law_used_full}} request {{title}} that you made to {{public_body}}, to \"{{display_status}}\" If you disagree with their categorisation, please update the status again yourself to what you believe to be more accurate." -msgstr "For å hjelpe oss å holde dette nettstedet ryddig, har noen andre oppdatert statusen for {{law_used_full}}-henvendelsen som du lagde til {{public_body}} slik at den er «{{display_status}}».. Hvis du er uenig i deres kategorisering, vær så snill å oppdater statusen på nytt selv til det du mener vil være mer presist." - -msgid "To let everyone know, follow this link and then select the appropriate box." -msgstr "For å orientere alle, følg denne linken og velg den aktuelle boksen." - -msgid "To log into the administrative interface" -msgstr "For å logge deg på admin grensesnittet" - -msgid "To make a batch request" -msgstr "For å lage en bunthenvendelse" - -msgid "To play the request categorisation game" -msgstr "For å spille henvendelseskategoriseringsspillet" - -msgid "To post your annotation" -msgstr "For å poste din kommentar" - -msgid "To reply to " -msgstr "For å svare til " - -msgid "To report this request" -msgstr "For å rapportere denne henvendelsen" - -msgid "To send a follow up message to " -msgstr "For å sende en oppfølgningsmelding til " - -msgid "To send a message to " -msgstr "For å sende en melding til " - -msgid "To send your FOI request" -msgstr "For å sende en innsynshenvendelse" - -msgid "To update the status of this FOI request" -msgstr "For å oppdatere status på denne innsynshenvendelsen" - -msgid "To upload a response, you must be logged in using an email address from " -msgstr "For å laste opp et svar, må du være pålogget med en e-post adresse fra " - -msgid "To use the advanced search, combine phrases and labels as described in the search tips below." -msgstr "For å bruke avansert søk, kombiner fraser og merkelapper som beskrevet i søketipsene under." - -msgid "To view the email address that we use to send FOI requests to {{public_body_name}}, please enter these words." -msgstr "For å se e-post-adressen som vi bruker til å sende innsynsbegjæringen til {{public_body_name}}, vennligst skriv inn disse ordene." - -msgid "To view the response, click on the link below." -msgstr "For å se svaret, klikk på lenken under." - -msgid "To {{public_body_link_absolute}}" -msgstr "Til {{public_body_link_absolute}}" - -msgid "To:" -msgstr "Til:" - -msgid "Today" -msgstr "Idag" - -msgid "Too many requests" -msgstr "For mange henvendelser" - -msgid "Top search results:" -msgstr "Beste søketreff:" - -msgid "Track thing" -msgstr "Følg ting" - -msgid "Track this person" -msgstr "Følg denne personen" - -msgid "Track this search" -msgstr "Følg dette søket" - -msgid "TrackThing|Track medium" -msgstr "TrackThing|Track medium" - -msgid "TrackThing|Track query" -msgstr "TrackThing|Track query" - -msgid "TrackThing|Track type" -msgstr "TrackThing|Track type" - -msgid "Turn off email alerts" -msgstr "Skru av e-postvarsling" - -msgid "Tweet this request" -msgstr "Tvitre om henvendelsen" - -msgid "Type <strong><code>01/01/2008..14/01/2008</code></strong> to only show things that happened in the first two weeks of January." -msgstr "Skriv <strong><code>01/01/2008..14/01/2008</code></strong> for å bare vise ting som har skjedd de to første ukene i januar." - -msgid "URL name can't be blank" -msgstr "URL navn kan ikke være blank" - -msgid "URL name is already taken" -msgstr "URL-navnet er allerede brukt" - -msgid "Unable to change email address on {{site_name}}" -msgstr "Klarte ikke endre e-post adresse på {{site_name}}" - -msgid "Unable to send a reply to {{username}}" -msgstr "Klarte ikke sende svar til {{username}}" - -msgid "Unable to send follow up message to {{username}}" -msgstr "Klarte ikke sende oppfølgningsmelding til {{username}}" - -msgid "Unclassified or hidden requests are not counted." -msgstr "Skjulte og uklassifiserte henvendelser blir ikke talt med." - -msgid "Unexpected search result type " -msgstr "Uventet type søke resultat " - -msgid "Unfortunately we don't know the FOI\\nemail address for that authority, so we can't validate this.\\nPlease <a href=\"{{url}}\">contact us</a> to sort it out." -msgstr "Desverre vet vi ikke e-post-adressen som bør brukes til innsynshenvendelser for denne\\nmyndigheten, så vi kan ikke validere dette.\\n<a href=\"{{url}}\">Ta kontakt</a> for å finne ut av dette." - -msgid "Unfortunately, we do not have a working address for {{public_body_names}}." -msgstr "Desverre har vi ikke en fungerende adresse for " - -msgid "Unfortunately, we do not have a working {{info_request_law_used_full}}\\naddress for" -msgstr "Beklageligvis har vi ikke en fungerende {{info_request_law_used_full}}-adresse for" - -msgid "Unknown" -msgstr "Ukjent" - -msgid "Unsubscribe" -msgstr "Meld deg av" - -msgid "Unusual response." -msgstr "Uvanlig svar." - -msgid "Update email address - {{public_body_name}}" -msgstr "Oppdater e-postadresse - " - -msgid "Update the address:" -msgstr "Oppdater adressen:" - -msgid "Update the status of this request" -msgstr "Oppdater status på denne henvendelsen" - -msgid "Update the status of your request to " -msgstr "Oppdater status på henvendelsen din til " - -msgid "Upload FOI response" -msgstr "Last opp innsynssvar" - -msgid "Use OR (in capital letters) where you don't mind which word, e.g. <strong><code>commons OR lords</code></strong>" -msgstr "Bruk OR (store bokstaver) der du vil ha treff på ett av ordene, for eksempel <strong><code>storting OR regjering</code></strong>" - -msgid "Use quotes when you want to find an exact phrase, e.g. <strong><code>\"Liverpool City Council\"</code></strong>" -msgstr "Bruk anførselstegn der du vil søke etter et nøyaktig uttrykk, for eksempel. <strong><code>\"Byrådsavdeling for finans\"</code></strong>" - -msgid "User" -msgstr "Bruker" - -msgid "User info request sent alert" -msgstr "" - -msgid "User – {{name}}" -msgstr "Bruker – {{name}}" - -msgid "UserInfoRequestSentAlert|Alert type" -msgstr "UserInfoRequestSentAlert|Alert type" - -msgid "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." -msgstr "Brukere kan normalt ikke lage bunthenvendelser til flere myndigheter på en gang, da vi ikke ønsker at offentlige myndigheter blir bombardert med et stort antall malplasserte henvendelser. <a href=\"{{url}}\">Ta kontakt med oss</a> hvis du tror du har en god grunn til å sende samme henvendelse til flere myndigheter på en gang." - -msgid "User|About me" -msgstr "Bruker|Om meg" - -msgid "User|Admin level" -msgstr "Bruker|Admin nivå" - -msgid "User|Ban text" -msgstr "Bruker|Ban tekst" - -msgid "User|Can make batch requests" -msgstr "User|Can make batch requests" - -msgid "User|Email" -msgstr "Bruker|E-post" - -msgid "User|Email bounce message" -msgstr "Bruker|E-post bounce melding" - -msgid "User|Email bounced at" -msgstr "User|Email bounced at" - -msgid "User|Email confirmed" -msgstr "Bruker|E-post bekreftet" - -msgid "User|Hashed password" -msgstr "Bruker|Hashet passord" - -msgid "User|Identity card number" -msgstr "User|Identity card number" - -msgid "User|Last daily track email" -msgstr "Bruker|Siste daglige track e-post" - -msgid "User|Locale" -msgstr "Bruker|Localisering" - -msgid "User|Name" -msgstr "Bruker|Navn" - -msgid "User|No limit" -msgstr "Bruker|Ingen grense" - -msgid "User|Receive email alerts" -msgstr "Bruker|Motta e-post notifikasjoner" - -msgid "User|Salt" -msgstr "Bruker|Salt" - -msgid "User|Url name" -msgstr "Bruker|Url navn" - -msgid "Version {{version}}" -msgstr "Versjon {{version}}" - -msgid "Vexatious" -msgstr "Sjikane" - -msgid "View FOI email address" -msgstr "Vis e-post adresse for innsyn" - -msgid "View FOI email address for '{{public_body_name}}'" -msgstr "Vis e-post adresse for innsyn mot '{{public_body_name}}'" - -msgid "View FOI email address for {{public_body_name}}" -msgstr "Vis e-post adresse for innsyn mot {{public_body_name}}" - -msgid "View Freedom of Information requests made by {{user_name}}:" -msgstr "Vis innsynsbegjæringer som er opprettet av {{user_name}}:" - -msgid "View authorities" -msgstr "Vis myndigheter" - -msgid "View email" -msgstr "Les e-post" - -msgid "Waiting clarification." -msgstr "Venter avklaring" - -msgid "Waiting for an <strong>internal review</strong> by {{public_body_link}} of their handling of this request." -msgstr "Venter på <strong>klagebehandling</string> hos {{public_body_link}}." - -msgid "Waiting for the public authority to complete an internal review of their handling of the request" -msgstr "Venter på at myndigheten skal utføre klagebehandling på denne henvendelsen/klagen" - -msgid "Waiting for the public authority to reply" -msgstr "Venter på svar fra myndigheten" - -msgid "Was the response you got to your FOI request any good?" -msgstr "Var svaret på innsynshenvendelsen din tilfredstillende?" - -msgid "We consider it is not a valid FOI request, and have therefore hidden it from other users." -msgstr "Vi ser på dette som en ikke gyldig innsynsbegjering, og har derfor gjemt den fra de andre brukerne." - -msgid "We consider it to be vexatious, and have therefore hidden it from other users." -msgstr "Vi ser på den som sjikanøs, og har derfor skjult den for de andre brukerne." - -msgid "We do not have a working request email address for this authority." -msgstr "Vi har ikke en gyldig e-post adresse for henvendelser for denne myndigheten" - -msgid "We do not have a working {{law_used_full}} address for {{public_body_name}}." -msgstr "Vi har ikke en fungerende {{law_used_full}}-adresse for {{public_body_name}}." - -msgid "We don't know whether the most recent response to this request contains\\n information or not\\n –\\n\tif you are {{user_link}} please <a href=\"{{url}}\">sign in</a> and let everyone know." -msgstr "" -"Vi vet ikke om sist mottatte svar på denne henvendelsen inneholder\\n\n" -"informasjon/dokumenter eller ikke\\n –\\n\n" -"om du er {{user_link}}, vennligst <a href=\"{{url}}\">logg inn</a> og gi alle beskjed." - -msgid "We will not reveal your email address to anybody unless you or\\n the law tell us to (<a href=\"{{url}}\">details</a>). " -msgstr "Vi vil aldri gi ut e-post adressen din til noen uten at du eller\\n retten ber oss om det (<a href=\"{{url}}\">detaljer</a>). " - -msgid "We will not reveal your email address to anybody unless you\\nor the law tell us to." -msgstr "Vi kommer ikke dele e-post-adressen din med noen, med mindre du eller en domstol ber oss om det." - -msgid "We will not reveal your email addresses to anybody unless you\\nor the law tell us to." -msgstr "Vi kommer ikke dele e-post-adressene dine med noen, med mindre du eller en domstol ber oss om det." - -msgid "We're waiting for" -msgstr "Vi venter på" - -msgid "We're waiting for someone to read" -msgstr "Vi venter på at noen leser" - -msgid "We've sent an email to your new email address. You'll need to click the link in\\nit before your email address will be changed." -msgstr "Vi har sent en mail til den nye e-post adressen din. Du må klikke på lenken i\\nden før e-post adressen din blir byttet." - -msgid "We've sent you an email, and you'll need to click the link in it before you can\\ncontinue." -msgstr "Vi har sendt deg en e-post, og du er nødt til å klikke på lenken i den før du kan\\nfortsette." - -msgid "We've sent you an email, click the link in it, then you can change your password." -msgstr "Vi har sendt deg en e-post, klikk på lenken i den, så du kan bytte passordet ditt." - -msgid "What are you doing?" -msgstr "Hva holder du på med?" - -msgid "What best describes the status of this request now?" -msgstr "Hva beskriver best status på denne henvendelsen?" - -msgid "What information has been released?" -msgstr "Hva slags informasjon er utlevert?" - -msgid "What information has been requested?" -msgstr "Hva slags informasjon er forespurt?" - -msgid "When you get there, please update the status to say if the response \\ncontains any useful information." -msgstr "Når du kommer dit, vær så snill å oppdatere statusen til å fortelle om svaret inneholdt noe nyttig informasjon." - -msgid "When you receive the paper response, please help\\n others find out what it says:" -msgstr "Når du mottar svar på papir, vær så snill å hjelp andre å finne ut hva det sier:" - -msgid "When you're done, <strong>come back here</strong>, <a href=\"{{url}}\">reload this page</a> and file your new request." -msgstr "Når du har gjort dette, <strong>kom tilbake hit</strong>, <a href=\"{{url}}\">last denne siden på nytt</a> og legg inn din nye henvendelse." - -msgid "Which of these is happening?" -msgstr "Hva av dette er det som skjer?" - -msgid "Who can I request information from?" -msgstr "Hvem kan jeg be om informasjon fra?" - -msgid "Why specifically do you consider this request unsuitable?" -msgstr "Hvorfor mener du denne henvendelsen er upassende?" - -msgid "Withdrawn by the requester." -msgstr "Trukket tilbake av henvenderen" - -msgid "Wk" -msgstr "" - -msgid "Would you like to see a website like this in your country?" -msgstr "Skulle du like å se en tilsvarende nettside i ditt land?" - -msgid "Write a reply" -msgstr "Skriv et svar" - -msgid "Write a reply to " -msgstr "Skriv et svar til " - -msgid "Write your FOI follow up message to " -msgstr "Skriv din oppfølgning til henvendelsen til " - -msgid "Write your request in <strong>simple, precise language</strong>." -msgstr "Skriv henvendelsen i <strong>enkelt, nøyaktig språk</strong>." - -msgid "You" -msgstr "Du" - -msgid "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." -msgstr "Du har allerede laget samme bunt med henvendelser den {{date}} Du kan enten se på <a href=\"{{existing_batch}}\">den eksisterende bunten</a>, eller redigere detaljene under for å lage en ny men lignende bunt med henvendelser." - -msgid "You are already following new requests" -msgstr "Du følger allerede nye henvendelser" - -msgid "You are already following requests to {{public_body_name}}" -msgstr "Du følger allerede henvendelser til {{public_body_name}}" - -msgid "You are already following things matching this search" -msgstr "Du følger allerede ting som treffer på dette søket" - -msgid "You are already following this person" -msgstr "Du følger allerede denne personen" - -msgid "You are already following this request" -msgstr "Du følger allerede denne henvendelsen" - -msgid "You are already subscribed to '{{link_to_authority}}', a public authority." -msgstr "Du abonnerer allerede på '{{link_to_authority}}', en offentlig myndighet." - -msgid "You are already subscribed to '{{link_to_request}}', a request." -msgstr "Du abonnerer allerede på henvendelsen «{{link_to_request}}»." - -msgid "You are already subscribed to '{{link_to_user}}', a person." -msgstr "Du abonnerer allerede på '{{link_to_user}}', en person." - -msgid "You are already subscribed to <a href=\"{{search_url}}\">this search</a>." -msgstr "Du abonnerer allerede på <a href=\"{{search_url}}\">dette søket</a>." - -msgid "You are already subscribed to any <a href=\"{{new_requests_url}}\">new requests</a>." -msgstr "Du abonnerer allerede på alle <a href=\"{{new_requests_url}}\">nye henvendelser</a>." - -msgid "You are already subscribed to any <a href=\"{{successful_requests_url}}\">successful requests</a>." -msgstr "Du abonnerer allerede på alle <a href=\"{{successful_requests_url}}\">vellykkede henvendelser</a>." - -msgid "You are currently receiving notification of new activity on your wall by email." -msgstr "Du mottar e-postvarsel om ny aktivitet på veggen din." - -msgid "You are following all new successful responses" -msgstr "Du følger all nye vellykkede svar" - -msgid "You are no longer following '{{link_to_authority}}', a public authority." -msgstr "Du følger ikke lenger med på myndigheten «{{link_to_authority}}»." - -msgid "You are no longer following '{{link_to_request}}', a request." -msgstr "Du følger ikke lenger med på henvendelsen «{{link_to_request}}»." - -msgid "You are no longer following '{{link_to_user}}', a person." -msgstr "Du følger ikke lenger med på personen «{{link_to_user}}»." - -msgid "You are no longer following <a href=\"{{new_requests_url}}\">new requests</a>." -msgstr "Du følger ikke lenger med på <a href=\"{{new_requests_url}}\">nye henvendelser</a>." - -msgid "You are no longer following <a href=\"{{search_url}}\">this search</a>." -msgstr "Du følger ikke lenger med på <a href=\"{{search_url}}\">dette søket</a>." - -msgid "You are no longer following <a href=\"{{successful_requests_url}}\">successful requests</a>." -msgstr "Du følger ikke lenger med på <a href=\"{{successful_requests_url}}\">vellykkede henvendelser</a>." - -msgid "You are now <a href=\"{{wall_url_user}}\">following</a> updates about '{{link_to_authority}}', a public authority." -msgstr "Du <a href=\"{{wall_url_user}}\">følger nå med på</a> oppdateringer om offentlig myndighet «{{link_to_authority}}»." - -msgid "You are now <a href=\"{{wall_url_user}}\">following</a> updates about '{{link_to_request}}', a request." -msgstr "Du <a href=\"{{wall_url_user}}\">følger nå med på</a> oppdateringer om henvendelsen «{{link_to_request}}»." - -msgid "You are now <a href=\"{{wall_url_user}}\">following</a> updates about '{{link_to_user}}', a person." -msgstr "Du <a href=\"{{wall_url_user}}\">følger nå med på</a> oppdateringer om person «{{link_to_user}}»." - -msgid "You are now <a href=\"{{wall_url_user}}\">following</a> updates about <a href=\"{{new_requests_url}}\">new requests</a>." -msgstr "Du <a href=\"{{wall_url_user}}\">følger nå med på</a> oppdateringer om <a href=\"{{new_requests_url}}\">nye henvendelser</a>." - -msgid "You are now <a href=\"{{wall_url_user}}\">following</a> updates about <a href=\"{{search_url}}\">this search</a>." -msgstr "Du <a href=\"{{wall_url_user}}\">følger nå med på</a> oppdateringer om <a href=\"{{search_url}}\">dette søket</a>." - -msgid "You are now <a href=\"{{wall_url_user}}\">following</a> updates about <a href=\"{{successful_requests_url}}\">successful requests</a>." -msgstr "Nå <a href=\"{{wall_url_user}}\">følger du</a> oppdateringer om <a href=\"{{successful_requests_url}}\">vellykkede henvendelser</a>." - -msgid "You can <strong>complain</strong> by" -msgstr "Du kan <strong>protestere</strong> ved å" - -msgid "You can change the requests and users you are following on <a href=\"{{profile_url}}\">your profile page</a>." -msgstr "Du kan endre hvilke henvendelser og brukere du følger på <a href=\"{{profile_url}}\">din profilside</a>." - -msgid "You can get this page in computer-readable format as part of the main JSON\\npage for the request. See the <a href=\"{{api_path}}\">API documentation</a>." -msgstr "Du kan få tak i denne siden på maskinlesbart format som del av\\nhoved-JSON-siden for henvendelsen. Se <a href=\"{{api_path}}\">API-dokumentasjonen</a>." - -msgid "You can only request information about the environment from this authority." -msgstr "Du kan kun spørre om miljøinformasjon fra denne myndigheten." - -msgid "You have a new response to the {{law_used_full}} request " -msgstr "Du har et nytt svar til {{law_used_full}} request " - -msgid "You have found a bug. Please <a href=\"{{contact_url}}\">contact us</a> to tell us about the problem" -msgstr "Du har funnet en feil. Vennligst <a href=\"{{contact_url}}\">kontakt oss</a> for å fortelle oss om problemet" - -msgid "You have hit the rate limit on new requests. Users are ordinarily limited to {{max_requests_per_user_per_day}} requests in any rolling 24-hour period. You will be able to make another request in {{can_make_another_request}}." -msgstr "Du har truffet grensen for antall nye henvendelser. Brukere er ordinært begrenset til {{max_requests_per_user_per_day}} henvendelser i en 24-timers periode. Du kan gjøre en ny henvendelse {{can_make_another_request}}." - -msgid "You have made no Freedom of Information requests using this site." -msgstr "Du har ikke laget noen innsynshenvendelser med denne tjenesten." - -msgid "You have now changed the text about you on your profile." -msgstr "Du har nå endret teksten om deg på din profil." - -msgid "You have now changed your email address used on {{site_name}}" -msgstr "Du har nå endret e-øost adressen brukt på {{site_name}}" - -msgid "You just tried to sign up to {{site_name}}, when you\\nalready have an account. Your name and password have been\\nleft as they previously were.\\n\\nPlease click on the link below." -msgstr "Du forsøkte å registrere deg på {{site_name}}, når du allerede\\nhar en konto. Ditt navn og passord har ikke blitt endret.\\n\\nVennligst klikk på lenken nedenfor." - -msgid "You know what caused the error, and can <strong>suggest a solution</strong>, such as a working email address." -msgstr "Du vet hva som forårsaket feilen, og kan <strong>foreslå en løsning</strong>, som en fungerende e-post adresse." - -msgid "You may <strong>include attachments</strong>. If you would like to attach a\\n file too large for email, use the form below." -msgstr "Du kan velge å <strong>legge med vedlegg</strong>. Om du vil legge med en\\nfil som er for stor for e-post, kan du bruke skjema under." - -msgid "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:" -msgstr "Det kan hende du finner en på deres nettsted, eller ved å ringe dem og spørre. Hvis du klarer å finne en, vær så snill og send den til oss:" - -msgid "You may be able to find\\n one on their website, or by phoning them up and asking. If you manage\\n to find one, then please <a href=\"{{url}}\">send it to us</a>." -msgstr "Du kan kanskje finne en på nettstedet deres, eller ved å ringe dem og spørre. Hvis du lykkes i å finne en, vær så snill <a href=\"{{url}}\">å send den til oss</a>." - -msgid "You may be able to find\\none on their website, or by phoning them up and asking. If you manage\\nto find one, then please <a href=\"{{help_url}}\">send it to us</a>." -msgstr "Du kan kanskje finne en på nettstedet deres, eller ved å ringe dem og spørre. Hvis du lukkes i å finne en, vær så snill <a href=\"{{help_url}}\">å send den til oss</a>." - -msgid "You need to be logged in to change the text about you on your profile." -msgstr "Du må være innlogget for å kunne endre teksten på din profil." - -msgid "You need to be logged in to change your profile photo." -msgstr "Du må være innlogget for å kunne profil-bildet." - -msgid "You need to be logged in to clear your profile photo." -msgstr "Du må være innlogget for å slett profil-bildet." - -msgid "You need to be logged in to edit your profile." -msgstr "Du må være innlogget for å endre profil-bildet." - -msgid "You need to be logged in to report a request for administrator attention" -msgstr "Du må være logget inn for å be om at en henvendelse ses på av adminstrasjonen" - -msgid "You previously submitted that exact follow up message for this request." -msgstr "Du har tidligere sendt inn en eksakt lik oppfølgingsbeskjed for denne begjæringen." - -msgid "You should have received a copy of the request by email, and you can respond\\n by <strong>simply replying</strong> to that email. For your convenience, here is the address:" -msgstr "Du skal ha fått tilsendt en kopi av innsynsbegjæringen på e-post, og du kan respondere\\n enkelt ved å <strong>svare på</strong> denne. For ordens skyld, her er e-postadressen: " - -msgid "You want to <strong>give your postal address</strong> to the authority in private." -msgstr "Du ønsker å <strong>gi din postadresse</strong> til myndigheten på en privat måte." - -msgid "You will be unable to make new requests, send follow ups, add annotations or\\nsend messages to other users. You may continue to view other requests, and set\\nup\\nemail alerts." -msgstr "Du vil ikke kunne lage nye henvendelser, sende oppfølginger, legge inn\\nkommentarer eller sende meldinger til andre brukere. Du kan fortsatt se andre\\nhenvendelser og sette opp e-postvarsling." - -msgid "You will no longer be emailed updates for those alerts" -msgstr "Du vil ikke lenger motta e-postoppdateringer for disse varslene" - -msgid "You will now be emailed updates about '{{link_to_authority}}', a public authority." -msgstr "Du vil nå motta e-postoppdateringer om offentlig myndighet '{{link_to_authority}}'." - -msgid "You will now be emailed updates about '{{link_to_request}}', a request." -msgstr "Du vil nå motta e-postoppdateringer om henvendelsen '{{link_to_request}}'." - -msgid "You will now be emailed updates about '{{link_to_user}}', a person." -msgstr "Du vil nå motta e-postoppdateringer om personen '{{link_to_user}}'." - -msgid "You will now be emailed updates about <a href=\"{{search_url}}\">this search</a>." -msgstr "Du vil nå motta e-postoppdateringer om <a href=\"{{search_url}}\">dette søket</a>." - -msgid "You will now be emailed updates about <a href=\"{{successful_requests_url}}\">successful requests</a>." -msgstr "Du vil nå motta e-postoppdateringer om <a href=\"{{successful_requests_url}}\">vellykkede henvendelser</a>." - -msgid "You will now be emailed updates about any <a href=\"{{new_requests_url}}\">new requests</a>." -msgstr "Du vil nå motta e-postoppdateringer om alle <a href=\"{{new_requests_url}}\">nye henvendelser</a>." - -msgid "You will only get an answer to your request if you follow up\\nwith the clarification." -msgstr "Du vil bare få svar på din henvendelse hvis du følger opp med klargjøringen." - -msgid "You will still be able to view it while logged in to the site. Please reply to this email if you would like to discuss this decision further." -msgstr "Du vil fortsatt være i stand til å se den når du er pålogget siden. Vennligst svar på denne e-posten om du har lyst til å diskutere denne avgjørelsen ytterligere." - -msgid "You're in. <a href=\"#\" id=\"send-request\">Continue sending your request</a>" -msgstr "Du er inne. <a href=\"#\" id=\"send-request\">Fortsett innsending av din henvendelse</a>" - -msgid "You're long overdue a response to your FOI request - " -msgstr "Du har ventet altfor lenge på svar på din henvendelse - " - -msgid "You're not following anything." -msgstr "Du følger ingenting." - -msgid "You've now cleared your profile photo" -msgstr "Du har nå slettet profil-bildet ditt" - -msgid "Your <strong>name will appear publicly</strong>\\n (<a href=\"{{why_url}}\">why?</a>)\\n on this website and in search engines. If you\\n are thinking of using a pseudonym, please\\n <a href=\"{{help_url}}\">read this first</a>." -msgstr "<strong>Navnet ditt vil vises offentlig</strong>\\n (<a href=\"{{why_url}}\">hvorfor?</a>)\\n på denne nettsiden og i søkemotorer. Om du\\n vurderer å bruke et pseudonym,\\n er det fint om du <a href=\"{{help_url}}\">leser dette først</a>." - -msgid "Your annotations" -msgstr "Dine merknader" - -msgid "Your batch request \"{{title}}\" has been sent" -msgstr "Din bunthenvendelse «{{title}}» er sendt" - -msgid "Your details, including your email address, have not been given to anyone." -msgstr "Din informasjon, inkludert din e-postadresse, har ikke blitt gitt til noen." - -msgid "Your e-mail:" -msgstr "Din e-post:" - -msgid "Your email doesn't look like a valid address" -msgstr "Din e-postadresse ser ikke gyldig ut" - -msgid "Your follow up has not been sent because this request has been stopped to prevent spam. Please <a href=\"{{url}}\">contact us</a> if you really want to send a follow up message." -msgstr "Din oppfølging har ikke blitt sendt på grunn av at denne henvendelsen har blitt stoppet for å hindre søppelpost. <a href=\"{{url}}\">Ta kontakt</a> hvis du virkelig ønsker å sende en oppfølgermelding." - -msgid "Your follow up message has been sent on its way." -msgstr "Oppfølgningsmesldingen din er sendt." - -msgid "Your internal review request has been sent on its way." -msgstr "Klagen din er sendt" - -msgid "Your message has been sent. Thank you for getting in touch! We'll get back to you soon." -msgstr "Meldingen din er sendt. Takk for at du tok kontakt! Du hører snart fra oss." - -msgid "Your message to {{recipient_user_name}} has been sent" -msgstr "Din beskjed til {{recipient_user_name}} har blitt sendt" - -msgid "Your message to {{recipient_user_name}} has been sent!" -msgstr "Din beskjed til {{recipient_user_name}} har blitt sendt!" - -msgid "Your message will appear in <strong>search engines</strong>" -msgstr "Meldingen din vil vises i <strong>søkemotorer</strong> som f.eks. Google." - -msgid "Your name and annotation will appear in <strong>search engines</strong>." -msgstr "Ditt navn og merknad vil dukke opp i <strong>søkemotorer</strong>." - -msgid "Your name, request and any responses will appear in <strong>search engines</strong>\\n (<a href=\"{{url}}\">details</a>)." -msgstr "Ditt navn, henvendelse og alle svar vil vises i <strong>søkemotorer</stronG>\\n (<a href=\"{{url}}\">detaljer</a>)." - -msgid "Your name:" -msgstr "Ditt navn:" - -msgid "Your original message is attached." -msgstr "Din opprinnelige beskjed er lagt ved." - -msgid "Your password has been changed." -msgstr "Passordet ditt er byttet" - -msgid "Your password:" -msgstr "Ditt passord:" - -msgid "Your photo will be shown in public <strong>on the Internet</strong>,\\n wherever you do something on {{site_name}}." -msgstr "Bildet ditt vil bli vist offentlig <strong>på Internettet</strong>,\\n uavhengig om du gjør noe på {{site_name}}." - -msgid "Your request '{{request}}' at {{url}} has been reviewed by moderators." -msgstr "Din henvendelse «{{request}}» på {{url}} har blitt sjekket av moderatorer." - -msgid "Your request on {{site_name}} hidden" -msgstr "Din henvendelse på {{site_name}} er skjult" - -msgid "Your request to add an authority has been sent. Thank you for getting in touch! We'll get back to you soon." -msgstr "Din henvendelse om å legge til en autoritet er sendt. Takk for at du tok kontakt! Vi svarer deg så snart som mulig." - -msgid "Your request to add {{public_body_name}} to {{site_name}}" -msgstr "Din henvendelse for å legge {{public_body_name}} til {{site_name}}" - -msgid "Your request to update the address for {{public_body_name}} has been sent. Thank you for getting in touch! We'll get back to you soon." -msgstr "Din henvendelse om å oppdatere adressen til {{public_body_name}} er sendt. Takk for at du tok kontakt. Vi vil snart komme tilbake til deg." - -msgid "Your request to update {{public_body_name}} on {{site_name}}" -msgstr "Din henvendelse om å oppdatere {{public_body_name}} på {{site_name}}" - -msgid "Your request was called {{info_request}}. Letting everyone know whether you got the information will help us keep tabs on" -msgstr "Din henvendelse ble kalt {{info_request}}. Ved å la alle vite hvorvidt du fikk informasjonen vil du hjelpe oss å holde rede på" - -msgid "Your request:" -msgstr "Henvendelsen:" - -msgid "Your response to an FOI request was not delivered" -msgstr "Ditt svar til en innsynsbegjæring ble ikke levert" - -msgid "Your response will <strong>appear on the Internet</strong>, <a href=\"{{url}}\">read why</a> and answers to other questions." -msgstr "Svaret ditt vil <strong>publiseres på Internettet<strong>, <a href=\"{{url}}\">les hvorfor</a>, og få svar på andre spørsmål." - -msgid "Your selected authorities" -msgstr "Dine valgte myndigheter" - -msgid "Your thoughts on what the {{site_name}} <strong>administrators</strong> should do about the request." -msgstr "Dine tanker rundt hva {{site_name}} <strong>administratorene</strong> burde gjøre med henvendelsen." - -msgid "Your {{count}} Freedom of Information request" -msgid_plural "Your {{count}} Freedom of Information requests" -msgstr[0] "Din {{count}} innsynshenvendelse" -msgstr[1] "Dine {{count}} innsynshenvendelser" - -msgid "Your {{count}} annotation" -msgid_plural "Your {{count}} annotations" -msgstr[0] "Din {{count}} merknad" -msgstr[1] "Dine {{count}} merknader" - -msgid "Your {{count}} batch requests" -msgid_plural "Your {{count}} batch requests" -msgstr[0] "Din {{count}} bunthenvendelse" -msgstr[1] "Dine {{count}} bunthenvendelser" - -msgid "Your {{site_name}} email alert" -msgstr "Ditt e-postvarsel fra {{site_name}}" - -msgid "Yours faithfully," -msgstr "Med vennlig hilsen," - -msgid "Yours sincerely," -msgstr "Med vennlig hilsen," - -msgid "Yours," -msgstr "Med vennlig hilsen," - -msgid "[Authority URL will be inserted here]" -msgstr "[Myndighets-URL vil bli satt inn her]" - -msgid "[FOI #{{request}} email]" -msgstr "" - -msgid "[{{public_body}} request email]" -msgstr "[{{public_body}} henvendelses-e-post-adresse]" - -msgid "[{{site_name}} contact email]" -msgstr "[{{site_name}} e-post-kontakt]" - -msgid "\\n\\n[ {{site_name}} note: The above text was badly encoded, and has had strange characters removed. ]" -msgstr "\\n\\n[ {{site_name}} NB: Teksten over var feil enkodet, og har fått rare tegn fjernet. ]" - -msgid "a one line summary of the information you are requesting, \\n\t\t\te.g." -msgstr "en linjes oppsummering av informasjonen du spør om, \\n\t\t\tf.eks.." - -msgid "admin" -msgstr "administrator" - -msgid "alaveteli_foi:The software that runs {{site_name}}" -msgstr "alaveteli_foi:Programvaren som kjører {{site_name}}" - -msgid "all requests" -msgstr "alle henvendelser" - -msgid "all requests or comments" -msgstr "alle henvendelser eller kommentarer" - -msgid "all requests or comments matching text '{{query}}'" -msgstr "alle henvendelser eller kommentarer som stemmer med teksten «{{query}}»" - -msgid "also called {{public_body_short_name}}" -msgstr "også kalt {{public_body_short_name}}" - -msgid "an anonymous user" -msgstr "en anonym bruker" - -msgid "and" -msgstr "og" - -msgid "and update the status accordingly. Perhaps <strong>you</strong> might like to help out by doing that?" -msgstr "og oppdater status tilsvarende. Kanskje <strong>du</strong> vil like å hjelpe til med det?" - -msgid "and update the status." -msgstr "og oppdater statusen" - -msgid "and we'll suggest <strong>what to do next</strong>" -msgstr "så skal vi foreslå hva du <strong>kan gjøre videre</strong>" - -msgid "anything matching text '{{query}}'" -msgstr "alt som treffer for teksten «{{query}}»" - -msgid "are long overdue." -msgstr "er svært forsinket." - -msgid "at" -msgstr "ved" - -msgid "authorities" -msgstr "myndigheter" - -msgid "beginning with ‘{{first_letter}}’" -msgstr "som begynner med '{{first_letter}}'" - -msgid "but followupable" -msgstr "men oppfølgbar" - -msgid "by" -msgstr "av" - -msgid "by <strong>{{date}}</strong>" -msgstr "før <strong>{{date}}</strong>" - -msgid "by {{user_link_absolute}}" -msgstr "av {{user_link_absolute}}" - -msgid "comments" -msgstr "kommentarer" - -msgid "containing your postal address, and asking them to reply to this request.\\n Or you could phone them." -msgstr "inneholder din post-adresse, og spør de om å svare på denne henvendelsen.\\n Eller du kan ringe de." - -msgid "details" -msgstr "detaljer" - -msgid "display_status only works for incoming and outgoing messages right now" -msgstr "vis status virker foreløpig kun for innkommende og utgående meldinger" - -msgid "during term time" -msgstr "" - -msgid "e.g. Ministry of Defence" -msgstr "f.eks. Forsvarsdepartementet" - -msgid "edit text about you" -msgstr "rediger tekst om deg" - -msgid "even during holidays" -msgstr "t.o.m. under helligdager" - -msgid "everything" -msgstr "alt" - -msgid "external" -msgstr "ekstern" - -msgid "has reported an" -msgstr "har rapportert en" - -msgid "have delayed." -msgstr "har blitt forsinket." - -msgid "hide quoted sections" -msgstr "fjern sitert seksjon" - -msgid "in term time" -msgstr "" - -msgid "in the category ‘{{category_name}}’" -msgstr "i kategorien '{{category_name}}'" - -msgid "internal error" -msgstr "intern feil" - -msgid "internal reviews" -msgstr "klager" - -msgid "is <strong>waiting for your clarification</strong>." -msgstr "<strong>venter på dine avklaringer</strong>" - -msgid "just to see how it works" -msgstr "bare for å se hvordan det fungerer" - -msgid "left an annotation" -msgstr "la igjen en merknad" - -msgid "made." -msgstr "laget." - -msgid "matching the tag ‘{{tag_name}}’" -msgstr "treffer taggen '{{tag_name}}'" - -msgid "messages from authorities" -msgstr "meldinger fra myndigheter" - -msgid "messages from users" -msgstr "meldinger fra brukere" - -msgid "move..." -msgstr "flytt..." - -msgid "new requests" -msgstr "nye henvendelser" - -msgid "no later than" -msgstr "ikke senere enn" - -msgid "no longer exists. If you are trying to make\\n From the request page, try replying to a particular message, rather than sending\\n a general followup. If you need to make a general followup, and know\\n an email which will go to the right place, please <a href=\"{{url}}\">send it to us</a>." -msgstr "" - -msgid "normally" -msgstr "vanligvis" - -msgid "not requestable due to: {{reason}}" -msgstr "kan ikke be om fordi: {{reason}}" - -msgid "please sign in as " -msgstr "logg deg inn som " - -msgid "requesting an internal review" -msgstr "be om en intern gjennomgang" - -msgid "requests" -msgstr "henvendelser" - -msgid "requests which are successful" -msgstr "vellykkede henvendelser" - -msgid "requests which are successful matching text '{{query}}'" -msgstr "vellykkede henvendelser som stemmer med teksten «{{query}}»" - -msgid "response as needing administrator attention. Take a look, and reply to this\\nemail to let them know what you are going to do about it." -msgstr "respons som trenger oppmerksomhet fra en administrator. Ta en titt, og svar\\npå denne eposten for å la dem vite hva du kommer til å gjøre med det." - -msgid "send a follow up message" -msgstr "send en oppfølgningsmelding" - -msgid "set to <strong>blank</strong> (empty string) if can't find an address; these emails are <strong>public</strong> as anyone can view with a CAPTCHA" -msgstr "sett til <strong>blank</strong> (tom streng) hvis ingen adresse kunne finnes. Disse e-postadressene er <strong>offentlige</strong> da enhver kan se dem ved hjelp av en CAPTCHA" - -msgid "show quoted sections" -msgstr "vis sitert seksjon" - -msgid "sign in" -msgstr "logg inn" - -msgid "simple_date_format" -msgstr "simple_date_format" - -msgid "successful requests" -msgstr "vellykkede henvendelser" - -msgid "that you made to" -msgstr "som du laget til" - -msgid "the main FOI contact address for {{public_body}}" -msgstr "postmottaket hos {{public_body}}" - -#. This phrase completes the following sentences: -#. Request an internal review from... -#. Send a public follow up message to... -#. Send a public reply to... -#. Don't want to address your message to... ? -msgid "the main FOI contact at {{public_body}}" -msgstr "postmottaket hos {{public_body}}" - -msgid "the requester" -msgstr "henvenderen" - -msgid "the {{site_name}} team" -msgstr "{{site_name}}-gjengen" - -msgid "to read" -msgstr "skal lese lese" - -msgid "to send a follow up message." -msgstr "for å sende en oppfølgningsmelding." - -msgid "to {{public_body}}" -msgstr "til {{public_body}}" - -msgid "type your search term here" -msgstr "skriv inn søketerm her" - -msgid "unknown reason " -msgstr "ukjent grunn " - -msgid "unknown status " -msgstr "ukjent status " - -msgid "unresolved requests" -msgstr "uavklarte henvendelser" - -msgid "unsubscribe" -msgstr "meld deg av" - -msgid "unsubscribe all" -msgstr "meld deg av alle" - -msgid "unsuccessful requests" -msgstr "mislykkede henvendelser" - -msgid "useful information." -msgstr "nyttig informasjon." - -msgid "users" -msgstr "brukere" - -msgid "what's that?" -msgstr "hva er det?" - -msgid "{{count}} FOI requests found" -msgstr "{{count}} innsynsbegjæringer funnet" - -msgid "{{count}} Freedom of Information request to {{public_body_name}}" -msgid_plural "{{count}} Freedom of Information requests to {{public_body_name}}" -msgstr[0] "{{count}} innsynshenvendelse til {{public_body_name}}" -msgstr[1] "{{count}} innsynshenvendelser til {{public_body_name}}" - -msgid "{{count}} person is following this authority" -msgid_plural "{{count}} people are following this authority" -msgstr[0] "{{count}} person følger denne myndigheten" -msgstr[1] "{{count}} personer følger denne myndigheten" - -msgid "{{count}} request" -msgid_plural "{{count}} requests" -msgstr[0] "{{count}} henvendelse" -msgstr[1] "{{count}} henvendelser" - -msgid "{{count}} request made." -msgid_plural "{{count}} requests made." -msgstr[0] "{{count}} henvendelse laget." -msgstr[1] "{{count}} henvendelser laget." - -msgid "{{existing_request_user}} already\\n created the same request on {{date}}. You can either view the <a href=\"{{existing_request}}\">existing request</a>,\\n or edit the details below to make a new but similar request." -msgstr "" - -msgid "{{foi_law}} requests to '{{public_body_name}}'" -msgstr "{{foi_law}} henvendelser til '{{public_body_name}}'" - -msgid "{{info_request_user_name}} only:" -msgstr "Bare {{info_request_user_name}} (henvender):" - -msgid "{{law_used_full}} request - {{title}}" -msgstr "{{law_used_full}} - {{title}}" - -msgid "{{law_used}} requests at {{public_body}}" -msgstr "{{law_used}} til {{public_body}}" - -msgid "{{length_of_time}} ago" -msgstr "for {{length_of_time}} siden" - -msgid "{{number_of_comments}} comments" -msgstr "{{number_of_comments}} kommentarer" - -msgid "{{public_body_link}} answered a request about" -msgstr "{{public_body_link}} svarte på en henvendelse om" - -msgid "{{public_body_link}} was sent a request about" -msgstr "{{public_body_link}} fikk tilsendt en henvendelse om" - -msgid "{{public_body_name}} only:" -msgstr "Bare {{public_body_name}} (myndighet):" - -msgid "{{public_body}} has asked you to explain part of your {{law_used}} request." -msgstr "{{public_body}} has spurt deg om å forklare deler av {{law_used}} henvendelsen" - -msgid "{{public_body}} sent a response to {{user_name}}" -msgstr "{{public_body}} sendte et svar til {{user_name}}" - -msgid "{{reason}}, please sign in or make a new account." -msgstr "{{reason}}, vennligst logg inn eller lag en ny konto." - -msgid "{{search_results}} matching '{{query}}'" -msgstr "{{search_results}} traff '{{query}}" - -msgid "{{site_name}} blog and tweets" -msgstr "{{site_name}} blogg og tveets" - -msgid "{{site_name}} covers requests to {{number_of_authorities}} authorities, including:" -msgstr "{{site_name}} dekker henvendelser til {{number_of_authorities}} myndigheter, inkludert:" - -msgid "{{site_name}} sends new requests to <strong>{{request_email}}</strong> for this authority." -msgstr "{{site_name}} sender nye henvendelser til <strong>{{request_email}}</strong> for denne myndigheten." - -msgid "{{site_name}} users have made {{number_of_requests}} requests, including:" -msgstr "{{site_name}}-brukere har skrevet {{number_of_requests}} henvendelser, inkludert:" - -msgid "{{thing_changed}} was changed from <code>{{from_value}}</code> to <code>{{to_value}}</code>" -msgstr "{{thing_changed}} ble forandret fra <code>{{from_value}}</code> til <code>{{to_value}}</code>" - -msgid "{{title}} - a Freedom of Information request to {{public_body}}" -msgstr "{{title}} - en innsynsbegjæring etter Offentlighetsloven til {{public_body}}" - -msgid "{{title}} - a batch request" -msgstr "{{title}} - en bunthenvendelse" - -msgid "{{user_name}} (Account suspended)" -msgstr "{{user_name}} (Konto er stengt)" - -msgid "{{user_name}} - Freedom of Information requests" -msgstr "{{user_name}} - Innsynsbegjæringer" - -msgid "{{user_name}} - user profile" -msgstr "{{user_name}} - brukerprofil" - -msgid "{{user_name}} added an annotation" -msgstr "{{user_name}} la til en merknad" - -msgid "{{user_name}} has annotated your {{law_used_short}} \\nrequest. Follow this link to see what they wrote." -msgstr "{{user_name}} har skrevet en merknad på din {{law_used_short}} \\nhenvendelse. Følg lenken nedenfor for å se hva de skrev." - -msgid "{{user_name}} has used {{site_name}} to send you the message below." -msgstr "{{user_name}} har brukt {{site_name}} for å sende deg meldingen nedenfor." - -msgid "{{user_name}} sent a follow up message to {{public_body}}" -msgstr "{{user_name}} sendte en oppfølgningsmelding til {{public_body}}" - -msgid "{{user_name}} sent a request to {{public_body}}" -msgstr "{{user_name}} sendte en innsynshenvendelse til {{public_body}}" - -msgid "{{user_name}} would like a new authority added to {{site_name}}" -msgstr "{{user_name}} ønsker en ny autoritet lagt til {{site_name}}" - -msgid "{{user_name}} would like the email address for {{public_body_name}} to be updated" -msgstr "{{user_name}} ønsker at e0postadressen til {{public_body_name}} skal oppdateres" - -msgid "{{username}} left an annotation:" -msgstr "{{username}} la igjen en merknad:" - -msgid "{{user}} ({{user_admin_link}}) made this {{law_used_full}} request (<a href=\"{{request_admin_url}}\">admin</a>) to {{public_body_link}} (<a href=\"{{public_body_admin_url}}\">admin</a>)" -msgstr "{{user}} ({{user_admin_link}}) laget denne {{law_used_full}} henvendelsen (<a href=\"{{request_admin_url}}\">admin</a>) to {{public_body_link}} (<a href=\"{{public_body_admin_url}}\">admin</a>)" - -msgid "{{user}} made this {{law_used_full}} request" -msgstr "{{user}} sendte denne henvendelsen om {{law_used_full}}" diff --git a/spec/controllers/admin_censor_rule_controller_spec.rb b/spec/controllers/admin_censor_rule_controller_spec.rb index 4df56a92b..68eaecd6a 100644 --- a/spec/controllers/admin_censor_rule_controller_spec.rb +++ b/spec/controllers/admin_censor_rule_controller_spec.rb @@ -5,76 +5,68 @@ describe AdminCensorRuleController do describe 'GET new' do - it 'returns a successful response' do - get :new - expect(response).to be_success - end + context 'request_id param' do - it 'initializes a new censor rule' do - get :new - expect(assigns[:censor_rule]).to be_new_record - end + before do + @info_request = FactoryGirl.create(:info_request) + get :new, :request_id => @info_request.id, :name_prefix => 'request_' + end - it 'renders the correct template' do - get :new - expect(response).to render_template('new') - end + it 'returns a successful response' do + expect(response).to be_success + end - it 'sets the URL for the form to POST to' do - get :new - expect(assigns[:form_url]).to eq(admin_rule_create_path) - end + it 'initializes a new censor rule' do + expect(assigns[:censor_rule]).to be_new_record + end - context 'info_request_id param' do + it 'renders the correct template' do + expect(response).to render_template('new') + end - it 'finds an info request if the info_request_id param is supplied' do - info_request = FactoryGirl.create(:info_request) - get :new, :info_request_id => info_request.id - expect(assigns[:info_request]).to eq(info_request) + it 'finds an info request if the request_id param is supplied' do + expect(assigns[:info_request]).to eq(@info_request) end it 'associates the info request with the new censor rule' do - info_request = FactoryGirl.create(:info_request) - get :new, :info_request_id => info_request.id - expect(assigns[:censor_rule].info_request).to eq(info_request) + expect(assigns[:censor_rule].info_request).to eq(@info_request) end it 'sets the URL for the form to POST to' do - info_request = FactoryGirl.create(:info_request) - get :new, :info_request_id => info_request.id - expect(assigns[:form_url]).to eq(admin_info_request_censor_rules_path(info_request)) - end - - it 'does not find an info request if no info_request_id param is supplied' do - get :new - expect(assigns[:info_request]).to be_nil + expect(assigns[:form_url]).to eq(admin_request_censor_rules_path(@info_request)) end end context 'user_id param' do + before do + @user = FactoryGirl.create(:user) + get :new, :user_id => @user.id, :name_prefix => 'user_' + end + + it 'returns a successful response' do + expect(response).to be_success + end + + it 'initializes a new censor rule' do + expect(assigns[:censor_rule]).to be_new_record + end + + it 'renders the correct template' do + expect(response).to render_template('new') + end + it 'finds a user if the user_id param is supplied' do - user = FactoryGirl.create(:user) - get :new, :user_id => user.id - expect(assigns[:censor_user]).to eq(user) + expect(assigns[:censor_user]).to eq(@user) end it 'associates the user with the new censor rule' do - user = FactoryGirl.create(:user) - get :new, :user_id => user.id - expect(assigns[:censor_rule].user).to eq(user) + expect(assigns[:censor_rule].user).to eq(@user) end it 'sets the URL for the form to POST to' do - user = FactoryGirl.create(:user) - get :new, :user_id => user.id - expect(assigns[:form_url]).to eq(admin_user_censor_rules_path(user)) - end - - it 'does not find a user if no user_id param is supplied' do - get :new - expect(assigns[:censor_user]).to be_nil + expect(assigns[:form_url]).to eq(admin_user_censor_rules_path(@user)) end end @@ -83,256 +75,292 @@ describe AdminCensorRuleController do describe 'POST create' do - before(:each) do - @censor_rule_params = FactoryGirl.build(:global_censor_rule).serializable_hash - # last_edit_editor gets set in the controller - @censor_rule_params.delete(:last_edit_editor) - end - - it 'sets the last_edit_editor to the current admin' do - post :create, :censor_rule => @censor_rule_params - expect(assigns[:censor_rule].last_edit_editor).to eq('*unknown*') - end + context 'request_id param' do - it 'sets the URL for the form to POST to' do - post :create, :censor_rule => @censor_rule_params - expect(assigns[:form_url]).to eq(admin_rule_create_path) - end + before(:each) do + @censor_rule_params = FactoryGirl.build(:info_request_censor_rule).serializable_hash + # last_edit_editor gets set in the controller + @censor_rule_params.delete(:last_edit_editor) + @info_request = FactoryGirl.create(:info_request) + post :create, :request_id => @info_request.id, + :censor_rule => @censor_rule_params, + :name_prefix => 'request_' + end - context 'info_request_id param' do + it 'sets the last_edit_editor to the current admin' do + expect(assigns[:censor_rule].last_edit_editor).to eq('*unknown*') + end - it 'finds an info request if the info_request_id param is supplied' do - info_request = FactoryGirl.create(:info_request) - post :create, :info_request_id => info_request.id, - :censor_rule => @censor_rule_params - expect(assigns[:info_request]).to eq(info_request) + it 'finds an info request if the request_id param is supplied' do + expect(assigns[:info_request]).to eq(@info_request) end it 'associates the info request with the new censor rule' do - info_request = FactoryGirl.create(:info_request) - post :create, :info_request_id => info_request.id, - :censor_rule => @censor_rule_params - expect(assigns[:censor_rule].info_request).to eq(info_request) + expect(assigns[:censor_rule].info_request).to eq(@info_request) end it 'sets the URL for the form to POST to' do - info_request = FactoryGirl.create(:info_request) - post :create, :info_request_id => info_request.id, - :censor_rule => @censor_rule_params - expect(assigns[:form_url]).to eq(admin_info_request_censor_rules_path(info_request)) + expect(assigns[:form_url]).to eq(admin_request_censor_rules_path(@info_request)) end - it 'does not find an info request if no info_request_id param is supplied' do - post :create, :censor_rule => @censor_rule_params - expect(assigns[:info_request]).to be_nil - end + context 'successfully saving the censor rule' do - end + it 'persists the censor rule' do + post :create, :censor_rule => @censor_rule_params, + :request_id => @info_request.id, + :name_prefix => 'request_' + expect(assigns[:censor_rule]).to be_persisted + end - context 'user_id param' do + it 'confirms the censor rule is created' do + post :create, :censor_rule => @censor_rule_params, + :request_id => @info_request.id, + :name_prefix => 'request_' + msg = 'CensorRule was successfully created.' + expect(flash[:notice]).to eq(msg) + end - it 'finds a user if the user_id param is supplied' do - user = FactoryGirl.create(:user) - post :create, :user_id => user.id, - :censor_rule => @censor_rule_params - expect(assigns[:censor_user]).to eq(user) - end + it 'purges the cache for the info request' do + @controller.should_receive(:expire_for_request). + with(@info_request) - it 'associates the user with the new censor rule' do - user = FactoryGirl.create(:user) - post :create, :user_id => user.id, - :censor_rule => @censor_rule_params - expect(assigns[:censor_rule].user).to eq(user) - end + post :create, :censor_rule => @censor_rule_params, + :request_id => @info_request.id, + :name_prefix => 'request_' + end - it 'sets the URL for the form to POST to' do - user = FactoryGirl.create(:user) - post :create, :user_id => user.id, - :censor_rule => @censor_rule_params - expect(assigns[:form_url]).to eq(admin_user_censor_rules_path(user)) + it 'redirects to the associated info request' do + post :create, :censor_rule => @censor_rule_params, + :request_id => @info_request.id, + :name_prefix => 'request_' + expect(response).to redirect_to( + admin_request_path(assigns[:censor_rule].info_request) + ) + end end - it 'does not find a user if no user_id param is supplied' do - post :create, :censor_rule => @censor_rule_params - expect(assigns[:censor_user]).to be_nil - end + context 'unsuccessfully saving the censor rule' do + + before(:each) do + CensorRule.any_instance.stub(:save).and_return(false) + end + + it 'does not persist the censor rule' do + post :create, :censor_rule => @censor_rule_params, + :request_id => @info_request.id, + :name_prefix => 'request_' + expect(assigns[:censor_rule]).to be_new_record + end + it 'renders the form' do + post :create, :censor_rule => @censor_rule_params, + :request_id => @info_request.id, + :name_prefix => 'request_' + expect(response).to render_template('new') + end + + end end - context 'successfully saving the censor rule' do + context 'user_id param' do before(:each) do - CensorRule.any_instance.stub(:save).and_return(true) + @censor_rule_params = FactoryGirl.build(:user_censor_rule).serializable_hash + # last_edit_editor gets set in the controller + @censor_rule_params.delete(:last_edit_editor) + @user = FactoryGirl.create(:user) + post :create, :user_id => @user.id, + :censor_rule => @censor_rule_params, + :name_prefix => 'user_' end - it 'persists the censor rule' do - pending("This raises an internal error in most cases") - post :create, :censor_rule => @censor_rule_params - expect(assigns[:censor_rule]).to be_persisted + it 'sets the last_edit_editor to the current admin' do + expect(assigns[:censor_rule].last_edit_editor).to eq('*unknown*') end - it 'confirms the censor rule is created' do - pending("This raises an internal error in most cases") - post :create, :censor_rule => @censor_rule_params - msg = 'CensorRule was successfully created.' - expect(flash[:notice]).to eq(msg) + it 'finds a user if the user_id param is supplied' do + expect(assigns[:censor_user]).to eq(@user) end - it 'raises an error after creating the rule' do - expect { - post :create, :censor_rule => @censor_rule_params - }.to raise_error 'internal error' + it 'associates the user with the new censor rule' do + expect(assigns[:censor_rule].user).to eq(@user) end - context 'a CensorRule with an associated InfoRequest' do + it 'sets the URL for the form to POST to' do + expect(assigns[:form_url]).to eq(admin_user_censor_rules_path(@user)) + end - before(:each) do - @censor_rule_params = FactoryGirl.build(:info_request_censor_rule).serializable_hash - # last_edit_editor gets set in the controller - @censor_rule_params.delete(:last_edit_editor) - end + context 'successfully saving the censor rule' do - it 'purges the cache for the info request' do + it 'purges the cache for the info request' do censor_rule = CensorRule.new(@censor_rule_params) - @controller.should_receive(:expire_for_request). - with(censor_rule.info_request) + @controller.should_receive(:expire_requests_for_user). + with(@user) - post :create, :censor_rule => @censor_rule_params + post :create, :censor_rule => @censor_rule_params, + :user_id => @user.id, + :name_prefix => 'user_' end it 'redirects to the associated info request' do - post :create, :censor_rule => @censor_rule_params + post :create, :censor_rule => @censor_rule_params, + :user_id => @user.id, + :name_prefix => 'user_' expect(response).to redirect_to( - admin_request_show_path(assigns[:censor_rule].info_request) + admin_user_path(assigns[:censor_rule].user) ) end end - context 'a CensorRule with an associated User' do + context 'unsuccessfully saving the censor rule' do before(:each) do - @censor_rule_params = FactoryGirl.build(:user_censor_rule).serializable_hash - # last_edit_editor gets set in the controller - @censor_rule_params.delete(:last_edit_editor) + CensorRule.any_instance.stub(:save).and_return(false) end - it 'purges the cache for the info request' do - censor_rule = CensorRule.new(@censor_rule_params) - @controller.should_receive(:expire_requests_for_user). - with(censor_rule.user) - - post :create, :censor_rule => @censor_rule_params + it 'does not persist the censor rule' do + post :create, :censor_rule => @censor_rule_params, + :user_id => @user.id, + :name_prefix => 'user_' + expect(assigns[:censor_rule]).to be_new_record end - it 'redirects to the associated info request' do - post :create, :censor_rule => @censor_rule_params - expect(response).to redirect_to( - admin_user_show_path(assigns[:censor_rule].user) - ) + it 'renders the form' do + post :create, :censor_rule => @censor_rule_params, + :user_id => @user.id, + :name_prefix => 'user_' + expect(response).to render_template('new') end end end - context 'unsuccessfully saving the censor rule' do + end + + describe 'GET edit' do + + context 'a CensorRule with an associated InfoRequest' do before(:each) do - CensorRule.any_instance.stub(:save).and_return(false) + @censor_rule = FactoryGirl.create(:info_request_censor_rule) end - it 'does not persist the censor rule' do - post :create, :censor_rule => @censor_rule_params - expect(assigns[:censor_rule]).to be_new_record + it 'returns a successful response' do + get :edit, :id => @censor_rule.id + expect(response).to be_success end - it 'renders the form' do - post :create, :censor_rule => @censor_rule_params - expect(response).to render_template('new') + it 'renders the correct template' do + get :edit, :id => @censor_rule.id + expect(response).to render_template('edit') + end + + it 'finds the correct censor rule to edit' do + get :edit, :id => @censor_rule.id + expect(assigns[:censor_rule]).to eq(@censor_rule) end end - end + context 'a CensorRule with an associated User' do - describe 'GET edit' do + before(:each) do + @censor_rule = FactoryGirl.create(:user_censor_rule) + end - before(:each) do - @censor_rule = FactoryGirl.create(:global_censor_rule) - end + it 'returns a successful response' do + get :edit, :id => @censor_rule.id + expect(response).to be_success + end - it 'returns a successful response' do - get :edit, :id => @censor_rule.id - expect(response).to be_success - end + it 'renders the correct template' do + get :edit, :id => @censor_rule.id + expect(response).to render_template('edit') + end + + it 'finds the correct censor rule to edit' do + get :edit, :id => @censor_rule.id + expect(assigns[:censor_rule]).to eq(@censor_rule) + end - it 'renders the correct template' do - get :edit, :id => @censor_rule.id - expect(response).to render_template('edit') end - it 'finds the correct censor rule to edit' do - get :edit, :id => @censor_rule.id - expect(assigns[:censor_rule]).to eq(@censor_rule) + context 'when editing a global rule' do + + before(:each) do + @censor_rule = FactoryGirl.create(:global_censor_rule) + end + + it 'shows an error notice' do + get :edit, :id => @censor_rule.id + flash[:notice].should == 'Only user and request censor rules can be edited' + end + + it 'redirects to the admin index' do + get :edit, :id => @censor_rule.id + expect(response).to redirect_to(admin_general_index_path) + end + end end describe 'PUT update' do - before(:each) do - @censor_rule = FactoryGirl.create(:global_censor_rule) - end + context 'a global CensorRule' do - it 'finds the correct censor rule to edit' do - put :update, :id => @censor_rule.id, - :censor_rule => { :text => 'different text' } + before(:each) do + @censor_rule = FactoryGirl.create(:global_censor_rule) + end - expect(assigns[:censor_rule]).to eq(@censor_rule) - end + it 'shows an error notice' do + get :edit, :id => @censor_rule.id + flash[:notice].should == 'Only user and request censor rules can be edited' + end - it 'sets the last_edit_editor to the current admin' do - put :update, :id => @censor_rule.id, - :censor_rule => { :text => 'different text' } + it 'redirects to the admin index' do + get :edit, :id => @censor_rule.id + expect(response).to redirect_to(admin_general_index_path) + end - expect(assigns[:censor_rule].last_edit_editor).to eq('*unknown*') end - context 'successfully saving the censor rule' do + context 'a CensorRule with an associated InfoRequest' do before(:each) do - CensorRule.any_instance.stub(:save).and_return(true) + @censor_rule = FactoryGirl.create(:info_request_censor_rule) end - it 'updates the censor rule' do - pending("This raises an internal error in most cases") + it 'finds the correct censor rule to edit' do put :update, :id => @censor_rule.id, :censor_rule => { :text => 'different text' } - @censor_rule.reload - expect(@censor_rule.text).to eq('different text') + + expect(assigns[:censor_rule]).to eq(@censor_rule) end - it 'confirms the censor rule is updated' do - pending("This raises an internal error in most cases") + it 'sets the last_edit_editor to the current admin' do put :update, :id => @censor_rule.id, :censor_rule => { :text => 'different text' } - msg = 'CensorRule was successfully updated.' - expect(flash[:notice]).to eq(msg) + expect(assigns[:censor_rule].last_edit_editor).to eq('*unknown*') end - it 'raises an error after updating the rule' do - expect { + context 'successfully saving the censor rule' do + + it 'updates the censor rule' do put :update, :id => @censor_rule.id, :censor_rule => { :text => 'different text' } - }.to raise_error 'internal error' - end - - context 'a CensorRule with an associated InfoRequest' do + @censor_rule.reload + expect(@censor_rule.text).to eq('different text') + end - before(:each) do - @censor_rule = FactoryGirl.create(:info_request_censor_rule) + it 'confirms the censor rule is updated' do + put :update, :id => @censor_rule.id, + :censor_rule => { :text => 'different text' } + msg = 'CensorRule was successfully updated.' + expect(flash[:notice]).to eq(msg) end it 'purges the cache for the info request' do @@ -348,87 +376,137 @@ describe AdminCensorRuleController do :censor_rule => { :text => 'different text' } expect(response).to redirect_to( - admin_request_show_path(assigns[:censor_rule].info_request) + admin_request_path(assigns[:censor_rule].info_request) ) end end - context 'a CensorRule with an associated User' do + context 'unsuccessfully saving the censor rule' do before(:each) do - @censor_rule = FactoryGirl.create(:user_censor_rule) + CensorRule.any_instance.stub(:save).and_return(false) end - it 'purges the cache for the info request' do - @controller.should_receive(:expire_requests_for_user). - with(@censor_rule.user) - + it 'does not update the censor rule' do put :update, :id => @censor_rule.id, :censor_rule => { :text => 'different text' } + @censor_rule.reload + expect(@censor_rule.text).to eq('some text to redact') end - it 'redirects to the associated info request' do + it 'renders the form' do put :update, :id => @censor_rule.id, :censor_rule => { :text => 'different text' } - expect(response).to redirect_to( - admin_user_show_path(assigns[:censor_rule].user) - ) + expect(response).to render_template('edit') end - end + end + end - context 'unsuccessfully saving the censor rule' do + context 'a CensorRule with an associated User' do before(:each) do - CensorRule.any_instance.stub(:save).and_return(false) + @censor_rule = FactoryGirl.create(:user_censor_rule) end - it 'does not update the censor rule' do + it 'finds the correct censor rule to edit' do put :update, :id => @censor_rule.id, :censor_rule => { :text => 'different text' } - @censor_rule.reload - expect(@censor_rule.text).to eq('some text to redact') + + expect(assigns[:censor_rule]).to eq(@censor_rule) end - it 'renders the form' do + it 'sets the last_edit_editor to the current admin' do put :update, :id => @censor_rule.id, :censor_rule => { :text => 'different text' } - expect(response).to render_template('edit') + expect(assigns[:censor_rule].last_edit_editor).to eq('*unknown*') + + end + + + context 'successfully saving the censor rule' do + + it 'updates the censor rule' do + put :update, :id => @censor_rule.id, + :censor_rule => { :text => 'different text' } + @censor_rule.reload + expect(@censor_rule.text).to eq('different text') + end + + it 'confirms the censor rule is updated' do + put :update, :id => @censor_rule.id, + :censor_rule => { :text => 'different text' } + msg = 'CensorRule was successfully updated.' + expect(flash[:notice]).to eq(msg) + end + + it 'purges the cache for the info request' do + @controller.should_receive(:expire_requests_for_user). + with(@censor_rule.user) + + put :update, :id => @censor_rule.id, + :censor_rule => { :text => 'different text' } + end + + it 'redirects to the associated info request' do + put :update, :id => @censor_rule.id, + :censor_rule => { :text => 'different text' } + + expect(response).to redirect_to( + admin_user_path(assigns[:censor_rule].user) + ) + end end + context 'unsuccessfully saving the censor rule' do + + before(:each) do + CensorRule.any_instance.stub(:save).and_return(false) + end + + it 'does not update the censor rule' do + put :update, :id => @censor_rule.id, + :censor_rule => { :text => 'different text' } + @censor_rule.reload + expect(@censor_rule.text).to eq('some text to redact') + end + + it 'renders the form' do + put :update, :id => @censor_rule.id, + :censor_rule => { :text => 'different text' } + + expect(response).to render_template('edit') + end + + end + end end describe 'DELETE destroy' do - before(:each) do - @censor_rule = FactoryGirl.create(:global_censor_rule) - end + context 'a global CensorRule' do - it 'finds the correct censor rule to destroy' do - pending("This raises an internal error in most cases") - # TODO: Replace :censor_rule_id with :id - delete :destroy, :censor_rule_id => @censor_rule.id - expect(assigns[:censor_rule]).to eq(@censor_rule) - end + before(:each) do + @censor_rule = FactoryGirl.create(:global_censor_rule) + end - it 'raises an error after destroying the rule' do - expect { - delete :destroy, :censor_rule_id => @censor_rule.id - }.to raise_error 'internal error' - end + it 'shows an error notice' do + get :edit, :id => @censor_rule.id + flash[:notice].should == 'Only user and request censor rules can be edited' + end + + it 'redirects to the admin index' do + get :edit, :id => @censor_rule.id + expect(response).to redirect_to(admin_general_index_path) + end - it 'confirms the censor rule is destroyed in all cases' do - pending("This actually raises an internal error anyway") - delete :destroy, :censor_rule_id => @censor_rule.id - msg = 'CensorRule was successfully destroyed.' - expect(flash[:notice]).to eq(msg) end context 'a CensorRule with an associated InfoRequest' do @@ -437,14 +515,25 @@ describe AdminCensorRuleController do @censor_rule = FactoryGirl.create(:info_request_censor_rule) end + it 'finds the correct censor rule to destroy' do + delete :destroy, :id => @censor_rule.id + expect(assigns[:censor_rule]).to eq(@censor_rule) + end + + it 'confirms the censor rule is destroyed in all cases' do + delete :destroy, :id => @censor_rule.id + msg = 'CensorRule was successfully destroyed.' + expect(flash[:notice]).to eq(msg) + end + it 'purges the cache for the info request' do @controller.should_receive(:expire_for_request).with(@censor_rule.info_request) - delete :destroy, :censor_rule_id => @censor_rule.id + delete :destroy, :id => @censor_rule.id end it 'redirects to the associated info request' do - delete :destroy, :censor_rule_id => @censor_rule.id - expect(response).to redirect_to(admin_request_show_path(@censor_rule.info_request)) + delete :destroy, :id => @censor_rule.id + expect(response).to redirect_to(admin_request_path(@censor_rule.info_request)) end end @@ -455,14 +544,25 @@ describe AdminCensorRuleController do @censor_rule = FactoryGirl.create(:user_censor_rule) end + it 'finds the correct censor rule to destroy' do + delete :destroy, :id => @censor_rule.id + expect(assigns[:censor_rule]).to eq(@censor_rule) + end + + it 'confirms the censor rule is destroyed in all cases' do + delete :destroy, :id => @censor_rule.id + msg = 'CensorRule was successfully destroyed.' + expect(flash[:notice]).to eq(msg) + end + it 'purges the cache for the user' do @controller.should_receive(:expire_requests_for_user).with(@censor_rule.user) - delete :destroy, :censor_rule_id => @censor_rule.id + delete :destroy, :id => @censor_rule.id end it 'redirects to the associated info request' do - delete :destroy, :censor_rule_id => @censor_rule.id - expect(response).to redirect_to(admin_user_show_path(@censor_rule.user)) + delete :destroy, :id => @censor_rule.id + expect(response).to redirect_to(admin_user_path(@censor_rule.user)) end end @@ -474,17 +574,17 @@ end describe AdminCensorRuleController, "when making censor rules from the admin interface" do render_views before { basic_auth_login @request } - + it "should create a censor rule and purge the corresponding request from varnish" do - ir = info_requests(:fancy_dog_request) - post :create, :censor_rule => { + ir = info_requests(:fancy_dog_request) + post :create, :request_id => ir.id, + :name_prefix => 'request_', + :censor_rule => { :text => "meat", :replacement => "tofu", - :last_edit_comment => "none", - :info_request_id => ir + :last_edit_comment => "none" } PurgeRequest.all().first.model_id.should == ir.id end - end diff --git a/spec/controllers/admin_comment_controller_spec.rb b/spec/controllers/admin_comment_controller_spec.rb new file mode 100644 index 000000000..f87231e3b --- /dev/null +++ b/spec/controllers/admin_comment_controller_spec.rb @@ -0,0 +1,66 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe AdminCommentController do + + describe :edit do + + before do + @comment = FactoryGirl.create(:comment) + get :edit, :id => @comment.id + end + + it 'renders the edit template' do + expect(response).to render_template('edit') + end + + it 'gets the comment' do + assigns[:comment].should == @comment + end + + end + + describe :update do + + context 'on valid data submission' do + + before do + @comment = FactoryGirl.create(:comment) + atts = FactoryGirl.attributes_for(:comment, :body => 'I am new') + put :update, :id => @comment.id, :comment => atts + end + + it 'gets the comment' do + assigns[:comment].should == @comment + end + + it 'updates the comment' do + Comment.find(@comment.id).body.should == 'I am new' + end + + it 'logs the update event' do + most_recent_event = Comment.find(@comment.id).info_request_events.last + most_recent_event.event_type.should == 'edit_comment' + most_recent_event.comment_id.should == @comment.id + end + + it 'shows a success notice' do + flash[:notice].should == "Comment successfully updated." + end + + it 'redirects to the request page' do + response.should redirect_to(admin_request_path(@comment.info_request)) + end + end + + context 'on invalid data submission' do + + it 'renders the edit template' do + @comment = FactoryGirl.create(:comment) + put :update, :id => @comment.id, :comment => {:body => ''} + response.should render_template('edit') + end + + end + end + +end diff --git a/spec/controllers/admin_holiday_imports_controller_spec.rb b/spec/controllers/admin_holiday_imports_controller_spec.rb new file mode 100644 index 000000000..dd23a022f --- /dev/null +++ b/spec/controllers/admin_holiday_imports_controller_spec.rb @@ -0,0 +1,73 @@ +require 'spec_helper' + +describe AdminHolidayImportsController do + + describe :new do + + it 'renders the new template' do + get :new + expect(response).to render_template('new') + end + + it 'creates an import' do + get :new + assigns[:holiday_import].should be_instance_of(HolidayImport) + end + + describe 'if the import is valid' do + + it 'populates the import' do + mock_import = mock(HolidayImport, :valid? => true, + :populate => nil) + HolidayImport.stub!(:new).and_return(mock_import) + mock_import.should_receive(:populate) + get :new + end + + end + + end + + describe :create do + + it 'creates an import' do + post :create + assigns[:holiday_import].should be_instance_of(HolidayImport) + end + + describe 'if the import can be saved' do + + before do + mock_import = mock(HolidayImport, :save => true) + HolidayImport.stub!(:new).and_return(mock_import) + post :create + end + + it 'should show a success notice' do + flash[:notice].should == 'Holidays successfully imported' + end + + it 'should redirect to the index' do + response.should redirect_to(admin_holidays_path) + end + + end + + describe 'if the import cannot be saved' do + + before do + mock_import = mock(HolidayImport, :save => false) + HolidayImport.stub!(:new).and_return(mock_import) + post :create + end + + it 'should render the new template' do + expect(response).to render_template('new') + end + + end + + end + + +end diff --git a/spec/controllers/admin_holidays_controller_spec.rb b/spec/controllers/admin_holidays_controller_spec.rb new file mode 100644 index 000000000..21cb51d29 --- /dev/null +++ b/spec/controllers/admin_holidays_controller_spec.rb @@ -0,0 +1,192 @@ +require 'spec_helper' + +describe AdminHolidaysController do + + describe :index do + + before do + @holiday_one = FactoryGirl.create(:holiday, :day => Date.new(2010, 1, 1)) + @holiday_two = FactoryGirl.create(:holiday, :day => Date.new(2011, 2, 2)) + @holiday_three = FactoryGirl.create(:holiday, :day => Date.new(2011, 3, 3)) + end + + it 'gets a hash of holidays keyed by year' do + get :index + assigns(:holidays_by_year)[2010].should include(@holiday_one) + assigns(:holidays_by_year)[2011].should include(@holiday_two) + assigns(:holidays_by_year)[2011].should include(@holiday_three) + end + + it 'gets a list of years with holidays' do + get :index + assigns(:years).should include(2010) + assigns(:years).should include(2011) + end + + it 'renders the index template' do + get :index + expect(response).to render_template('index') + end + + end + + describe :new do + + + describe 'when not using ajax' do + + it 'renders the new template' do + get :new + expect(response).to render_template('new') + end + + end + + describe 'when using ajax' do + + it 'renders the new form partial' do + xhr :get, :new + expect(response).to render_template('new_form') + end + end + + it 'creates a new holiday' do + get :new + assigns[:holiday].should be_instance_of(Holiday) + end + + end + + describe :create do + + before do + @holiday_params = { :description => "New Year's Day", + 'day(1i)' => '2010', + 'day(2i)' => '1', + 'day(3i)' => '1' } + post :create, :holiday => @holiday_params + end + + it 'creates a new holiday' do + assigns(:holiday).description.should == @holiday_params[:description] + assigns(:holiday).day.should == Date.new(2010, 1, 1) + assigns(:holiday).should be_persisted + end + + it 'shows the admin a success message' do + flash[:notice].should == 'Holiday successfully created.' + end + + it 'redirects to the index' do + response.should redirect_to admin_holidays_path + end + + context 'when there are errors' do + + before do + Holiday.any_instance.stub(:save).and_return(false) + post :create, :holiday => @holiday_params + end + + it 'renders the new template' do + expect(response).to render_template('new') + end + end + + end + + describe :edit do + + before do + @holiday = FactoryGirl.create(:holiday) + end + + describe 'when not using ajax' do + + it 'renders the edit template' do + get :edit, :id => @holiday.id + expect(response).to render_template('edit') + end + + end + + describe 'when using ajax' do + + it 'renders the edit form partial' do + xhr :get, :edit, :id => @holiday.id + expect(response).to render_template('edit_form') + end + + end + + it 'gets the holiday in the id param' do + get :edit, :id => @holiday.id + assigns[:holiday].should == @holiday + end + + end + + describe :update do + + before do + @holiday = FactoryGirl.create(:holiday, :day => Date.new(2010, 1, 1), + :description => "Test Holiday") + put :update, :id => @holiday.id, :holiday => { :description => 'New Test Holiday' } + end + + it 'gets the holiday in the id param' do + assigns[:holiday].should == @holiday + end + + it 'updates the holiday' do + holiday = Holiday.find(@holiday.id).description.should == 'New Test Holiday' + end + + it 'shows the admin a success message' do + flash[:notice].should == 'Holiday successfully updated.' + end + + it 'redirects to the index' do + response.should redirect_to admin_holidays_path + end + + context 'when there are errors' do + + before do + Holiday.any_instance.stub(:update_attributes).and_return(false) + put :update, :id => @holiday.id, :holiday => { :description => 'New Test Holiday' } + end + + it 'renders the edit template' do + expect(response).to render_template('edit') + end + end + + end + + describe :destroy do + + before(:each) do + @holiday = FactoryGirl.create(:holiday) + delete :destroy, :id => @holiday.id + end + + it 'finds the holiday to destroy' do + assigns(:holiday).should == @holiday + end + + it 'destroys the holiday' do + assigns(:holiday).should be_destroyed + end + + it 'tells the admin the holiday has been destroyed' do + msg = "Holiday successfully destroyed" + flash[:notice].should == msg + end + + it 'redirects to the index action' do + expect(response).to redirect_to(admin_holidays_path) + end + end + + end diff --git a/spec/controllers/admin_incoming_message_controller_spec.rb b/spec/controllers/admin_incoming_message_controller_spec.rb index 21c744e5b..24a526ca4 100644 --- a/spec/controllers/admin_incoming_message_controller_spec.rb +++ b/spec/controllers/admin_incoming_message_controller_spec.rb @@ -17,19 +17,19 @@ describe AdminIncomingMessageController, "when administering incoming messages" it "destroys the raw email file" do raw_email = @im.raw_email.filepath assert_equal File.exists?(raw_email), true - post :destroy, :incoming_message_id => @im.id + post :destroy, :id => @im.id assert_equal File.exists?(raw_email), false end it 'asks the incoming message to fully destroy itself' do IncomingMessage.stub!(:find).and_return(@im) @im.should_receive(:fully_destroy) - post :destroy, :incoming_message_id => @im.id + post :destroy, :id => @im.id end it 'expires the file cache for the associated info_request' do @controller.should_receive(:expire_for_request).with(@im.info_request) - post :destroy, :incoming_message_id => @im.id + post :destroy, :id => @im.id end end @@ -46,7 +46,7 @@ describe AdminIncomingMessageController, "when administering incoming messages" destination_info_request = info_requests(:naughty_chicken_request) incoming_message = incoming_messages(:useless_incoming_message) @controller.should_receive(:expire_for_request).with(current_info_request) - post :redeliver, :redeliver_incoming_message_id => incoming_message.id, + post :redeliver, :id => incoming_message.id, :url_title => destination_info_request.url_title end @@ -56,7 +56,7 @@ describe AdminIncomingMessageController, "when administering incoming messages" current_info_request = info_requests(:fancy_dog_request) destination_info_request = info_requests(:naughty_chicken_request) incoming_message = incoming_messages(:useless_incoming_message) - post :redeliver, :redeliver_incoming_message_id => incoming_message.id, + post :redeliver, :id => incoming_message.id, :url_title => destination_info_request.url_title end @@ -130,7 +130,7 @@ describe AdminIncomingMessageController, "when administering incoming messages" it 'should redirect to the admin info request view' do make_request - response.should redirect_to admin_request_show_url(@incoming.info_request) + response.should redirect_to admin_request_url(@incoming.info_request) end it 'should show a message that the incoming message has been updated' do diff --git a/spec/controllers/admin_info_request_event_controller_spec.rb b/spec/controllers/admin_info_request_event_controller_spec.rb new file mode 100644 index 000000000..23300a0b8 --- /dev/null +++ b/spec/controllers/admin_info_request_event_controller_spec.rb @@ -0,0 +1,41 @@ +# coding: utf-8 +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe AdminInfoRequestEventController do + + describe :update do + + describe 'when handling valid data' do + + before do + @info_request_event = FactoryGirl.create(:info_request_event) + put :update, :id => @info_request_event + end + + it 'gets the info request event' do + assigns[:info_request_event].should == @info_request_event + end + + it 'sets the described and calculated states on the event' do + event = InfoRequestEvent.find(@info_request_event.id) + event.described_state.should == 'waiting_clarification' + event.calculated_state.should == 'waiting_clarification' + end + + it 'shows a success notice' do + flash[:notice].should == 'Old response marked as having been a clarification' + end + + it 'redirects to the request admin page' do + response.should redirect_to(admin_request_url(@info_request_event.info_request)) + end + end + + it 'raises an exception if the event is not a response' do + @info_request_event = FactoryGirl.create(:sent_event) + lambda{ put :update, :id => @info_request_event }.should raise_error + end + + end + +end diff --git a/spec/controllers/admin_outgoing_message_controller_spec.rb b/spec/controllers/admin_outgoing_message_controller_spec.rb index 0dde53b86..a46a077da 100644 --- a/spec/controllers/admin_outgoing_message_controller_spec.rb +++ b/spec/controllers/admin_outgoing_message_controller_spec.rb @@ -79,7 +79,7 @@ describe AdminOutgoingMessageController do it 'should redirect to the admin info request view' do make_request - response.should redirect_to admin_request_show_url(@info_request) + response.should redirect_to admin_request_url(@info_request) end it 'should show a message that the incoming message has been updated' do diff --git a/spec/controllers/admin_public_body_controller_spec.rb b/spec/controllers/admin_public_body_controller_spec.rb index f176150da..3ab58317a 100644 --- a/spec/controllers/admin_public_body_controller_spec.rb +++ b/spec/controllers/admin_public_body_controller_spec.rb @@ -402,7 +402,7 @@ describe AdminPublicBodyController, "when destroying a public body" do it "destroys a public body" do n = PublicBody.count post :destroy, { :id => public_bodies(:forlorn_public_body).id } - response.should redirect_to(:controller=>'admin_public_body', :action=>'list') + response.should redirect_to admin_bodies_path PublicBody.count.should == n - 1 end @@ -416,7 +416,7 @@ describe AdminPublicBodyController, "when assigning public body tags" do n = PublicBody.joins(:translations).where([condition, "en"]).count post :mass_tag_add, { :new_tag => "department", :table_name => "substring" } request.flash[:notice].should == "Added tag to table of bodies." - response.should redirect_to(:action=>'list') + response.should redirect_to admin_bodies_path PublicBody.find_by_tag("department").count.should == n end end diff --git a/spec/controllers/admin_raw_email_controller_spec.rb b/spec/controllers/admin_raw_email_controller_spec.rb new file mode 100644 index 000000000..77c57c38b --- /dev/null +++ b/spec/controllers/admin_raw_email_controller_spec.rb @@ -0,0 +1,30 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe AdminRawEmailController do + + describe :show do + + before do + @raw_email = FactoryGirl.create(:incoming_message).raw_email + end + + describe 'html version' do + + it 'renders the show template' do + get :show, :id => @raw_email.id + end + + end + + describe 'text version' do + + it 'sends the email as an RFC-822 attachment' do + get :show, :id => @raw_email.id, :format => 'txt' + response.content_type.should == 'message/rfc822' + response.body.should == @raw_email.data + end + end + + end + +end diff --git a/spec/controllers/admin_request_controller_spec.rb b/spec/controllers/admin_request_controller_spec.rb index 7c5253f49..4eb463963 100644 --- a/spec/controllers/admin_request_controller_spec.rb +++ b/spec/controllers/admin_request_controller_spec.rb @@ -57,12 +57,12 @@ describe AdminRequestController, "when administering requests" do it 'expires the file cache for that request' do info_request = info_requests(:badger_request) @controller.should_receive(:expire_for_request).with(info_request) - get :fully_destroy, { :id => info_request } + get :destroy, { :id => info_request } end it 'uses a different flash message to avoid trying to fetch a non existent user record' do info_request = info_requests(:external_request) - post :fully_destroy, { :id => info_request.id } + post :destroy, { :id => info_request.id } request.flash[:notice].should include('external') end @@ -77,34 +77,6 @@ describe AdminRequestController, "when administering the holding pen" do load_raw_emails_data end - it "shows a rejection reason for an incoming message from an invalid address" do - ir = info_requests(:fancy_dog_request) - ir.allow_new_responses_from = 'authority_only' - ir.handle_rejected_responses = 'holding_pen' - ir.save! - receive_incoming_mail('incoming-request-plain.email', ir.incoming_email, "frob@nowhere.com") - get :show_raw_email, :id => InfoRequest.holding_pen_request.get_last_public_response.raw_email.id - response.should contain "Only the authority can reply to this request" - end - - it "guesses a misdirected request" do - ir = info_requests(:fancy_dog_request) - ir.handle_rejected_responses = 'holding_pen' - ir.allow_new_responses_from = 'authority_only' - ir.save! - mail_to = "request-#{ir.id}-asdfg@example.com" - receive_incoming_mail('incoming-request-plain.email', mail_to) - interesting_email = InfoRequest.holding_pen_request.get_last_public_response.raw_email.id - # now we add another message to the queue, which we're not interested in - receive_incoming_mail('incoming-request-plain.email', ir.incoming_email, "") - InfoRequest.holding_pen_request.incoming_messages.length.should == 2 - get :show_raw_email, :id => interesting_email - response.should contain "Could not identify the request" - assigns[:info_requests][0].should == ir - end - - - it "shows a suitable default 'your email has been hidden' message" do ir = info_requests(:fancy_dog_request) get :show, :id => ir.id @@ -119,7 +91,7 @@ describe AdminRequestController, "when administering the holding pen" do it "hides requests and sends a notification email that it has done so" do ir = info_requests(:fancy_dog_request) - post :hide_request, :id => ir.id, :explanation => "Foo", :reason => "vexatious" + post :hide, :id => ir.id, :explanation => "Foo", :reason => "vexatious" ir.reload ir.prominence.should == "requester_only" ir.described_state.should == "vexatious" @@ -132,7 +104,7 @@ describe AdminRequestController, "when administering the holding pen" do it 'expires the file cache for the request' do ir = info_requests(:fancy_dog_request) @controller.should_receive(:expire_for_request).with(ir) - post :hide_request, :id => ir.id, :explanation => "Foo", :reason => "vexatious" + post :hide, :id => ir.id, :explanation => "Foo", :reason => "vexatious" end describe 'when hiding an external request' do @@ -153,7 +125,7 @@ describe AdminRequestController, "when administering the holding pen" do end def make_request(params=@default_params) - post :hide_request, params + post :hide, params end it 'should redirect the the admin page for the request' do diff --git a/spec/controllers/admin_track_controller_spec.rb b/spec/controllers/admin_track_controller_spec.rb index f2de6c0d3..d29db4966 100644 --- a/spec/controllers/admin_track_controller_spec.rb +++ b/spec/controllers/admin_track_controller_spec.rb @@ -1,9 +1,8 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe AdminTrackController, "when administering tracks" do - render_views - - it "shows the list page" do - get :list + + it "shows the index page" do + get :index end end diff --git a/spec/controllers/admin_user_controller_spec.rb b/spec/controllers/admin_user_controller_spec.rb index 8b89506f9..e979355cf 100644 --- a/spec/controllers/admin_user_controller_spec.rb +++ b/spec/controllers/admin_user_controller_spec.rb @@ -2,13 +2,13 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe AdminUserController, "when administering users" do render_views - - it "shows the index/list page" do + + it "shows the index page" do get :index end it "searches for 'bob'" do - get :list, :query => "bob" + get :index, :query => "bob" assigns[:admin_users].should == [ users(:bob_smith_user) ] end @@ -51,7 +51,7 @@ describe AdminUserController do before(:each) do @user = FactoryGirl.create(:user) - request.env["HTTP_REFERER"] = admin_user_show_path(@user) + request.env["HTTP_REFERER"] = admin_user_path(@user) end it 'redirects to the page the admin was previously on' do @@ -61,7 +61,7 @@ describe AdminUserController do :comment_ids => comment.id, :hide_selected => 'hidden' } - response.should redirect_to(admin_user_show_path(@user)) + response.should redirect_to(admin_user_path(@user)) end it 'sets the given comments visibility to hidden' do diff --git a/spec/controllers/general_controller_spec.rb b/spec/controllers/general_controller_spec.rb index 8652d9b17..128a42556 100644 --- a/spec/controllers/general_controller_spec.rb +++ b/spec/controllers/general_controller_spec.rb @@ -138,6 +138,35 @@ describe GeneralController, "when showing the frontpage" do end + describe 'when handling logged-in users' do + + before do + @user = FactoryGirl.create(:user) + session[:user_id] = @user.id + end + + it 'should set a time to live on a non "remember me" session' do + get :frontpage + response.body.should match @user.name + session[:ttl].should be_within(1).of(Time.now) + end + + it 'should not set a time to live on a "remember me" session' do + session[:remember_me] = true + get :frontpage + response.body.should match @user.name + session[:ttl].should be_nil + end + + it 'should end a logged-in session whose ttl has expired' do + session[:ttl] = Time.now - 4.hours + get :frontpage + response.should redirect_to signin_path + session[:user_id].should be_nil + end + + end + end diff --git a/spec/controllers/public_body_change_requests_controller_spec.rb b/spec/controllers/public_body_change_requests_controller_spec.rb index 8fe7befeb..4053b2f40 100644 --- a/spec/controllers/public_body_change_requests_controller_spec.rb +++ b/spec/controllers/public_body_change_requests_controller_spec.rb @@ -28,6 +28,7 @@ describe PublicBodyChangeRequestsController, "creating a change request" do it "should send an email to the site contact address" do post :create, {:public_body_change_request => @change_request_params} + change_request_id = assigns[:change_request].id deliveries = ActionMailer::Base.deliveries deliveries.size.should == 1 mail = deliveries[0] @@ -37,8 +38,8 @@ describe PublicBodyChangeRequestsController, "creating a change request" do mail.body.should include('new_body@example.com') mail.body.should include('New Body') mail.body.should include("Please") - mail.body.should include('http://test.host/admin/body/new?change_request_id=') - mail.body.should include('http://test.host/admin/change_request/edit/') + mail.body.should include("http://test.host/admin/bodies/new?change_request_id=#{change_request_id}") + mail.body.should include("http://test.host/admin/change_requests/#{change_request_id}/edit") end it 'should show a notice' do @@ -83,6 +84,7 @@ describe PublicBodyChangeRequestsController, "creating a change request" do it 'should send an email to the site contact address' do post :create, {:public_body_change_request => @change_request_params} + change_request_id = assigns[:change_request].id deliveries = ActionMailer::Base.deliveries deliveries.size.should == 1 mail = deliveries[0] @@ -92,8 +94,8 @@ describe PublicBodyChangeRequestsController, "creating a change request" do mail.body.should include('new_body@example.com') mail.body.should include(@public_body.name) mail.body.should include("Please") - mail.body.should include("http://test.host/admin/body/edit/#{@public_body.id}?change_request_id=") - mail.body.should include('http://test.host/admin/change_request/edit/') + mail.body.should include("http://test.host/admin/bodies/#{@public_body.id}/edit?change_request_id=#{change_request_id}") + mail.body.should include("http://test.host/admin/change_requests/#{change_request_id}/edit") end it 'should show a notice' do diff --git a/spec/controllers/public_body_controller_spec.rb b/spec/controllers/public_body_controller_spec.rb index 840b4bb28..130631ef6 100644 --- a/spec/controllers/public_body_controller_spec.rb +++ b/spec/controllers/public_body_controller_spec.rb @@ -70,6 +70,18 @@ describe PublicBodyController, "when showing a body" do get :show, :url_name => "dFh", :view => 'all' response.should redirect_to(:controller => 'public_body', :action => 'show', :url_name => "dfh") end + + it 'keeps the search_params flash' do + # Make two get requests to simulate the flash getting swept after the + # first response. + search_params = { 'query' => 'Quango' } + get :show, { :url_name => 'dfh', :view => 'all' }, + nil, + { :search_params => search_params } + get :show, :url_name => 'dfh', :view => 'all' + expect(flash[:search_params]).to eq(search_params) + end + end describe PublicBodyController, "when listing bodies" do @@ -479,4 +491,15 @@ describe PublicBodyController, "when doing type ahead searches" do response.should render_template('public_body/_search_ahead') assigns[:xapian_requests].should be_nil end + + it 'remembers the search params' do + search_params = { + 'query' => 'Quango', + 'page' => '1', + 'bodies' => '1' + } + get :search_typeahead, search_params + expect(flash[:search_params]).to eq(search_params) + end + end diff --git a/spec/controllers/request_controller_spec.rb b/spec/controllers/request_controller_spec.rb index 26e46a966..02237b29d 100644 --- a/spec/controllers/request_controller_spec.rb +++ b/spec/controllers/request_controller_spec.rb @@ -956,6 +956,20 @@ describe RequestController, "when searching for an authority" do }.should_not raise_error(StandardError) end end + + it "remembers the search params" do + session[:user_id] = @user.id + search_params = { + 'query' => 'Quango', + 'page' => '1', + 'bodies' => '1' + } + + get :select_authority, search_params + + expect(flash[:search_params]).to eq(search_params) + end + end describe RequestController, "when creating a new request" do @@ -1073,6 +1087,16 @@ describe RequestController, "when creating a new request" do response.redirect_url.should =~ /request\/why_is_your_quango_called_gerald\/new$/ end + it "sets the request_sent flash to true if successful" do + session[:user_id] = @user.id + post :new, :info_request => { :public_body_id => @body.id, + :title => "Why is your quango called Geraldine?", :tag_string => "" }, + :outgoing_message => { :body => "This is a silly letter. It is too short to be interesting." }, + :submitted_new_request => 1, :preview => 0 + + expect(flash[:request_sent]).to be_true + end + it "should give an error if the same request is submitted twice" do session[:user_id] = @user.id @@ -2392,6 +2416,23 @@ describe RequestController, "when doing type ahead searches" do get :search_typeahead, :q => "dog -chicken" assigns[:xapian_requests].results.size.should == 1 end + + it 'can filter search results by public body' do + get :search_typeahead, :q => 'boring', :requested_from => 'dfh' + expect(assigns[:query]).to eq('requested_from:dfh boring') + end + + it 'defaults to 25 results per page' do + get :search_typeahead, :q => 'boring' + expect(assigns[:per_page]).to eq(25) + end + + it 'can limit the number of searches returned' do + get :search_typeahead, :q => 'boring', :per_page => '1' + expect(assigns[:per_page]).to eq(1) + expect(assigns[:xapian_requests].results.size).to eq(1) + end + end describe RequestController, "when showing similar requests" do @@ -2442,7 +2483,7 @@ describe RequestController, "when caching fragments" do :info_request_id => 132, :id => 44, :get_attachments_for_display => nil, - :html_mask_stuff! => nil, + :apply_masks! => nil, :user_can_view? => true, :all_can_view? => true) attachment = FactoryGirl.build(:body_text, :filename => long_name) @@ -2537,10 +2578,9 @@ describe RequestController, "#new_batch" do assigns[:existing_batch].should_not be_nil end - it 'should display a success notice' do + it 'sets the batch_sent flash to true' do make_request - notice_text = "<p>Your Freedom of Information requests will be <strong>sent</strong> shortly!" - flash[:notice].should match notice_text + expect(flash[:batch_sent]).to be_true end end @@ -2655,7 +2695,7 @@ describe RequestController, "#select_authorities" do end - context 'when asked for JSON', :focus => true do + context 'when asked for JSON' do it 'should be successful' do get :select_authorities, {:public_body_query => "Quan", :format => 'json'}, {:user_id => @user.id} diff --git a/spec/controllers/services_controller_spec.rb b/spec/controllers/services_controller_spec.rb index 14731f090..621dbaaac 100644 --- a/spec/controllers/services_controller_spec.rb +++ b/spec/controllers/services_controller_spec.rb @@ -12,6 +12,14 @@ describe ServicesController, "when returning a message for people in other count @old_locale = FastGettext.locale() end + it 'keeps the flash' do + # Make two get requests to simulate the flash getting swept after the + # first response. + get :other_country_message, nil, nil, :some_flash_key => 'abc' + get :other_country_message + expect(flash[:some_flash_key]).to eq('abc') + end + it "should show no alaveteli message when in the deployed country" do config = MySociety::Config.load_default() config['ISO_COUNTRY_CODE'] = "DE" @@ -60,21 +68,25 @@ describe ServicesController, "when returning a message for people in other count response.should be_success response.body.should == 'Hello! We have an <a href="/help/alaveteli?country_name=Deutschland">important message</a> for visitors outside Deutschland' end + it "should default to no message if the country_from_ip domain doesn't exist" do AlaveteliConfiguration.stub!(:gaze_url).and_return('http://12123sdf14qsd.com') get :other_country_message response.should be_success response.body.should == '' end + it "should default to no message if the country_from_ip service doesn't exist" do AlaveteliConfiguration.stub!(:gaze_url).and_return('http://www.google.com') get :other_country_message response.should be_success response.body.should == '' end - it "should default to no message if the country_from_ip service returns an error" do + + it "should default to no message and log the error with url if the country_from_ip service returns an error" do FakeWeb.register_uri(:get, %r|500.com|, :body => "Error", :status => ["500", "Error"]) AlaveteliConfiguration.stub!(:gaze_url).and_return('http://500.com') + Rails.logger.should_receive(:warn).with /500\.com.*500 Error/ get :other_country_message response.should be_success response.body.should == '' diff --git a/spec/factories/holidays.rb b/spec/factories/holidays.rb new file mode 100644 index 000000000..531130c8a --- /dev/null +++ b/spec/factories/holidays.rb @@ -0,0 +1,8 @@ +FactoryGirl.define do + + factory :holiday do + day Date.new(2010, 1, 1) + description "New Year's Day" + end + +end diff --git a/spec/factories/incoming_messages.rb b/spec/factories/incoming_messages.rb index ec0afdcd0..b29fe8ce9 100644 --- a/spec/factories/incoming_messages.rb +++ b/spec/factories/incoming_messages.rb @@ -10,6 +10,9 @@ FactoryGirl.define do FactoryGirl.create(:body_text, :incoming_message => incoming_message, :url_part_number => 1) + + incoming_message.raw_email.incoming_message = incoming_message + incoming_message.raw_email.data = "somedata" end factory :plain_incoming_message do diff --git a/spec/factories/info_request_events.rb b/spec/factories/info_request_events.rb new file mode 100644 index 000000000..cdd303ad6 --- /dev/null +++ b/spec/factories/info_request_events.rb @@ -0,0 +1,12 @@ +FactoryGirl.define do + + factory :info_request_event do + info_request + event_type 'response' + params_yaml '' + factory :sent_event do + event_type 'sent' + end + end + +end diff --git a/spec/fixtures/files/ical-holidays.ics b/spec/fixtures/files/ical-holidays.ics new file mode 100644 index 000000000..6ccf31202 --- /dev/null +++ b/spec/fixtures/files/ical-holidays.ics @@ -0,0 +1,22 @@ +BEGIN:VCALENDAR +VERSION:2.0 +METHOD:PUBLISH +PRODID:-//uk.gov/GOVUK calendars//EN +CALSCALE:GREGORIAN +BEGIN:VEVENT +DTEND;VALUE=DATE:20140102 +DTSTART;VALUE=DATE:20140101 +SUMMARY:New Year's Day +UID:ca6af7456b0088abad9a69f9f620f5ac-17@gov.uk +SEQUENCE:0 +DTSTAMP:20140916T090346Z +END:VEVENT +BEGIN:VEVENT +DTEND;VALUE=DATE:20150102 +DTSTART;VALUE=DATE:20150101 +SUMMARY:New Year's Day +UID:ca6af7456b00a69f9f620f5ac-17@gov.uk +SEQUENCE:0 +DTSTAMP:20140916T090346Z +END:VEVENT +END:VCALENDAR diff --git a/spec/integration/admin_public_body_edit_spec.rb b/spec/integration/admin_public_body_edit_spec.rb index 613793dd4..aeec3e65a 100644 --- a/spec/integration/admin_public_body_edit_spec.rb +++ b/spec/integration/admin_public_body_edit_spec.rb @@ -18,7 +18,7 @@ describe 'Editing a Public Body' do end it 'can edit the default locale' do - @admin.visit admin_body_edit_path(@body) + @admin.visit edit_admin_body_path(@body) @admin.fill_in 'public_body_name__en', :with => 'New Quango EN' @admin.click_button 'Save' @@ -29,7 +29,7 @@ describe 'Editing a Public Body' do it 'can add a translation for a single locale' do expect(@body.find_translation_by_locale('fr')).to be_nil - @admin.visit admin_body_edit_path(@body) + @admin.visit edit_admin_body_path(@body) @admin.fill_in 'public_body_translations_attributes_fr_name__fr', :with => 'New Quango FR' @admin.click_button 'Save' @@ -40,19 +40,19 @@ describe 'Editing a Public Body' do end it 'can add a translation for multiple locales', :focus => true do - @admin.visit admin_body_edit_path(@body) + @admin.visit edit_admin_body_path(@body) @admin.fill_in 'public_body_name__en', :with => 'New Quango EN' @admin.click_button 'Save' # Add FR translation expect(@body.find_translation_by_locale('fr')).to be_nil - @admin.visit admin_body_edit_path(@body) + @admin.visit edit_admin_body_path(@body) @admin.fill_in 'public_body_translations_attributes_fr_name__fr', :with => 'New Quango FR' @admin.click_button 'Save' # Add ES translation expect(@body.find_translation_by_locale('es')).to be_nil - @admin.visit admin_body_edit_path(@body) + @admin.visit edit_admin_body_path(@body) @admin.fill_in 'public_body_translations_attributes_es_name__es', :with => 'New Quango ES' @admin.click_button 'Save' diff --git a/spec/integration/admin_spec.rb b/spec/integration/admin_spec.rb index 8e6351d2c..bdd6e9d8c 100644 --- a/spec/integration/admin_spec.rb +++ b/spec/integration/admin_spec.rb @@ -5,29 +5,25 @@ describe "When administering the site" do before do AlaveteliConfiguration.stub!(:skip_admin_auth).and_return(false) + confirm(:admin_user) + @admin = login(:admin_user) end it "allows an admin to log in as another user" do - # First log in as Joe Admin - confirm(:admin_user) - admin = login(:admin_user) - - # Now fetch the "log in as" link to log in as Bob - admin.get_via_redirect "/en/admin/user/login_as/#{users(:bob_smith_user).id}" - admin.response.should be_success - admin.session[:user_id].should == users(:bob_smith_user).id + # post to the "log in as" url to log in as Bob + @admin.post_via_redirect "/en/admin/users/#{users(:bob_smith_user).id}/login_as" + @admin.response.should be_success + @admin.session[:user_id].should == users(:bob_smith_user).id end it 'does not allow a non-admin user to login as another user' do robin = login(:robin_user) - robin.get_via_redirect "/en/admin/user/login_as/#{users(:bob_smith_user).id}" + robin.post_via_redirect "/en/admin/users/#{users(:bob_smith_user).id}/login_as" robin.response.should be_success robin.session[:user_id].should_not == users(:bob_smith_user).id end it "allows redelivery of an incoming message to a closed request" do - confirm(:admin_user) - admin = login(:admin_user) ir = info_requests(:fancy_dog_request) close_request(ir) InfoRequest.holding_pen_request.incoming_messages.length.should == 0 @@ -36,10 +32,9 @@ describe "When administering the site" do InfoRequest.holding_pen_request.incoming_messages.length.should == 1 new_im = InfoRequest.holding_pen_request.incoming_messages[0] ir.incoming_messages.length.should == 1 - post_params = {'redeliver_incoming_message_id' => new_im.id, - 'url_title' => ir.url_title} - admin.post '/en/admin/incoming/redeliver', post_params - admin.response.location.should == 'http://www.example.com/en/admin/request/show/101' + post_params = { 'url_title' => ir.url_title } + @admin.post "/en/admin/incoming_messages/#{new_im.id}/redeliver", post_params + @admin.response.location.should == 'http://www.example.com/en/admin/requests/101' ir = InfoRequest.find_by_url_title(ir.url_title) ir.incoming_messages.length.should == 2 @@ -47,8 +42,6 @@ describe "When administering the site" do end it "allows redelivery of an incoming message to more than one request" do - confirm(:admin_user) - admin = login(:admin_user) ir1 = info_requests(:fancy_dog_request) close_request(ir1) @@ -60,15 +53,41 @@ describe "When administering the site" do InfoRequest.holding_pen_request.incoming_messages.length.should == 1 new_im = InfoRequest.holding_pen_request.incoming_messages[0] - post_params = {'redeliver_incoming_message_id' => new_im.id, - 'url_title' => "#{ir1.url_title},#{ir2.url_title}"} - admin.post '/en/admin/incoming/redeliver', post_params + post_params = { 'url_title' => "#{ir1.url_title},#{ir2.url_title}" } + @admin.post "/en/admin/incoming_messages/#{new_im.id}/redeliver", post_params ir1.reload ir1.incoming_messages.length.should == 2 ir2.reload ir2.incoming_messages.length.should == 2 - admin.response.location.should == 'http://www.example.com/en/admin/request/show/106' + @admin.response.location.should == 'http://www.example.com/en/admin/requests/106' InfoRequest.holding_pen_request.incoming_messages.length.should == 0 end + describe 'when administering the holding pen' do + + it "shows a rejection reason for an incoming message from an invalid address" do + ir = FactoryGirl.create(:info_request, :allow_new_responses_from => 'authority_only', + :handle_rejected_responses => 'holding_pen') + receive_incoming_mail('incoming-request-plain.email', ir.incoming_email, "frob@nowhere.com") + raw_email = InfoRequest.holding_pen_request.get_last_public_response.raw_email + @admin.get "/en/admin/raw_emails/#{raw_email.id}" + @admin.response.should contain "Only the authority can reply to this request" + end + + it "guesses a misdirected request" do + ir = FactoryGirl.create(:info_request, :allow_new_responses_from => 'authority_only', + :handle_rejected_responses => 'holding_pen') + mail_to = "request-#{ir.id}-asdfg@example.com" + receive_incoming_mail('incoming-request-plain.email', mail_to) + interesting_email = InfoRequest.holding_pen_request.get_last_public_response.raw_email + # now we add another message to the queue, which we're not interested in + receive_incoming_mail('incoming-request-plain.email', ir.incoming_email, "") + InfoRequest.holding_pen_request.incoming_messages.length.should == 2 + @admin.get "/en/admin/raw_emails/#{interesting_email.id}" + @admin.response.should contain "Could not identify the request" + @admin.response.should contain ir.title + end + + + end end diff --git a/spec/integration/alaveteli_dsl.rb b/spec/integration/alaveteli_dsl.rb index 1d56abbdf..370628d98 100644 --- a/spec/integration/alaveteli_dsl.rb +++ b/spec/integration/alaveteli_dsl.rb @@ -21,7 +21,7 @@ module AlaveteliDsl response.should redirect_to(:controller => 'user', :action => 'signin', :token => post_redirect.token) follow_redirect! response.should render_template("user/sign") - response.body.should match(/To send your FOI request, please sign in or make a new account./) + response.body.should match(/To send your FOI request, create an account or sign in/) end end @@ -33,15 +33,16 @@ def login(user) sess.reset! sess.extend(AlaveteliDsl) - if user.is_a? User - u = user - else - u = users(user) - end + u = user.is_a?(User) ? user : users(user) + sess.visit signin_path - sess.fill_in "Your e-mail:", :with => u.email - sess.fill_in "Password:", :with => "jonespassword" - sess.click_button "Sign in" + + sess.within '#signin_form' do + sess.fill_in "Your e-mail:", :with => u.email + sess.fill_in "Password:", :with => "jonespassword" + sess.click_button "Sign in" + end + assert sess.session[:user_id] == u.id end end diff --git a/spec/integration/download_request_spec.rb b/spec/integration/download_request_spec.rb index 638198cde..48b42b11d 100644 --- a/spec/integration/download_request_spec.rb +++ b/spec/integration/download_request_spec.rb @@ -56,7 +56,7 @@ describe 'when making a zipfile available' do admin = login(FactoryGirl.create(:admin_user)) post_data = {:incoming_message => {:prominence => 'requester_only', :prominence_reason => 'boring'}} - admin.post_via_redirect "/en/admin/incoming/update/#{info_request.incoming_messages.first.id}", post_data + admin.put_via_redirect "/en/admin/incoming_messages/#{info_request.incoming_messages.first.id}", post_data admin.response.should be_success # Admin retains the requester only things @@ -104,7 +104,7 @@ describe 'when making a zipfile available' do post_data = {:outgoing_message => {:prominence => 'requester_only', :prominence_reason => 'boring', :body => 'Some information please'}} - admin.post_via_redirect "/en/admin/outgoing/update/#{info_request.outgoing_messages.first.id}", post_data + admin.put_via_redirect "/en/admin/outgoing_messages/#{info_request.outgoing_messages.first.id}", post_data admin.response.should be_success # Admin retains the requester only things @@ -237,7 +237,7 @@ describe 'when making a zipfile available' do admin = login(FactoryGirl.create(:admin_user)) post_data = {:incoming_message => {:prominence => 'requester_only', :prominence_reason => 'boring'}} - admin.post_via_redirect "/en/admin/incoming/update/#{info_request.incoming_messages.first.id}", post_data + admin.put_via_redirect "/en/admin/incoming_messages/#{info_request.incoming_messages.first.id}", post_data admin.response.should be_success # Admin retains the requester only things @@ -285,7 +285,7 @@ describe 'when making a zipfile available' do post_data = {:outgoing_message => {:prominence => 'requester_only', :prominence_reason => 'boring', :body => 'Some information please'}} - admin.post_via_redirect "/en/admin/outgoing/update/#{info_request.outgoing_messages.first.id}", post_data + admin.put_via_redirect "/en/admin/outgoing_messages/#{info_request.outgoing_messages.first.id}", post_data admin.response.should be_success # Admin retains the requester only things diff --git a/spec/integration/errors_spec.rb b/spec/integration/errors_spec.rb index 4fa12fb21..39f1279ce 100644 --- a/spec/integration/errors_spec.rb +++ b/spec/integration/errors_spec.rb @@ -59,7 +59,6 @@ describe "When errors occur" do response.should render_template('general/exception_caught') response.code.should == '404' response.body.should match("Sorry, we couldn't find that page") - response.body.should match(%Q(invalid value for Integer)) end # it 'should handle non utf-8 parameters' do @@ -76,7 +75,6 @@ describe "When errors occur" do InfoRequest.stub!(:find_by_url_title!).and_raise("An example error") get("/request/example") response.should render_template('general/exception_caught') - response.body.should match('An example error') response.code.should == "500" end @@ -111,7 +109,6 @@ describe "When errors occur" do get("/es/request/example") response.should render_template('general/exception_caught') response.body.should match('Lo sentimos, hubo un problema procesando esta página') - response.body.should match('An example error') end it "should render a 403 with text body for attempts at directory listing for attachments" do @@ -136,7 +133,7 @@ describe "When errors occur" do it 'should show a full trace for general errors' do InfoRequest.stub!(:find).and_raise("An example error") - get("/admin/request/show/333") + get("/admin/requests/333") response.body.should have_selector('div[id=traces]') response.body.should match('An example error') end diff --git a/spec/integration/view_request_spec.rb b/spec/integration/view_request_spec.rb index eecb984f5..4d04c97d7 100644 --- a/spec/integration/view_request_spec.rb +++ b/spec/integration/view_request_spec.rb @@ -33,7 +33,7 @@ describe "When viewing requests" do # Admin makes the incoming message requester only post_data = {:incoming_message => {:prominence => 'hidden', :prominence_reason => 'boring'}} - admin.post_via_redirect "/admin/incoming/update/#{info_request.incoming_messages.first.id}", post_data + admin.put_via_redirect "/admin/incoming_messages/#{info_request.incoming_messages.first.id}", post_data admin.response.should be_success cache_directories_exist?(info_request).should be_false diff --git a/spec/lib/alaveteli_text_masker_spec.rb b/spec/lib/alaveteli_text_masker_spec.rb new file mode 100644 index 000000000..1a4782a83 --- /dev/null +++ b/spec/lib/alaveteli_text_masker_spec.rb @@ -0,0 +1,146 @@ +# -*- coding: utf-8 -*- +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe AlaveteliTextMasker do + include AlaveteliTextMasker + + describe :apply_masks! do + + describe 'when applying censor rules' do + + before do + @cheese_censor_rule = FactoryGirl.build(:censor_rule, :text => 'Stilton', + :replacement => 'Jarlsberg') + @colour_censor_rule = FactoryGirl.build(:censor_rule, :text => 'blue', + :replacement => 'yellow') + @regex_censor_rule = FactoryGirl.build(:censor_rule, :text => 'm[a-z][a-z][a-z]e', + :replacement => 'cat', + :regexp => true) + @censor_rules = [@cheese_censor_rule, @colour_censor_rule, @regex_censor_rule] + end + + it "should do nothing to a JPEG" do + data = "There was a mouse called Stilton, he wished that he was blue." + apply_masks!(data, "image/jpeg", :censor_rules => @censor_rules) + data.should == "There was a mouse called Stilton, he wished that he was blue." + end + + it "should replace censor text in Word documents" do + data = "There was a mouse called Stilton, he wished that he was blue." + apply_masks!(data, "application/vnd.ms-word", :censor_rules => @censor_rules) + data.should == "There was a xxxxx called xxxxxxx, he wished that he was xxxx." + end + + it 'should handle multibyte characters correctly' do + data = 'á mouse' + @regex_censor_rule.text = 'á' + apply_masks!(data, "application/octet-stream", :censor_rules => @censor_rules).should == 'x mouse' + end + + it "should apply censor rules to HTML files" do + data = "There was a mouse called Stilton, he wished that he was blue." + apply_masks!(data, 'text/html', :censor_rules => @censor_rules) + data.should == "There was a cat called Jarlsberg, he wished that he was yellow." + end + + end + + it "should replace ASCII email addresses in Word documents" do + data = "His email was foo@bar.com" + expected = "His email was xxx@xxx.xxx" + apply_masks!(data, "application/vnd.ms-word") + data.should == expected + end + + + it "should replace UCS-2 addresses in Word documents" do + data = "His email was f\000o\000o\000@\000b\000a\000r\000.\000c\000o\000m\000, indeed" + apply_masks!(data, "application/vnd.ms-word") + data.should == "His email was x\000x\000x\000@\000x\000x\000x\000.\000x\000x\000x\000, indeed" + end + + def pdf_replacement_test(use_ghostscript_compression) + config = MySociety::Config.load_default() + previous = config['USE_GHOSTSCRIPT_COMPRESSION'] + config['USE_GHOSTSCRIPT_COMPRESSION'] = use_ghostscript_compression + orig_pdf = load_file_fixture('tfl.pdf') + pdf = orig_pdf.dup + + orig_text = MailHandler.get_attachment_text_one_file('application/pdf', pdf) + orig_text.should match(/foi@tfl.gov.uk/) + + apply_masks!(pdf, "application/pdf") + + masked_text = MailHandler.get_attachment_text_one_file('application/pdf', pdf) + masked_text.should_not match(/foi@tfl.gov.uk/) + masked_text.should match(/xxx@xxx.xxx.xx/) + config['USE_GHOSTSCRIPT_COMPRESSION'] = previous + end + + it "should replace everything in PDF files using pdftk" do + pdf_replacement_test(false) + end + + it "should replace everything in PDF files using ghostscript" do + pdf_replacement_test(true) + end + + it "should not produce zero length output if pdftk silently fails" do + orig_pdf = load_file_fixture('psni.pdf') + pdf = orig_pdf.dup + apply_masks!(pdf, "application/pdf") + pdf.should_not == "" + end + + it "should apply hard-coded privacy rules to HTML files" do + data = "http://test.host/c/cheese" + apply_masks!(data, 'text/html') + data.should == "[Alaveteli login link]" + end + + it 'should replace a simple email address' do + expected = "the address is [email address]" + apply_masks!("the address is test@example.com", 'text/html', {}).should == expected + end + + it 'should replace a mobile phone number prefixed with "Mobile"' do + expected = "the mobile is [mobile number]" + apply_masks!("the mobile is Mobile 55555 555555", 'text/html', {}).should == expected + end + + it 'should replace a mobile phone number prefixed with "Mob Tel"' do + expected = "the mobile is [mobile number]" + apply_masks!("the mobile is Mob Tel: 55555 555 555", 'text/html', {}).should == expected + end + + it 'should replace a mobile phone number prefixed with "Mob/Fax:"' do + expected = "the mobile is [mobile number]" + apply_masks!("the mobile is Mob/Fax: 55555 555555", 'text/html', {}).should == expected + end + + it "should replace an Alaveteli login link" do + expected = "the login link is [Alaveteli login link]" + apply_masks!("the login link is http://test.host/c/ekfmsdfkm", 'text/html', {}).should == expected + end + + it "should replace a https Alaveteli login link" do + expected = "the login link is [Alaveteli login link]" + apply_masks!("the login link is https://test.host/c/ekfmsdfkm", 'text/html', {}).should == expected + end + + it "should apply censor rules to text" do + censor_rule = FactoryGirl.build(:censor_rule, :text => 'mouse', :replacement => 'cat') + expected = "here is a cat" + apply_masks!("here is a mouse", 'text/html', {:censor_rules => [ censor_rule ]}).should == expected + end + + it 'should apply extra masks to text' do + mask = {:to_replace => 'mouse', :replacement => 'cat'} + expected = "here is a cat" + apply_masks!("here is a mouse", 'text/html', {:masks => [ mask ]}).should == expected + end + + end + +end + diff --git a/spec/mailers/outgoing_mailer_spec.rb b/spec/mailers/outgoing_mailer_spec.rb index a11d56dd3..3df5018fe 100644 --- a/spec/mailers/outgoing_mailer_spec.rb +++ b/spec/mailers/outgoing_mailer_spec.rb @@ -75,14 +75,14 @@ describe OutgoingMailer, "when working out follow up subjects" do ir = info_requests(:fancy_dog_request) im = ir.incoming_messages[0] - ir.email_subject_request.should == "Freedom of Information request - Why do you have & such a fancy dog?" + ir.email_subject_request(:html => false).should == "Freedom of Information request - Why do you have & such a fancy dog?" end it "should use 'Re:' and inital request subject for followups which aren't replies to particular messages" do ir = info_requests(:fancy_dog_request) om = outgoing_messages(:useless_outgoing_message) - OutgoingMailer.subject_for_followup(ir, om).should == "Re: Freedom of Information request - Why do you have & such a fancy dog?" + OutgoingMailer.subject_for_followup(ir, om, :html => false).should == "Re: Freedom of Information request - Why do you have & such a fancy dog?" end it "should prefix with Re: the subject of the message being replied to" do @@ -91,7 +91,7 @@ describe OutgoingMailer, "when working out follow up subjects" do om = outgoing_messages(:useless_outgoing_message) om.incoming_message_followup = im - OutgoingMailer.subject_for_followup(ir, om).should == "Re: Geraldine FOI Code AZXB421" + OutgoingMailer.subject_for_followup(ir, om, :html => false).should == "Re: Geraldine FOI Code AZXB421" end it "should not add Re: prefix if there already is such a prefix" do @@ -101,7 +101,7 @@ describe OutgoingMailer, "when working out follow up subjects" do om.incoming_message_followup = im im.raw_email.data = im.raw_email.data.sub("Subject: Geraldine FOI Code AZXB421", "Subject: Re: Geraldine FOI Code AZXB421") - OutgoingMailer.subject_for_followup(ir, om).should == "Re: Geraldine FOI Code AZXB421" + OutgoingMailer.subject_for_followup(ir, om, :html => false).should == "Re: Geraldine FOI Code AZXB421" end it "should not add Re: prefix if there already is a lower case re: prefix" do @@ -113,7 +113,7 @@ describe OutgoingMailer, "when working out follow up subjects" do im.raw_email.data = im.raw_email.data.sub("Subject: Geraldine FOI Code AZXB421", "Subject: re: Geraldine FOI Code AZXB421") im.parse_raw_email! true - OutgoingMailer.subject_for_followup(ir, om).should == "re: Geraldine FOI Code AZXB421" + OutgoingMailer.subject_for_followup(ir, om, :html => false).should == "re: Geraldine FOI Code AZXB421" end it "should use 'Re:' and initial request subject when replying to failed delivery notifications" do @@ -126,7 +126,7 @@ describe OutgoingMailer, "when working out follow up subjects" do im.raw_email.data = im.raw_email.data.sub("Subject: Geraldine FOI Code AZXB421", "Subject: Delivery Failed") im.parse_raw_email! true - OutgoingMailer.subject_for_followup(ir, om).should == "Re: Freedom of Information request - Why do you have & such a fancy dog?" + OutgoingMailer.subject_for_followup(ir, om, :html => false).should == "Re: Freedom of Information request - Why do you have & such a fancy dog?" end end diff --git a/spec/mailers/request_mailer_spec.rb b/spec/mailers/request_mailer_spec.rb index 8ba2a7bec..9e98dbc00 100644 --- a/spec/mailers/request_mailer_spec.rb +++ b/spec/mailers/request_mailer_spec.rb @@ -427,8 +427,7 @@ describe RequestMailer, 'requires_admin' do it 'body should contain the full admin URL' do mail = RequestMailer.requires_admin(@info_request).deliver - - mail.body.should include('http://test.host/en/admin/request/show/123') + mail.body.should include('http://test.host/en/admin/requests/123') end it "body should contain the message from the user" do diff --git a/spec/models/holiday_import_spec.rb b/spec/models/holiday_import_spec.rb new file mode 100644 index 000000000..21061f63f --- /dev/null +++ b/spec/models/holiday_import_spec.rb @@ -0,0 +1,157 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe HolidayImport do + + it 'validates the presence of a feed if the source is a feed' do + holiday_import = HolidayImport.new(:source => 'feed') + holiday_import.valid?.should be_false + holiday_import.errors[:ical_feed_url].should == ["can't be blank"] + end + + it 'does not validate the presence of a feed if the source is suggestions' do + holiday_import = HolidayImport.new(:source => 'suggestions') + holiday_import.valid?.should be_true + end + + it 'validates that the source is either "feed" or "suggestions"' do + holiday_import = HolidayImport.new(:source => 'something') + holiday_import.valid?.should be_false + holiday_import.errors[:source].should == ["is not included in the list"] + end + + it 'validates that all holidays create from attributes are valid' do + holiday_import = HolidayImport.new(:source => 'suggestions', + :holidays_attributes => {"0" => {:description => '', + "day(1i)"=>"", + "day(2i)"=>"", + "day(3i)"=>""}}) + holiday_import.valid?.should be_false + holiday_import.errors[:base].should == ["These holidays could not be imported"] + end + + it 'validates that all holidays to import are valid' do + holiday_import = HolidayImport.new + holiday_import.holidays = [ Holiday.new ] + holiday_import.valid?.should be_false + holiday_import.errors[:base].should == ['These holidays could not be imported'] + end + + it 'defaults to importing holidays for the current year' do + holiday_import = HolidayImport.new + holiday_import.start_year.should == Time.now.year + holiday_import.end_year.should == Time.now.year + end + + it 'allows the start and end year to be set' do + holiday_import = HolidayImport.new(:start_year => 2011, :end_year => 2012) + holiday_import.start_year.should == 2011 + holiday_import.end_year.should == 2012 + end + + it 'sets the start and end dates to the beginning and end of the year' do + holiday_import = HolidayImport.new(:start_year => 2011, :end_year => 2012) + holiday_import.start_date.should == Date.new(2011, 1, 1) + holiday_import.end_date.should == Date.new(2012, 12, 31) + end + + it 'sets a default source of suggestions' do + holiday_import = HolidayImport.new + holiday_import.source.should == 'suggestions' + end + + it 'allows the source to be set' do + holiday_import = HolidayImport.new(:source => 'feed') + holiday_import.source.should == 'feed' + end + + it 'allows an iCal feed URL to be set' do + holiday_import = HolidayImport.new(:ical_feed_url => 'http://www.example.com') + holiday_import.ical_feed_url.should == 'http://www.example.com' + end + + it 'sets a default populated flag to false' do + holiday_import = HolidayImport.new + holiday_import.populated.should == false + end + + it 'returns a readable description of the period for multiple years' do + HolidayImport.new(:start_year => 2011, :end_year => 2012).period.should == '2011-2012' + end + + it 'returns a readable description of the period for a single year' do + HolidayImport.new(:start_year => 2011, :end_year => 2011).period.should == '2011' + end + + it 'returns the country name for which suggestions are generated' do + HolidayImport.new.suggestions_country_name.should == 'Germany' + end + + describe 'when populating a set of holidays to import from suggestions' do + + before do + holidays = [ { :date => Date.new(2014, 1, 1), :name => "New Year's Day", :regions => [:gb] } ] + Holidays.stub!(:between).and_return(holidays) + @holiday_import = HolidayImport.new(:source => 'suggestions') + @holiday_import.populate + end + + it 'should populate holidays from the suggestions' do + @holiday_import.holidays.size.should == 1 + holiday = @holiday_import.holidays.first + holiday.description.should == "New Year's Day" + holiday.day.should == Date.new(2014, 1, 1) + end + + it 'should return a flag that it has been populated' do + @holiday_import.populated.should == true + end + + end + + describe 'when populating a set of holidays to import from a feed' do + + before do + @holiday_import = HolidayImport.new(:source => 'feed', + :ical_feed_url => 'http://www.example.com', + :start_year => 2014, + :end_year => 2014) + end + + it 'should populate holidays from the feed that are between the dates' do + @holiday_import.stub!(:open).and_return(load_file_fixture('ical-holidays.ics')) + @holiday_import.populate + @holiday_import.holidays.size.should == 1 + holiday = @holiday_import.holidays.first + holiday.description.should == "New Year's Day" + holiday.day.should == Date.new(2014, 1, 1) + end + + it 'should add an error if the calendar cannot be parsed' do + @holiday_import.stub!(:open).and_return('some invalid data') + @holiday_import.populate + expected = ["Sorry, there's a problem with the format of that feed."] + @holiday_import.errors[:ical_feed_url].should == expected + end + + it 'should add an error if the calendar cannot be found' do + @holiday_import.stub!(:open).and_raise Errno::ENOENT.new('No such file or directory') + @holiday_import.populate + expected = ["Sorry we couldn't find that feed."] + @holiday_import.errors[:ical_feed_url].should == expected + end + + end + + describe 'when saving' do + + it 'saves all holidays' do + holiday = Holiday.new + holiday_import = HolidayImport.new + holiday_import.holidays = [ holiday ] + holiday.should_receive(:save) + holiday_import.save + end + + end + +end diff --git a/spec/models/holiday_spec.rb b/spec/models/holiday_spec.rb index 89849abb7..2f8eeabd9 100644 --- a/spec/models/holiday_spec.rb +++ b/spec/models/holiday_spec.rb @@ -9,87 +9,98 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') -describe Holiday, " when calculating due date" do +describe Holiday do - def due_date(ymd) - return Holiday.due_date_from_working_days(Date.strptime(ymd), 20).strftime("%F") - end + describe :new do - context "in working days" do - it "handles no holidays" do - due_date('2008-10-01').should == '2008-10-29' + it 'should require a day' do + holiday = Holiday.new + holiday.valid?.should be_false + holiday.errors[:day].should == ["can't be blank"] end + end - it "handles non leap years" do - due_date('2007-02-01').should == '2007-03-01' - end + describe " when calculating due date" do - it "handles leap years" do - due_date('2008-02-01').should == '2008-02-29' + def due_date(ymd) + return Holiday.due_date_from_working_days(Date.strptime(ymd), 20).strftime("%F") end - it "handles Thursday start" do - due_date('2009-03-12').should == '2009-04-14' - end + context "in working days" do + it "handles no holidays" do + due_date('2008-10-01').should == '2008-10-29' + end - it "handles Friday start" do - due_date('2009-03-13').should == '2009-04-15' - end + it "handles non leap years" do + due_date('2007-02-01').should == '2007-03-01' + end - # Delivery at the weekend ends up the same due day as if it had arrived on - # the Friday before. This is because the next working day (Monday) counts - # as day 1. - # See http://www.whatdotheyknow.com/help/officers#days - it "handles Saturday start" do - due_date('2009-03-14').should == '2009-04-15' - end - it "handles Sunday start" do - due_date('2009-03-15').should == '2009-04-15' - end + it "handles leap years" do + due_date('2008-02-01').should == '2008-02-29' + end - it "handles Monday start" do - due_date('2009-03-16').should == '2009-04-16' - end + it "handles Thursday start" do + due_date('2009-03-12').should == '2009-04-14' + end - it "handles Time objects" do - Holiday.due_date_from_working_days(Time.utc(2009, 03, 16, 12, 0, 0), 20).strftime('%F').should == '2009-04-16' - end - end + it "handles Friday start" do + due_date('2009-03-13').should == '2009-04-15' + end - context "in calendar days" do - it "handles no holidays" do - Holiday.due_date_from_calendar_days(Date.new(2008, 10, 1), 20).should == Date.new(2008, 10, 21) - end + # Delivery at the weekend ends up the same due day as if it had arrived on + # the Friday before. This is because the next working day (Monday) counts + # as day 1. + # See http://www.whatdotheyknow.com/help/officers#days + it "handles Saturday start" do + due_date('2009-03-14').should == '2009-04-15' + end + it "handles Sunday start" do + due_date('2009-03-15').should == '2009-04-15' + end - it "handles the due date falling on a Friday" do - Holiday.due_date_from_calendar_days(Date.new(2008, 10, 4), 20).should == Date.new(2008, 10, 24) - end + it "handles Monday start" do + due_date('2009-03-16').should == '2009-04-16' + end - # If the due date would fall on a Saturday it should in fact fall on the next day that isn't a weekend - # or a holiday - it "handles the due date falling on a Saturday" do - Holiday.due_date_from_calendar_days(Date.new(2008, 10, 5), 20).should == Date.new(2008, 10, 27) + it "handles Time objects" do + Holiday.due_date_from_working_days(Time.utc(2009, 03, 16, 12, 0, 0), 20).strftime('%F').should == '2009-04-16' + end end - it "handles the due date falling on a Sunday" do - Holiday.due_date_from_calendar_days(Date.new(2008, 10, 6), 20).should == Date.new(2008, 10, 27) - end + context "in calendar days" do + it "handles no holidays" do + Holiday.due_date_from_calendar_days(Date.new(2008, 10, 1), 20).should == Date.new(2008, 10, 21) + end - it "handles the due date falling on a Monday" do - Holiday.due_date_from_calendar_days(Date.new(2008, 10, 7), 20).should == Date.new(2008, 10, 27) - end + it "handles the due date falling on a Friday" do + Holiday.due_date_from_calendar_days(Date.new(2008, 10, 4), 20).should == Date.new(2008, 10, 24) + end - it "handles the due date falling on a day before a Holiday" do - Holiday.due_date_from_calendar_days(Date.new(2008, 12, 4), 20).should == Date.new(2008, 12, 24) - end + # If the due date would fall on a Saturday it should in fact fall on the next day that isn't a weekend + # or a holiday + it "handles the due date falling on a Saturday" do + Holiday.due_date_from_calendar_days(Date.new(2008, 10, 5), 20).should == Date.new(2008, 10, 27) + end - it "handles the due date falling on a Holiday" do - Holiday.due_date_from_calendar_days(Date.new(2008, 12, 5), 20).should == Date.new(2008, 12, 29) - end + it "handles the due date falling on a Sunday" do + Holiday.due_date_from_calendar_days(Date.new(2008, 10, 6), 20).should == Date.new(2008, 10, 27) + end + + it "handles the due date falling on a Monday" do + Holiday.due_date_from_calendar_days(Date.new(2008, 10, 7), 20).should == Date.new(2008, 10, 27) + end + + it "handles the due date falling on a day before a Holiday" do + Holiday.due_date_from_calendar_days(Date.new(2008, 12, 4), 20).should == Date.new(2008, 12, 24) + end - it "handles Time objects" do - Holiday.due_date_from_calendar_days(Time.utc(2009, 03, 17, 12, 0, 0), 20).should == Date.new(2009, 4, 6) + it "handles the due date falling on a Holiday" do + Holiday.due_date_from_calendar_days(Date.new(2008, 12, 5), 20).should == Date.new(2008, 12, 29) + end + + it "handles Time objects" do + Holiday.due_date_from_calendar_days(Time.utc(2009, 03, 17, 12, 0, 0), 20).should == Date.new(2009, 4, 6) + end end end end - diff --git a/spec/models/incoming_message_spec.rb b/spec/models/incoming_message_spec.rb index 3b6887f76..f6e524de3 100644 --- a/spec/models/incoming_message_spec.rb +++ b/spec/models/incoming_message_spec.rb @@ -423,127 +423,50 @@ describe IncomingMessage, " checking validity to reply to with real emails" do end -describe IncomingMessage, " when censoring data" do - - before(:each) do - @test_data = "There was a mouse called Stilton, he wished that he was blue." - - @im = incoming_messages(:useless_incoming_message) - - @censor_rule_1 = CensorRule.new() - @censor_rule_1.text = "Stilton" - @censor_rule_1.replacement = "Jarlsberg" - @censor_rule_1.last_edit_editor = "unknown" - @censor_rule_1.last_edit_comment = "none" - @im.info_request.censor_rules << @censor_rule_1 - - @censor_rule_2 = CensorRule.new() - @censor_rule_2.text = "blue" - @censor_rule_2.replacement = "yellow" - @censor_rule_2.last_edit_editor = "unknown" - @censor_rule_2.last_edit_comment = "none" - @im.info_request.censor_rules << @censor_rule_2 - - @regex_censor_rule = CensorRule.new() - @regex_censor_rule.text = 'm[a-z][a-z][a-z]e' - @regex_censor_rule.regexp = true - @regex_censor_rule.replacement = 'cat' - @regex_censor_rule.last_edit_editor = 'unknown' - @regex_censor_rule.last_edit_comment = 'none' - @im.info_request.censor_rules << @regex_censor_rule - load_raw_emails_data - end - - it "should do nothing to a JPEG" do - data = @test_data.dup - @im.binary_mask_stuff!(data, "image/jpeg") - data.should == @test_data - end - - it "should replace censor text in Word documents" do - data = @test_data.dup - @im.binary_mask_stuff!(data, "application/vnd.ms-word") - data.should == "There was a xxxxx called xxxxxxx, he wished that he was xxxx." - end - - it "should replace ASCII email addresses in Word documents" do - orig_data = "His email was foo@bar.com" - data = orig_data.dup - @im.binary_mask_stuff!(data, "application/vnd.ms-word") - data.should == "His email was xxx@xxx.xxx" - end - - it "should replace UCS-2 addresses in Word documents" do - orig_data = "His email was f\000o\000o\000@\000b\000a\000r\000.\000c\000o\000m\000, indeed" - data = orig_data.dup - @im.binary_mask_stuff!(data, "application/vnd.ms-word") - data.should == "His email was x\000x\000x\000@\000x\000x\000x\000.\000x\000x\000x\000, indeed" - end - - it 'should handle multibyte characters correctly' do - orig_data = 'á' - data = orig_data.dup - @regex_censor_rule = CensorRule.new() - @regex_censor_rule.text = 'á' - @regex_censor_rule.regexp = true - @regex_censor_rule.replacement = 'cat' - @regex_censor_rule.last_edit_editor = 'unknown' - @regex_censor_rule.last_edit_comment = 'none' - @im.info_request.censor_rules << @regex_censor_rule - lambda{ @im.binary_mask_stuff!(data, "text/plain") }.should_not raise_error - end - def pdf_replacement_test(use_ghostscript_compression) - config = MySociety::Config.load_default() - previous = config['USE_GHOSTSCRIPT_COMPRESSION'] - config['USE_GHOSTSCRIPT_COMPRESSION'] = use_ghostscript_compression - orig_pdf = load_file_fixture('tfl.pdf') - pdf = orig_pdf.dup - - orig_text = MailHandler.get_attachment_text_one_file('application/pdf', pdf) - orig_text.should match(/foi@tfl.gov.uk/) - - @im.binary_mask_stuff!(pdf, "application/pdf") - - masked_text = MailHandler.get_attachment_text_one_file('application/pdf', pdf) - masked_text.should_not match(/foi@tfl.gov.uk/) - masked_text.should match(/xxx@xxx.xxx.xx/) - config['USE_GHOSTSCRIPT_COMPRESSION'] = previous - end - - it "should replace everything in PDF files using pdftk" do - pdf_replacement_test(false) - end - - it "should replace everything in PDF files using ghostscript" do - pdf_replacement_test(true) - end - - it "should not produce zero length output if pdftk silently fails" do - orig_pdf = load_file_fixture('psni.pdf') - pdf = orig_pdf.dup - @im.binary_mask_stuff!(pdf, "application/pdf") - pdf.should_not == "" - end - - it "should apply censor rules to HTML files" do - data = @test_data.dup - @im.html_mask_stuff!(data) - data.should == "There was a cat called Jarlsberg, he wished that he was yellow." - end - - it "should apply hard-coded privacy rules to HTML files" do - data = "http://#{AlaveteliConfiguration::domain}/c/cheese" - @im.html_mask_stuff!(data) - data.should == "[WDTK login link]" - end +describe IncomingMessage, " when censoring data" do - it "should apply censor rules to From: addresses" do - @im.stub!(:mail_from).and_return("Stilton Mouse") - @im.stub!(:last_parsed).and_return(Time.now) - safe_mail_from = @im.safe_mail_from - safe_mail_from.should == "Jarlsberg Mouse" - end + before(:each) do + @test_data = "There was a mouse called Stilton, he wished that he was blue." + + @im = incoming_messages(:useless_incoming_message) + + @censor_rule_1 = CensorRule.new() + @censor_rule_1.text = "Stilton" + @censor_rule_1.replacement = "Jarlsberg" + @censor_rule_1.last_edit_editor = "unknown" + @censor_rule_1.last_edit_comment = "none" + @im.info_request.censor_rules << @censor_rule_1 + + @censor_rule_2 = CensorRule.new() + @censor_rule_2.text = "blue" + @censor_rule_2.replacement = "yellow" + @censor_rule_2.last_edit_editor = "unknown" + @censor_rule_2.last_edit_comment = "none" + @im.info_request.censor_rules << @censor_rule_2 + + @regex_censor_rule = CensorRule.new() + @regex_censor_rule.text = 'm[a-z][a-z][a-z]e' + @regex_censor_rule.regexp = true + @regex_censor_rule.replacement = 'cat' + @regex_censor_rule.last_edit_editor = 'unknown' + @regex_censor_rule.last_edit_comment = 'none' + @im.info_request.censor_rules << @regex_censor_rule + load_raw_emails_data + end + + it "should replace censor text" do + data = "There was a mouse called Stilton, he wished that he was blue." + @im.apply_masks!(data, "application/vnd.ms-word") + data.should == "There was a xxxxx called xxxxxxx, he wished that he was xxxx." + end + + it "should apply censor rules to From: addresses" do + @im.stub!(:mail_from).and_return("Stilton Mouse") + @im.stub!(:last_parsed).and_return(Time.now) + safe_mail_from = @im.safe_mail_from + safe_mail_from.should == "Jarlsberg Mouse" + end end @@ -565,15 +488,16 @@ describe IncomingMessage, " when censoring whole users" do it "should apply censor rules to HTML files" do data = @test_data.dup - @im.html_mask_stuff!(data) + @im.apply_masks!(data, 'text/html') data.should == "There was a mouse called Gorgonzola, he wished that he was blue." end it "should replace censor text to Word documents" do data = @test_data.dup - @im.binary_mask_stuff!(data, "application/vnd.ms-word") + @im.apply_masks!(data, "application/vnd.ms-word") data.should == "There was a mouse called xxxxxxx, he wished that he was blue." end + end @@ -770,3 +694,16 @@ describe IncomingMessage, "when extracting attachments" do end end + +describe IncomingMessage, 'when getting the body of a message for html display' do + + it 'should replace any masked email addresses with a link to the help page' do + incoming_message = IncomingMessage.new + body_text = 'there was an [email address] here' + incoming_message.stub!(:get_main_body_text_folded).and_return(body_text) + incoming_message.stub!(:get_main_body_text_unfolded).and_return(body_text) + expected = 'there was an [<a href="/help/officers#mobiles">email address</a>] here' + incoming_message.get_body_for_html_display.should == expected + end + +end diff --git a/spec/models/info_request_spec.rb b/spec/models/info_request_spec.rb index 9ad616ea5..70947584b 100644 --- a/spec/models/info_request_spec.rb +++ b/spec/models/info_request_spec.rb @@ -824,7 +824,7 @@ describe InfoRequest do im = mock_model(IncomingMessage, :subject => nil, :valid_to_reply_to? => true) - subject = ir.email_subject_followup im + subject = ir.email_subject_followup(:incoming_message => im, :html => false) subject.should match(/^Re: Freedom of Information request.*fancy dog/) end diff --git a/spec/models/public_body_category_link_spec.rb b/spec/models/public_body_category_link_spec.rb index 8d91f02d5..fd5608480 100644 --- a/spec/models/public_body_category_link_spec.rb +++ b/spec/models/public_body_category_link_spec.rb @@ -1,10 +1,11 @@ # == Schema Information # -# Table name: public_body_category_link +# Table name: public_body_category_links # -# public_body_category_id :integer not null -# public_body_heading_id :integer not null -# category_display_order :integer +# public_body_category_id :integer not null +# public_body_heading_id :integer not null +# category_display_order :integer +# id :integer not null, primary key # require 'spec_helper' diff --git a/spec/models/public_body_category_spec.rb b/spec/models/public_body_category_spec.rb index c185a3169..96fe5686b 100644 --- a/spec/models/public_body_category_spec.rb +++ b/spec/models/public_body_category_spec.rb @@ -2,12 +2,8 @@ # # Table name: public_body_categories # -# id :integer not null, primary key -# locale :string -# title :text not null -# category_tag :text not null -# description :text not null -# display_order :integer +# id :integer not null, primary key +# category_tag :text not null # require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') diff --git a/spec/models/public_body_heading_spec.rb b/spec/models/public_body_heading_spec.rb index add2cac60..9372e0a07 100644 --- a/spec/models/public_body_heading_spec.rb +++ b/spec/models/public_body_heading_spec.rb @@ -2,9 +2,7 @@ # # Table name: public_body_headings # -# id :integer not null, primary key -# locale :string -# name :text not null +# id :integer not null, primary key # display_order :integer # diff --git a/spec/models/public_body_spec.rb b/spec/models/public_body_spec.rb index f12582f21..a9e801bfd 100644 --- a/spec/models/public_body_spec.rb +++ b/spec/models/public_body_spec.rb @@ -30,6 +30,112 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe PublicBody do + describe :type_of_authority do + + it 'falls back to "A public authority"' do + public_body = FactoryGirl.build(:public_body) + expect(public_body.type_of_authority).to eq('A public authority') + end + + it 'handles Unicode' do + category = FactoryGirl.create(:public_body_category, :category_tag => 'spec', + :description => 'ünicode category') + heading = FactoryGirl.create(:public_body_heading) + heading.add_category(category) + public_body = FactoryGirl.create(:public_body, :tag_string => 'spec') + + + expect(public_body.type_of_authority).to eq('Ünicode category') + end + + it 'constructs the correct string if there are tags which are not categories' do + heading = FactoryGirl.create(:public_body_heading) + 3.times do |i| + category = FactoryGirl.create(:public_body_category, :category_tag => "spec_#{i}", + :description => "spec category #{i}") + heading.add_category(category) + end + public_body = FactoryGirl.create(:public_body, :tag_string => 'spec_0 spec_2 unknown') + + expect(public_body.type_of_authority).to eq('Spec category 0 and spec category 2') + end + + context 'when associated with one category' do + + it 'returns the capitalised category description' do + category = FactoryGirl.create(:public_body_category, :category_tag => 'spec', + :description => 'spec category') + heading = FactoryGirl.create(:public_body_heading) + heading.add_category(category) + public_body = FactoryGirl.create(:public_body, :tag_string => 'spec') + + expect(public_body.type_of_authority).to eq('Spec category') + end + + end + + context 'when associated with several categories' do + + it 'joins the category descriptions and capitalizes the first letter' do + heading = FactoryGirl.create(:public_body_heading) + 3.times do |i| + category = FactoryGirl.create(:public_body_category, :category_tag => "spec_#{i}", + :description => "spec category #{i}") + heading.add_category(category) + end + public_body = FactoryGirl.create(:public_body, :tag_string => 'spec_0 spec_1 spec_2') + + description = 'Spec category 0, spec category 1 and spec category 2' + expect(public_body.type_of_authority).to eq(description) + end + + end + + context 'when the html parameter is true' do + + context 'when associated with one category' do + + it 'returns the description wrapped in an anchor tag' do + category = FactoryGirl.create(:public_body_category, :category_tag => 'spec', + :description => 'spec category') + heading = FactoryGirl.create(:public_body_heading) + heading.add_category(category) + public_body = FactoryGirl.create(:public_body, :tag_string => 'spec') + + anchor = %Q(<a href="/body/list/spec">Spec category</a>) + expect(public_body.type_of_authority(true)).to eq(anchor) + end + + end + + context 'when associated with several categories' do + + it 'joins the category descriptions and capitalizes the first letter' do + heading = FactoryGirl.create(:public_body_heading) + 3.times do |i| + category = FactoryGirl.create(:public_body_category, :category_tag => "spec_#{i}", + :description => "spec category #{i}") + heading.add_category(category) + end + public_body = FactoryGirl.create(:public_body, :tag_string => 'spec_0 spec_1 spec_2') + + description = [ + %Q(<a href="/body/list/spec_0">Spec category 0</a>), + ', ', + %Q(<a href="/body/list/spec_1">spec category 1</a>), + ' and ', + %Q(<a href="/body/list/spec_2">spec category 2</a>) + ].join('') + + expect(public_body.type_of_authority(true)).to eq(description) + end + + end + + end + + end + describe :translations_attributes= do context 'translation_attrs is a Hash' do |