Skip to content

Commit

Permalink
[pre-commit.ci] auto fixes from pre-commit.com hooks
Browse files Browse the repository at this point in the history
for more information, see https://pre-commit.ci
  • Loading branch information
pre-commit-ci[bot] committed Jan 1, 2024
1 parent 1098dc6 commit 0e39bfd
Show file tree
Hide file tree
Showing 11 changed files with 2,526 additions and 1,552 deletions.
12 changes: 6 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
- added alchemy text on centroid api
- map Component added to main
- add script to generate openapi.json
- Added a new function to perform the conversion of task_boundary from GeoJSON to .osm format.
- Added a new function to perform the conversion of task_boundary from GeoJSON to .osm format.
- download button for data extract on project details fix Add option to download the data extract fix #779
- api for download data extract
- added download data extract loading
Expand All @@ -30,7 +30,7 @@
- use loguru stdout + json file logging
- form validation added on custom form
- added organisation_id on create project frontend
- organisation Id on create project api
- organisation Id on create project api
- added api to centroid logo
- added projectId on projectbyid
- Tailwindcss integrated
Expand Down Expand Up @@ -220,7 +220,7 @@
- minimum 5 of splitting algorithm
- Project name should accept other characters too. #754
- organization_id none case handled
- task splitted is not shown in map, although the number of tasks are determined and generated #750
- task splitted is not shown in map, although the number of tasks are determined and generated #750
- previous button wrong route issue
- project_id added in the tile_instance
- set tile_path_instance outside try, ref before assign
Expand Down Expand Up @@ -261,7 +261,7 @@
- pwa fixes for icon
- merge conflicts
- data Cleaning fix
- removed api listing static content
- removed api listing static content
- projects can be filter based on user_id and hashtags present in the project
- filtering by hashtags check if project hashtags overlap with requested hashtags
- task spliting for geojson with polygons instead of features
Expand Down Expand Up @@ -322,7 +322,7 @@
- osm-fieldwork import
- osm-fieldwork imports
- Fixes Create Project Section : The input file name has design issues. #452
- Create Project Section - Upload Area subsection : Alignment of the map elements need to be maintained. #451
- Create Project Section - Upload Area subsection : Alignment of the map elements need to be maintained. #451
- handle click outside issue
- organization post
- adjusted map page of home
Expand Down Expand Up @@ -435,7 +435,7 @@
- move app backend server files to app dir
- move backend code out of app dir for rebase
- add additional logging to odkcentral connection
- update __version__.py path in pyproject.toml
- update **version**.py path in pyproject.toml
- remove FMTM_TEST_DB_NAME, DB_URL --> FMTM_DB_URL
- ignore osm-fieldwork local dir
- remove tests dir in root (under src dirs)
Expand Down
10 changes: 7 additions & 3 deletions src/backend/app/auth/auth_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@
from loguru import logger as log
from sqlalchemy.orm import Session

from app.auth.osm import AuthUser, init_osm_auth, login_required
from app.db import database
from app.db.db_models import DbUser
from app.users import user_crud
from app.auth.osm import AuthUser, init_osm_auth, login_required

router = APIRouter(
prefix="/auth",
Expand Down Expand Up @@ -108,9 +108,13 @@ async def my_data(
"Please contact the administrator."
),
)

# Add user to database
db_user = DbUser(id=user_data["id"], username=user_data["username"], profile_img = user_data["img_url"])
db_user = DbUser(
id=user_data["id"],
username=user_data["username"],
profile_img=user_data["img_url"],
)
db.add(db_user)
db.commit()
else:
Expand Down
55 changes: 34 additions & 21 deletions src/backend/app/projects/project_crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@
from app.db import db_models
from app.db.database import get_db
from app.db.postgis_utils import geometry_to_geojson, timestamp
from app.organization import organization_crud
from app.projects import project_schemas
from app.s3 import get_obj_from_bucket
from app.submission import submission_crud
from app.tasks import tasks_crud
from app.users import user_crud
from app.submission import submission_crud
from app.s3 import get_obj_from_bucket
from app.organization import organization_crud

