Skip to content

Commit

Permalink
Merge pull request #6153 from hotosm/feat/active-projects-api-for-exp…
Browse files Browse the repository at this point in the history
…ort-tool

feat: new active projects api for export tool
  • Loading branch information
kshitijrajsharma authored Jan 8, 2024
2 parents ae66919 + c3f5aca commit af75feb
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 0 deletions.
5 changes: 5 additions & 0 deletions backend/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ def add_api_endpoints(app):
ProjectsQueriesPriorityAreasAPI,
ProjectsQueriesFeaturedAPI,
ProjectQueriesSimilarProjectsAPI,
ProjectQueriesActiveProjectsAPI,
)
from backend.api.projects.activities import (
ProjectsActivitiesAPI,
Expand Down Expand Up @@ -428,6 +429,10 @@ def add_api_endpoints(app):
ProjectQueriesSimilarProjectsAPI,
format_url("projects/queries/<int:project_id>/similar-projects/"),
)
api.add_resource(
ProjectQueriesActiveProjectsAPI,
format_url("projects/queries/active/"),
)

# Projects' addtional resources
api.add_resource(
Expand Down
45 changes: 45 additions & 0 deletions backend/api/projects/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -1164,3 +1164,48 @@ def get(self, project_id):
project_id, authenticated_user_id, preferred_locale, limit
)
return projects_dto.to_primitive(), 200


class ProjectQueriesActiveProjectsAPI(Resource):
@token_auth.login_required(optional=True)
def get(self):
"""
Get active projects
---
tags:
- projects
produces:
- application/json
parameters:
- in: header
name: Authorization
description: Base64 encoded session token
required: false
type: string
default: Token sessionTokenHere==
- name: interval
in: path
description: Time interval in hours to get active project
required: false
type: integer
default: 24
responses:
200:
description: Active projects geojson
404:
description: Project not found or project is not published
500:
description: Internal Server Error
"""
interval = request.args.get("interval", "24")
if not interval.isdigit():
return {
"Error": "Interval must be a number greater than 0 and less than or equal to 24"
}, 400
interval = int(interval)
if interval <= 0 or interval > 24:
return {
"Error": "Interval must be a number greater than 0 and less than or equal to 24"
}, 400
projects_dto = ProjectService.get_active_projects(interval)
return projects_dto, 200
36 changes: 36 additions & 0 deletions backend/services/project_service.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import threading
from cachetools import TTLCache, cached
from flask import current_app
import geojson
from datetime import datetime, timedelta, timezone

from backend.exceptions import NotFound
from backend.models.dtos.mapping_dto import TaskDTOs
Expand Down Expand Up @@ -615,3 +617,37 @@ def send_email_on_project_progress(project_id):
project_completion,
),
).start()

@staticmethod
def get_active_projects(interval):
action_date = datetime.now(timezone.utc) - timedelta(hours=interval)
result = (
TaskHistory.query.with_entities(TaskHistory.project_id)
.distinct()
.filter(TaskHistory.action_date >= action_date)
.all()
)
project_ids = [row.project_id for row in result]
projects = (
Project.query.with_entities(
Project.id,
Project.mapping_types,
Project.geometry.ST_AsGeoJSON().label("geometry"),
)
.filter(
Project.status == ProjectStatus.PUBLISHED.value,
Project.id.in_(project_ids),
)
.all()
)
features = []
for project in projects:
properties = {
"project_id": project.id,
"mapping_types": project.mapping_types,
}
feature = geojson.Feature(
geometry=geojson.loads(project.geometry), properties=properties
)
features.append(feature)
return geojson.FeatureCollection(features)

0 comments on commit af75feb

Please sign in to comment.