Skip to content

Commit 686e6b3

Browse files
author
msj
committed
Initial commit
0 parents  commit 686e6b3

56 files changed

Lines changed: 59098 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
## Overview
2+
3+
Brief description of what this PR does, and why it is needed.
4+
5+
Closes #XXX
6+
7+
- [ ] Includes a test
8+
9+
### Demo
10+
11+
Optional. Screenshots, `curl` examples, etc.
12+
13+
### Notes
14+
15+
Optional. Ancillary topics, caveats, alternative strategies that didn't work out, anything else.
16+
17+
## Testing Instructions
18+
19+
- How to test this PR
20+
- Prefer bulleted description
21+
- Start after checking out this branch
22+
- Include any setup required, such as bundling scripts, restarting services, etc.
23+
- Include test case, and expected output

.github/workflows/main.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: Run tests
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- deploy
8+
pull_request:
9+
branches:
10+
- main
11+
12+
jobs:
13+
test:
14+
name: Run tests
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v3
18+
- name: Run tests
19+
run: |
20+
docker compose -f docker-compose.yml \
21+
-f tests/docker-compose.yml \
22+
run --rm app

.gitignore

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
.DS_Store
2+
3+
webpack-stats.json
4+
5+
out.txt
6+
/data/final/*.csv
7+
/data/shapefiles/*
8+
/data/intermediate/*.sql
9+
10+
# Byte-compiled / optimized / DLL files
11+
__pycache__/
12+
*.py[cod]
13+
*$py.class
14+
15+
# C extensions
16+
*.so
17+
18+
# Distribution / packaging
19+
.Python
20+
build/
21+
develop-eggs/
22+
dist/
23+
downloads/
24+
eggs/
25+
.eggs/
26+
lib64/
27+
parts/
28+
sdist/
29+
var/
30+
wheels/
31+
*.egg-info/
32+
.installed.cfg
33+
*.egg
34+
MANIFEST
35+
36+
# PyInstaller
37+
# Usually these files are written by a python script from a template
38+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
39+
*.manifest
40+
*.spec
41+
42+
# Installer logs
43+
pip-log.txt
44+
pip-delete-this-directory.txt
45+
46+
# Unit test / coverage reports
47+
htmlcov/
48+
.tox/
49+
.coverage
50+
.coverage.*
51+
.cache
52+
nosetests.xml
53+
coverage.xml
54+
*.cover
55+
.hypothesis/
56+
.pytest_cache/
57+
58+
# Translations
59+
*.pot
60+
61+
# Django stuff:
62+
*.log
63+
local_settings.py
64+
db.sqlite3
65+
66+
# Flask stuff:
67+
instance/
68+
.webassets-cache
69+
70+
# Scrapy stuff:
71+
.scrapy
72+
73+
# Sphinx documentation
74+
docs/_build/
75+
76+
# PyBuilder
77+
target/
78+
79+
# Jupyter Notebook
80+
.ipynb_checkpoints
81+
82+
# pyenv
83+
.python-version
84+
85+
# celery beat schedule file
86+
celerybeat-schedule
87+
88+
# SageMath parsed files
89+
*.sage.py
90+
91+
# Environments
92+
.env
93+
.venv
94+
env/
95+
venv/
96+
ENV/
97+
env.bak/
98+
venv.bak/
99+
100+
# Spyder project settings
101+
.spyderproject
102+
.spyproject
103+
104+
# Rope project settings
105+
.ropeproject
106+
107+
# mkdocs documentation
108+
/site
109+
110+
# mypy
111+
.mypy_cache/
112+
113+
# Compiled JavaScript
114+
node_modules/
115+
map/static/compressor/*
116+
!map/static/js/lib/
117+
118+
# Local uploads
119+
media/

Dockerfile

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
FROM node:25-slim AS node
2+
3+
# Inside the container, create an app directory and switch into it
4+
RUN mkdir /app
5+
WORKDIR /app
6+
7+
COPY ./package.json package.json
8+
RUN npm install
9+
10+
FROM python:3.14.3 AS app
11+
12+
LABEL maintainer "DataMade <info@datamade.us>"
13+
14+
RUN apt-get update && \
15+
apt-get install -y --no-install-recommends --purge postgresql-client gdal-bin && \
16+
apt-get autoclean && \
17+
rm -rf /var/lib/apt/lists/* && \
18+
rm -rf /tmp/*
19+
20+
RUN mkdir /app
21+
WORKDIR /app
22+
23+
COPY ./requirements.txt /app/requirements.txt
24+
RUN pip install --no-cache-dir -r requirements.txt
25+
26+
# Get NodeJS & npm
27+
COPY --from=node /usr/local/bin /usr/local/bin
28+
COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules
29+
30+
# Get app dependencies
31+
COPY --from=node /app/node_modules /app/node_modules
32+
33+
COPY . /app

Makefile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
.PHONY: all
2+
all: load_community_areas load_data
3+
4+
.PHONY: clean
5+
clean:
6+
rm data/raw/chicago-restaurants.csv data/raw/community-areas.geojson
7+
8+
.PHONY: load_community_areas
9+
load_community_areas: data/raw/community-areas.geojson
10+
python manage.py load_community_areas $^
11+
12+
.PHONY: load_data
13+
load_data: data/raw/chicago-restaurants.csv
14+
python manage.py load_restaurant_permits $^
15+
16+
data/raw/chicago-restaurants.csv:
17+
curl "https://data.cityofchicago.org/api/v3/views/fr9j-f3pa/query.csv?query=SELECT%0A%20%20%60id%60%2C%0A%20%20%60permit_%60%2C%0A%20%20%60permit_type%60%2C%0A%20%20%60review_type%60%2C%0A%20%20%60application_start_date%60%2C%0A%20%20%60issue_date%60%2C%0A%20%20%60processing_time%60%2C%0A%20%20%60street_number%60%2C%0A%20%20%60street_direction%60%2C%0A%20%20%60street_name%60%2C%0A%20%20%60work_description%60%2C%0A%20%20%60building_fee_paid%60%2C%0A%20%20%60zoning_fee_paid%60%2C%0A%20%20%60other_fee_paid%60%2C%0A%20%20%60subtotal_paid%60%2C%0A%20%20%60building_fee_unpaid%60%2C%0A%20%20%60zoning_fee_unpaid%60%2C%0A%20%20%60other_fee_unpaid%60%2C%0A%20%20%60subtotal_unpaid%60%2C%0A%20%20%60building_fee_waived%60%2C%0A%20%20%60zoning_fee_waived%60%2C%0A%20%20%60other_fee_waived%60%2C%0A%20%20%60subtotal_waived%60%2C%0A%20%20%60total_fee%60%2C%0A%20%20%60reported_cost%60%2C%0A%20%20%60community_area%60%2C%0A%20%20%60census_tract%60%2C%0A%20%20%60ward%60%2C%0A%20%20%60latitude%60%2C%0A%20%20%60longitude%60%2C%0A%20%20%60location%60%0AWHERE%0A%20%20%60issue_date%60%0A%20%20%20%20BETWEEN%20%222016-01-01T00%3A00%3A00%22%20%3A%3A%20floating_timestamp%0A%20%20%20%20AND%20%222026-03-09T00%3A00%3A00%22%20%3A%3A%20floating_timestamp&app_token=$$CDP_APP_TOKEN" -o $@
18+
19+
data/raw/community-areas.geojson:
20+
curl https://data.cityofchicago.org/resource/igwz-8jzy.geojson -o $@

README.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# DataMade Code Challenge: React Map
2+
3+
![2026 DataMade Code Challenge](https://github.com/datamade/code-challenge-v2/blob/main/map/static/images/2026-datamade-code-challenge.jpg)
4+
5+
Welcome to the 2026 DataMade code challenge! 👋
6+
7+
## Overview
8+
9+
Your task is to complete the following programming exercise to show us some of your code! This exercise is based on work that DataMade does every day: pulling data from the web, debugging tricky code, and presenting information to the world.
10+
11+
Submissions should be submitted as a pull request against your fork of this original repository. **Make sure to make your pull request against your own fork of the repository, not the original DataMade repository**.
12+
13+
There’s no time limit, but don’t feel the need to go over the top with your submission. We expect this task to take about two hours to complete, but it could take more or less time depending on your familiarity with Django and React. When you’re all set, share your code with us as a repository on GitHub.
14+
15+
We’ll be evaluating whether the code works, as well as its quality. Before submitting, make sure that your code does what you expect it to do, that it’s clean and neat enough to meet your standards, and that you’ve provided us some instructions on how to run it.
16+
17+
## Installation
18+
19+
Development requires a local installation of [Docker](https://docs.docker.com/get-started/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/). These are the only two system-level dependencies you should need.
20+
21+
Once you have Docker and Docker Compose installed, build the application containers from the project's root directory:
22+
23+
```bash
24+
docker compose build
25+
```
26+
27+
Load in the data:
28+
29+
```bash
30+
docker compose run --rm app python manage.py loaddata map/fixtures/restaurant_permits.json map/fixtures/community_areas.json
31+
```
32+
33+
And finally, run the app:
34+
35+
```bash
36+
docker compose up
37+
```
38+
39+
The app will log to the console, and you should be able to visit it at http://localhost:8000
40+
41+
## Completing the Challenge
42+
43+
Once you have the app up and running on your computer, you'll need to flesh out certain code blocks to make the map functional. You'll be using [Django](https://docs.djangoproject.com/en/6.0/) and [React-Leaflet](https://react-leaflet.js.org/docs/api-components/) to complete this task. By the end of this challenge, you should have:
44+
45+
- a map that displays Chicago's community areas, shaded depending on how many new restaurant permits were issued in a given year
46+
- community area shapes that show some light details on that community area when a user interacts with them
47+
- a filter that allows users to request permits that were issued in a given year
48+
- UI components that display the total number of permits and max number of permits in one community area for that year
49+
50+
This way you go about completing these goals is meant to be open-ended, so tackle the following steps in whatever way you're most comfortable!
51+
52+
### Step 1: Supplement the community area geojson data
53+
54+
In `map/serializers.py`, supplement each community area with data on the amount of permits issued in each area during the currently filtered year. From here, the view will pass that data to the front end.
55+
56+
### Step 2: Write a test for your data endpoint
57+
58+
In `tests/test_views.py` implement a test to validate the data that your endpoint produces. You will want to create some test `CommunityArea` and `RestaurantPermit` objects and then assert that the expected values are returned when querying the endpoint.
59+
60+
Use this command to run tests:
61+
62+
```bash
63+
docker compose -f docker-compose.yml -f tests/docker-compose.yml run --rm app
64+
```
65+
66+
### Step 3: Filter results by a specific year
67+
68+
In `map/static/js/RestaurantPermitMap.js`, create a filter that allows users to send a request for a specific year to the backend. The options shoulds be any year between 2016 and 2026, inclusive. Then, use the fetch api in the map component to make a request and receive that data.
69+
70+
### Step 4: Display results on the page
71+
72+
In the map component, process the community area and use it to display shapes for all areas on the map. Then, display the total number of restaurant permits that year as well as the maximum number of permits in any one area.
73+
74+
### Step 5: Make the map dynamic
75+
76+
Start displaying some data! Use the `setAreaInteraction()` method to shade the map according to how many permits it has in a year, making sure that it updates automatically when a new year is selected. In this same method, have each area display a popup during some kind of user interaction. The popup should have some light details to help the user understand what they're looking at.
77+
78+
### Step 6: Submit your work
79+
80+
To submit your work, create a feature branch for your code, commit your changes, push your commits up to your fork, and open up a pull request against main. Finally, drop a link to your pull request in your application.
81+
82+
_Note: If you would prefer to keep your code challenge private, please share access with the following members of DataMade on GitHub:_
83+
84+
| Member | GitHub Account |
85+
| --------- | -------------------------------- |
86+
| Hannah | https://github.com/hancush |
87+
| Derek | https://github.com/derekeder |
88+
| Monkruman | https://github.com/antidipyramid |
89+
| Xavier | https://github.com/xmedr |
90+
| Hayley | https://github.com/haowens |
91+
92+
Keep in mind that you cannot create a private fork of a public repository on GitHub, so you’ll need to [follow these instructions](https://gist.github.com/0xjac/85097472043b697ab57ba1b1c7530274) to create a private copy of the repo.

app.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"name": "map",
3+
"scripts": {},
4+
"env": {
5+
"DJANGO_ALLOWED_HOSTS": {
6+
"required": true
7+
},
8+
"DJANGO_SECRET_KEY": {
9+
"required": true
10+
},
11+
"AWS_ACCESS_KEY_ID": {
12+
"required": true
13+
},
14+
"AWS_SECRET_ACCESS_KEY": {
15+
"required": true
16+
},
17+
"AWS_STORAGE_BUCKET_NAME": {
18+
"required": true
19+
}
20+
},
21+
"formation": {
22+
"web": {
23+
"quantity": 1,
24+
"size": "basic"
25+
}
26+
},
27+
"environments": {
28+
"review": {
29+
"addons": ["heroku-postgresql:mini"]
30+
}
31+
},
32+
"buildpacks": [],
33+
"stack": "container"
34+
}

assets/.gitkeep

Whitespace-only changes.

data/raw/.gitkeep

Whitespace-only changes.

0 commit comments

Comments
 (0)