Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Download all local authority links #413

Merged
merged 6 commits into from
Apr 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ gem 'uglifier', '>= 1.3.0'
gem 'whenever', require: false

group :development do
gem 'better_errors', '~> 2.5.1'
gem 'binding_of_caller', '~> 0.8.0'
gem 'capistrano-rails'
gem 'web-console', '~> 3.7' # Access an IRB console by using <%= console %> in views
end
Expand All @@ -41,7 +43,7 @@ group :development, :test do
end

group :test do
gem 'govuk_test'
gem 'govuk_test', '~> 0.4.2'
gem 'capybara', '~> 3.10'
gem 'timecop'
gem 'webmock', '~> 3.5.1'
Expand Down
13 changes: 11 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,13 @@ GEM
execjs
aws-xray-sdk (0.10.2)
oj (~> 3.0)
better_errors (2.5.1)
coderay (>= 1.0.0)
erubi (>= 1.0.0)
rack (>= 0.9.0)
bindex (0.5.0)
binding_of_caller (0.8.0)
debug_inspector (>= 0.0.1)
bootstrap-sass (3.4.1)
autoprefixer-rails (>= 5.2.1)
sassc (>= 2.0.0)
Expand Down Expand Up @@ -90,6 +96,7 @@ GEM
safe_yaml (~> 1.0.0)
crass (1.0.4)
dalli (2.7.10)
debug_inspector (0.0.3)
declarative (0.0.10)
declarative-option (0.1.0)
diff-lcs (1.3)
Expand Down Expand Up @@ -153,7 +160,7 @@ GEM
sentry-raven (~> 2.7.1)
statsd-ruby (~> 1.4.0)
unicorn (~> 5.4.0)
govuk_test (0.4.1)
govuk_test (0.4.2)
capybara
chromedriver-helper
ptools
Expand Down Expand Up @@ -418,6 +425,8 @@ PLATFORMS

DEPENDENCIES
addressable (~> 2.6.0)
better_errors (~> 2.5.1)
binding_of_caller (~> 0.8.0)
capistrano-rails
capybara (~> 3.10)
dalli
Expand All @@ -429,7 +438,7 @@ DEPENDENCIES
govuk-lint
govuk_admin_template (~> 6.7)
govuk_app_config (~> 1.15.1)
govuk_test
govuk_test (~> 0.4.2)
gretel (= 3.0.9)
jbuilder (~> 2.8)
mlanett-redis-lock (= 0.2.7)
Expand Down
17 changes: 17 additions & 0 deletions app/assets/javascripts/local_authorities.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
document.addEventListener("DOMContentLoaded", function(event) {
var checkboxes = document.getElementsByClassName('links_status_checkbox');
var links_download_button = document.getElementById('links_download_button');
var url = links_download_button.href.split('?')[0];

for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].addEventListener('change', function() {
var params = [];
for (var j = 0; j < checkboxes.length; j++) {
if (checkboxes[j].checked) {
params.push(checkboxes[j].name + '=' + checkboxes[j].value)
}
}
links_download_button.href = url + '?' + params.join('&')
});
}
});
6 changes: 3 additions & 3 deletions app/controllers/local_authorities_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ def show
@link_count = links_for_authority.count
end

def broken_links_csv
def links_csv
@authority = LocalAuthority.find_by_slug!(params[:local_authority_slug])
authority_name = @authority.name.parameterize.underscore
data = LocalLinksManager::Export::LinksExporter.new.export_broken_links(@authority)
send_data data, filename: "#{authority_name}_broken_links.csv"
data = LocalLinksManager::Export::LinksExporter.new.export_links(@authority.id, params)
send_data data, filename: "#{authority_name}_links.csv"
end

def bad_homepage_url_and_status_csv
Expand Down
7 changes: 5 additions & 2 deletions app/models/link.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ class Link < ApplicationRecord
scope :with_url, -> { where.not(url: nil) }
scope :without_url, -> { where(url: nil) }

