diff --git a/app/assets/stylesheets/responsive/_citations.scss b/app/assets/stylesheets/responsive/_citations.scss
new file mode 100644
index 0000000000..e84e21d271
--- /dev/null
+++ b/app/assets/stylesheets/responsive/_citations.scss
@@ -0,0 +1,33 @@
+.citations-types {
+ border-top: 1px solid #d1d1d1;
+ border-bottom: 1px solid #d1d1d1;
+ margin-top: 2em;
+ margin-bottom: 1em;
+}
+
+ul.citations-list {
+ list-style: none;
+ padding-left: 0;
+
+ li.citations-list__citation {
+ padding: 1em 0;
+ border-bottom: 1px solid #d1d1d1;
+
+ display: flex;
+ align-items: flex-start;
+ gap: 1em;
+
+ .citation_icon {
+ flex-shrink: 0;
+ }
+
+ .citation__title {
+ flex-basis: 50%;
+ word-break: break-word;
+ }
+
+ .citation__description {
+ flex-basis: 50%;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/responsive/_sidebar_layout.scss b/app/assets/stylesheets/responsive/_sidebar_layout.scss
index 8b8c6691d4..d0d689eac3 100644
--- a/app/assets/stylesheets/responsive/_sidebar_layout.scss
+++ b/app/assets/stylesheets/responsive/_sidebar_layout.scss
@@ -36,7 +36,7 @@
}
.sidebar__section.citations {
- .citations-list {
+ .citations-list--compact {
overflow-wrap: break-word;
}
}
diff --git a/app/assets/stylesheets/responsive/_sidebar_style.scss b/app/assets/stylesheets/responsive/_sidebar_style.scss
index 094a85d0df..29bc3d11df 100644
--- a/app/assets/stylesheets/responsive/_sidebar_style.scss
+++ b/app/assets/stylesheets/responsive/_sidebar_style.scss
@@ -109,7 +109,7 @@
}
.sidebar__section.citations {
- .citations-list {
+ .citations-list--compact {
list-style: none;
padding: 0;
}
diff --git a/app/assets/stylesheets/responsive/all.scss b/app/assets/stylesheets/responsive/all.scss
index 0181ce6d08..deed7da137 100644
--- a/app/assets/stylesheets/responsive/all.scss
+++ b/app/assets/stylesheets/responsive/all.scss
@@ -89,6 +89,8 @@
@import "responsive/_notes_layout.scss";
@import "responsive/_notes_styles.scss";
+@import "responsive/_citations";
+
@import "responsive/alaveteli_pro/_pro_layout";
@import "responsive/alaveteli_pro/_pro_style";
diff --git a/app/controllers/admin/citations_controller.rb b/app/controllers/admin/citations_controller.rb
index 51a42fa130..f5d0d348c9 100644
--- a/app/controllers/admin/citations_controller.rb
+++ b/app/controllers/admin/citations_controller.rb
@@ -1,8 +1,36 @@
class Admin::CitationsController < AdminController
+ before_action :find_citation, except: :index
+
def index
@citations =
Citation.
order(created_at: :desc).
paginate(page: params[:page], per_page: 50)
end
+
+ def edit
+ end
+
+ def update
+ if @citation.update(citation_params)
+ redirect_to admin_citations_path, notice: 'Citation updated successfully.'
+ else
+ render :edit
+ end
+ end
+
+ def destroy
+ @citation.destroy
+ redirect_to admin_citations_path, notice: 'Citation deleted successfully.'
+ end
+
+ private
+
+ def find_citation
+ @citation = Citation.find(params[:id])
+ end
+
+ def citation_params
+ params.require(:citation).permit(:source_url, :title, :description)
+ end
end
diff --git a/app/controllers/citations_controller.rb b/app/controllers/citations_controller.rb
index 541c42a5f9..6c1968eddf 100644
--- a/app/controllers/citations_controller.rb
+++ b/app/controllers/citations_controller.rb
@@ -2,9 +2,24 @@
# Controller to create a new Citation for an InfoRequest or an InfoRequestBatch.
#
class CitationsController < ApplicationController
- before_action :authenticate
- before_action :load_resource_and_authorise
- before_action :set_in_pro_area
+ before_action :authenticate, except: :index
+ before_action :load_resource_and_authorise, except: :index
+ before_action :set_in_pro_area, except: :index
+
+ skip_before_action :html_response, only: :index
+
+ def index
+ per_page = 10
+ page = get_search_page_from_params
+
+ @citations = Citation.not_embargoed.order(created_at: :desc).
+ paginate(page: page, per_page: per_page)
+
+ respond_to do |format|
+ format.html { @has_json = true }
+ format.json { render json: @citations }
+ end
+ end
def new
@citation = current_user.citations.build
diff --git a/app/helpers/admin/citations_helper.rb b/app/helpers/admin/citations_helper.rb
index a383aa7d67..a26e947f73 100644
--- a/app/helpers/admin/citations_helper.rb
+++ b/app/helpers/admin/citations_helper.rb
@@ -3,16 +3,24 @@ module Admin::CitationsHelper
ICONS = {
journalism: '🗞️',
campaigning: '📣',
- academic: '🎓',
+ research: '📚',
other: '🌐'
}.with_indifferent_access.freeze
+ def citation_title(citation)
+ citation.title.presence || citation.source_url
+ end
+
def citation_icon(citation)
+ citation_icon_for_type(citation.type)
+ end
+
+ def citation_icon_for_type(type)
html_attrs = {
- title: citation.type.humanize,
- class: "citation-icon citation-icon--#{citation.type}"
+ title: type.humanize,
+ class: "citation-icon citation-icon--#{type}"
}
- tag.span(ICONS.fetch(citation.type), **html_attrs)
+ tag.span(ICONS.fetch(type), **html_attrs)
end
end
diff --git a/app/helpers/admin/link_helper.rb b/app/helpers/admin/link_helper.rb
index d9241392d8..8cc4c433c6 100644
--- a/app/helpers/admin/link_helper.rb
+++ b/app/helpers/admin/link_helper.rb
@@ -108,6 +108,15 @@ def category_both_links(category)
title: admin_title)
end
+ def citation_both_links(citation)
+ title = 'View citation'
+ icon = eye
+
+ link_to(icon, citation.source_url, title: title) + ' ' +
+ link_to(citation.source_url, edit_admin_citation_path(citation),
+ title: admin_title)
+ end
+
def admin_title
'View full details'
end
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
index b3ed67569f..a52c3985bb 100644
--- a/app/models/application_record.rb
+++ b/app/models/application_record.rb
@@ -8,4 +8,28 @@ class ApplicationRecord < ActiveRecord::Base
def self.admin_title
name
end
+
+ def self.belongs_to(name, scope = nil, **options)
+ if options.key?(:via)
+ via = options.delete(:via)
+ polymorphic_association = reflect_on_association(via)
+
+ unless polymorphic_association&.polymorphic?
+ raise ArgumentError, "Association #{via} must be polymorphic"
+ end
+
+ options[:foreign_key] ||= polymorphic_association.foreign_key
+ options[:class_name] ||= name.to_s.classify
+
+ scope = -> {
+ where(
+ polymorphic_association.active_record.table_name => {
+ polymorphic_association.foreign_type => options[:class_name]
+ }
+ )
+ }
+ end
+
+ super(name, scope, **options)
+ end
end
diff --git a/app/models/citation.rb b/app/models/citation.rb
index 460eb357ef..11bc602fc1 100644
--- a/app/models/citation.rb
+++ b/app/models/citation.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 20210114161442
+# Schema version: 20241007090524
#
# Table name: citations
#
@@ -11,31 +11,48 @@
# type :string
# created_at :datetime not null
# updated_at :datetime not null
+# title :string
+# description :text
#
##
-# A Citation of an InfoRequest or InfoRequestBatch in news stories or an
-# academic paper
+# A Citation of an InfoRequest or InfoRequestBatch
#
class Citation < ApplicationRecord
+ include Rails.application.routes.url_helpers
+ include LinkToHelper
+
self.inheritance_column = nil
belongs_to :user, inverse_of: :citations
belongs_to :citable, polymorphic: true
+ belongs_to :info_request, via: :citable
+ belongs_to :info_request_batch, via: :citable
+
validates :user, :citable, presence: true
validates :citable_type, inclusion: { in: %w(InfoRequest InfoRequestBatch) }
validates :source_url, length: { maximum: 255,
message: _('Source URL is too long') },
format: { with: /\Ahttps?:\/\/.*\z/,
message: _('Please enter a Source URL') }
- validates :type, inclusion: { in: %w(journalism academic campaigning other),
+ validates :type, inclusion: { in: %w(journalism research campaigning other),
message: _('Please select a type') }
scope :newest, ->(limit = 1) do
order(created_at: :desc).limit(limit)
end
+ scope :not_embargoed, -> do
+ left_joins(info_request: :embargo, info_request_batch: []).
+ where(citable_type: 'InfoRequest').
+ merge(InfoRequest.not_embargoed).
+ or(
+ where(citable_type: 'InfoRequestBatch').
+ merge(InfoRequestBatch.not_embargoed)
+ )
+ end
+
scope :for_request, ->(info_request) do
where(citable: info_request).
or(where(citable: info_request.info_request_batch))
@@ -49,4 +66,17 @@ class Citation < ApplicationRecord
def applies_to_batch_request?
citable.is_a?(InfoRequestBatch)
end
+
+ def as_json(_options)
+ citable_path = case citable
+ when InfoRequest
+ request_path(citable)
+ when InfoRequestBatch
+ info_request_batch_path(citable)
+ end
+
+ attributes.
+ except('user_id', 'citable_id', 'citable_type').
+ merge(citable_path: citable_path)
+ end
end
diff --git a/app/views/admin/citations/_list.html.erb b/app/views/admin/citations/_list.html.erb
index d620a9b7f7..63b4a59715 100644
--- a/app/views/admin/citations/_list.html.erb
+++ b/app/views/admin/citations/_list.html.erb
@@ -4,7 +4,7 @@
<%= citation_icon(citation) %>
- <%= link_to citation.source_url, citation.source_url %>
+ <%= both_links(citation) %>
diff --git a/app/views/admin/citations/edit.html.erb b/app/views/admin/citations/edit.html.erb
new file mode 100644
index 0000000000..68469be920
--- /dev/null
+++ b/app/views/admin/citations/edit.html.erb
@@ -0,0 +1,41 @@
+
+
+<%= form_for [:admin, @citation], class: 'form form-inline' do |f| %>
+
+ <%= f.label :source_url %>
+
+ <%= f.text_field :source_url, class: 'form-control' %>
+
+
+
+
+ <%= f.label :title %>
+
+ <%= f.text_field :title, class: 'form-control' %>
+
+
+
+
+ <%= f.label :description, class: 'control-label' %>
+
+ <%= f.text_area :description, class: 'input-block-level', rows: 10 %>
+
+
+
+
+ <%= f.submit 'Update ciation', class: 'btn btn-success' %>
+
+<% end %>
+
+<%= form_for [:admin, @citation], class: 'form form-inline', method: 'delete' do |f| %>
+ <%= f.submit 'Destroy citation',
+ class: 'btn btn-danger',
+ data: { confirm: 'Are you sure? This is irreversible.' } %>
+ (this is permanent!)
+<% end %>
diff --git a/app/views/citations/_citation.html.erb b/app/views/citations/_citation.html.erb
index eb4543302d..88324c94a6 100644
--- a/app/views/citations/_citation.html.erb
+++ b/app/views/citations/_citation.html.erb
@@ -1,7 +1,29 @@
- <%=
- MySociety::Format.make_clickable(
- citation.source_url, contract: true, nofollow: true
- ).html_safe
- %>
+
+ <%= citation_icon(citation) %>
+
+
+
+
<%= link_to citation_title(citation), citation.source_url, rel: 'nofollow' %>
+
+ <% case citation.citable %>
+ <% when InfoRequest %>
+ <%= _('
{{title}} requested from
{{public_body_name}} on {{date}}',
+ title: citation.citable.title,
+ info_request_url: request_path(citation.citable),
+ public_body_name: citation.citable.public_body.name,
+ public_body_url: public_body_path(citation.citable.public_body),
+ date: simple_date(citation.citable.created_at)) %>
+ <% when InfoRequestBatch %>
+ <%= _('
{{title}} part of a batch sent to {{count}} authorities on {{date}}',
+ title: citation.citable.title,
+ info_request_batch_url: info_request_batch_path(citation.citable),
+ count: citation.citable.public_bodies.count,
+ date: simple_date(citation.citable.created_at)) %>
+ <% end %>
+
+
+
+ <%= citation.description %>
+
diff --git a/app/views/citations/_compact.html.erb b/app/views/citations/_compact.html.erb
new file mode 100644
index 0000000000..1df58e66b7
--- /dev/null
+++ b/app/views/citations/_compact.html.erb
@@ -0,0 +1,3 @@
+
+ <%= link_to citation_title(citation), citation.source_url, rel: 'nofollow' %>
+
diff --git a/app/views/citations/index.html.erb b/app/views/citations/index.html.erb
new file mode 100644
index 0000000000..1221e42dd0
--- /dev/null
+++ b/app/views/citations/index.html.erb
@@ -0,0 +1,76 @@
+<% @title = _('FOI in Action') %>
+<%= @title %>
+
+
+ <%= _(<<~TXT)
+ Freedom of Information requests empower individuals, journalists, \
+ researchers, and campaigners to hold organisations accountable and shed \
+ light on matters of public interest. Below are real-world examples where \
+ FOI responses have made a significant impact.
+ TXT
+ %>
+
+
+
+
+
+ <%= citation_icon_for_type('journalism') %>
+ <%= _('Journalism') %>
+
+
+ <%= _(<<~TXT)
+ Journalists often use FOI data to uncover stories that inform the \
+ public, reveal injustices, or investigate policy failures
+ TXT
+ %>
+
+
+
+
+
+ <%= citation_icon_for_type('research') %>
+ <%= _('Research') %>
+
+
+ <%= _(<<~TXT)
+ FOI requests are a valuable tool for researchers seeking data that \
+ might otherwise remain behind closed doors
+ TXT
+ %>
+
+
+
+
+
+ <%= citation_icon_for_type('campaigning') %>
+ <%= _('Campaigning and Advocacy') %>
+
+
+ <%= _(<<~TXT)
+ FOI requests help campaigners bring critical information to light, \
+ often influencing public discourse and policy decisions
+ TXT
+ %>
+
+
+
+
+
+ <%= citation_icon_for_type('other') %>
+ <%= _('Other') %>
+
+
+ <%= _(<<~TXT)
+ FOI requests serve as a cornerstone of democracy by providing \
+ transparency in government and public institutions
+ TXT
+ %>
+
+
+
+
+
+ <%= render @citations %>
+
+
+<%= will_paginate(@citations) %>
diff --git a/app/views/citations/new.html.erb b/app/views/citations/new.html.erb
index 996858f3dd..ac78742a95 100644
--- a/app/views/citations/new.html.erb
+++ b/app/views/citations/new.html.erb
@@ -1,13 +1,17 @@
-<%= _('In the News') %>
+<%= _('FOI in Action') %>
<% if @resource.is_a?(InfoRequestBatch) %>
- <%= _('Has this batch request been referenced in a news article or ' \
- 'academic paper? Let us know:') %>
+ <%= _('Has this batch request been referenced in journalism, ' \
+ 'campaigning, or research?') %>
<% else %>
- <%= _('Has this request been referenced in a news article or academic ' \
- 'paper? Let us know:') %>
+ <%= _('Has this request been referenced in journalism, campaigning, ' \
+ 'or research?') %>
<% end %>
+
+ <%= _('Let us know about great examples of ' \
+ 'FOI in Action .',
+ citations_path: citations_path) %>
<%= form_for @citation,
@@ -40,9 +44,9 @@
<%= _('Campaigning') %>
-
- <%= f.radio_button :type, 'academic' %>
- <%= _('Academic') %>
+
+ <%= f.radio_button :type, 'research' %>
+ <%= _('Research') %>
diff --git a/app/views/info_request_batch/_citations.html.erb b/app/views/info_request_batch/_citations.html.erb
index 26bf65a70f..a4ba0cefba 100644
--- a/app/views/info_request_batch/_citations.html.erb
+++ b/app/views/info_request_batch/_citations.html.erb
@@ -1,23 +1,33 @@
<% if can?(:create_citation, info_request_batch) || citations.any? %>
<% end %>
diff --git a/app/views/request/_citations.html.erb b/app/views/request/_citations.html.erb
index 351c5839dd..1f49396ed9 100644
--- a/app/views/request/_citations.html.erb
+++ b/app/views/request/_citations.html.erb
@@ -1,23 +1,33 @@
<% if can?(:create_citation, info_request) || citations.any? %>
<% end %>
diff --git a/app/views/request/_tabs.html.erb b/app/views/request/_tabs.html.erb
index c833ec344f..4d5c8fc840 100644
--- a/app/views/request/_tabs.html.erb
+++ b/app/views/request/_tabs.html.erb
@@ -5,4 +5,7 @@
<%= link_to _('Browse by category'), requests_path %>
+
+ <%= link_to _('FOI in Action'), citations_path %>
+
<% end %>
diff --git a/config/routes.rb b/config/routes.rb
index 10c4047911..14a77c88c6 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -173,18 +173,29 @@ def matches?(request)
end
####
+ #### Citations controller
+ resources :citations, only: [:index]
+
scope path: 'request/:url_title' do
- #### Citations controller
- resources :citations, only: [:new, :create],
+ resources :citations,
+ only: [:new, :create],
defaults: { resource: 'InfoRequest' }
- ####
+ end
+
+ resources :info_request_batch, :only => :show do
+ resources :citations,
+ only: [:new, :create],
+ defaults: { resource: 'InfoRequestBatch' }
+ end
+ ####
- #### Classifications controller
+ #### Classifications controller
+ scope path: 'request/:url_title' do
resources :classifications, only: [:create], param: :described_state do
get :message, on: :member
end
- ####
end
+ ####
#### Followups controller
match '/request/:request_url_title/followups/new' => 'followups#new',
@@ -237,13 +248,6 @@ def matches?(request)
resources :widget_votes, :only => [:create]
end
- resources :info_request_batch, :only => :show do
- #### Citations controller
- resources :citations, only: [:new, :create],
- defaults: { resource: 'InfoRequestBatch' }
- ####
- end
-
#### OutgoingMessage controller
resources :outgoing_messages, :only => [] do
resource :delivery_status, :only => [:show], :module => 'outgoing_messages'
@@ -528,7 +532,7 @@ def matches?(request)
#### Admin::Citations controller
namespace :admin do
- resources :citations, only: [:index]
+ resources :citations, only: [:index, :edit, :update, :destroy]
end
####
diff --git a/db/migrate/20241001114832_change_citation_type_values_again.rb b/db/migrate/20241001114832_change_citation_type_values_again.rb
new file mode 100644
index 0000000000..b375d234ea
--- /dev/null
+++ b/db/migrate/20241001114832_change_citation_type_values_again.rb
@@ -0,0 +1,21 @@
+class ChangeCitationTypeValuesAgain < ActiveRecord::Migration[7.0]
+ CHANGES = {
+ 'academic' => 'research'
+ }
+
+ def up
+ perform(CHANGES)
+ end
+
+ def down
+ perform(CHANGES.invert)
+ end
+
+ private
+
+ def perform(data)
+ data.each_pair do |before, after|
+ Citation.where(type: before).update_all(type: after)
+ end
+ end
+end
diff --git a/db/migrate/20241007090524_add_title_and_description_to_citations.rb b/db/migrate/20241007090524_add_title_and_description_to_citations.rb
new file mode 100644
index 0000000000..27fbe247ae
--- /dev/null
+++ b/db/migrate/20241007090524_add_title_and_description_to_citations.rb
@@ -0,0 +1,6 @@
+class AddTitleAndDescriptionToCitations < ActiveRecord::Migration[7.0]
+ def change
+ add_column :citations, :title, :string
+ add_column :citations, :description, :text
+ end
+end
diff --git a/doc/CHANGES.md b/doc/CHANGES.md
index d23e713bb7..9482d76981 100644
--- a/doc/CHANGES.md
+++ b/doc/CHANGES.md
@@ -2,6 +2,9 @@
## Highlighted Features
+* Improve citations admin to allow title and description updates (Graeme
+ Porteous)
+* Add public citations view (Graeme Porteous)
* Add project dataset question "select" format (Graeme Porteous)
* Fix script/mailin when multiple EXCEPTION_NOTIFICATIONS_TO addresses are
specified (Graeme Porteous)
@@ -33,7 +36,7 @@
* Strengthen 2FA warning. Users *must* remember to keep this code safe (Gareth
Rees)
* Broaden citation type classifications to cover wider thematic areas and add
- "campaigning" type (Gareth Rees)
+ "campaigning" type (Gareth Rees, Graeme Porteous)
* Treat unstemmed words as normal search terms. (Matthew Somerville)
* Update `/alaveteli_pro` base path to `/pro` (Alexander Griffen, Graeme
Porteous)
diff --git a/spec/controllers/admin/citations_controller_spec.rb b/spec/controllers/admin/citations_controller_spec.rb
index b9a34d43a0..a68f82f1b4 100644
--- a/spec/controllers/admin/citations_controller_spec.rb
+++ b/spec/controllers/admin/citations_controller_spec.rb
@@ -19,4 +19,71 @@
expect(response).to render_template(:index)
end
end
+
+ describe 'GET edit' do
+ let(:citation) { FactoryBot.create(:citation) }
+ before { get :edit, params: { id: citation.id } }
+
+ it 'returns a successful response' do
+ expect(response).to be_successful
+ end
+
+ it 'assigns the citation' do
+ expect(assigns[:citation]).to eq(citation)
+ end
+
+ it 'renders the correct template' do
+ expect(response).to render_template(:edit)
+ end
+ end
+
+ describe 'PUT update' do
+ let(:citation) { FactoryBot.create(:citation) }
+ let(:valid_attributes) { { title: 'Updated Title' } }
+
+ context 'with valid params' do
+ before do
+ put :update, params: { id: citation.id, citation: valid_attributes }
+ end
+
+ it 'updates the citation' do
+ citation.reload
+ expect(citation.title).to eq('Updated Title')
+ end
+
+ it 'redirects to the citation' do
+ expect(response).to redirect_to(admin_citations_url)
+ end
+ end
+
+ context 'with invalid params' do
+ before do
+ put :update, params: { id: citation.id, citation: { source_url: '' } }
+ end
+
+ it 'does not update the citation' do
+ citation.reload
+ expect(citation.source_url).not_to eq('')
+ end
+
+ it 're-renders the edit template' do
+ expect(response).to render_template(:edit)
+ end
+ end
+ end
+
+ describe 'DELETE destroy' do
+ let!(:citation) { FactoryBot.create(:citation) }
+
+ it 'destroys the requested citation' do
+ expect {
+ delete :destroy, params: { id: citation.id }
+ }.to change(Citation, :count).by(-1)
+ end
+
+ it 'redirects to the citations list' do
+ delete :destroy, params: { id: citation.id }
+ expect(response).to redirect_to(admin_citations_url)
+ end
+ end
end
diff --git a/spec/factories/citations.rb b/spec/factories/citations.rb
index b2bbf2ab70..47566c1371 100644
--- a/spec/factories/citations.rb
+++ b/spec/factories/citations.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 20210114161442
+# Schema version: 20241007090524
#
# Table name: citations
#
@@ -11,6 +11,8 @@
# type :string
# created_at :datetime not null
# updated_at :datetime not null
+# title :string
+# description :text
#
FactoryBot.define do
diff --git a/spec/helpers/admin/citations_helper_spec.rb b/spec/helpers/admin/citations_helper_spec.rb
index 1e31a47fa8..290a542bdb 100644
--- a/spec/helpers/admin/citations_helper_spec.rb
+++ b/spec/helpers/admin/citations_helper_spec.rb
@@ -3,6 +3,23 @@
RSpec.describe Admin::CitationsHelper do
include Admin::CitationsHelper
+ describe '#citation_title' do
+ subject { citation_title(citation) }
+
+ context 'with a citation that has a title' do
+ let(:citation) { FactoryBot.build(:citation, title: 'Example Title') }
+ it { is_expected.to eq('Example Title') }
+ end
+
+ context 'with a citation that has a blank title' do
+ let(:citation) do
+ FactoryBot.build(:citation, title: '', source_url: 'http://example.com')
+ end
+
+ it { is_expected.to eq('http://example.com') }
+ end
+ end
+
describe '#citation_icon' do
subject { citation_icon(citation) }
@@ -12,10 +29,10 @@
it { is_expected.to include('citation-icon--journalism') }
end
- context 'with an academic link' do
- let(:citation) { FactoryBot.build(:citation, type: 'academic') }
- it { is_expected.to include('🎓') }
- it { is_expected.to include('citation-icon--academic') }
+ context 'with an research link' do
+ let(:citation) { FactoryBot.build(:citation, type: 'research') }
+ it { is_expected.to include('📚') }
+ it { is_expected.to include('citation-icon--research') }
end
context 'with a generic link' do
diff --git a/spec/helpers/admin/link_helper_spec.rb b/spec/helpers/admin/link_helper_spec.rb
index 9c054c1788..3fa106a4c9 100644
--- a/spec/helpers/admin/link_helper_spec.rb
+++ b/spec/helpers/admin/link_helper_spec.rb
@@ -118,5 +118,13 @@
end
end
end
+
+ context 'with a Citation' do
+ let(:record) { FactoryBot.create(:citation) }
+
+ it { is_expected.to include('icon-eye-open') }
+ it { is_expected.to include(record.source_url) }
+ it { is_expected.to include(edit_admin_citation_path(record)) }
+ end
end
end
diff --git a/spec/models/citation_spec.rb b/spec/models/citation_spec.rb
index 46d940ac03..cb948ba137 100644
--- a/spec/models/citation_spec.rb
+++ b/spec/models/citation_spec.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 20210114161442
+# Schema version: 20241007090524
#
# Table name: citations
#
@@ -11,6 +11,8 @@
# type :string
# created_at :datetime not null
# updated_at :datetime not null
+# title :string
+# description :text
#
require 'spec_helper'
@@ -48,10 +50,17 @@ def setup_for_x_scope_data
FactoryBot.create(:citation, citable: info_request_c)
end
+ # Citations on single InfoRequest: D
+ let!(:info_request_d) { FactoryBot.create(:info_request, :embargoed) }
+
+ let!(:citation_info_request_d) do
+ FactoryBot.create(:citation, citable: info_request_d)
+ end
+
# Batch and Requests: X
# Unused, but required to ensure we're not finding incorrect citations
let!(:batch_x) do
- FactoryBot.create(:info_request_batch, :sent)
+ FactoryBot.create(:info_request_batch, :sent, :embargoed)
end
let!(:batch_x_info_request_a) { batch_x.info_requests.first }
@@ -85,6 +94,22 @@ def setup_for_x_scope_data
end
end
+ describe '.not_embargoed' do
+ subject { described_class.not_embargoed }
+
+ setup_for_x_scope_data
+
+ it 'returns citations belonging to unembargoed requests and batches' do
+ is_expected.to match_array(
+ [
+ citation_batch_a, citation_batch_a_request_a,
+ citation_batch_b,
+ citation_info_request_c
+ ]
+ )
+ end
+ end
+
describe '.for_request' do
subject { described_class.for_request(info_request) }
@@ -203,7 +228,7 @@ def setup_for_x_scope_data
is_expected.to be_valid
citation.type = 'campaigning'
is_expected.to be_valid
- citation.type = 'academic'
+ citation.type = 'research'
is_expected.to be_valid
citation.type = 'other'
is_expected.to be_valid
diff --git a/spec/views/info_request_batch/_citations.html.erb_spec.rb b/spec/views/info_request_batch/_citations.html.erb_spec.rb
index 38e584f418..6142dfb209 100644
--- a/spec/views/info_request_batch/_citations.html.erb_spec.rb
+++ b/spec/views/info_request_batch/_citations.html.erb_spec.rb
@@ -34,7 +34,7 @@ def render_view
before { render_view }
it 'renders the section' do
- expect(rendered).to match(/In the News/)
+ expect(rendered).to match(/FOI in Action/)
end
it 'renders the blank slate text' do
@@ -59,11 +59,7 @@ def render_view
before { render_view }
it 'renders the section' do
- expect(rendered).to match(/In the News/)
- end
-
- it 'does not render the blank slate text' do
- expect(rendered).not_to match(/Has this batch request been referenced/)
+ expect(rendered).to match(/FOI in Action/)
end
it 'renders the citations' do
@@ -81,19 +77,19 @@ def render_view
before { render_view }
it 'renders the section' do
- expect(rendered).to match(/In the News/)
- end
-
- it 'does not render the blank slate text' do
- expect(rendered).not_to match(/Has this request been referenced/)
+ expect(rendered).to match(/FOI in Action/)
end
it 'renders the citations' do
expect(rendered).to match(/citations-list/)
end
+ it 'renders the blank slate text' do
+ expect(rendered).to match(/Has this batch request been referenced/)
+ end
+
it 'renders the link to add citations' do
- expect(rendered).to match('New Citation')
+ expect(rendered).to match('Let us know')
end
end
end
diff --git a/spec/views/request/_citations.html.erb_spec.rb b/spec/views/request/_citations.html.erb_spec.rb
index 6f9b940744..c8354085e1 100644
--- a/spec/views/request/_citations.html.erb_spec.rb
+++ b/spec/views/request/_citations.html.erb_spec.rb
@@ -32,7 +32,7 @@ def render_view
before { render_view }
it 'renders the section' do
- expect(rendered).to match(/In the News/)
+ expect(rendered).to match(/FOI in Action/)
end
it 'renders the blank slate text' do
@@ -57,7 +57,7 @@ def render_view
before { render_view }
it 'renders the section' do
- expect(rendered).to match(/In the News/)
+ expect(rendered).to match(/FOI in Action/)
end
it 'does not render the blank slate text' do
@@ -79,19 +79,19 @@ def render_view
before { render_view }
it 'renders the section' do
- expect(rendered).to match(/In the News/)
- end
-
- it 'does not render the blank slate text' do
- expect(rendered).not_to match(/Has this request been referenced/)
+ expect(rendered).to match(/FOI in Action/)
end
it 'renders the citations' do
expect(rendered).to match(/citations-list/)
end
+ it 'renders the blank slate text' do
+ expect(rendered).to match(/Has this request been referenced/)
+ end
+
it 'renders the link to add citations' do
- expect(rendered).to match('New Citation')
+ expect(rendered).to match('Let us know')
end
end
end