Skip to content

Commit 07c00fa

Browse files
authored
Merge pull request #118 from mapswipe/feature/street-project
2 parents 6008fec + a48328d commit 07c00fa

File tree

24 files changed

+1765
-633
lines changed

24 files changed

+1765
-633
lines changed

apps/project/graphql/inputs/inputs.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from .project_types.compare import CompareProjectPropertyInput
1919
from .project_types.completeness import CompletenessProjectPropertyInput
2020
from .project_types.find import FindProjectPropertyInput
21+
from .project_types.street import StreetProjectPropertyInput
2122
from .project_types.validate import ValidateProjectPropertyInput
2223
from .project_types.validate_image import ValidateImageProjectPropertyInput
2324

@@ -51,6 +52,7 @@ class ProjectTypeSpecificInput:
5152
completeness: CompletenessProjectPropertyInput | None = strawberry.UNSET
5253
validate: ValidateProjectPropertyInput | None = strawberry.UNSET
5354
validate_image: ValidateImageProjectPropertyInput | None = strawberry.UNSET
55+
street: StreetProjectPropertyInput | None = strawberry.UNSET
5456

5557

5658
# NOTE: Make sure this matches with the serializers ../serializers.py
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import strawberry
2+
3+
from project_types.street import project as street_project
4+
5+
6+
@strawberry.experimental.pydantic.input(model=street_project.StreetMapillaryImageFilters, all_fields=True)
7+
class StreetMapillaryImageFiltersInput: ...
8+
9+
10+
@strawberry.experimental.pydantic.input(model=street_project.StreetProjectProperty, all_fields=True)
11+
class StreetProjectPropertyInput: ...
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import strawberry
2+
3+
from project_types.street import project as street_project
4+
5+
6+
@strawberry.experimental.pydantic.type(model=street_project.StreetMapillaryImageFilters, all_fields=True)
7+
class StreetMapillaryImageFilters: ...
8+
9+
10+
@strawberry.experimental.pydantic.type(model=street_project.StreetProjectProperty, all_fields=True)
11+
class StreetProjectPropertyType: ...

apps/project/graphql/types/types.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from apps.tutorial.graphql.types.types import TutorialType
1515
from main.config import Config
1616
from main.graphql.context import Info
17+
from project_types.street import project as street_project
1718
from project_types.tile_map_service.compare import project as compare_project
1819
from project_types.tile_map_service.completeness import project as completeness_project
1920
from project_types.tile_map_service.find import project as find_project
@@ -31,6 +32,7 @@
3132
from .project_types.compare import CompareProjectPropertyType
3233
from .project_types.completeness import CompletenessProjectPropertyType
3334
from .project_types.find import FindProjectPropertyType
35+
from .project_types.street import StreetProjectPropertyType
3436
from .project_types.validate import ValidateProjectPropertyType
3537
from .project_types.validate_image import ValidateImageProjectPropertyType
3638

@@ -188,6 +190,7 @@ async def project_type_specifics(
188190
| ValidateProjectPropertyType
189191
| ValidateImageProjectPropertyType
190192
| CompletenessProjectPropertyType
193+
| StreetProjectPropertyType
191194
| None
192195
):
193196
data = project.project_type_specifics
@@ -209,4 +212,9 @@ async def project_type_specifics(
209212
"CompletenessProjectPropertyType",
210213
completeness_project.CompletenessProjectProperty.model_validate(data),
211214
)
215+
if project.project_type_enum == Project.Type.STREET:
216+
return typing.cast(
217+
"StreetProjectPropertyType",
218+
street_project.StreetProjectProperty.model_validate(data),
219+
)
212220
typing.assert_never(project.project_type_enum)

apps/project/models.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,9 @@ class ProjectTypeEnum(models.IntegerChoices):
109109

110110
# MEDIA = 5, "Media"
111111
# DIGITIZATION = 6, "Digitization"
112-
# STREET = 7, "Street"
112+
STREET = 7, "Street"
113+
""" Street project type. """
114+
113115
# TODO(thenav56): Confirm if we have more/less
114116