scope :ok, -> { where(status: "ok") }
scope :broken, -> { where(status: "broken") }
scope :caution, -> { where(status: "caution") }
scope :missing, -> { where(status: "missing") }
scope :currently_broken, -> { where(status: "broken") }
scope :broken_or_missing, -> { currently_broken.or(missing) }
scope :pending, -> { where(status: "pending") }
scope :broken_or_missing, -> { broken.or(missing) }

scope :last_checked_before, ->(last_checked) {
where("link_last_checked IS NULL OR link_last_checked < ?", last_checked)
Expand Down
27 changes: 26 additions & 1 deletion app/views/shared/_local_authority_details.html.erb
Original file line number Diff line number Diff line change
@@ -1,9 +1,34 @@
<%= javascript_include_tag params[:controller] %>

<div class="page-title">
<h1><%= authority.name %></h1>
<p>
Homepage <%= link_to_if(authority.homepage_url, nil, authority.homepage_url) %><br>
<span class="<%= authority.label_status_class %> text-muted"><b><%= authority.homepage_status %></b></span>
<span class="text-muted"><%= authority.homepage_link_last_checked %></span>
<p><%= link_to('Download broken links', broken_links_csv_local_authority_path, class: "btn btn-default btn-s") %></p>
<p>
<%= check_box_tag(:ok, :ok, true, class: 'links_status_checkbox') %>
<%= label_tag(:ok, 'OK') %>
<%= check_box_tag(:broken, :broken, true, class: 'links_status_checkbox') %>
<%= label_tag(:broken, 'Broken') %>
<%= check_box_tag(:caution, :caution, true, class: 'links_status_checkbox') %>
<%= label_tag(:caution, 'Caution') %>
<%= check_box_tag(:missing, :missing, true, class: 'links_status_checkbox') %>
<%= label_tag(:missing, 'Missing') %>
<%= check_box_tag(:pending, :pending, true, class: 'links_status_checkbox') %>
<%= label_tag(:pending, 'Pending') %>
<%= link_to(
'Download links',
links_csv_local_authority_path(
ok: :ok,
broken: :broken,
caution: :caution,
missing: :missing,
pending: :pending
),
class: "btn btn-default btn-s",
id: "links_download_button"
) %>
</p>
</p>
</div>
1 change: 1 addition & 0 deletions config/environments/development.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
config.reload_classes_only_on_change = false

# Do not eager load code on boot.
config.eager_load = false
Expand Down
1 change: 1 addition & 0 deletions config/initializers/assets.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
# Rails.application.config.assets.precompile += %w( search.js )
Rails.application.config.assets.precompile += %w( local_authorities.js )
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

resources 'local_authorities', only: [:index, :show], param: :local_authority_slug do
member do
get 'broken_links_csv'
get 'links_csv'
end
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def self.local_authority_bad_homepage_url_and_status_csv
def self.bad_links_url_and_status_csv(with_ga_headings: false)
CSV.generate do |csv|
csv << (with_ga_headings ? GA_HEADINGS : HEADINGS)
Link.enabled_links.currently_broken.distinct.pluck(:url, :problem_summary).each do |row|
Link.enabled_links.broken.distinct.pluck(:url, :problem_summary).each do |row|
csv << row
end
end
Expand Down
71 changes: 39 additions & 32 deletions lib/local-links-manager/export/links_exporter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,29 @@
module LocalLinksManager
module Export
class LinksExporter
HEADINGS = ["Authority Name", "SNAC", "GSS", "Description", "LGSL", "LGIL", "URL"].freeze
ALL_LINKS_HEADINGS = ["Supported by GOV.UK"].freeze
BROKEN_LINKS_HEADINGS = ["New URL"].freeze
SELECTION = [
"local_authorities.name",
:snac,
:gss,
"services.label as service_label",
"interactions.label as interaction_label",
"links.status as status",
:lgsl_code,
:lgil_code,
:url,
:enabled
].freeze
COMMON_HEADINGS = [
"Authority Name",
"SNAC",
"GSS",
"Description",
"LGSL",
"LGIL",
"URL",
"Supported by GOV.UK"
].freeze
EXTRA_HEADINGS = ["Status", "New URL"].freeze

def self.export_links
path = Rails.root.join("public", "data", 'links_to_services_provided_by_local_authorities.csv')
Expand All @@ -17,54 +37,40 @@ def self.export_links

def export(io)
output = CSV.generate do |csv|
csv << HEADINGS + ALL_LINKS_HEADINGS
csv << COMMON_HEADINGS
records.each do |record|
csv << format(record).push(record.enabled)
csv << format(record)
end
end
io.write(output)
end

def export_broken_links(local_authority_id)
def export_links(local_authority_id, params)
statuses = params.slice('ok', 'broken', 'caution', 'missing', 'pending').keys
CSV.generate do |csv|
csv << HEADINGS + BROKEN_LINKS_HEADINGS
broken_links(local_authority_id).each do |link|
csv << format(link)
csv << COMMON_HEADINGS + EXTRA_HEADINGS
statuses.each do |status|
links(local_authority_id, status).each do |link|
csv << format(link).push(link.status)
end
end
end
end

def records
Link.with_url.joins(:local_authority, :service, :interaction)
.select(
"local_authorities.name",
:snac,
:gss,
"services.label as service_label",
"interactions.label as interaction_label",
:lgsl_code,
:lgil_code,
:url,
:enabled
).order("local_authorities.name", "services.lgsl_code", "interactions.lgil_code").all
.select(*SELECTION)
.order("local_authorities.name", "services.lgsl_code", "interactions.lgil_code").all
end

private

def broken_links(local_authority_id)
Link.enabled_links.currently_broken
def links(local_authority_id, status)
Link.enabled_links.public_send(status)
.where(local_authority_id: local_authority_id)
.joins(:local_authority, :service, :interaction)
.select(
"local_authorities.name",
:snac,
:gss,
"services.label as service_label",
"interactions.label as interaction_label",
:lgsl_code,
:lgil_code,
:url,
).order("services.lgsl_code", "interactions.lgil_code").all
.select(*SELECTION)
.order("services.lgsl_code", "interactions.lgil_code").all
end

def format(record)
Expand All @@ -76,6 +82,7 @@ def format(record)
record.lgsl_code,
record.lgil_code,
record.url,
record.enabled
]
end

