Skip to content

Commit a3b82e0

Browse files
committed
Continue to send full submission records in existing list endpoint; add new endpoint for slim records
1 parent e58493f commit a3b82e0

File tree

6 files changed

+98
-45
lines changed

6 files changed

+98
-45
lines changed

nmdc_server/api.py

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,26 +1055,48 @@ async def get_metadata_submissions_report(
10551055
return response
10561056

10571057

1058-
@router.get(
1059-
"/metadata_submission",
1060-
tags=["metadata_submission"],
1061-
responses=login_required_responses,
1062-
response_model=query.Paginated[schemas_submission.SubmissionMetadataSchemaListItem],
1063-
)
1064-
async def list_submissions(
1058+
async def get_paginated_submission_list(
10651059
db: Session = Depends(get_db),
10661060
user: models.User = Depends(get_current_user),
10671061
pagination: Pagination = Depends(),
10681062
column_sort: str = "created",
10691063
sort_order: str = "desc",
10701064
is_test_submission_filter: Optional[bool] = None,
10711065
):
1066+
"""
1067+
Dependency function for getting a list of submissions with pagination, sorting, and filtering
1068+
applied.
1069+
"""
10721070
query = crud.get_submissions_for_user(
10731071
db, user, column_sort, sort_order, is_test_submission_filter
10741072
)
10751073
return pagination.response(query)
10761074

10771075

1076+
# The following two endpoints perform the same underlying query, but only differ in the
1077+
# response model they return.
1078+
@router.get(
1079+
"/metadata_submission",
1080+
tags=["metadata_submission"],
1081+
responses=login_required_responses,
1082+
response_model=query.Paginated[schemas_submission.SubmissionMetadataSchema],
1083+
)
1084+
async def list_submissions(submissions=Depends(get_paginated_submission_list)):
1085+
"""Return a paginated list of submissions in full detail."""
1086+
return submissions
1087+
1088+
1089+
@router.get(
1090+
"/metadata_submission/slim",
1091+
tags=["metadata_submission"],
1092+
responses=login_required_responses,
1093+
response_model=query.Paginated[schemas_submission.SubmissionMetadataSchemaSlim],
1094+
)
1095+
async def list_submissions_slim(submissions=Depends(get_paginated_submission_list)):
1096+
"""Return a paginated list of submissions in slim format."""
1097+
return submissions
1098+
1099+
10781100
@router.get(
10791101
"/metadata_submission/{id}",
10801102
tags=["metadata_submission"],
@@ -1228,10 +1250,7 @@ def create_github_issue(submission: schemas_submission.SubmissionMetadataSchema,
12281250
data_generated = "Yes" if multiomics_form.dataGenerated else "No"
12291251
omics_processing_types = ", ".join(multiomics_form.omicsProcessingTypes)
12301252
sample_types = ", ".join(submission.metadata_submission.templates)
1231-
sample_data = submission.metadata_submission.sampleData
1232-
num_samples = 0
1233-
for key in sample_data:
1234-
num_samples = max(num_samples, len(sample_data[key]))
1253+
num_samples = submission.sample_count
12351254

12361255
# some variable data to supply depending on if data has been generated or not
12371256
id_dict = {

nmdc_server/models.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,21 @@ class SubmissionImagesObject(Base):
944944
),
945945
)
946946

947+
# TODO: It would be nice if this could be derived from the schema
948+
ENVIRONMENTAL_DATA_SLOTS = [
949+
"air_data",
950+
"built_env_data",
951+
"host_associated_data",
952+
"hcr_cores_data",
953+
"hcr_fluids_swabs_data",
954+
"biofilm_data",
955+
"misc_envs_data",
956+
"plant_associated_data",
957+
"sediment_data",
958+
"soil_data",
959+
"water_data",
960+
]
961+
947962

948963
class SubmissionMetadata(Base):
949964
__tablename__ = "submission_metadata"
@@ -1038,14 +1053,28 @@ def owners(self) -> list[str]:
10381053
]
10391054

10401055
@property
1041-
def study_images_total_size(self):
1056+
def study_images_total_size(self) -> int:
10421057
"""Calculate the total size of all study images associated with this submission."""
10431058
return (
10441059
sum(image.size for image in self.study_images) # type: ignore
10451060
if self.study_images
10461061
else 0
10471062
)
10481063

1064+
@property
1065+
def sample_count(self) -> int:
1066+
if not self.metadata_submission or not isinstance(self.metadata_submission, dict):
1067+
return 0
1068+
sample_data = self.metadata_submission.get("sampleData", {})
1069+
if not sample_data:
1070+
return 0
1071+
count = 0
1072+
for slot in sample_data:
1073+
if slot in ENVIRONMENTAL_DATA_SLOTS:
1074+
samples = sample_data.get(slot, [])
1075+
count += len(samples)
1076+
return count
1077+
10491078

10501079
class SubmissionRole(Base):
10511080
__tablename__ = "submission_role"

nmdc_server/schemas_submission.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ class SubmissionMetadataSchemaPatch(BaseModel):
135135
field_notes_metadata: Optional[Dict[str, Any]] = None
136136

137137

138-
class SubmissionMetadataSchemaListItem(BaseModel):
138+
class SubmissionMetadataSchemaSlim(BaseModel):
139139
id: UUID
140140
author: schemas.User
141141
study_name: Optional[str] = None
@@ -144,6 +144,7 @@ class SubmissionMetadataSchemaListItem(BaseModel):
144144
date_last_modified: datetime
145145
created: datetime
146146
is_test_submission: bool = False
147+
sample_count: int = 0
147148

148149

149150
class SubmissionImagesObject(BaseModel):
@@ -154,7 +155,7 @@ class SubmissionImagesObject(BaseModel):
154155
content_type: str
155156

156157

157-
class SubmissionMetadataSchema(SubmissionMetadataSchemaListItem, SubmissionMetadataSchemaCreate):
158+
class SubmissionMetadataSchema(SubmissionMetadataSchemaSlim, SubmissionMetadataSchemaCreate):
158159
model_config = ConfigDict(from_attributes=True)
159160

160161
author_orcid: str

web/src/views/SubmissionPortal/Components/SubmissionList.vue

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ import IntroBlurb from '@/views/SubmissionPortal/Components/IntroBlurb.vue';
1616
import ContactCard from '@/views/SubmissionPortal/Components/ContactCard.vue';
1717
import { SearchParams } from '@/data/api';
1818
import { deleteSubmission } from '../store/api';
19-
import { HARMONIZER_TEMPLATES, MetadataSubmissionRecord, PaginatedResponse } from '@/views/SubmissionPortal/types';
19+
import {
20+
HARMONIZER_TEMPLATES,
21+
MetadataSubmissionRecord,
22+
MetadataSubmissionRecordSlim,
23+
PaginatedResponse,
24+
} from '@/views/SubmissionPortal/types';
2025
2126
const headers: DataTableHeader[] = [
2227
{
@@ -65,14 +70,14 @@ export default defineComponent({
6570
mustSort: false,
6671
});
6772
const isDeleteDialogOpen = ref(false);
68-
const deleteDialogSubmission = ref<MetadataSubmissionRecord | null>(null);
73+
const deleteDialogSubmission = ref<MetadataSubmissionRecordSlim | null>(null);
6974
const isTestFilter = ref(null);
7075
const testFilterValues = [
7176
{ text: 'Show all submissions', val: null },
7277
{ text: 'Show only test submissions', val: true },
7378
{ text: 'Hide test submissions', val: false }];
7479
75-
async function getSubmissions(params: SearchParams): Promise<PaginatedResponse<MetadataSubmissionRecord>> {
80+
async function getSubmissions(params: SearchParams): Promise<PaginatedResponse<MetadataSubmissionRecordSlim>> {
7681
return api.listRecords(params, isTestFilter.value);
7782
}
7883
@@ -106,14 +111,14 @@ export default defineComponent({
106111
submission.setSortOptions(options.value.sortBy[0], sortOrder);
107112
}, { deep: true });
108113
109-
function handleOpenDeleteDialog(item: MetadataSubmissionRecord | null) {
114+
function handleOpenDeleteDialog(item: MetadataSubmissionRecordSlim | null) {
110115
deleteDialogSubmission.value = item;
111116
if (deleteDialogSubmission) {
112117
isDeleteDialogOpen.value = true;
113118
}
114119
}
115120
116-
async function handleDelete(item: MetadataSubmissionRecord | null) {
121+
async function handleDelete(item: MetadataSubmissionRecordSlim | null) {
117122
if (!item) {
118123
return;
119124
}

web/src/views/SubmissionPortal/store/api.ts

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
LockOperationResult,
55
MetadataSubmission,
66
MetadataSubmissionRecord,
7+
MetadataSubmissionRecordSlim,
78
MetadataSuggestion,
89
MetadataSuggestionRequest,
910
NmdcAddress,
@@ -47,27 +48,20 @@ async function updateRecord(id: string, record: Partial<MetadataSubmission>, sta
4748
return { data: resp.data, httpStatus: resp.status };
4849
}
4950

50-
async function listRecords(params: SearchParams, isTestFilter: boolean | null) {
51+
async function listRecords(searchParams: SearchParams, isTestFilter: boolean | null) {
52+
const params: Record<string, any> = {
53+
limit: searchParams.limit,
54+
offset: searchParams.offset,
55+
column_sort: searchParams.sortColumn,
56+
sort_order: searchParams.sortOrder,
57+
};
5158
if (isTestFilter !== null) {
52-
const resp = await client.get<PaginatedResponse<MetadataSubmissionRecord>>('metadata_submission', {
53-
params: {
54-
limit: params.limit,
55-
offset: params.offset,
56-
column_sort: params.sortColumn,
57-
sort_order: params.sortOrder,
58-
is_test_submission_filter: isTestFilter,
59-
},
60-
});
61-
return resp.data;
59+
params.is_test_submission_filter = isTestFilter;
6260
}
63-
const resp = await client.get<PaginatedResponse<MetadataSubmissionRecord>>('metadata_submission', {
64-
params: {
65-
limit: params.limit,
66-
offset: params.offset,
67-
column_sort: params.sortColumn,
68-
sort_order: params.sortOrder,
69-
},
70-
});
61+
const resp = await client.get<PaginatedResponse<MetadataSubmissionRecordSlim>>(
62+
'metadata_submission/slim',
63+
{ params },
64+
);
7165
return resp.data;
7266
}
7367

web/src/views/SubmissionPortal/types.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -231,20 +231,25 @@ export interface MetadataSubmission {
231231
sampleData: Record<string, any[]>;
232232
}
233233

234-
export interface MetadataSubmissionRecord {
234+
export interface MetadataSubmissionRecordSlim {
235235
id: string;
236-
author_orcid: string;
236+
author: User;
237+
study_name: string;
238+
templates: string[];
239+
status: string;
240+
date_last_modified: string;
237241
created: string;
242+
is_test_submission: boolean;
243+
sample_count: number;
244+
}
245+
246+
export interface MetadataSubmissionRecord extends MetadataSubmissionRecordSlim {
247+
author_orcid: string;
238248
metadata_submission: MetadataSubmission;
239-
status: string;
240249
locked_by: User;
241250
lock_updated: string;
242251
permission_level: string | null;
243252
source_client: 'submission_portal' | 'field_notes' | 'nmdc_edge' | null;
244-
study_name: string;
245-
templates: string[];
246-
is_test_submission: boolean;
247-
date_last_modified: string;
248253
}
249254

250255
export interface PaginatedResponse<T> {

0 commit comments

Comments
 (0)