115117
@classmethod
@@ -130,6 +132,8 @@ def to_firebase(self) -> firebase_models.FbEnumProjectType:
130132
return firebase_models.FbEnumProjectType.VALIDATE
131133
case ProjectTypeEnum.VALIDATE_IMAGE:
132134
return firebase_models.FbEnumProjectType.VALIDATE_IMAGE
135+
case ProjectTypeEnum.STREET:
136+
return firebase_models.FbEnumProjectType.STREET
133137

134138

135139
class ProjectStatusEnum(models.IntegerChoices):

apps/project/tests/mutation_test.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from PIL import Image
99
from ulid import ULID
1010

11+
from apps.common.models import IconEnum
1112
from apps.contributor.factories import ContributorTeamFactory
1213
from apps.project.factories import OrganizationFactory, ProjectFactory
1314
from apps.project.models import (
@@ -25,6 +26,7 @@
2526
from apps.user.factories import UserFactory
2627
from main.config import Config
2728
from main.tests import TestCase
29+
from project_types.street import project as street_project
2830
from project_types.tile_map_service.compare import project as compare_project
2931
from utils.geo.raster_tile_server.config import RasterTileServerNameEnum
3032

@@ -1546,3 +1548,103 @@ class TaskGroupType(typing.TypedDict):
15461548
# project is sync to firebase after publish
15471549
fb_project: typing.Any = project_ref.get()
15481550
assert fb_project is not None
1551+
1552+
@patch("apps.project.serializers.process_project_task.delay")
1553+
def test_project_street(self, mock_requests):
1554+
self.force_login(self.user)
1555+
project_data = {
1556+
**self.project_data,
1557+
"clientId": str(ULID()),
1558+
"projectType": self.genum(ProjectTypeEnum.STREET),
1559+
}
1560+
content = self._create_project_mutation(project_data)
1561+
resp_data = content["data"]["createProject"]
1562+
assert resp_data["errors"] is None, content
1563+
1564+
project_id = resp_data["result"]["id"]
1565+
project_client_id = resp_data["result"]["clientId"]
1566+
1567+
# Creating AOI Project Asset
1568+
project_asset_data = {
1569+
"project": project_id,
1570+
"clientId": str(ULID()),
1571+
}
1572+
1573+
content = self._create_project_aoi_asset(project_asset_data, assert_errors=True)
1574+
resp_data = content["data"]["createProjectAsset"]
1575+
assert resp_data["errors"] is None, content
1576+
aoi_geometry_asset = resp_data["result"]
1577+
1578+
# Creating Project Image Asset
1579+
project_asset_data = {
1580+
"project": project_id,
1581+
"clientId": str(ULID()),
1582+
}
1583+
content = self._create_project_image_asset(project_asset_data, assert_errors=True)
1584+
resp_data = content["data"]["createProjectAsset"]
1585+
assert resp_data["errors"] is None, content
1586+
image_asset = resp_data["result"]
1587+
1588+
# Updating Project
1589+
project_data = {
1590+
"clientId": project_client_id,
1591+
"image": image_asset["id"],
1592+
"verificationNumber": 10,
1593+
"projectTypeSpecifics": {
1594+
"street": {
1595+
"aoiGeometry": aoi_geometry_asset["id"],
1596+
"customOptions": {
1597+
"clientId": str(ULID()),
1598+
"description": "Street project description",
1599+
"icon": self.genum(IconEnum.ADD_OUTLINE),
1600+
"iconColor": "#FF0000",
1601+
"title": "Street Project Title",
1602+
"value": 1,
1603+
"subOptions": [
1604+
{
1605+
"clientId": str(ULID()),
1606+
"value": 1,
1607+
"description": "Street sub option description",
1608+
},
1609+
],
1610+
},
1611+
"mapillaryImageFilters": {
1612+
"isPano": True,
1613+
"creatorId": None,
1614+
"organizationId": None,
1615+
"startTime": None,
1616+
"endTime": None,
1617+
"randomizeOrder": False,
1618+
"samplingThreshold": None,
1619+
},
1620+
},
1621+
},
1622+
}
1623+
content = self._update_project_mutation(project_id, project_data)
1624+
resp_data = content["data"]["updateProject"]
1625+
assert resp_data["errors"] is None, content
1626+
1627+
latest_project = Project.objects.get(pk=project_id)
1628+
assert latest_project.created_by_id == self.user.pk
1629+
assert latest_project.modified_by_id == self.user.pk
1630+
assert latest_project.image_id == int(image_asset["id"])
1631+
assert latest_project.project_type_specifics is not None
1632+
1633+
street_project.StreetProjectProperty.model_validate(
1634+
latest_project.project_type_specifics,
1635+
context={"project_id": latest_project.pk},
1636+
)
1637+
1638+
# Updating Project:
1639+
# Test project processing
1640+
project_data = {
1641+
"clientId": project_client_id,
1642+
"status": self.genum(Project.Status.MARKED_AS_READY),
1643+
}
1644+
content = self._update_project_status_mutation(project_id, project_data)
1645+
resp_data = content["data"]["updateProjectStatus"]
1646+
assert resp_data["errors"] is None, content
1647+
assert resp_data["result"]["status"] == self.genum(Project.Status.MARKED_AS_READY)
1648+
1649+
mock_requests.assert_called_once()
1650+
mock_requests.assert_has_calls([call(int(project_id))])
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import strawberry
2+
3+
from project_types.street import tutorial as street_tutorial
4+
5+
6+
@strawberry.experimental.pydantic.type(model=street_tutorial.StreetTutorialTaskProperty, all_fields=True)
7+
class StreetTutorialTaskPropertyType: ...

apps/tutorial/graphql/types/types.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import apps.project.graphql.types.asset_types # noqa: F401 # isort: skip # type: ignore[reportUnusedImport]
1919

20+
from project_types.street import tutorial as street_tutorial
2021
from project_types.tile_map_service.compare import tutorial as compare_tutorial
2122
from project_types.tile_map_service.completeness import tutorial as completeness_tutorial
2223
from project_types.tile_map_service.find import tutorial as find_tutorial
@@ -26,6 +27,7 @@
2627
from .project_types.compare import CompareTutorialTaskPropertyType
2728
from .project_types.completeness import CompletenessTutorialTaskPropertyType
2829
from .project_types.find import FindTutorialTaskPropertyType
30+
from .project_types.street import StreetTutorialTaskPropertyType
2931
from .project_types.validate import ValidateTutorialTaskPropertyType
3032
from .project_types.validate_image import ValidateImageTutorialTaskPropertyType
3133

@@ -62,6 +64,7 @@ async def project_type_specifics(
6264
| ValidateTutorialTaskPropertyType
6365
| ValidateImageTutorialTaskPropertyType
6466
| CompletenessTutorialTaskPropertyType
67+
| StreetTutorialTaskPropertyType
6568
| None
6669
):
6770
data = task.project_type_specifics
@@ -91,6 +94,11 @@ async def project_type_specifics(
9194
"CompletenessTutorialTaskPropertyType",
9295
completeness_tutorial.CompletenessTutorialTaskProperty.model_validate(data),
9396
)
97+
if project_type_enum == Project.Type.STREET:
98+
return typing.cast(
99+
"StreetTutorialTaskPropertyType",
100+
street_tutorial.StreetTutorialTaskProperty.model_validate(data),
101+
)
94102
typing.assert_never(project_type_enum)
95103

96104

docker-compose.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ x-server: &base_server_setup
5353
MAP_IMAGE_ESRI_BETA_API_KEY: ${MAP_IMAGE_ESRI_BETA_API_KEY:-dummy-esri-beta}
5454
# MAP_IMAGE_DIGITAL_GLOBE_API_KEY: ${MAP_IMAGE_DIGITAL_GLOBE_API_KEY:-dummy-digital-globe}
5555
OSMCHA_API_KEY: ${OSMCHA_API_KEY:-dummy-osmcha-api-key}
56+
MAPILLARY_API_KEY: ${MAPILLARY_API_KEY:-dummy-mapillary-api-key}
5657
# Firebase
5758
FIREBASE_EMULATOR_USE: ${FIREBASE_EMULATOR_USE:-true}
5859
FIREBASE_EMULATOR_PROJECT_ID: ${FIREBASE_EMULATOR_PROJECT_ID:-dev-mapswipe}

0 commit comments

Comments
 (0)