diff --git a/apps/project/graphql/queries.py b/apps/project/graphql/queries.py index 482c82d8..116ad3dc 100644 --- a/apps/project/graphql/queries.py +++ b/apps/project/graphql/queries.py @@ -7,6 +7,7 @@ from apps.project.custom_options import get_custom_options from apps.project.graphql.inputs.inputs import ProjectNameInput +from apps.project.graphql.types.public.types import PublicProjectType from apps.project.models import Organization, Project, ProjectTypeEnum from utils.geo.raster_tile_server.config import RasterConfig, RasterTileServerNameEnum, RasterTileServerNameEnumWithoutCustom from utils.geo.vector_tile_server.config import VectorConfig, VectorTileServerNameEnum, VectorTileServerNameEnumWithoutCustom @@ -82,7 +83,7 @@ def default_custom_options(self, project_type: ProjectTypeEnum) -> list[CustomOp # Private -------------------- project: ProjectType = strawberry_django.field(extensions=[IsAuthenticated()]) - public_project: ProjectType = strawberry_django.field() + public_project: PublicProjectType = strawberry_django.field() project_asset: ProjectAssetType = strawberry_django.field(extensions=[IsAuthenticated()]) @@ -145,7 +146,7 @@ def projects( ).all() @strawberry_django.offset_paginated( - OffsetPaginated[ProjectType], + OffsetPaginated[PublicProjectType], order=ProjectOrder, filters=ProjectFilter, ) diff --git a/apps/project/graphql/types/public/__init__.py b/apps/project/graphql/types/public/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/project/graphql/types/public/types.py b/apps/project/graphql/types/public/types.py new file mode 100644 index 00000000..dfeee93b --- /dev/null +++ b/apps/project/graphql/types/public/types.py @@ -0,0 +1,42 @@ +import datetime + +import strawberry +import strawberry_django + +from apps.project.graphql.types.types import GeometryType, OrganizationType, ProjectAssetType, ProjectExportAssetTypeMixin +from apps.project.models import Project + + +# Project +@strawberry_django.type(Project) +class PublicProjectType(ProjectExportAssetTypeMixin): + id: strawberry.ID + firebase_id: str + project_type: strawberry.auto + requesting_organization_id: strawberry.ID + requesting_organization: OrganizationType + region: strawberry.auto + description: strawberry.auto + image: ProjectAssetType | None + status: strawberry.auto + created_at: datetime.datetime + modified_at: datetime.datetime + + total_area: strawberry.auto + aoi_geometry: GeometryType | None + + number_of_contributor_users: strawberry.auto + + @strawberry_django.field( + description=str(Project._meta.get_field("progress").help_text), # type: ignore[reportAttributeAccessIssue] + ) + def progress(self, project: strawberry.Parent[Project]) -> float: + return project.progress / 100 + + @strawberry_django.field( + only=["topic", "region", "project_number", "requesting_organization__name", "project_type"], + annotate={"generated_name": Project.generate_name_query()}, + description="Project name generated from topic, region, project number, and requesting organization name.", + ) + def name(self, project: strawberry.Parent[Project]) -> str: + return project.generated_name # type: ignore[reportAttributeAccessIssue] diff --git a/apps/project/graphql/types/types.py b/apps/project/graphql/types/types.py index a1ee2ed9..e60896b3 100644 --- a/apps/project/graphql/types/types.py +++ b/apps/project/graphql/types/types.py @@ -86,6 +86,7 @@ async def asset_type_specifics( # Project +# NOTE: This is also used for public project type. @strawberry.interface class ProjectExportAssetTypeMixin: @strawberry.field diff --git a/schema.graphql b/schema.graphql index 8ab6df98..30caf219 100644 --- a/schema.graphql +++ b/schema.graphql @@ -2003,6 +2003,58 @@ type ProjectVectorTileServerCustomConfig { url: String! } +"""Model representing the project.""" +type PublicProjectType implements ProjectExportAssetTypeMixin { + aoiGeometry: GeometryType + createdAt: DateTime! + description: String + exportAggregatedResults: ProjectAssetType + exportAggregatedResultsWithGeometry: ProjectAssetType + exportAreaOfInterest: ProjectAssetType + exportGroups: ProjectAssetType + exportHistory: ProjectAssetType + exportHotTaskingManagerGeometries: ProjectAssetType + exportModerateToHighAgreementYesMaybeGeometries: ProjectAssetType + exportResults: ProjectAssetType + exportTasks: ProjectAssetType + exportUsers: ProjectAssetType + firebaseId: String! + id: ID! + image: ProjectAssetType + modifiedAt: DateTime! + + """ + Project name generated from topic, region, project number, and requesting organization name. + """ + name: String! + + """Number of users who made contributions to this project""" + numberOfContributorUsers: Int! + + """Percentage of the required contribution that has been completed""" + progress: Float! + projectType: ProjectTypeEnum! + region: String! + + """Which group, institution or community is requesting this project?""" + requestingOrganization: OrganizationType! + + """Which group, institution or community is requesting this project?""" + requestingOrganizationId: ID! + status: ProjectStatusEnum! + totalArea: Float +} + +type PublicProjectTypeOffsetPaginated { + pageInfo: OffsetPaginationInfo! + + """List of paginated results.""" + results: [PublicProjectType!]! + + """Total count of existing results.""" + totalCount: Int! +} + type Query { communityFilteredStats(dateRange: DateRangeInput = null): CommunityFilteredStats! communityStats: CommunityStatsType! @@ -2033,8 +2085,8 @@ type Query { projects(includeAll: Boolean! = false, filters: ProjectFilter, order: ProjectOrder, pagination: OffsetPaginationInput): ProjectTypeOffsetPaginated! @isAuthenticated publicOrganization(id: ID!): OrganizationType! publicOrganizations(filters: OrganizationFilter, order: OrganizationOrder, pagination: OffsetPaginationInput): OrganizationTypeOffsetPaginated! - publicProject(id: ID!): ProjectType! - publicProjects(filters: ProjectFilter, order: ProjectOrder, pagination: OffsetPaginationInput): ProjectTypeOffsetPaginated! + publicProject(id: ID!): PublicProjectType! + publicProjects(filters: ProjectFilter, order: ProjectOrder, pagination: OffsetPaginationInput): PublicProjectTypeOffsetPaginated! tileServers: RasterTileServersType! @isAuthenticated tutorial(id: ID!): TutorialType! @isAuthenticated tutorialAsset(id: ID!): TutorialAssetType! @isAuthenticated