Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorporate climate change project feedback #419

Merged
merged 10 commits into from
Sep 27, 2024
Merged
19 changes: 17 additions & 2 deletions backend/src/app/core/analysis/annotated_segments.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from app.core.data.orm.source_document import SourceDocumentORM
from app.core.data.orm.span_annotation import SpanAnnotationORM
from app.core.data.orm.span_text import SpanTextORM
from app.core.data.orm.user import UserORM
from app.core.db.sql_service import SQLService
from app.core.filters.columns import (
AbstractColumns,
Expand All @@ -43,6 +44,7 @@ def aggregate_ids(column: InstrumentedAttribute, label: str):
class AnnotatedSegmentsColumns(str, AbstractColumns):
SPAN_TEXT = "ASC_SPAN_TEXT"
CODE_ID = "ASC_CODE_ID"
USER_ID = "ASC_USER_ID"
MEMO_CONTENT = "ASC_MEMO_CONTENT"
SOURCE_DOCUMENT_FILENAME = "ASC_SOURCE_SOURCE_DOCUMENT_FILENAME"
DOCUMENT_TAG_ID_LIST = "ASC_DOCUMENT_DOCUMENT_TAG_ID_LIST"
Expand All @@ -59,6 +61,8 @@ def get_filter_column(self, **kwargs):
return SpanTextORM.text
case AnnotatedSegmentsColumns.MEMO_CONTENT:
return MemoORM.content
case AnnotatedSegmentsColumns.USER_ID:
return UserORM.id

def get_filter_operator(self) -> FilterOperator:
match self:
Expand All @@ -72,6 +76,8 @@ def get_filter_operator(self) -> FilterOperator:
return FilterOperator.STRING
case AnnotatedSegmentsColumns.MEMO_CONTENT:
return FilterOperator.STRING
case AnnotatedSegmentsColumns.USER_ID:
return FilterOperator.ID

def get_filter_value_type(self) -> FilterValueType:
match self:
Expand All @@ -85,6 +91,8 @@ def get_filter_value_type(self) -> FilterValueType:
return FilterValueType.INFER_FROM_OPERATOR
case AnnotatedSegmentsColumns.MEMO_CONTENT:
return FilterValueType.INFER_FROM_OPERATOR
case AnnotatedSegmentsColumns.USER_ID:
return FilterValueType.USER_ID

def get_sort_column(self, **kwargs):
match self:
Expand All @@ -98,6 +106,8 @@ def get_sort_column(self, **kwargs):
return SpanTextORM.text
case AnnotatedSegmentsColumns.MEMO_CONTENT:
return MemoORM.content
case AnnotatedSegmentsColumns.USER_ID:
return UserORM.last_name

def get_label(self) -> str:
match self:
Expand All @@ -111,6 +121,8 @@ def get_label(self) -> str:
return "Annotated text"
case AnnotatedSegmentsColumns.MEMO_CONTENT:
return "Memo content"
case AnnotatedSegmentsColumns.USER_ID:
return "User"


def find_annotated_segments_info(
Expand Down Expand Up @@ -152,7 +164,6 @@ def find_annotated_segments(
.filter(
MemoORM.project_id == project_id, # memo is in the correct project
MemoORM.user_id == user_id, # i own the memo
AnnotationDocumentORM.user_id == user_id, # i own the annotation
)
.subquery()
)
Expand All @@ -175,6 +186,11 @@ def find_annotated_segments(
SourceDocumentORM,
SourceDocumentORM.id == AnnotationDocumentORM.source_document_id,
)
# join with User
.join(
UserORM,
UserORM.id == AnnotationDocumentORM.user_id,
)
# join Source Document with Document Tag
.join(SourceDocumentORM.document_tags, isouter=True)
# join Span Annotation with Code
Expand All @@ -200,7 +216,6 @@ def find_annotated_segments(
MemoORM.content,
)
.filter(
AnnotationDocumentORM.user_id == user_id,
SourceDocumentORM.project_id == project_id,
)
)
Expand Down
24 changes: 17 additions & 7 deletions backend/src/app/core/data/dto/export_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ class ExportFormat(str, Enum):
class ExportJobType(str, Enum):
SINGLE_PROJECT_ALL_DATA = "SINGLE_PROJECT_ALL_DATA"
SINGLE_PROJECT_ALL_TAGS = "SINGLE_PROJECT_ALL_TAGS"
SINGLE_PROJECT_ALL_CODES = "SINGLE_PROJECT_ALL_CODES"
SINGLE_PROJECT_SELECTED_SDOCS = "SINGLE_PROJECT_SELECTED_SDOCS"
SINGLE_PROJECT_SELECTED_SPAN_ANNOTATIONS = (
"SINGLE_PROJECT_SELECTED_SPAN_ANNOTATIONS"
)

SINGLE_USER_ALL_DATA = "SINGLE_USER_ALL_DATA"
SINGLE_USER_ALL_CODES = "SINGLE_USER_ALL_CODES"
SINGLE_USER_ALL_MEMOS = "SINGLE_USER_ALL_MEMOS"
SINGLE_USER_LOGBOOK = "SINGLE_USER_LOGBOOK"

Expand All @@ -42,18 +45,24 @@ class SingleProjectAllTagsExportJobParams(SpecificExportJobParameters):
export_job_type: Literal[ExportJobType.SINGLE_PROJECT_ALL_TAGS]


class SingleProjectAllCodesExportJobParams(SpecificExportJobParameters):
export_job_type: Literal[ExportJobType.SINGLE_PROJECT_ALL_CODES]


class SingleProjectSelectedSdocsParams(SpecificExportJobParameters):
export_job_type: Literal[ExportJobType.SINGLE_PROJECT_SELECTED_SDOCS]
sdoc_ids: List[int] = Field(description="IDs of the source documents to export")


class SingleUserAllDataExportJobParams(SpecificExportJobParameters):
export_job_type: Literal[ExportJobType.SINGLE_USER_ALL_DATA]
user_id: int = Field(description="The ID of the User to get the data from.")
class SingleProjectSelectedSpanAnnotationsParams(SpecificExportJobParameters):
export_job_type: Literal[ExportJobType.SINGLE_PROJECT_SELECTED_SPAN_ANNOTATIONS]
span_annotation_ids: List[int] = Field(
description="IDs of the span annotations to export"
)


class SingleUserAllCodesExportJobParams(SpecificExportJobParameters):
export_job_type: Literal[ExportJobType.SINGLE_USER_ALL_CODES]
class SingleUserAllDataExportJobParams(SpecificExportJobParameters):
export_job_type: Literal[ExportJobType.SINGLE_USER_ALL_DATA]
user_id: int = Field(description="The ID of the User to get the data from.")


Expand Down Expand Up @@ -89,9 +98,10 @@ class ExportJobParameters(BaseModel):
specific_export_job_parameters: Union[
SingleProjectAllDataExportJobParams,
SingleProjectAllTagsExportJobParams,
SingleProjectAllCodesExportJobParams,
SingleProjectSelectedSdocsParams,
SingleProjectSelectedSpanAnnotationsParams,
SingleUserAllDataExportJobParams,
SingleUserAllCodesExportJobParams,
SingleUserAllMemosExportJobParams,
SingleUserLogbookExportJobParams,
SingleDocAllUserAnnotationsExportJobParams,
Expand Down
77 changes: 77 additions & 0 deletions backend/src/app/core/data/export/export_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from app.core.data.crud.project import crud_project
from app.core.data.crud.source_document import crud_sdoc
from app.core.data.crud.source_document_metadata import crud_sdoc_meta
from app.core.data.crud.span_annotation import crud_span_anno
from app.core.data.crud.user import crud_user
from app.core.data.dto.background_job_base import BackgroundJobStatus
from app.core.data.dto.bbox_annotation import (
Expand Down Expand Up @@ -100,7 +101,9 @@ def __new__(cls, *args, **kwargs):
cls.export_method_for_job_type: Dict[ExportJobType, Callable[..., str]] = {
ExportJobType.SINGLE_PROJECT_ALL_DATA: cls._export_all_data_from_proj,
ExportJobType.SINGLE_PROJECT_ALL_TAGS: cls._export_all_tags_from_proj,
ExportJobType.SINGLE_PROJECT_ALL_CODES: cls._export_all_codes_from_proj,
ExportJobType.SINGLE_PROJECT_SELECTED_SDOCS: cls._export_selected_sdocs_from_proj,
ExportJobType.SINGLE_PROJECT_SELECTED_SPAN_ANNOTATIONS: cls._export_selected_span_annotations_from_proj,
ExportJobType.SINGLE_USER_ALL_DATA: cls._export_user_data_from_proj,
ExportJobType.SINGLE_USER_ALL_MEMOS: cls._export_user_memos_from_proj,
ExportJobType.SINGLE_USER_LOGBOOK: cls._export_user_logbook_from_proj,
Expand Down Expand Up @@ -272,6 +275,40 @@ def __generate_export_df_for_adoc(
df = pd.DataFrame(data=data)
return df

def __generate_export_df_for_span_annotations(
self,
db: Session,
span_annotations: List[SpanAnnotationORM],
) -> pd.DataFrame:
logger.info(f"Exporting {len(span_annotations)} Annotations ...")

# fill the DataFrame
data = {
"sdoc_name": [],
"user_first_name": [],
"user_last_name": [],
"code_name": [],
"created": [],
"text": [],
"text_begin_char": [],
"text_end_char": [],
}

for span in span_annotations:
sdoc = span.annotation_document.source_document
user = span.annotation_document.user
data["sdoc_name"].append(sdoc.filename)
data["user_first_name"].append(user.first_name)
data["user_last_name"].append(user.last_name)
data["code_name"].append(span.code.name)
data["created"].append(span.created)
data["text"].append(span.text)
data["text_begin_char"].append(span.begin)
data["text_end_char"].append(span.end)

df = pd.DataFrame(data=data)
return df

def __generate_export_df_for_memo(
self,
db: Session,
Expand Down Expand Up @@ -894,6 +931,30 @@ def _export_all_tags_from_proj(
logger.error(msg)
raise NoDataToExportError(msg)

def _export_all_codes_from_proj(
self,
db: Session,
project_id: int,
export_format: ExportFormat = ExportFormat.CSV,
) -> str:
ex_codes = self.__generate_export_dfs_for_all_codes_in_project(
db=db, project_id=project_id
)

# one file for all tags
if len(ex_codes) > 0:
export_data = pd.concat(ex_codes)
export_file = self.__write_export_data_to_temp_file(
data=export_data,
export_format=export_format,
fn=f"project_{project_id}_codes",
)
export_url = self.repo.get_temp_file_url(export_file.name, relative=True)
return export_url
msg = f"No Codes to export in Project {project_id}"
logger.error(msg)
raise NoDataToExportError(msg)

def _export_selected_sdocs_from_proj(
self, db: Session, project_id: int, sdoc_ids: List[int]
) -> str:
Expand All @@ -904,6 +965,22 @@ def _export_selected_sdocs_from_proj(

return self.repo.get_temp_file_url(zip.name, relative=True)

def _export_selected_span_annotations_from_proj(
self, db: Session, project_id: int, span_annotation_ids: List[int]
) -> str:
# get the annotations
span_annotations = crud_span_anno.read_by_ids(db=db, ids=span_annotation_ids)

export_data = self.__generate_export_df_for_span_annotations(
db=db, span_annotations=span_annotations
)
export_file = self.__write_export_data_to_temp_file(
data=export_data,
export_format=ExportFormat.CSV,
fn=f"project_{project_id}_selected_annotations_export",
)
return self.repo.get_temp_file_url(export_file.name, relative=True)

def _assert_all_requested_data_exists(
self, export_params: ExportJobParameters
) -> None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
export enum AnnotatedSegmentsColumns {
ASC_SPAN_TEXT = "ASC_SPAN_TEXT",
ASC_CODE_ID = "ASC_CODE_ID",
ASC_USER_ID = "ASC_USER_ID",
ASC_MEMO_CONTENT = "ASC_MEMO_CONTENT",
ASC_SOURCE_SOURCE_DOCUMENT_FILENAME = "ASC_SOURCE_SOURCE_DOCUMENT_FILENAME",
ASC_DOCUMENT_DOCUMENT_TAG_ID_LIST = "ASC_DOCUMENT_DOCUMENT_TAG_ID_LIST",
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/api/openapi/models/ExportJobParameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import type { ExportFormat } from "./ExportFormat";
import type { ExportJobType } from "./ExportJobType";
import type { SingleDocAllUserAnnotationsExportJobParams } from "./SingleDocAllUserAnnotationsExportJobParams";
import type { SingleDocSingleUserAnnotationsExportJobParams } from "./SingleDocSingleUserAnnotationsExportJobParams";
import type { SingleProjectAllCodesExportJobParams } from "./SingleProjectAllCodesExportJobParams";
import type { SingleProjectAllDataExportJobParams } from "./SingleProjectAllDataExportJobParams";
import type { SingleProjectAllTagsExportJobParams } from "./SingleProjectAllTagsExportJobParams";
import type { SingleProjectSelectedSdocsParams } from "./SingleProjectSelectedSdocsParams";
import type { SingleUserAllCodesExportJobParams } from "./SingleUserAllCodesExportJobParams";
import type { SingleProjectSelectedSpanAnnotationsParams } from "./SingleProjectSelectedSpanAnnotationsParams";
import type { SingleUserAllDataExportJobParams } from "./SingleUserAllDataExportJobParams";
import type { SingleUserAllMemosExportJobParams } from "./SingleUserAllMemosExportJobParams";
import type { SingleUserLogbookExportJobParams } from "./SingleUserLogbookExportJobParams";
Expand All @@ -28,9 +29,10 @@ export type ExportJobParameters = {
specific_export_job_parameters:
| SingleProjectAllDataExportJobParams
| SingleProjectAllTagsExportJobParams
| SingleProjectAllCodesExportJobParams
| SingleProjectSelectedSdocsParams
| SingleProjectSelectedSpanAnnotationsParams
| SingleUserAllDataExportJobParams
| SingleUserAllCodesExportJobParams
| SingleUserAllMemosExportJobParams
| SingleUserLogbookExportJobParams
| SingleDocAllUserAnnotationsExportJobParams
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/api/openapi/models/ExportJobType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
export enum ExportJobType {
SINGLE_PROJECT_ALL_DATA = "SINGLE_PROJECT_ALL_DATA",
SINGLE_PROJECT_ALL_TAGS = "SINGLE_PROJECT_ALL_TAGS",
SINGLE_PROJECT_ALL_CODES = "SINGLE_PROJECT_ALL_CODES",
SINGLE_PROJECT_SELECTED_SDOCS = "SINGLE_PROJECT_SELECTED_SDOCS",
SINGLE_PROJECT_SELECTED_SPAN_ANNOTATIONS = "SINGLE_PROJECT_SELECTED_SPAN_ANNOTATIONS",
SINGLE_USER_ALL_DATA = "SINGLE_USER_ALL_DATA",
SINGLE_USER_ALL_CODES = "SINGLE_USER_ALL_CODES",
SINGLE_USER_ALL_MEMOS = "SINGLE_USER_ALL_MEMOS",
SINGLE_USER_LOGBOOK = "SINGLE_USER_LOGBOOK",
SINGLE_DOC_ALL_USER_ANNOTATIONS = "SINGLE_DOC_ALL_USER_ANNOTATIONS",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,10 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type SingleUserAllCodesExportJobParams = {
export type SingleProjectAllCodesExportJobParams = {
/**
* The ID of the Project to export from
*/
project_id: number;
export_job_type: any;
/**
* The ID of the User to get the data from.
*/
user_id: number;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type SingleProjectSelectedSpanAnnotationsParams = {
/**
* The ID of the Project to export from
*/
project_id: number;
export_job_type: any;
/**
* IDs of the span annotations to export
*/
span_annotation_ids: Array<number>;
};
11 changes: 5 additions & 6 deletions frontend/src/components/Exporter/ExporterDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ import { ExportJobParameters } from "../../api/openapi/models/ExportJobParameter
import { ExportJobType } from "../../api/openapi/models/ExportJobType.ts";
import { SingleDocAllUserAnnotationsExportJobParams } from "../../api/openapi/models/SingleDocAllUserAnnotationsExportJobParams.ts";
import { SingleDocSingleUserAnnotationsExportJobParams } from "../../api/openapi/models/SingleDocSingleUserAnnotationsExportJobParams.ts";
import { SingleProjectAllCodesExportJobParams } from "../../api/openapi/models/SingleProjectAllCodesExportJobParams.ts";
import { SingleProjectAllDataExportJobParams } from "../../api/openapi/models/SingleProjectAllDataExportJobParams.ts";
import { SingleProjectAllTagsExportJobParams } from "../../api/openapi/models/SingleProjectAllTagsExportJobParams.ts";
import { SingleUserAllCodesExportJobParams } from "../../api/openapi/models/SingleUserAllCodesExportJobParams.ts";
import { SingleUserAllMemosExportJobParams } from "../../api/openapi/models/SingleUserAllMemosExportJobParams.ts";
import { SingleUserLogbookExportJobParams } from "../../api/openapi/models/SingleUserLogbookExportJobParams.ts";
import { useAuth } from "../../auth/useAuth.ts";
Expand All @@ -44,7 +44,7 @@ const enabledComponentsPerType = new Map<string, string[]>(
Object.entries({
Project: [],
Tagset: [],
Codeset: ["users"],
Codeset: [],
Memos: ["users"],
Logbook: ["users"],
Annotations: ["singleUser"],
Expand Down Expand Up @@ -93,12 +93,11 @@ const exporterInfoToExporterJobParameters = (exporterData: ExporterInfo, project
};
case "Codeset":
return {
export_job_type: ExportJobType.SINGLE_USER_ALL_CODES,
export_job_type: ExportJobType.SINGLE_PROJECT_ALL_CODES,
specific_export_job_parameters: {
project_id: projectId,
export_job_type: ExportJobType.SINGLE_USER_ALL_CODES,
user_id: exporterData.users[0],
} as SingleUserAllCodesExportJobParams,
export_job_type: ExportJobType.SINGLE_PROJECT_ALL_CODES,
} as SingleProjectAllCodesExportJobParams,
export_format: ExportFormat.CSV,
};
case "Memos":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export interface SATToolbarProps {
filterName: string;
table: MRT_TableInstance<AnnotationTableRow>;
anchor: React.RefObject<HTMLElement>;
selectedUserId: number;
selectedAnnotations: AnnotationTableRow[];
}

Expand Down
Loading
Loading