From 8c3b3c4d78d112e6f7420efb37f07c21b5280e86 Mon Sep 17 00:00:00 2001 From: DianaDrzikova Date: Fri, 7 Jun 2024 14:40:10 +0200 Subject: [PATCH 1/2] Annotation result loading both cards and table. 100 per page. --- backend/semant_annotation/db/crud_task.py | 30 +++- .../semant_annotation/routes/task_routes.py | 26 ++- .../semant_annotation/schemas/base_objects.py | 4 +- .../components/annotations/TaskInstance.vue | 21 +-- frontend/src/pages/ResultsPage.vue | 170 ++++++++++++++---- 5 files changed, 196 insertions(+), 55 deletions(-) diff --git a/backend/semant_annotation/db/crud_task.py b/backend/semant_annotation/db/crud_task.py index a2350f1..ce6ba93 100644 --- a/backend/semant_annotation/db/crud_task.py +++ b/backend/semant_annotation/db/crud_task.py @@ -1,7 +1,7 @@ import logging from sqlalchemy.ext.asyncio import AsyncSession -from sqlalchemy import exc, select, or_, update +from sqlalchemy import exc, select, or_, update, func from .database import DBError from . import model from semant_annotation.schemas import base_objects @@ -71,7 +71,7 @@ async def get_task_instance_random(db: AsyncSession, task_id: UUID, result_count raise DBError(f'Failed fetching task instance from database.') -async def get_task_instance_results(db: AsyncSession, task_id: UUID, user_id: UUID=None, from_date: datetime=None, +async def get_task_instance_results(db: AsyncSession, task_id: UUID, offset: int, page_size: int, user_id: UUID=None, from_date: datetime=None, to_date: datetime=None) -> base_objects.AnnotationTaskResult: try: async with db.begin(): @@ -83,13 +83,36 @@ async def get_task_instance_results(db: AsyncSession, task_id: UUID, user_id: UU stmt = stmt.where(model.AnnotationTaskResult.created_date >= from_date) if to_date: stmt = stmt.where(model.AnnotationTaskResult.created_date <= to_date) + + stmt = stmt.offset(offset).limit(page_size) result = await db.execute(stmt) db_task_instance_result = result.scalars().all() + return [base_objects.AnnotationTaskResult.model_validate(db_task_instance_result) for db_task_instance_result in db_task_instance_result] except exc.SQLAlchemyError as e: logging.error(str(e)) raise DBError(f'Failed fetching task instance result from database.') +async def get_task_instance_results_count(db: AsyncSession, task_id: UUID, user_id: UUID=None, from_date: datetime=None, + to_date: datetime=None) -> int: + try: + async with db.begin(): + stmt = select(func.count()).select_from(model.AnnotationTaskResult).join(model.AnnotationTaskInstance)\ + .where(model.AnnotationTaskInstance.annotation_task_id == task_id) + if user_id: + stmt = stmt.where(model.AnnotationTaskResult.user_id == user_id) + if from_date: + stmt = stmt.where(model.AnnotationTaskResult.created_date >= from_date) + if to_date: + stmt = stmt.where(model.AnnotationTaskResult.created_date <= to_date) + + result = await db.execute(stmt) + count = result.scalar() + + return count + except exc.SQLAlchemyError as e: + logging.error(str(e)) + raise DBError(f'Failed fetching total count of task instance results from database.') async def get_task_instance_result_times(db: AsyncSession, task_id: UUID = None, user_id: UUID=None, from_date: datetime=None, to_date: datetime=None) -> base_objects.SimplifiedAnnotationTaskResult: @@ -112,5 +135,4 @@ async def get_task_instance_result_times(db: AsyncSession, task_id: UUID = None, return [base_objects.SimplifiedAnnotationTaskResult.model_validate(db_task_instance_result) for db_task_instance_result in db_task_instance_result] except exc.SQLAlchemyError as e: logging.error(str(e)) - raise DBError(f'Failed fetching task instance result from database.') - + raise DBError(f'Failed fetching task instance result from database.') \ No newline at end of file diff --git a/backend/semant_annotation/routes/task_routes.py b/backend/semant_annotation/routes/task_routes.py index 6cd79b9..ff623e6 100644 --- a/backend/semant_annotation/routes/task_routes.py +++ b/backend/semant_annotation/routes/task_routes.py @@ -53,6 +53,12 @@ async def delete_task(task_id: UUID, await crud_general.delete_obj(db, task_id, model.AnnotationTask) +@task_route.get("/types/", response_model=List[base_objects.AnnotationResultType], tags=["Task"]) +async def get_types( + user_token: TokenData = Depends(get_current_user), db: AsyncSession = Depends(get_async_session)): + return [type_.value for type_ in base_objects.AnnotationResultType] + + @task_route.post("/subtask", tags=["Task"]) async def new_subtask(subtask: base_objects.AnnotationSubtaskUpdate, user_token: TokenData = Depends(get_current_admin), db: AsyncSession = Depends(get_async_session)): @@ -109,9 +115,23 @@ async def update_task_instance_result(task_instance_result: base_objects.Annotat @task_route.post("/results", response_model=List[base_objects.AnnotationTaskResult], tags=["Task"]) async def get_task_instance_result(query: base_objects.AnnotationTaskResultQuery, user_token: TokenData = Depends(get_current_admin), db: AsyncSession = Depends(get_async_session)): - return await crud_task.get_task_instance_results(db, query.annotation_task_id, query.user_id, + + offset = (query.page - 1) * query.page_size + print(offset) + return await crud_task.get_task_instance_results(db, query.annotation_task_id, offset, query.page_size, query.user_id, query.from_date, query.to_date) +@task_route.post("/results/count", response_model=int, tags=["Task"]) +async def get_task_instance_results_count(query: base_objects.AnnotationTaskResultQuery, + user_token: TokenData = Depends(get_current_admin), db: AsyncSession = Depends(get_async_session)): + try: + count = await crud_task.get_task_instance_results_count(db, query.annotation_task_id, query.user_id, + query.from_date, query.to_date) + return count + except DBError as e: + raise HTTPException(status_code=500, detail=str(e)) + + @task_route.post("/result_times", response_model=List[base_objects.SimplifiedAnnotationTaskResult], tags=["Task"]) async def get_task_instance_result_times(query: base_objects.AnnotationTaskResultQuery, @@ -121,6 +141,8 @@ async def get_task_instance_result_times(query: base_objects.AnnotationTaskResul return await crud_task.get_task_instance_result_times(db, query.annotation_task_id, query.user_id, query.from_date, query.to_date) + + async def get_image_path(image_id: UUID, task_id: UUID, make_dir: bool = True): path = os.path.join(config.UPLOADED_IMAGES_FOLDER, str(task_id)) if make_dir: @@ -129,7 +151,7 @@ async def get_image_path(image_id: UUID, task_id: UUID, make_dir: bool = True): @task_route.get("/image/{task_id}/{image_id}", tags=["Task"]) -async def get_image(task_id: UUID, image_id: UUID, +async def get_image(task_id: UUID, image_id: UUID, user_token: TokenData = Depends(get_current_user)): path = await get_image_path(image_id=image_id, task_id=task_id, make_dir=False) if not os.path.exists(path): diff --git a/backend/semant_annotation/schemas/base_objects.py b/backend/semant_annotation/schemas/base_objects.py index a7e0ac8..9264892 100644 --- a/backend/semant_annotation/schemas/base_objects.py +++ b/backend/semant_annotation/schemas/base_objects.py @@ -106,8 +106,8 @@ class Config: class SimplifiedAnnotationTaskResult(BaseModel): start_time: datetime end_time: datetime - result_type: AnnotationResultType user_id: UUID + subtasks: List[AnnotationSubtask] = [] class Config: from_attributes = True @@ -133,6 +133,8 @@ class Config: class AnnotationTaskResultQuery(BaseModel): annotation_task_id: UUID + page: int + page_size: int from_date: date = None to_date: date = None user_id: UUID = None diff --git a/frontend/src/components/annotations/TaskInstance.vue b/frontend/src/components/annotations/TaskInstance.vue index c85428e..8a7294f 100644 --- a/frontend/src/components/annotations/TaskInstance.vue +++ b/frontend/src/components/annotations/TaskInstance.vue @@ -17,23 +17,24 @@ diff --git a/frontend/src/pages/ResultsPage.vue b/frontend/src/pages/ResultsPage.vue index 9504b2a..7415683 100644 --- a/frontend/src/pages/ResultsPage.vue +++ b/frontend/src/pages/ResultsPage.vue @@ -3,50 +3,53 @@ + v-model="selected_task" + :options="tasks" + label="Task" + clearable + option-label="name" /> + v-model="selected_user" + :options="users" + label="User" + option-label="username" + clearable /> - - - Select task first -
-
Total results: {{ results.length }}
-
Annotated: {{ annotatedCount }}
-
Rejected: {{ rejectedCount }}
+
Results: {{ totalResults }}
+
Results: 0
+ + +
+
+ +
+
- +
- +
User: {{ result.user }}
-
Created: {{ result.created_date }}
-
Type: {{ result.result_type }}
+
Date: {{ result.created_date }}
+
Type: {{ result.result_type }}
@@ -62,17 +65,21 @@
+ +