diff --git a/src/backend/app/auth/auth_routes.py b/src/backend/app/auth/auth_routes.py index 38a3167869..62b4b6c500 100644 --- a/src/backend/app/auth/auth_routes.py +++ b/src/backend/app/auth/auth_routes.py @@ -23,10 +23,10 @@ from loguru import logger as log from sqlalchemy.orm import Session -from ..db import database -from ..db.db_models import DbUser -from ..users import user_crud -from .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", @@ -108,10 +108,14 @@ async def my_data( "Please contact the administrator." ), ) - + # Add user to database - db_user = DbUser(id=user_data["id"], username=user_data["username"]) + db_user = DbUser(id=user_data["id"], username=user_data["username"], profile_img = user_data["img_url"]) db.add(db_user) db.commit() + else: + if user_data.get("img_url"): + user.profile_img = user_data["img_url"] + db.commit() return JSONResponse(content={"user_data": user_data}, status_code=200) diff --git a/src/backend/app/db/db_models.py b/src/backend/app/db/db_models.py index 824f88aed0..35bd3d7724 100644 --- a/src/backend/app/db/db_models.py +++ b/src/backend/app/db/db_models.py @@ -70,6 +70,7 @@ class DbUser(Base): id = Column(BigInteger, primary_key=True, index=True) username = Column(String, unique=True) + profile_img = Column(String) role = Column(Enum(UserRole), default=UserRole.MAPPER) name = Column(String) diff --git a/src/backend/app/tasks/tasks_crud.py b/src/backend/app/tasks/tasks_crud.py index 0ab706de57..e8d9d1cd13 100644 --- a/src/backend/app/tasks/tasks_crud.py +++ b/src/backend/app/tasks/tasks_crud.py @@ -16,8 +16,9 @@ # along with FMTM. If not, see . # import base64 +from typing import List -from fastapi import HTTPException +from fastapi import HTTPException, Depends from geoalchemy2.shape import from_shape from geojson import dump from loguru import logger as log @@ -26,15 +27,16 @@ from sqlalchemy.orm import Session from sqlalchemy.sql import text -from ..central import central_crud -from ..db import db_models -from ..models.enums import ( +from app.tasks import tasks_schemas +from app.central import central_crud +from app.db import db_models, database +from app.models.enums import ( TaskStatus, get_action_for_status_change, verify_valid_status_update, ) -from ..projects import project_crud -from ..users import user_crud +from app.projects import project_crud +from app.users import user_crud async def get_task_count_in_project(db: Session, project_id: int): @@ -317,3 +319,23 @@ async def edit_task_boundary(db: Session, task_id: int, boundary: str): ) return True + + +async def update_task_history(tasks: List[tasks_schemas.TaskBase], db: Session = Depends(database.get_db)): + def process_history_entry(history_entry): + status = history_entry.action_text.split() + history_entry.status = status[5] + + if history_entry.user_id: + user = db.query(db_models.DbUser).filter_by(id=history_entry.user_id).first() + if user: + history_entry.username = user.username + history_entry.profile_img = user.profile_img + + for task in tasks if isinstance(tasks, list) else [tasks]: + task_history = task.task_history + if isinstance(task_history, list): + for history_entry in task_history: + process_history_entry(history_entry) + + return tasks \ No newline at end of file diff --git a/src/backend/app/tasks/tasks_routes.py b/src/backend/app/tasks/tasks_routes.py index d816cbe298..44f79cdaae 100644 --- a/src/backend/app/tasks/tasks_routes.py +++ b/src/backend/app/tasks/tasks_routes.py @@ -23,11 +23,11 @@ from sqlalchemy.orm import Session from sqlalchemy.sql import text -from ..central import central_crud -from ..db import database -from ..models.enums import TaskStatus -from ..projects import project_crud, project_schemas -from ..users import user_schemas +from app.central import central_crud +from app.db import database +from app.models.enums import TaskStatus +from app.projects import project_crud, project_schemas +from app.users import user_schemas from . import tasks_crud, tasks_schemas router = APIRouter( @@ -37,17 +37,17 @@ responses={404: {"description": "Not found"}}, ) - -@router.get("/task-list", response_model=List[tasks_schemas.Task]) +@router.get("/task-list", response_model=List[tasks_schemas.ReadTask]) async def read_task_list( project_id: int, limit: int = 1000, db: Session = Depends(database.get_db), ): tasks = await tasks_crud.get_tasks(db, project_id, limit) + updated_tasks = await tasks_crud.update_task_history(tasks, db) if not tasks: raise HTTPException(status_code=404, detail="Tasks not found") - return tasks + return updated_tasks @router.get("/", response_model=List[tasks_schemas.Task]) @@ -109,7 +109,7 @@ async def read_tasks(task_id: int, db: Session = Depends(database.get_db)): return task -@router.post("/{task_id}/new_status/{new_status}", response_model=tasks_schemas.Task) +@router.post("/{task_id}/new_status/{new_status}", response_model=tasks_schemas.ReadTask) async def update_task_status( user: user_schemas.User, task_id: int, @@ -120,9 +120,10 @@ async def update_task_status( user_id = user.id task = await tasks_crud.update_task_status(db, user_id, task_id, new_status) + updated_task = await tasks_crud.update_task_history(task, db) if not task: raise HTTPException(status_code=404, detail="Task status could not be updated.") - return task + return updated_task @router.post("/task-qr-code/{task_id}") diff --git a/src/backend/app/tasks/tasks_schemas.py b/src/backend/app/tasks/tasks_schemas.py index 4cd8fe51e4..0036ce0520 100644 --- a/src/backend/app/tasks/tasks_schemas.py +++ b/src/backend/app/tasks/tasks_schemas.py @@ -41,8 +41,9 @@ class TaskHistoryBase(BaseModel): class TaskHistoryOut(TaskHistoryBase): """Task mapping history display.""" - - pass + status: str + username: str + profile_img: Optional[str] class TaskBase(BaseModel): @@ -144,3 +145,8 @@ def get_qrcode_base64(cls, v: Any, info: ValidationInfo) -> str: else: log.warning(f"No QR code found for task ID {info.data.get('id')}") return "" + +class ReadTask(Task): + """Task details plus updated task history.""" + + task_history: Optional[List[TaskHistoryOut]] = None \ No newline at end of file diff --git a/src/backend/migrations/002-add-profile-img.sql b/src/backend/migrations/002-add-profile-img.sql new file mode 100644 index 0000000000..ae7f620918 --- /dev/null +++ b/src/backend/migrations/002-add-profile-img.sql @@ -0,0 +1,10 @@ +-- ## Migration to: +-- * Add field user.profile_img (str). + +-- Start a transaction +BEGIN; + +ALTER TABLE IF EXISTS public.users + ADD COLUMN IF NOT EXISTS profile_img VARCHAR; +-- Commit the transaction +COMMIT; \ No newline at end of file diff --git a/src/backend/migrations/revert/002-add-profile-img.sql b/src/backend/migrations/revert/002-add-profile-img.sql new file mode 100644 index 0000000000..49b3e65f1d --- /dev/null +++ b/src/backend/migrations/revert/002-add-profile-img.sql @@ -0,0 +1,9 @@ +-- Start a transaction +BEGIN; + +-- Remove the profile_img column from the public.users table +ALTER TABLE IF EXISTS public.users + DROP COLUMN IF EXISTS profile_img; + +-- Commit the transaction +COMMIT; \ No newline at end of file