QR_CODES_DIR = "QR_codes/"
TASK_GEOJSON_DIR = "geojson/"
Expand Down Expand Up @@ -2392,9 +2392,10 @@ async def get_pagination(page: int, count: int, results_per_page: int, total: in

async def get_dashboard_detail(project_id: int, db: Session):
"""Get project details for project dashboard."""

project = await get_project(db, project_id)
db_organization = await organization_crud.get_organisation_by_id(db, project.organisation_id)
db_organization = await organization_crud.get_organisation_by_id(
db, project.organisation_id
)

s3_project_path = f"/{project.organisation_id}/{project_id}"
s3_submission_path = f"/{s3_project_path}/submissions.meta.json"
Expand All @@ -2404,20 +2405,28 @@ async def get_dashboard_detail(project_id: int, db: Session):
except ValueError:
pass

contributors = db.query(db_models.DbTaskHistory).filter(db_models.DbTaskHistory.project_id==project_id).all()
unique_user_ids = {user.user_id for user in contributors if user.user_id is not None}
contributors = (
db.query(db_models.DbTaskHistory)
.filter(db_models.DbTaskHistory.project_id == project_id)
.all()
)
unique_user_ids = {
user.user_id for user in contributors if user.user_id is not None
}

project.organization = db_organization.name
project.organization_logo = db_organization.logo
project.total_contributors = len(unique_user_ids)
project.total_submission = await submission_crud.get_submission_count_of_a_project(db, project_id)
project.total_submission = await submission_crud.get_submission_count_of_a_project(
db, project_id
)
project.total_tasks = await tasks_crud.get_task_count_in_project(db, project_id)

return project

async def get_project_users(db:Session, project_id:int):
"""
Get the users and their contributions for a project.

async def get_project_users(db: Session, project_id: int):
"""Get the users and their contributions for a project.
Args:
db (Session): The database session.
Expand All @@ -2426,22 +2435,27 @@ async def get_project_users(db:Session, project_id:int):
Returns:
List[Dict[str, Union[str, int]]]: A list of dictionaries containing the username and the number of contributions made by each user for the specified project.
"""

contributors = db.query(db_models.DbTaskHistory).filter(db_models.DbTaskHistory.project_id==project_id).all()
unique_user_ids = {user.user_id for user in contributors if user.user_id is not None}
contributors = (
db.query(db_models.DbTaskHistory)
.filter(db_models.DbTaskHistory.project_id == project_id)
.all()
)
unique_user_ids = {
user.user_id for user in contributors if user.user_id is not None
}
response = []

for user_id in unique_user_ids:
contributions = count_user_contributions(db, user_id, project_id)
db_user = await user_crud.get_user(db, user_id)
response.append({"user":db_user.username, "contributions":contributions})
response.append({"user": db_user.username, "contributions": contributions})

response = sorted(response, key=lambda x: x["contributions"], reverse=True)
return response


def count_user_contributions(db: Session, user_id: int, project_id: int) -> int:
"""
Count contributions for a specific user.
"""Count contributions for a specific user.
Args:
db (Session): The database session.
Expand All @@ -2451,14 +2465,13 @@ def count_user_contributions(db: Session, user_id: int, project_id: int) -> int:
Returns:
int: The number of contributions made by the user for the specified project.
"""

contributions_count = (
db.query(func.count(db_models.DbTaskHistory.user_id))
.filter(
db_models.DbTaskHistory.user_id == user_id,
db_models.DbTaskHistory.project_id == project_id
db_models.DbTaskHistory.project_id == project_id,
)
.scalar()
)

return contributions_count
return contributions_count
15 changes: 7 additions & 8 deletions src/backend/app/projects/project_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1218,12 +1218,11 @@ async def get_template_file(
)


@router.get("/project_dashboard/{project_id}", response_model=project_schemas.ProjectDashboard)
async def project_dashboard(
project_id: int, db: Session = Depends(database.get_db)
):
"""
Get the project dashboard details.
@router.get(
"/project_dashboard/{project_id}", response_model=project_schemas.ProjectDashboard
)
async def project_dashboard(project_id: int, db: Session = Depends(database.get_db)):
"""Get the project dashboard details.
Args:
project_id (int): The ID of the project.
Expand All @@ -1232,9 +1231,9 @@ async def project_dashboard(
Returns:
ProjectDashboard: The project dashboard details.
"""

return await project_crud.get_dashboard_detail(project_id, db)


@router.get("/contributors/{project_id}")
async def get_contributors(project_id: int, db: Session = Depends(database.get_db)):
"""Get contributors of a project.
Expand All @@ -1246,4 +1245,4 @@ async def get_contributors(project_id: int, db: Session = Depends(database.get_d
list[project_schemas.ProjectUser]: List of project users.
"""
project_users = await project_crud.get_project_users(db, project_id)
return project_users
return project_users
10 changes: 5 additions & 5 deletions src/backend/app/projects/project_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@

import uuid
from datetime import datetime
from dateutil import parser
from typing import List, Optional

from dateutil import parser
from geojson_pydantic import Feature as GeojsonFeature
from pydantic import BaseModel, validator

Expand Down Expand Up @@ -161,7 +161,7 @@ class ProjectDashboard(BaseModel):
def get_created(cls, value, values):
date = value.strftime("%d %b %Y")
return date

@validator("last_active", pre=False, always=True)
def get_last_active(cls, value, values):
if value is None:
Expand All @@ -175,10 +175,10 @@ def get_last_active(cls, value, values):
days_difference = time_difference.days

if days_difference == 0:
return 'today'
return "today"
elif days_difference == 1:
return 'yesterday'
return "yesterday"
elif days_difference < 7:
return f'{days_difference} day{"s" if days_difference > 1 else ""} ago'
else:
return last_active.strftime("%d %b %Y")
return last_active.strftime("%d %b %Y")
35 changes: 20 additions & 15 deletions src/backend/app/submission/submission_crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@
import threading
import uuid
from asyncio import gather
from datetime import datetime
from io import BytesIO
from pathlib import Path
from collections import Counter
from datetime import datetime, timedelta
from io import BytesIO
from pathlib import Path

import sozipfile.sozipfile as zipfile
from asgiref.sync import async_to_sync
Expand Down Expand Up @@ -821,9 +820,10 @@ async def get_submission_count_of_a_project(db: Session, project_id: int):
return len(files)


async def get_submissions_by_date(db: Session, project_id: int, days: int, planned_task: int):
"""
Get submissions by date.
async def get_submissions_by_date(
db: Session, project_id: int, days: int, planned_task: int
):
"""Get submissions by date.
Fetches the submissions for a given project within a specified number of days.
Expand All @@ -839,31 +839,37 @@ async def get_submissions_by_date(db: Session, project_id: int, days: int, plann
# Fetch submissions for project with ID 1 within the last 7 days
submissions = await get_submissions_by_date(db, 1, 7)
"""

project = await project_crud.get_project(db, project_id)
s3_project_path = f"/{project.organisation_id}/{project_id}"
s3_submission_path = f"/{s3_project_path}/submission.zip"

try:
file = get_obj_from_bucket(settings.S3_BUCKET_NAME, s3_submission_path)
except ValueError as e:
except ValueError:
return []

with zipfile.ZipFile(file, "r") as zip_ref:
with zip_ref.open("submissions.json") as file_in_zip:
content = file_in_zip.read()

content = json.loads(content)
end_dates = [datetime.fromisoformat(entry["end"].split('+')[0]) for entry in content if entry.get("end")]

dates = [date.strftime('%m/%d') for date in end_dates if datetime.now() - date <= timedelta(days=days)]
end_dates = [
datetime.fromisoformat(entry["end"].split("+")[0])
for entry in content
if entry.get("end")
]

dates = [
date.strftime("%m/%d")
for date in end_dates
if datetime.now() - date <= timedelta(days=days)
]

submission_counts = Counter(sorted(dates))

response = [
{"date": key, "count": value}
for key, value in submission_counts.items()
]
{"date": key, "count": value} for key, value in submission_counts.items()
]
if planned_task:
count_dict = {}
cummulative_count = 0
Expand All @@ -876,4 +882,3 @@ async def get_submissions_by_date(db: Session, project_id: int, days: int, plann
]

return response

11 changes: 5 additions & 6 deletions src/backend/app/submission/submission_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
from app.config import settings
from app.db import database
from app.projects import project_crud, project_schemas

from app.submission import submission_crud

router = APIRouter(
Expand Down Expand Up @@ -315,13 +314,13 @@ async def get_submission_page(
planned_task: Optional[int] = None,
db: Session = Depends(database.get_db),
):
"""
This api returns the submission page of a project.
"""This api returns the submission page of a project.
It takes one parameter: project_id.
project_id: The ID of the project. This endpoint returns the submission page of this project.
"""

data = await submission_crud.get_submissions_by_date(db, project_id, days, planned_task)
data = await submission_crud.get_submissions_by_date(
db, project_id, days, planned_task
)

# Update submission cache in the background
background_task_id = await project_crud.insert_background_task_into_database(
Expand All @@ -332,4 +331,4 @@ async def get_submission_page(
submission_crud.update_submission_in_s3, db, project_id, background_task_id
)

return data
return data
Loading

0 comments on commit 0e39bfd

Please sign in to comment.