From 3eb761d3746f3deb1d81643636bf316093e8ded6 Mon Sep 17 00:00:00 2001 From: mohith01 Date: Tue, 23 Jul 2024 18:40:25 -0700 Subject: [PATCH 1/4] Fixed DockerFile by adding npm command --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 4c464fdf..d250560a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - # # Read more on Dockerfile best practices at the source: # https://docs.docker.com/develop/develop-images/dockerfile_best-practices -RUN apt-get update && apt-get install -y --no-install-recommends postgresql-client nodejs +RUN apt-get update && apt-get install -y --no-install-recommends postgresql-client nodejs npm # Inside the container, create an app directory and switch into it RUN mkdir /app From e4bc3ddfb6104d8fc44c85e463cf78fce38773a2 Mon Sep 17 00:00:00 2001 From: mohith01 Date: Tue, 23 Jul 2024 19:12:10 -0700 Subject: [PATCH 2/4] Implemented the API Endpoint, Can implement Suggestions if Repeated --- parserator_web/views.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/parserator_web/views.py b/parserator_web/views.py index 0be3f4a9..e05ff226 100644 --- a/parserator_web/views.py +++ b/parserator_web/views.py @@ -16,9 +16,18 @@ class AddressParse(APIView): def get(self, request): # TODO: Flesh out this method to parse an address string using the # parse() method and return the parsed components to the frontend. - return Response({}) + request_params = request.query_params + d = {'payload':'','errors':''} + if 'address' in request_params: + try: + d['payload']=self.parse(request_params['address']) + except usaddress.RepeatedLabelError as e: + d['errors'] = 'Repeated Labels' + d['payload'] = usaddress.parse(request_params['address']) #The error feedback can be improved + return Response(d) def parse(self, address): # TODO: Implement this method to return the parsed components of a # given address using usaddress: https://github.com/datamade/usaddress + (address_components, address_type) = usaddress.tag(address) return address_components, address_type From 5a79b84539ea7f1872e9981546c6bf7ddf1f8f4d Mon Sep 17 00:00:00 2001 From: mohith01 Date: Tue, 23 Jul 2024 21:05:08 -0700 Subject: [PATCH 3/4] Added the javascript and tested for Valid Address Error --- parserator_web/static/js/index.js | 42 ++++ .../templates/parserator_web/base.html | 184 +++++++++--------- .../templates/parserator_web/index.html | 17 +- parserator_web/views.py | 16 +- 4 files changed, 155 insertions(+), 104 deletions(-) diff --git a/parserator_web/static/js/index.js b/parserator_web/static/js/index.js index 492674cc..292b8124 100644 --- a/parserator_web/static/js/index.js +++ b/parserator_web/static/js/index.js @@ -1,2 +1,44 @@ /* TODO: Flesh this out to connect the form to the API and render results in the #address-results div. */ +const api_url = "/api/parse"; +const button = document.getElementById("submit"); +const address = document.getElementById("address"); +const parse_type = document.getElementById("parse-type") +button.addEventListener("click", function (event) { + event.preventDefault(); + fetch(api_url + `?address=${address.value}`).then(response => response.json()) + .then(data => { + // If errors exist + const table_body = document.getElementById("table_body") + table_body.innerHTML = ''; + document.getElementById("address-results").style.display = "none"; + const errors = document.getElementById('errors'); + errors.style.display = "none" + if (data.errors) { + errors.innerText = data.errors; + errors.style.display = "block" + } + else { + let address_parts, address_type; + [address_parts, address_type] = data.payload; + parse_type.innerText = address_type + for (const key in address_parts) { + // table_body.appendChild(`${key}${address_parts[key]}`) + let r1 = document.createElement("tr") + let c1 = document.createElement("td") + c1.innerText = key + let c2 = document.createElement("td") + c2.innerText = address_parts[key] + r1.appendChild(c1); + r1.appendChild(c2); + table_body.appendChild(r1); + } + + document.getElementById("address-results").style.display = "block"; + } + }) + .catch(error => { + console.error('Error', error); + }); + +}); \ No newline at end of file diff --git a/parserator_web/templates/parserator_web/base.html b/parserator_web/templates/parserator_web/base.html index 8de4f844..15bebcd4 100644 --- a/parserator_web/templates/parserator_web/base.html +++ b/parserator_web/templates/parserator_web/base.html @@ -1,98 +1,96 @@ {% load static %} - - - - - {% block title %}{% endblock %} | Parserator - - - - - - - - - - - - - - - - - - - - - - - {% block extra_meta %}{% endblock %} - - - - - - - - - - - - - - {% block extra_css %}{% endblock %} - - - - - -
-
- {% block body %}{% endblock %} -
+ + + + + + {% block title %}{% endblock %} | Parserator + + + + + + + + + + + + + + + + + + + + + + + {% block extra_meta %}{% endblock %} + + + + + + + + + + + + + + {% block extra_css %}{% endblock %} + + + + + +
+
+ {% block body %}{% endblock %}
+
+ +
+
+

+ Parserator +

+

+ Website by
+ + DataMade + +
+ ... and Mohit! +

+
+
+ + + + + + + + + {% block extra_js %}{% endblock %} + -
-
-

- Parserator -

-

- Website by
- - DataMade - -
- ... and you! -

-
-
- - - - - - - - - {% block extra_js %}{% endblock %} - - + \ No newline at end of file diff --git a/parserator_web/templates/parserator_web/index.html b/parserator_web/templates/parserator_web/index.html index a72d9c80..ed403a93 100644 --- a/parserator_web/templates/parserator_web/index.html +++ b/parserator_web/templates/parserator_web/index.html @@ -10,12 +10,19 @@

U.S. address parser

Dealing with some messy or unstructured addresses? We can parse them for you.

