Skip to content

Commit

Permalink
[45] Location autocomplete (#46)
Browse files Browse the repository at this point in the history
* WIP tooltips

* wip error message

* Rename view to admin

* Rename location in data-serving

* update naming

* Final cleanup

* Finished tests and cleared up form

* Update geocoder.py

* Update geocoder.py

* Fix tests for location after naming and component change

* Fix cypress tests

* Update geocoder

* Update test_suggestions.py

* Update test_suggestions.py

* Update test_suggestions.py

* Update test_suggestions.py

* WIP location form based on geocoding

* Working admin selection

* Update wiki id on name change also

* Update test_suggestions.py

* Fix eslint issues

* Fix finding entry

* WIP update tests

* Update main.py

* Add flask api library

* Use flask_api

* Update main.py

* Fix flaskapi

* Review v2
  • Loading branch information
stanislaw-zakrzewski committed Feb 23, 2024
1 parent 7f546c9 commit 7feafa1
Show file tree
Hide file tree
Showing 46 changed files with 1,901 additions and 715 deletions.
33 changes: 24 additions & 9 deletions data-serving/data-service/api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1000,11 +1000,17 @@ components:
country:
type: string
description: name of a country
region:
admin1:
type: string
district:
admin1WikiId:
type: string
place:
admin2:
type: string
admin2WikiId:
type: string
admin3:
type: string
admin3WikiId:
type: string
location:
type: string
Expand Down Expand Up @@ -1035,18 +1041,27 @@ components:
type: string
description: Third administrative subdivision of a country
example: Any district in Costa Rica
region:
admin1:
type: string
description: Name of the region this location refers to
description: Name of the area in admin1 resolution for given country
example: Lodz Voivodeship
district:
admin1WikiId:
type: string
description: Name of the district this location refers to
description: Wiki identifier of the area in admin1 resolution
admin2:
type: string
description: Name of the area in admin2 resolution for given admin1 area and country
example: Lodz County
place:
admin2WikiId:
type: string
description: Wiki identifier of the area in admin2 resolution
admin3:
type: string
description: Name of the place this location refers to
description: Name of the area in admin3 resolution for given admin2 area, admin1 area and country
example: Boston Children's Hospital
admin3WikiId:
type: string
description: Wiki identifier of the area in admin3 resolution
name:
type: string
description: >
Expand Down
6 changes: 3 additions & 3 deletions data-serving/data-service/src/controllers/case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1330,11 +1330,11 @@ export class CasesController {
if (location.geoResolution) return;
if (location.geometry?.longitude && location.geometry?.latitude) {
req.body.location.geoResolution = 'Point';
} else if (location.place) {
} else if (location.admin3) {
req.body.location.geoResolution = 'Admin3';
} else if (location.district) {
} else if (location.admin2) {
req.body.location.geoResolution = 'Admin2';
} else if (location.region) {
} else if (location.admin1) {
req.body.location.geoResolution = 'Admin1';
} else if (location.country) {
req.body.location.geoResolution = 'Country';
Expand Down
14 changes: 7 additions & 7 deletions data-serving/data-service/src/geocoding/geocoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ export interface GeocodeResult {
administrativeAreaLevel2?: string;
// Third administrative division (cities usually).
administrativeAreaLevel3?: string;
// Region, equivalent to mapbox admin1.
region: string | undefined;
// District, equivalent to mapbox admin2.
district: string | undefined;
// A precise location, such as an establishment or POI, equivalent to mapbox admin3.
place: string | undefined;
// Human readable place name.
// Area in admin1 resolution.
admin1: string | undefined;
// Area in admin2 resolution.
admin2: string | undefined;
// Area in admin3 resolution.
admin3: string | undefined;
// Human-readable place name.
name: string;
// How granular the geocode is.
geoResolution: Resolution;
Expand Down
6 changes: 3 additions & 3 deletions data-serving/data-service/src/model/fields.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@
"events.dateRecovered",
"location.country",
"location.countryISO3",
"location.region",
"location.district",
"location.place",
"location.admin1",
"location.admin2",
"location.admin3",
"location.location",
"location.query",
"preexistingConditions.previousInfection",
Expand Down
18 changes: 12 additions & 6 deletions data-serving/data-service/src/model/location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ export const locationSchema = new mongoose.Schema(
geoResolution: String,
// Location represents a precise location, such as an establishment or POI.
location: String,
region: String,
district: String,
place: String,
admin1: String,
admin1WikiId: String,
admin2: String,
admin2WikiId: String,
admin3: String,
admin3WikiId: String,
query: String,
name: String,
geometry: {
Expand All @@ -34,9 +37,12 @@ export type LocationDocument = mongoose.Document & {
countryISO3: string;
geoResolution: string;
location?: string;
region?: string;
district?: string;
place?: string;
admin1?: string;
admin1WikiId?: string;
admin2?: string;
admin2WikiId?: string;
admin3?: string;
admin3WikiId?: string;
query?: string;
name?: string;
geometry?: {
Expand Down
10 changes: 6 additions & 4 deletions data-serving/data-service/src/util/case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export enum SortBy {
Default = 'default',
ConfirmationDate = 'confirmationDate',
Country = 'country',
Place = 'place',
Admin3 = 'admin3',
Location = 'location',
Age = 'age',
Occupation = 'occupation',
Expand Down Expand Up @@ -65,8 +65,8 @@ export const getSortByKeyword = (sortBy: SortBy): string => {
case SortBy.Country:
keyword = 'location.countryISO3';
break;
case SortBy.Place:
keyword = 'location.place';
case SortBy.Admin3:
keyword = 'location.admin3';
break;
case SortBy.Location:
keyword = 'location.location';
Expand Down Expand Up @@ -255,7 +255,9 @@ function denormalizeLocationFields(
denormalizedData['location.country'] = doc.country || '';
denormalizedData['location.countryISO3'] = doc.countryISO3 || '';
denormalizedData['location.location'] = doc.location || '';
denormalizedData['location.place'] = doc.place || '';
denormalizedData['location.admin1'] = doc.admin1 || '';
denormalizedData['location.admin2'] = doc.admin2 || '';
denormalizedData['location.admin3'] = doc.admin3 || '';
denormalizedData['location.geoResolution'] = doc.geoResolution || '';
denormalizedData['location.geometry.latitude'] =
doc.geometry?.latitude || '';
Expand Down
42 changes: 21 additions & 21 deletions data-serving/data-service/test/controllers/case.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -463,13 +463,13 @@ describe('POST', () => {

expect(res.body.location).toEqual(expectedLocation);
});
it('create with location containing region should complete geoResolution with "Admin1"', async () => {
it('create with location containing admin1 should complete geoResolution with "Admin1"', async () => {
const minimalLocationRequest = {
...minimalRequest,
location: {
countryISO3: 'USA',
country: 'United States of America',
region: 'Florida',
admin1: 'Florida',
query: 'Florida, United States of America',
},
};
Expand All @@ -478,7 +478,7 @@ describe('POST', () => {
country: 'United States of America',
geoResolution: 'Admin1',
countryISO3: 'USA',
region: 'Florida',
admin1: 'Florida',
query: 'Florida, United States of America',
};

Expand All @@ -493,14 +493,14 @@ describe('POST', () => {

expect(res.body.location).toEqual(expectedLocation);
});
it('create with location containing district should complete geoResolution with "Admin2"', async () => {
it('create with location containing admin2 should complete geoResolution with "Admin2"', async () => {
const minimalLocationRequest = {
...minimalRequest,
location: {
countryISO3: 'USA',
country: 'United States of America',
region: 'Florida',
district: 'Collier County',
admin1: 'Florida',
admin2: 'Collier County',
query: 'Collier County, Florida, United States of America',
},
};
Expand All @@ -509,8 +509,8 @@ describe('POST', () => {
country: 'United States of America',
geoResolution: 'Admin2',
countryISO3: 'USA',
region: 'Florida',
district: 'Collier County',
admin1: 'Florida',
admin2: 'Collier County',
query: 'Collier County, Florida, United States of America',
};

Expand All @@ -525,15 +525,15 @@ describe('POST', () => {

expect(res.body.location).toEqual(expectedLocation);
});
it('create with location containing place should complete geoResolution with "Admin3"', async () => {
it('create with location containing admin3 should complete geoResolution with "Admin3"', async () => {
const minimalLocationRequest = {
...minimalRequest,
location: {
countryISO3: 'USA',
country: 'United States of America',
region: 'Florida',
district: 'Collier County',
place: 'Naples',
admin1: 'Florida',
admin2: 'Collier County',
admin3: 'Naples',
query:
'Naples, Collier County, Florida, United States of America',
},
Expand All @@ -543,9 +543,9 @@ describe('POST', () => {
country: 'United States of America',
geoResolution: 'Admin3',
countryISO3: 'USA',
region: 'Florida',
district: 'Collier County',
place: 'Naples',
admin1: 'Florida',
admin2: 'Collier County',
admin3: 'Naples',
query: 'Naples, Collier County, Florida, United States of America',
};

Expand All @@ -566,9 +566,9 @@ describe('POST', () => {
location: {
countryISO3: 'USA',
country: 'United States of America',
region: 'Florida',
district: 'Collier County',
place: 'Naples',
admin1: 'Florida',
admin2: 'Collier County',
admin3: 'Naples',
geometry: {
latitude: 26.1295,
longitude: -81.8056,
Expand All @@ -582,9 +582,9 @@ describe('POST', () => {
country: 'United States of America',
geoResolution: 'Point',
countryISO3: 'USA',
region: 'Florida',
district: 'Collier County',
place: 'Naples',
admin1: 'Florida',
admin2: 'Collier County',
admin3: 'Naples',
geometry: {
latitude: 26.1295,
longitude: -81.8056,
Expand Down
36 changes: 23 additions & 13 deletions data-serving/data-service/test/util/case.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ describe('Case', () => {
'location.geometry.latitude',
'location.geometry.longitude',
'location.name',
'location.place',
'location.admin1',
'location.admin2',
'location.admin3',
'location.query',
'pathogens',
'preexistingConditions.hasPreexistingConditions',
Expand Down Expand Up @@ -159,7 +161,9 @@ describe('Case', () => {
'location.geometry.latitude',
'location.geometry.longitude',
'location.name',
'location.place',
'location.admin1',
'location.admin2',
'location.admin3',
'location.query',
'pathogens',
'preexistingConditions.hasPreexistingConditions',
Expand Down Expand Up @@ -252,9 +256,9 @@ describe('Case', () => {
expect(denormalizedCase['events.dateRecovered']).toEqual('');

expect(denormalizedCase['location.country']).toEqual('');
expect(denormalizedCase['location.countryISO3']).toEqual('');
expect(denormalizedCase['location.location']).toEqual('');
expect(denormalizedCase['location.place']).toEqual('');
expect(denormalizedCase['location.admin1']).toEqual('');
expect(denormalizedCase['location.admin2']).toEqual('');
expect(denormalizedCase['location.admin3']).toEqual('');
expect(denormalizedCase['location.geoResolution']).toEqual('');
expect(denormalizedCase['location.geometry.latitude']).toEqual('');
expect(denormalizedCase['location.geometry.longitude']).toEqual('');
Expand Down Expand Up @@ -446,14 +450,16 @@ describe('Case', () => {
});
it('denormalizes location fields', async () => {
const locationDoc = {
country: 'Georgia',
countryISO3: 'GEO',
name: 'Tbilisi',
place: 'Tibilisi',
country: 'Germany',
countryISO3: 'DEU',
name: 'Berlin',
admin1: 'Berlin',
admin2: 'SK Berlin',
admin3: 'Berlin',
geoResolution: 'Point',
geometry: {
latitude: 41.7151,
longitude: 44.8271,
latitude: 52.52,
longitude: 13.405,
},
} as LocationDocument;

Expand All @@ -479,8 +485,12 @@ describe('Case', () => {
expect(denormalizedCase['location.country']).toEqual(
locationDoc.country,
);
expect(denormalizedCase['location.countryISO3']).toEqual('GEO');
expect(denormalizedCase['location.place']).toEqual(locationDoc.place);
expect(denormalizedCase['location.countryISO3']).toEqual(
locationDoc.countryISO3,
);
expect(denormalizedCase['location.admin1']).toEqual(locationDoc.admin1);
expect(denormalizedCase['location.admin2']).toEqual(locationDoc.admin2);
expect(denormalizedCase['location.admin3']).toEqual(locationDoc.admin3);
expect(denormalizedCase['location.geoResolution']).toEqual(
locationDoc.geoResolution,
);
Expand Down
Loading

0 comments on commit 7feafa1

Please sign in to comment.