diff --git a/requirements.txt b/requirements.txt index a19e9db0f2ea3d56ced4a29681563dc53d257303..28331ab437c9506c0e464e3d3124a5acd55316d3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,4 @@ pymitter==0.5.0 uvicorn==0.27.1 python-multipart==0.0.9 aiosmtplib==3.0.1 -nacsos_data[scripts,server,utils] @ git+ssh://git@gitlab.pik-potsdam.de/mcc-apsis/nacsos/nacsos-data.git@v0.14.5 +nacsos_data[scripts,server,utils] @ git+ssh://git@gitlab.pik-potsdam.de/mcc-apsis/nacsos/nacsos-data.git@v0.14.6 diff --git a/server/api/routes/export.py b/server/api/routes/export.py index 3be91c3639b356a605929bedf2306fe67203858a..52506ca918a668dcb0cfe7a0302eb8d28f204fc4 100644 --- a/server/api/routes/export.py +++ b/server/api/routes/export.py @@ -6,21 +6,21 @@ from typing import TYPE_CHECKING from nacsos_data.db.crud.projects import read_project_by_id -from fastapi import APIRouter, Depends, Query -from nacsos_data.db.schemas import ItemType -from nacsos_data.util.annotations.export import \ - prepare_export_table, \ - get_project_labels, \ - get_project_scopes, \ - get_project_bot_scopes, \ - get_project_users, \ +from fastapi import APIRouter, Depends +from nacsos_data.models.nql import NQLFilter +from nacsos_data.util.annotations.export import ( + prepare_export_table, + get_project_labels, + get_project_scopes, + get_project_bot_scopes, + get_project_users, LabelOptions +) from pydantic import BaseModel from starlette.background import BackgroundTask from starlette.responses import FileResponse -from server.util.security import \ - UserPermissionChecker +from server.util.security import UserPermissionChecker from nacsos_data.util.auth import UserPermissions @@ -40,23 +40,27 @@ class CFR(FileResponse): # custom file response to set the media type media_type = 'application/csv' +class ExportRequest(BaseModel): + labels: list[LabelOptions] + nql_filter: NQLFilter | None = None + bot_annotation_metadata_ids: list[str] | None = None + assignment_scope_ids: list[str] | None = None + user_ids: list[str] | None = None + ignore_hierarchy: bool = True + ignore_repeat: bool = True + + @router.post('/annotations/csv', response_class=CFR) -async def get_annotations_csv(labels: list[LabelOptions], - bot_annotation_metadata_ids: list[str] | None = Query(default=None), - assignment_scope_ids: list[str] | None = Query(default=None), - user_ids: list[str] | None = Query(default=None), - ignore_hierarchy: bool = Query(default=True), - ignore_repeat: bool = Query(default=True), - item_fields: list[str] | None = Query(default=None), +async def get_annotations_csv(query: ExportRequest, permissions: UserPermissions = Depends(UserPermissionChecker('annotations_read'))): - result = await prepare_export_table(bot_annotation_metadata_ids=bot_annotation_metadata_ids, - assignment_scope_ids=assignment_scope_ids, - user_ids=user_ids, + result = await prepare_export_table(bot_annotation_metadata_ids=query.bot_annotation_metadata_ids, + assignment_scope_ids=query.assignment_scope_ids, + user_ids=query.user_ids, project_id=permissions.permissions.project_id, - labels=labels, - ignore_repeat=ignore_repeat, - ignore_hierarchy=ignore_hierarchy, - item_fields=item_fields, + labels=query.labels, + nql_filter=query.nql_filter, + ignore_repeat=query.ignore_repeat, + ignore_hierarchy=query.ignore_hierarchy, db_engine=db_engine) with tempfile.NamedTemporaryFile(suffix='.csv', mode='w', newline='', delete=False) as fp: @@ -87,7 +91,6 @@ class ProjectBaseInfo(BaseModel): scopes: list[ProjectBaseInfoScopeEntry] bot_scopes: list[ProjectBaseInfoEntry] labels: dict[str, LabelOptions] - fields: list[str] @router.get('/project/baseinfo', response_model=ProjectBaseInfo) @@ -105,17 +108,7 @@ async def get_export_baseinfo(permissions: UserPermissions = Depends(UserPermiss if project is None: raise RuntimeError('Invalid state!') - if project.type == ItemType.twitter: - fields = ['text', 'twitter_id', 'created_at', 'twitter_author_id', 'conversation_id'] - elif project.type == ItemType.academic: - fields = ['text', 'title', 'doi', 'wos_id', 'scopus_id', 'openalex_id', 'publication_year', 'source'] - elif project.type == ItemType.lexis: - fields = ['text', 'teaser', 'author'] # TODO: ideally we would also export the source data - else: - fields = ['text'] - return ProjectBaseInfo(users=[ProjectBaseInfoEntry.model_validate(pu) for pu in project_users], scopes=[ProjectBaseInfoScopeEntry.model_validate(ps) for ps in project_scopes], bot_scopes=[ProjectBaseInfoEntry.model_validate(pbs) for pbs in project_bot_scopes], - labels=project_labels, - fields=fields) + labels=project_labels)