Skip to content

Commit

Permalink
Merge pull request #1984 from unboxed/reviewer-constraints-map
Browse files Browse the repository at this point in the history
Reviewer constraints map
  • Loading branch information
EGiataganas authored Oct 21, 2024
2 parents a6bb4b3 + 7dd9a9a commit 0215fe3
Show file tree
Hide file tree
Showing 13 changed files with 267 additions and 59 deletions.
1 change: 1 addition & 0 deletions app/assets/stylesheets/_main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ $govuk-page-width: 1100px;
@import "components/task_list";
@import "consultation";
@import "decision_notice";
@import "map-constraints";
@import "proposal";

.accordion-tr:last-child > td {
Expand Down
57 changes: 57 additions & 0 deletions app/assets/stylesheets/map-constraints.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
$constraints-colours: (
"agricultural-land-classification": (#00703c33, #00703c),
"ancient-woodland": (#00703c33, #00703c),
"area-of-outstanding-natural-beauty": (#d5388099, #d53880),
"article-4-direction-area": (#00307899, #003078),
"battlefield": (#4d294233, #4d2942),
"border": (#0b0c0c19, #0b0c0c),
"brownfield-site": (#74572999, #745729),
"building-preservation-notice": (#f944c799, #f944c7),
"built-up-area": (#f4773899, #f47738),
"central-activities-zone": (#00307899, #003078),
"certificate-of-immunity": (#D8760D99, #D8760D),
"conservation-area": (#78AA0099, #78AA00),
"design-code-area": (#00307899, #003078),
"educational-establishment": (#00307899, #003078),
"flood-risk-zone": (#00307899, #003078),
"flood-storage-area": (#00307899, #003078),
"green-belt": (#85994b99, #85994b),
"heritage-at-risk": (#8D73AF99, #8D73AF),
"heritage-coast": (#912b8899, #912b88),
"infrastructure-project": (#00307899, #003078),
"listed-building-outline": (#F9C74499, #F9C744),
"local-authority-district": (#0b0c0c19, #0b0c0c),
"locally-listed-building": (#F9C74499, #F9C744),
"local-nature-reserve": (#00307899, #003078),
"local-planning-authority": (#00307899, #003078),
"local-resilience-forum-boundary": (#f499be19, #f499be),
"national-nature-reserve": (#00307899, #003078),
"national-park": (#3DA52C99, #3DA52C),
"nature-improvement-area": (#00307899, #003078),
"parish": (#5694ca99, #5694ca),
"park-and-garden": (#0EB95199, #0EB951),
"protected-wreck-site": (#0b0c0c99, #0b0c0c),
"ramsar": (#7fcdff99, #7fcdff),
"region": (#00307899, #003078),
"scheduled-monument": (#0F9CDA99, #0F9CDA),
"site-of-special-scientific-interest": (#308fac99, #308fac),
"special-area-of-conservation": (#7A870599, #7A8705),
"special-protection-area": (#00307899, #003078),
"title-boundary": (#00307899, #003078),
"transport-access-node": (#00307899, #003078),
"tree-preservation-zone": (#00307899, #003078),
"ward": (#3DA52C99, #3DA52C),
"world-heritage-site": (#EB1EE599, #EB1EE5),
"world-heritage-site-buffer-zone": (#EB1EE533, #EB1EE5)
);

@each $type, $colours in $constraints-colours {
.constraint-#{$type} {
background-color: nth($colours, 1);
border: 1px solid nth($colours, 2);
width: 20px;
height: 20px;
display: inline-block;
margin-right: 5px;
}
}
8 changes: 6 additions & 2 deletions app/components/site_map_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
latLong: [planning_application.latitude, planning_application.longitude].join(","),
layers: {
redline: planning_application.boundary_geojson,
neighbours: neighbours_layers
neighbours: neighbours_layers,
constraints: constraints_layers
}
} do %>
<%= tag.div id: :map %>
Expand Down Expand Up @@ -55,7 +56,10 @@
<ul class="govuk-list govuk-!-font-size-16">
<% planning_application_constraint.entities.each do |name, entity| %>
<% entity_name = name.present? ? name.titleize : "Entity ##{entity}" %>
<li><%= govuk_link_to entity_name, helpers.planning_data_entity_url(entity), new_tab: true %></li>
<li>
<span class="constraint-<%= planning_application_constraint.planning_data_dataset %>"></span>
<%= govuk_link_to entity_name, helpers.planning_data_entity_url(entity), new_tab: true %>
</li>
<% end %>
</ul>
<% end %>
Expand Down
6 changes: 6 additions & 0 deletions app/components/site_map_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,10 @@ def unresponsive_neighbours_layer

unresponsive_neighbours.map { |neighbour| RGeo::GeoJSON.encode(neighbour.lonlat) }.compact
end

def constraints_layers
planning_application.planning_application_constraints.present? && planning_application.planning_application_constraints.map do |planning_application_constraint|
planning_application_constraint.entity_data
end.reduce({}, :merge)
end
end
86 changes: 86 additions & 0 deletions app/javascript/controllers/map_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default class extends Controller {
const layerData = JSON.parse(this.element.dataset.layers)
const redline = layerData.redline
const neighbours = layerData.neighbours
const constraints = layerData.constraints

const layers = []

Expand Down Expand Up @@ -49,6 +50,17 @@ export default class extends Controller {
}
}

if (constraints !== null) {
for (const constraintEntity in constraints) {
layers.push(
this.buildConstraintsLayer(
constraintEntity,
constraints[constraintEntity],
),
)
}
}

for (const layer of layers) {
layer.addTo(this.map)
}
Expand Down Expand Up @@ -93,6 +105,80 @@ export default class extends Controller {
})
}

buildConstraintsLayer(constraintEntity, geoJsonData) {
const colours = {
"agricultural-land-classification": {
fill: "#00703c33",
border: "#00703c",
},
"ancient-woodland": { fill: "#00703c33", border: "#00703c" },
"area-of-outstanding-natural-beauty": {
fill: "#d5388099",
border: "#d53880",
},
"article-4-direction-area": { fill: "#00307899", border: "#003078" },
battlefield: { fill: "#4d294233", border: "#4d2942" },
border: { fill: "#0b0c0c19", border: "#0b0c0c" },
"brownfield-site": { fill: "#74572999", border: "#745729" },
"building-preservation-notice": { fill: "#f944c799", border: "#f944c7" },
"built-up-area": { fill: "#f4773899", border: "#f47738" },
"central-activities-zone": { fill: "#00307899", border: "#003078" },
"certificate-of-immunity": { fill: "#D8760D99", border: "#D8760D" },
"conservation-area": { fill: "#78AA0099", border: "#78AA00" },
"design-code-area": { fill: "#00307899", border: "#003078" },
"educational-establishment": { fill: "#00307899", border: "#003078" },
"flood-risk-zone": { fill: "#00307899", border: "#003078" },
"flood-storage-area": { fill: "#00307899", border: "#003078" },
"green-belt": { fill: "#85994b99", border: "#85994b" },
"heritage-at-risk": { fill: "#8D73AF99", border: "#8D73AF" },
"heritage-coast": { fill: "#912b8899", border: "#912b88" },
"infrastructure-project": { fill: "#00307899", border: "#003078" },
"listed-building-outline": { fill: "#F9C74499", border: "#F9C744" },
"local-authority-district": { fill: "#0b0c0c19", border: "#0b0c0c" },
"locally-listed-building": { fill: "#F9C74499", border: "#F9C744" },
"local-nature-reserve": { fill: "#00307899", border: "#003078" },
"local-planning-authority": { fill: "#00307899", border: "#003078" },
"local-resilience-forum-boundary": {
fill: "#f499be19",
border: "#f499be",
},
"national-nature-reserve": { fill: "#00307899", border: "#003078" },
"national-park": { fill: "#3DA52C99", border: "#3DA52C" },
"nature-improvement-area": { fill: "#00307899", border: "#003078" },
parish: { fill: "#5694ca99", border: "#5694ca" },
"park-and-garden": { fill: "#0EB95199", border: "#0EB951" },
"protected-wreck-site": { fill: "#0b0c0c99", border: "#0b0c0c" },
ramsar: { fill: "#7fcdff99", border: "#7fcdff" },
region: { fill: "#00307899", border: "#003078" },
"scheduled-monument": { fill: "#0F9CDA99", border: "#0F9CDA" },
"site-of-special-scientific-interest": {
fill: "#308fac99",
border: "#308fac",
},
"special-area-of-conservation": { fill: "#7A870599", border: "#7A8705" },
"special-protection-area": { fill: "#00307899", border: "#003078" },
"title-boundary": { fill: "#00307899", border: "#003078" },
"transport-access-node": { fill: "#00307899", border: "#003078" },
"tree-preservation-zone": { fill: "#00307899", border: "#003078" },
ward: { fill: "#3DA52C99", border: "#3DA52C" },
"world-heritage-site": { fill: "#EB1EE599", border: "#EB1EE5" },
"world-heritage-site-buffer-zone": {
fill: "#EB1EE533",
border: "#EB1EE5",
},
}

return L.geoJson(geoJsonData, {
style: {
fillColor: colours[constraintEntity]?.fill || "#00000033",
color: colours[constraintEntity]?.border || "#000000",
weight: 2,
opacity: 1,
fillOpacity: 0.5,
},
})
}

showMapData(ev) {
ev.target.classList.add("govuk-!-display-none")
ev.target.parentNode
Expand Down
2 changes: 1 addition & 1 deletion app/models/local_authority.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def plan_x?
end

def planning_data
@planning_data ||= Apis::PlanningData::Query.new.council_code(council_code)
@planning_data ||= Apis::PlanningData::Query.new.get_council_code(council_code)
end

def planning_data?
Expand Down
16 changes: 16 additions & 0 deletions app/models/planning_application_constraint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ def entities
data&.pluck("name", "entity")
end

def entity_data
(planning_data_dataset && planning_data_geojson) ? {planning_data_dataset => planning_data_geojson} : {}
end

def planning_data_dataset
planning_data_geojson.dig(:properties, :dataset)
end

private

def identified_and_removed?
Expand All @@ -61,4 +69,12 @@ def audit_constraint_added!
def audit_constraint_removed!
audit!(activity_type: "constraint_removed", audit_comment: constraint.type_code)
end

def entity
data&.pick("entity")
end

def planning_data_geojson
@planning_data_geojson ||= Apis::PlanningData::Query.new.get_entity_geojson(entity)
end
end
11 changes: 7 additions & 4 deletions app/services/apis/planning_data/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,19 @@ class Client
HOST = "https://www.planning.data.gov.uk"
TIMEOUT = 5

def call(query)
faraday.get("/entity.json?#{query}") do |request|
request.options[:timeout] = TIMEOUT
end
def get(query)
faraday.get("/entity.json?#{query}")
end

def get_entity_geojson(query)
faraday.get("/entity/#{query}.geojson")
end

private

def faraday
@faraday ||= Faraday.new(url: HOST) do |f|
f.options[:timeout] = TIMEOUT
f.response :raise_error
end
end
Expand Down
56 changes: 39 additions & 17 deletions app/services/apis/planning_data/query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,54 @@
module Apis
module PlanningData
class Query
def fetch(reference, datasets = [])
datasets = [datasets] unless datasets.is_a? Enumerable
query = "reference=#{reference}&" + datasets.map { |dataset| "dataset=#{dataset}" }.join("&")
response = client.call(query)

if response.success?
JSON.parse(response.body, symbolize_names: true)
else
{}
end
rescue Faraday::ResourceNotFound, Faraday::ClientError
def get_council_code(reference)
body = query_entity(reference, ["local-authority"])
(body[:count] == 1 && body[:"end-date"].blank?) ? body[:entities].first[:reference] : nil
end

def get_entity_geojson(reference)
handle_request { client.get_entity_geojson(reference) }
end

private

def query_entity(reference, datasets = [])
handle_request { client.get(query(reference, datasets)) }
end

def handle_request
response = yield
response.success? ? parse_response(response) : {}
rescue Faraday::ResourceNotFound, Faraday::ClientError => e
Rails.logger.debug e.message
Rails.logger.debug e.response
{}
rescue Faraday::Error => e
Appsignal.send_exception(e)
{}
end

def council_code(reference)
body = fetch(reference, ["local-authority"])
(body[:count] == 1 && body[:"end-date"].blank?) ? body[:entities].first[:reference] : nil
def client
@client ||= Apis::PlanningData::Client.new
end

private
def query(reference, datasets)
[reference_query(reference), dataset_query(datasets)].join("&")
end

def client
@client ||= Apis::PlanningData::Client.new
def reference_query(reference)
"reference=#{reference}"
end

def dataset_query(datasets)
Array(datasets).map { |dataset| "dataset=#{dataset}" }.join("&")
end

def parse_response(response)
JSON.parse(response.body, symbolize_names: true)
rescue JSON::ParserError => e
Rails.logger.debug e.message
{}
end
end
end
Expand Down
1 change: 1 addition & 0 deletions spec/fixtures/files/entities/1000005.geojson

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions spec/services/apis/planning_data/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@
RSpec.describe Apis::PlanningData::Client do
let(:client) { described_class.new }

describe "#call" do
describe "#get" do
it "is successful" do
expect(client.call("reference=LBH&dataset=local-authority").status).to eq(200)
expect(client.get("reference=LBH&dataset=local-authority").status).to eq(200)
end
end

describe "#get_entity_geojson" do
it "is successful" do
expect(client.get_entity_geojson("1000005").status).to eq(200)
end
end
end
Loading

0 comments on commit 0215fe3

Please sign in to comment.