7777from physionet .enums import LogCategory
7878from console import forms , utility , services
7979from console .forms import ProjectFilterForm , UserFilterForm
80+ from console .file_utils import FileUnpacker
8081from project .cloud .s3 import (
8182 create_s3_bucket ,
8283 upload_project_to_S3 ,
@@ -282,7 +283,8 @@ def submission_info_card_params(request,
282283 embargo_form ,
283284 internal_note_form ,
284285 bulk_download ,
285- force_calculate ):
286+ force_calculate ,
287+ file_unpack_form = None ):
286288 """
287289 Parameters used across submission_info_card.html pages, including:
288290
@@ -311,6 +313,7 @@ def submission_info_card_params(request,
311313 'embargo_form' : embargo_form ,
312314 'notes' : notes ,
313315 'internal_note_form' : internal_note_form ,
316+ 'file_unpack_form' : file_unpack_form ,
314317 }
315318
316319
@@ -328,6 +331,7 @@ def submission_info(request, project_slug):
328331 reassign_editor_form = forms .ReassignEditorForm (project = project , data = data )
329332 internal_note_form = forms .InternalNoteForm (data )
330333 embargo_form = forms .EmbargoFilesDaysForm ()
334+ file_unpack_form = forms .FileUnpackForm (data )
331335 passphrase = ''
332336 anonymous_url = project .get_anonymous_url ()
333337
@@ -376,6 +380,40 @@ def submission_info(request, project_slug):
376380 else :
377381 messages .error (request , "You are not authorized to delete this note." )
378382 return redirect (f'{ request .path } ?tab=notes' )
383+ elif 'unpack_file' in request .POST and user == project .editor :
384+ if file_unpack_form .is_valid ():
385+ try :
386+ project_root = project .file_root ()
387+
388+ LOGGER .info (f"Project root: { project_root } " )
389+ LOGGER .info (f"File path: { file_unpack_form .cleaned_data ['file_path' ]} " )
390+ LOGGER .info (f"Full file path: { os .path .join (project_root , file_unpack_form .cleaned_data ['file_path' ])} " )
391+
392+ result = FileUnpacker .unpack_file (
393+ project_root = project_root ,
394+ file_path = file_unpack_form .cleaned_data ['file_path' ],
395+ target_directory = file_unpack_form .cleaned_data ['target_directory' ] or None ,
396+ overwrite_existing = file_unpack_form .cleaned_data ['overwrite_existing' ]
397+ )
398+
399+ if result ['success' ]:
400+ messages .success (
401+ request ,
402+ f"Successfully unpacked { len (result ['extracted_files' ])} files to { result ['extract_directory' ]} "
403+ )
404+ # Reset form after successful unpacking
405+ file_unpack_form = forms .FileUnpackForm ()
406+ else :
407+ messages .error (request , "File unpacking failed" )
408+
409+ except Exception as e :
410+ error_msg = f"Error unpacking file: { str (e )} "
411+ if "File not found" in str (e ):
412+ error_msg += f" (searched in: { project_root } )"
413+ messages .error (request , error_msg )
414+ LOGGER .error (f"File unpacking error for project { project .slug } : { str (e )} " )
415+ else :
416+ messages .error (request , 'Invalid file unpacking submission. See errors below.' )
379417
380418 return render (request , 'console/submission_info.html' ,
381419 {** submission_info_card_params (
@@ -385,11 +423,13 @@ def submission_info(request, project_slug):
385423 embargo_form ,
386424 internal_note_form ,
387425 bulk_download = True ,
388- force_calculate = False
426+ force_calculate = False ,
427+ file_unpack_form = file_unpack_form
389428 ),
390429 'copyedit_logs' : copyedit_logs ,
391430 'passphrase' : passphrase ,
392431 'anonymous_url' : anonymous_url ,
432+ 'file_unpack_form' : file_unpack_form ,
393433 }
394434 )
395435
@@ -449,7 +489,8 @@ def edit_submission(request, project_slug, *args, **kwargs):
449489 embargo_form ,
450490 internal_note_form ,
451491 bulk_download = True ,
452- force_calculate = False
492+ force_calculate = False ,
493+ file_unpack_form = None
453494 ),
454495 'edit_submission_form' : edit_submission_form ,
455496 'editor_home' : True ,
@@ -590,15 +631,16 @@ def copyedit_submission(request, project_slug, *args, **kwargs):
590631 response = render (
591632 request ,
592633 'console/copyedit_submission.html' ,
593- {** submission_info_card_params (
594- request ,
595- project ,
596- reassign_editor_form ,
597- embargo_form ,
598- internal_note_form ,
599- bulk_download = False ,
600- force_calculate = True ,
601- ),
634+ {** submission_info_card_params (
635+ request ,
636+ project ,
637+ reassign_editor_form ,
638+ embargo_form ,
639+ internal_note_form ,
640+ bulk_download = False ,
641+ force_calculate = True ,
642+ file_unpack_form = None
643+ ),
602644 'description_form' : description_form ,
603645 'ethics_form' : ethics_form ,
604646 'individual_size_limit' : readable_size (ActiveProject .INDIVIDUAL_FILE_SIZE_LIMIT ),
@@ -674,6 +716,7 @@ def awaiting_authors(request, project_slug, *args, **kwargs):
674716 internal_note_form ,
675717 bulk_download = True ,
676718 force_calculate = False ,
719+ file_unpack_form = None
677720 ),
678721 'copyedit_logs' : copyedit_logs ,
679722 'outstanding_emails' : outstanding_emails ,
@@ -790,7 +833,8 @@ def publish_submission(request, project_slug, *args, **kwargs):
790833 embargo_form ,
791834 internal_note_form ,
792835 bulk_download = True ,
793- force_calculate = True
836+ force_calculate = True ,
837+ file_unpack_form = None
794838 ),
795839 'publishable' : publishable ,
796840 'copyedit_logs' : copyedit_logs ,
0 commit comments