-

Try it out! Parse an address in the United States into fields like AddressNumber, StreetName and ZipCode.

+

Try it out! Parse an address in the United States into fields like + AddressNumber, StreetName and ZipCode. +

{% csrf_token %} - +
+
+ + @@ -38,5 +45,5 @@

Parsing results

{% endblock %} {% block extra_js %} - -{% endblock %} + +{% endblock %} \ No newline at end of file diff --git a/parserator_web/views.py b/parserator_web/views.py index e05ff226..8a5de419 100644 --- a/parserator_web/views.py +++ b/parserator_web/views.py @@ -18,16 +18,20 @@ def get(self, request): # parse() method and return the parsed components to the frontend. request_params = request.query_params d = {'payload':'','errors':''} - if 'address' in request_params: - try: - d['payload']=self.parse(request_params['address']) - except usaddress.RepeatedLabelError as e: - d['errors'] = 'Repeated Labels' - d['payload'] = usaddress.parse(request_params['address']) #The error feedback can be improved + try: + if 'address' in request_params: + try: + d['payload']=self.parse(request_params['address']) + except usaddress.RepeatedLabelError as e: + d['errors'] = 'Repeated Labels' + except ValueError: + d['errors'] = 'Fill a valid address' return Response(d) def parse(self, address): # TODO: Implement this method to return the parsed components of a # given address using usaddress: https://github.com/datamade/usaddress + if address=="": + raise ValueError("Parse again") (address_components, address_type) = usaddress.tag(address) return address_components, address_type From 6cdedcb404bc08fa2780c61d1f329167438340ce Mon Sep 17 00:00:00 2001 From: mohith01 Date: Tue, 23 Jul 2024 21:57:50 -0700 Subject: [PATCH 4/4] Fixed Linting Issues and modified the code --- parserator_web/static/js/index.js | 12 +++++------- parserator_web/views.py | 11 +++++------ tests/test_views.py | 26 ++++++++++++++++++++++++-- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/parserator_web/static/js/index.js b/parserator_web/static/js/index.js index 292b8124..0feeaa34 100644 --- a/parserator_web/static/js/index.js +++ b/parserator_web/static/js/index.js @@ -1,14 +1,13 @@ /* TODO: Flesh this out to connect the form to the API and render results in the #address-results div. */ -const api_url = "/api/parse"; -const button = document.getElementById("submit"); -const address = document.getElementById("address"); -const parse_type = document.getElementById("parse-type") +var api_url = "/api/parse"; +var button = document.getElementById("submit"); +var address = document.getElementById("address"); +var parse_type = document.getElementById("parse-type") button.addEventListener("click", function (event) { event.preventDefault(); - fetch(api_url + `?address=${address.value}`).then(response => response.json()) + fetch(api_url + "?address=" + address.value).then(response => response.json()) .then(data => { - // If errors exist const table_body = document.getElementById("table_body") table_body.innerHTML = ''; document.getElementById("address-results").style.display = "none"; @@ -23,7 +22,6 @@ button.addEventListener("click", function (event) { [address_parts, address_type] = data.payload; parse_type.innerText = address_type for (const key in address_parts) { - // table_body.appendChild(`${key}${address_parts[key]}`) let r1 = document.createElement("tr") let c1 = document.createElement("td") c1.innerText = key diff --git a/parserator_web/views.py b/parserator_web/views.py index 8a5de419..c2f5ab8c 100644 --- a/parserator_web/views.py +++ b/parserator_web/views.py @@ -3,7 +3,6 @@ from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.renderers import JSONRenderer -from rest_framework.exceptions import ParseError class Home(TemplateView): @@ -17,12 +16,12 @@ def get(self, request): # TODO: Flesh out this method to parse an address string using the # parse() method and return the parsed components to the frontend. request_params = request.query_params - d = {'payload':'','errors':''} + d = {'payload': '', 'errors': ''} try: if 'address' in request_params: try: - d['payload']=self.parse(request_params['address']) - except usaddress.RepeatedLabelError as e: + d['payload'] = self.parse(request_params['address']) + except usaddress.RepeatedLabelError: d['errors'] = 'Repeated Labels' except ValueError: d['errors'] = 'Fill a valid address' @@ -31,7 +30,7 @@ def get(self, request): def parse(self, address): # TODO: Implement this method to return the parsed components of a # given address using usaddress: https://github.com/datamade/usaddress - if address=="": - raise ValueError("Parse again") + if address == "": + raise ValueError("Parse again") (address_components, address_type) = usaddress.tag(address) return address_components, address_type diff --git a/tests/test_views.py b/tests/test_views.py index bfd5d0b7..e480007f 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -5,11 +5,33 @@ def test_api_parse_succeeds(client): # TODO: Finish this test. Send a request to the API and confirm that the # data comes back in the appropriate format. address_string = '123 main st chicago il' - pytest.fail() + response = client.get("/api/parse", {"address": address_string}, follow=True) + expected_answer = {"payload": [ + { + "AddressNumber": "123", + "StreetName": "main", + "StreetNamePostType": "st", + "PlaceName": "chicago", + "StateName": "il" + }, + "Street Address" + ], + "errors": "" + } + if response.json()['errors'] != '': + pytest.fail() + assert response.json()['payload'] == expected_answer['payload'] def test_api_parse_raises_error(client): # TODO: Finish this test. The address_string below will raise a # RepeatedLabelError, so ParseAddress.parse() will not be able to parse it. address_string = '123 main st chicago il 123 main st' - pytest.fail() + response = client.get("/api/parse", {"address": address_string}, follow=True) + expected_answer = { + "payload": "", + "errors": "Repeated Labels" + } + if response.json()['errors'] == '': + pytest.fail() + assert response.json()['errors'] == expected_answer['errors']