122
122
</div >
123
123
124
124
<!-- Overall Status -->
125
- <div v-if =" allTasksCompleted" class =" text-center mt-3 p-3" style =" background-color : var (--green-100 ); border : 1px solid var (--green-300 ); border-radius : 6px ;" >
126
- <i class =" pi pi-check-circle text-green-600 mr-2" style =" font-size : 1.5rem " ></i >
127
- <span class =" text-green-700 font-medium text-lg" >Cohort setup complete! All metadata and files uploaded.</span >
125
+ <div v-if =" allTasksCompleted && !validationPassed" class =" text-center mt-3 p-3" style =" background-color : var (--blue-50 ); border : 1px solid var (--blue-200 ); border-radius : 6px ;" >
126
+ <i class =" pi pi-info-circle text-blue-600 mr-2" style =" font-size : 1.5rem " ></i >
127
+ <div class =" mb-3" >
128
+ <span class =" text-blue-800 font-medium text-lg" >All files uploaded successfully!</span >
129
+ <p class =" text-blue-700 text-sm mt-2 mb-0" >Ready to run inter-file validations to finalize your cohort upload.</p >
130
+ </div >
128
131
129
- <div class = " mt-3 " >
132
+ <div >
130
133
<Button
131
- label =" Finalize Cohort Upload "
132
- icon =" pi pi-check "
133
- class =" p-button-success "
134
+ label =" Run Inter-File Validations "
135
+ icon =" pi pi-cog "
136
+ class =" p-button-info "
134
137
@click =" validateAllConsistency"
135
138
:loading =" validatingConsistency"
136
139
/>
137
140
</div >
138
141
</div >
139
- <div v-else class =" text-center mt-3 p-2" style =" background-color : var (--orange-100 ); border : 1px solid var (--orange-300 ); border-radius : 6px ;" >
142
+
143
+ <!-- Validation Complete Status -->
144
+ <div v-if =" validationPassed" class =" text-center mt-3 p-3" style =" background-color : var (--green-50 ); border : 1px solid var (--green-200 ); border-radius : 6px ;" >
145
+ <i class =" pi pi-check-circle text-green-600 mr-2" style =" font-size : 1.5rem " ></i >
146
+ <div >
147
+ <span class =" text-green-800 font-medium text-lg" >Cohort upload complete!</span >
148
+ <p class =" text-green-700 text-sm mt-2 mb-0" >All files uploaded and validated successfully. Your cohort is now finalized.</p >
149
+ </div >
150
+ </div >
151
+ <div v-else-if =" !validationPassed && remainingTasksCount > 0" class =" text-center mt-3 p-2" style =" background-color : var (--orange-100 ); border : 1px solid var (--orange-300 ); border-radius : 6px ;" >
140
152
<i class =" pi pi-info-circle text-orange-600 mr-2" ></i >
141
153
<span class =" text-orange-700 font-medium" >{{ remainingTasksCount }} task{{ remainingTasksCount === 1 ? '' : 's' }} remaining</span >
142
154
</div >
872
884
<Dialog
873
885
v-model:visible =" store.showNotification"
874
886
modal
875
- header =" Upload Error"
887
+ header =" Error"
876
888
:style =" { width: '600px' }"
877
889
:closable =" true"
878
890
@hide =" store.showNotification = false"
@@ -932,6 +944,7 @@ const loading = ref(true);
932
944
const cohortData = ref (null );
933
945
const metadataSaved = ref (false );
934
946
const validatingConsistency = ref (false );
947
+ const validationPassed = ref (false );
935
948
936
949
// File upload reactive variables
937
950
const activeAccordionIndex = ref (0 );
@@ -1304,11 +1317,11 @@ onMounted(async () => {
1304
1317
existingFiles .value .casesControlsFemale = fileInfo;
1305
1318
} else if (row .file_type === ' cases_controls_both' ) {
1306
1319
existingFiles .value .casesControlsBoth = fileInfo;
1307
- } else if (row .file_type === ' cooccurrenceMale ' ) {
1320
+ } else if (row .file_type === ' cooccurrence_male ' ) {
1308
1321
existingFiles .value .cooccurrenceMale = fileInfo;
1309
- } else if (row .file_type === ' cooccurrenceFemale ' ) {
1322
+ } else if (row .file_type === ' cooccurrence_female ' ) {
1310
1323
existingFiles .value .cooccurrenceFemale = fileInfo;
1311
- } else if (row .file_type === ' cooccurrenceBoth ' ) {
1324
+ } else if (row .file_type === ' cooccurrence_both ' ) {
1312
1325
existingFiles .value .cooccurrenceBoth = fileInfo;
1313
1326
} else if (row .file_type === ' cohort_description' ) {
1314
1327
existingFiles .value .cohortDescription = fileInfo;
@@ -1321,11 +1334,17 @@ onMounted(async () => {
1321
1334
casesControlsMale: uploadedFileTypes .has (' cases_controls_male' ),
1322
1335
casesControlsFemale: uploadedFileTypes .has (' cases_controls_female' ),
1323
1336
casesControlsBoth: uploadedFileTypes .has (' cases_controls_both' ),
1324
- cooccurrenceMale: uploadedFileTypes .has (' cooccurrenceMale ' ),
1325
- cooccurrenceFemale: uploadedFileTypes .has (' cooccurrenceFemale ' ),
1326
- cooccurrenceBoth: uploadedFileTypes .has (' cooccurrenceBoth ' ),
1337
+ cooccurrenceMale: uploadedFileTypes .has (' cooccurrence_male ' ),
1338
+ cooccurrenceFemale: uploadedFileTypes .has (' cooccurrence_female ' ),
1339
+ cooccurrenceBoth: uploadedFileTypes .has (' cooccurrence_both ' ),
1327
1340
cohortDescription: uploadedFileTypes .has (' cohort_description' )
1328
1341
};
1342
+
1343
+ // Initialize validation status from cohort data
1344
+ console .log (' cohortInfo.validation_status:' , cohortInfo .validation_status );
1345
+ console .log (' Type of validation_status:' , typeof cohortInfo .validation_status );
1346
+ validationPassed .value = !! cohortInfo .validation_status ;
1347
+ console .log (' Set validationPassed to:' , validationPassed .value );
1329
1348
1330
1349
// Set initial accordion tab based on completion status
1331
1350
// If everything is complete, leave all tabs closed (activeAccordionIndex = null)
@@ -1376,15 +1395,46 @@ onMounted(async () => {
1376
1395
// Handle metadata update
1377
1396
function handleMetadataUpdated (response ) {
1378
1397
console .log (' Metadata updated:' , response);
1379
- // Update cohort data with all fields from the response
1380
- cohortData .value = {
1398
+ console .log (' Current cohortData before update:' , cohortData .value );
1399
+
1400
+ // Handle the response - it could be an array (like fetch) or an object
1401
+ const cohortInfo = Array .isArray (response) ? response[0 ] : response;
1402
+
1403
+ // Create the updated data object
1404
+ const updatedData = {
1381
1405
... cohortData .value ,
1382
- id: response .cohort_id || response .id , // Handle both field names
1383
- name: response .name ,
1384
- total_sample_size: response .total_sample_size ,
1385
- number_of_males: response .number_of_males ,
1386
- number_of_females: response .number_of_females
1406
+ id: cohortInfo .cohort_id || cohortInfo .id , // Handle both field names
1407
+ name: cohortInfo .name ,
1408
+ total_sample_size: cohortInfo .total_sample_size ,
1409
+ number_of_males: cohortInfo .number_of_males ,
1410
+ number_of_females: cohortInfo .number_of_females ,
1411
+ uploaded_by: cohortInfo .uploaded_by ,
1412
+ created_at: cohortInfo .created_at ,
1413
+ updated_at: cohortInfo .updated_at ,
1414
+ // Extract cohort metadata fields if they exist
1415
+ ... (cohortInfo .cohort_metadata ? {
1416
+ phenotype_coding_system: cohortInfo .cohort_metadata .phenotype_coding_system || ' ' ,
1417
+ phenotype_mapping_issues: cohortInfo .cohort_metadata .phenotype_mapping_issues || ' ' ,
1418
+ industry_involvement: cohortInfo .cohort_metadata .industry_involvement || ' ' ,
1419
+ industry_authorship: cohortInfo .cohort_metadata .industry_authorship ,
1420
+ data_restrictions: cohortInfo .cohort_metadata .data_restrictions || ' '
1421
+ } : {
1422
+ phenotype_coding_system: cohortData .value .phenotype_coding_system || ' ' ,
1423
+ phenotype_mapping_issues: cohortData .value .phenotype_mapping_issues || ' ' ,
1424
+ industry_involvement: cohortData .value .industry_involvement || ' ' ,
1425
+ industry_authorship: cohortData .value .industry_authorship ,
1426
+ data_restrictions: cohortData .value .data_restrictions || ' '
1427
+ })
1387
1428
};
1429
+
1430
+ console .log (' Updated cohortData after processing:' , updatedData);
1431
+
1432
+ // Update cohort data
1433
+ cohortData .value = updatedData;
1434
+
1435
+ // Reset validation status since metadata has changed
1436
+ validationPassed .value = false ;
1437
+
1388
1438
// Show the file upload accordion
1389
1439
metadataSaved .value = true ;
1390
1440
}
@@ -1626,7 +1676,7 @@ async function uploadCooccurrenceFile(gender = 'male') {
1626
1676
const result = await store .uploadSGCFile (
1627
1677
fileRef .value ,
1628
1678
cohortId,
1629
- ' cooccurrence ' ,
1679
+ ` cooccurrence_ ${ gender } ` ,
1630
1680
statusKey,
1631
1681
createFlippedMapping (mappingRef)
1632
1682
);
@@ -1947,6 +1997,77 @@ function openNextAccordion() {
1947
1997
}
1948
1998
}, 500 );
1949
1999
}
2000
+
2001
+ // Function to validate all file consistency
2002
+ async function validateAllConsistency () {
2003
+ validatingConsistency .value = true ;
2004
+
2005
+ // Clear any previous error state to prevent interceptor interference
2006
+ store .errorMessage = ' ' ;
2007
+ store .showNotification = false ;
2008
+
2009
+ try {
2010
+ const result = await store .validateAllConsistency (cohortId);
2011
+
2012
+ // Check if validation passed based on the API response
2013
+ if (result && result .validation_status ) {
2014
+ // Update validation status to hide UI elements
2015
+ validationPassed .value = true ;
2016
+
2017
+ // Show success message using toast for positive feedback
2018
+ toast .add ({
2019
+ severity: ' success' ,
2020
+ summary: ' Validation Complete' ,
2021
+ detail: ' All inter-file validations passed successfully! Your cohort is now finalized.' ,
2022
+ life: 5000
2023
+ });
2024
+
2025
+ // Optionally redirect to the cohort list after showing success
2026
+ setTimeout (() => {
2027
+ navigateTo (' /sgc' );
2028
+ }, 3000 );
2029
+ } else {
2030
+ // Handle case where API returns 200 but validation_status is false
2031
+ toast .add ({
2032
+ severity: ' error' ,
2033
+ summary: ' Validation Failed' ,
2034
+ detail: result? .message || ' Inter-file validation failed. Please check your files and try again.' ,
2035
+ life: 8000
2036
+ });
2037
+ }
2038
+
2039
+ } catch (error) {
2040
+ console .error (' Validation error:' , error);
2041
+ store .processing = false ;
2042
+
2043
+ // Handle server validation errors (400 responses) - exact same pattern as cohort description upload
2044
+ let errorMessage = ' Inter-file validation failed. Please check your files and try again.' ;
2045
+ if (error .status === 400 || error .response ? .status === 400 ) {
2046
+ // Server returned validation errors - check both error.data and error.response.data
2047
+ const errorData = error .data || error .response ? .data ;
2048
+
2049
+ if (typeof errorData === ' string' ) {
2050
+ errorMessage = errorData;
2051
+ } else if (errorData? .detail ) {
2052
+ errorMessage = errorData .detail ;
2053
+ } else if (errorData? .message ) {
2054
+ errorMessage = errorData .message ;
2055
+ }
2056
+ } else if (error .message ) {
2057
+ errorMessage = error .message ;
2058
+ }
2059
+
2060
+ toast .add ({
2061
+ severity: ' error' ,
2062
+ summary: ' Validation Error' ,
2063
+ detail: errorMessage,
2064
+ life: 8000 // Longer display time for validation errors
2065
+ });
2066
+
2067
+ } finally {
2068
+ validatingConsistency .value = false ;
2069
+ }
2070
+ }
1950
2071
< / script>
1951
2072
1952
2073
< style scoped>
0 commit comments