Skip to content
Open
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
29 changes: 8 additions & 21 deletions map/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,16 @@
class CommunityAreaSerializer(serializers.ModelSerializer):
class Meta:
model = CommunityArea
fields = ["name", "num_permits"]
fields = ["name", "area_id", "num_permits"]

num_permits = serializers.SerializerMethodField()

def get_num_permits(self, obj):
"""
TODO: supplement each community area object with the number
of permits issued in the given year.
year = self.context.get("year")
if not year:
return 0

e.g. The endpoint /map-data/?year=2017 should return something like:
[
{
"ROGERS PARK": {
area_id: 17,
num_permits: 2
},
"BEVERLY": {
area_id: 72,
num_permits: 2
},
...
}
]
"""

pass
return RestaurantPermit.objects.filter(
community_area_id=str(obj.area_id),
issue_date__year=year,
).count()
79 changes: 45 additions & 34 deletions map/static/js/RestaurantPermitMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,14 @@ import "leaflet/dist/leaflet.css"

import RAW_COMMUNITY_AREAS from "../../../data/raw/community-areas.geojson"

function YearSelect({ setFilterVal }) {
// Filter by the permit issue year for each restaurant
function YearSelect({ filterVal, setFilterVal }) {
const startYear = 2026
const years = [...Array(11).keys()].map((increment) => {
return startYear - increment
})
const options = years.map((year) => {
return (
<option value={year} key={year}>
{year}
</option>
)
})
const years = [...Array(11).keys()].map((increment) => startYear - increment)
const options = years.map((year) => (
<option value={year} key={year}>
{year}
</option>
))

return (
<>
Expand All @@ -28,6 +23,7 @@ function YearSelect({ setFilterVal }) {
<select
id="yearSelect"
className="form-select form-select-lg mb-3"
value={filterVal}
onChange={(e) => setFilterVal(e.target.value)}
>
{options}
Expand All @@ -45,34 +41,49 @@ export default function RestaurantPermitMap() {
const yearlyDataEndpoint = `/map-data/?year=${year}`

useEffect(() => {
fetch()
fetch(yearlyDataEndpoint)
.then((res) => res.json())
.then((data) => {
/**
* TODO: Fetch the data needed to supply to map with data
*/
setCurrentYearData(data)
})
}, [yearlyDataEndpoint])

const totalPermits = currentYearData.reduce(
(sum, area) => sum + area.num_permits,
0
)
const maxNumPermits = currentYearData.reduce(
(max, area) => Math.max(max, area.num_permits),
0
)

function getColor(percentageOfPermits) {
/**
* TODO: Use this function in setAreaInteraction to set a community
* area's color using the communityAreaColors constant above
*/
if (percentageOfPermits > 0.75) return communityAreaColors[3]
if (percentageOfPermits > 0.5) return communityAreaColors[2]
if (percentageOfPermits > 0.25) return communityAreaColors[1]
return communityAreaColors[0]
}

function setAreaInteraction(feature, layer) {
/**
* TODO: Use the methods below to:
* 1) Shade each community area according to what percentage of
* permits were issued there in the selected year
* 2) On hover, display a popup with the community area's raw
* permit count for the year
*/
layer.setStyle()
layer.on("", () => {
layer.bindPopup("")
const areaNumber = feature.properties.area_numbe
const areaData = currentYearData.find(
(area) => String(area.area_id) === String(areaNumber)
)
const numPermits = areaData ? areaData.num_permits : 0
const percentage = maxNumPermits > 0 ? numPermits / maxNumPermits : 0

layer.setStyle({
fillColor: getColor(percentage),
weight: 1,
opacity: 1,
color: "#666",
fillOpacity: 0.7,
})

layer.on("mouseover", () => {
layer.bindPopup(
`<strong>${feature.properties.community}</strong><br/>Permits: ${numPermits}`
)
layer.openPopup()
})
}
Expand All @@ -81,11 +92,11 @@ export default function RestaurantPermitMap() {
<>
<YearSelect filterVal={year} setFilterVal={setYear} />
<p className="fs-4">
Restaurant permits issued this year: {/* TODO: display this value */}
Restaurant permits issued this year: {totalPermits}
</p>
<p className="fs-4">
Maximum number of restaurant permits in a single area:
{/* TODO: display this value */}
Maximum number of restaurant permits in a single area:{" "}
{maxNumPermits}
</p>
<MapContainer
id="restaurant-map"
Expand All @@ -100,7 +111,7 @@ export default function RestaurantPermitMap() {
<GeoJSON
data={RAW_COMMUNITY_AREAS}
onEachFeature={setAreaInteraction}
key={maxNumPermits}
key={`${year}-${maxNumPermits}`}
/>
) : null}
</MapContainer>
Expand Down
45 changes: 29 additions & 16 deletions tests/test_views.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,54 @@
import pytest
from datetime import date

from django.shortcuts import reverse
from django.urls import reverse
from rest_framework.test import APIClient

from map.models import CommunityArea, RestaurantPermit


@pytest.mark.django_db
def test_map_data_view():
# Create some test community areas
area1 = CommunityArea.objects.create(name="Beverly", area_id="1")
area2 = CommunityArea.objects.create(name="Lincoln Park", area_id="2")
area1 = CommunityArea.objects.create(name="Beverly", area_id=1)
area2 = CommunityArea.objects.create(name="Lincoln Park", area_id=2)

# Test permits for Beverly
# Beverly: 2 permits in 2021
RestaurantPermit.objects.create(
community_area_id=area1.area_id, issue_date=date(2021, 1, 15)
community_area_id=str(area1.area_id), issue_date=date(2021, 1, 15)
)
RestaurantPermit.objects.create(
community_area_id=area1.area_id, issue_date=date(2021, 2, 20)
community_area_id=str(area1.area_id), issue_date=date(2021, 2, 20)
)

# Test permits for Lincoln Park
# Lincoln Park: 3 permits in 2021
RestaurantPermit.objects.create(
community_area_id=area2.area_id, issue_date=date(2021, 3, 10)
community_area_id=str(area2.area_id), issue_date=date(2021, 3, 10)
)
RestaurantPermit.objects.create(
community_area_id=area2.area_id, issue_date=date(2021, 2, 14)
community_area_id=str(area2.area_id), issue_date=date(2021, 2, 14)
)
RestaurantPermit.objects.create(
community_area_id=area2.area_id, issue_date=date(2021, 6, 22)
community_area_id=str(area2.area_id), issue_date=date(2021, 6, 22)
)

# A permit in a different year should not be counted
RestaurantPermit.objects.create(
community_area_id=str(area1.area_id), issue_date=date(2020, 5, 1)
)

# Query the map data endpoint
client = APIClient()
response = client.get(reverse("map_data", query={"year": 2021}))
response = client.get(reverse("map_data"), {"year": 2021})

assert response.status_code == 200

data = response.json()
assert len(data) == 2

beverly = next(area for area in data if area["name"] == "Beverly")
lincoln_park = next(area for area in data if area["name"] == "Lincoln Park")

assert beverly["num_permits"] == 2
assert beverly["area_id"] == 1

# TODO: Complete the test by asserting that the /map-data/ endpoint
# returns the correct number of permits for Beverly and Lincoln
# Park in 2021
assert lincoln_park["num_permits"] == 3
assert lincoln_park["area_id"] == 2