diff --git a/app/controllers/admin/citations_controller.rb b/app/controllers/admin/citations_controller.rb
index 51a42fa130..19ced491f2 100644
--- a/app/controllers/admin/citations_controller.rb
+++ b/app/controllers/admin/citations_controller.rb
@@ -1,7 +1,17 @@
class Admin::CitationsController < AdminController
def index
+ @query = params[:query]
+
+ citations = (
+ if @query
+ Citation.search(@query)
+ else
+ Citation
+ end
+ )
+
@citations =
- Citation.
+ citations.
order(created_at: :desc).
paginate(page: params[:page], per_page: 50)
end
diff --git a/app/models/citation.rb b/app/models/citation.rb
index 460eb357ef..b5d0313b8c 100644
--- a/app/models/citation.rb
+++ b/app/models/citation.rb
@@ -46,6 +46,12 @@ class Citation < ApplicationRecord
or(where(citable: info_request_batch.info_requests))
end
+ def self.search(query)
+ where(<<~SQL, query: query)
+ lower(citations.source_url) LIKE lower('%'||:query||'%')
+ SQL
+ end
+
def applies_to_batch_request?
citable.is_a?(InfoRequestBatch)
end
diff --git a/app/views/admin/citations/index.html.erb b/app/views/admin/citations/index.html.erb
index 4992d55dd1..86ae2f7dde 100644
--- a/app/views/admin/citations/index.html.erb
+++ b/app/views/admin/citations/index.html.erb
@@ -14,6 +14,17 @@
+
+<%= 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, source_url)
+<% end %>
+
+
<%= render partial: 'admin/citations/list',
locals: { citations: @citations } %>
diff --git a/doc/CHANGES.md b/doc/CHANGES.md
index 116e1ab02d..638385fbb2 100644
--- a/doc/CHANGES.md
+++ b/doc/CHANGES.md
@@ -2,6 +2,7 @@
## Highlighted Features
+* Add basic Citation searching in admin UI (Gareth Rees)
* Fix script/mailin when multiple EXCEPTION_NOTIFICATIONS_TO addresses are
specified (Graeme Porteous)
* Add example logrotate configuration (Graeme Porteous)
diff --git a/spec/controllers/admin/citations_controller_spec.rb b/spec/controllers/admin/citations_controller_spec.rb
index b9a34d43a0..7f04d204a3 100644
--- a/spec/controllers/admin/citations_controller_spec.rb
+++ b/spec/controllers/admin/citations_controller_spec.rb
@@ -15,6 +15,19 @@
expect(assigns[:citations]).to all(be_a(Citation))
end
+ it 'assigns the query' do
+ get :index, params: { query: 'hello' }
+ expect(assigns[:query]).to eq('hello')
+ end
+
+ it 'filters citations by the search query' do
+ net = FactoryBot.create(:citation, source_url: 'https://example.net/a')
+ org = FactoryBot.create(:citation, source_url: 'https://example.org/b')
+ get :index, params: { query: 'example.net' }
+ expect(assigns[:citations]).to include(net)
+ expect(assigns[:citations]).not_to include(org)
+ end
+
it 'renders the correct template' do
expect(response).to render_template(:index)
end
diff --git a/spec/models/citation_spec.rb b/spec/models/citation_spec.rb
index 46d940ac03..25a60f4819 100644
--- a/spec/models/citation_spec.rb
+++ b/spec/models/citation_spec.rb
@@ -130,6 +130,23 @@ def setup_for_x_scope_data
end
end
+ describe '.search' do
+ subject { described_class.search(query) }
+
+ let!(:net) do
+ FactoryBot.create(:citation, source_url: 'https://example.net/story')
+ end
+
+ let!(:org) do
+ FactoryBot.create(:citation, source_url: 'https://example.org/story')
+ end
+
+ let(:query) { 'example.net' }
+
+ it { is_expected.to include(net) }
+ it { is_expected.not_to include(org) }
+ end
+
subject(:citation) { FactoryBot.build(:citation) }
describe 'associations' do