Expand Down
14 changes: 12 additions & 2 deletions spec/controllers/local_authorities_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,24 @@
end
end

describe "GET broken_links_csv" do
describe "GET links_csv" do
before do
@local_authority = create(:local_authority)
end

it "retrieves HTTP success" do
login_as_stub_user
get :broken_links_csv, params: { local_authority_slug: @local_authority.slug }
get(
:links_csv,
params: {
local_authority_slug: @local_authority.slug,
ok: 'ok',
broken: 'broken',
caution: 'caution',
missing: 'missing',
pending: 'pending'
}
)
expect(response).to have_http_status(200)
expect(response.headers["Content-Type"]).to eq("text/csv")
end
Expand Down
18 changes: 15 additions & 3 deletions spec/factories/links.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,26 @@
analytics { 0 }
end

factory :ok_link, parent: :link do
status { "ok" }
end

factory :broken_link, parent: :link do
sequence(:url) { |n| "hhhttttttppp://www.example.com/broken-#{n}" }
status { "broken" }
end

factory :caution_link, parent: :link do
status { "caution" }
end

factory :missing_link, parent: :link do
url { nil }
status { "missing" }
end

factory :broken_link, parent: :link do
url { nil }
status { "broken" }
factory :pending_link, parent: :link do
status { "pending" }
end

factory :link_for_disabled_service, parent: :link do
Expand Down
Loading