diff --git a/MisplaceAI/process_misplaced_manager/urls.py b/MisplaceAI/process_misplaced_manager/urls.py index 04a85b3e9c53c86641500e5d1c1d275b20122d3f..5d28647bd095ccaae2e0a4f911ce279ca323e99e 100644 --- a/MisplaceAI/process_misplaced_manager/urls.py +++ b/MisplaceAI/process_misplaced_manager/urls.py @@ -4,7 +4,7 @@ from rest_framework.routers import DefaultRouter from .views import ( UploadedImageViewSet, UploadedVideoViewSet, normal_detection, - display_results, display_video_results,upload_video, download_image, delete_image + display_results, display_video_results,upload_video, download_image, delete_image,delete_video ) router = DefaultRouter() @@ -22,9 +22,6 @@ urlpatterns = [ path('display-results/<int:image_id>/', display_results, name='display_results'), path('download/<path:file_path>/', download_image, name='download_image'), path('delete-image/<str:image_name>/', delete_image, name='delete_image_by_name'), - - - - + path('delete-video/<str:video_name>/', delete_video, name='delete_video'), ] diff --git a/MisplaceAI/process_misplaced_manager/views.py b/MisplaceAI/process_misplaced_manager/views.py index 11d3ac0633a17fae256710d4231297a696e83b4d..96ed40653c737de209d5e5796b82aabf5d24cbbd 100644 --- a/MisplaceAI/process_misplaced_manager/views.py +++ b/MisplaceAI/process_misplaced_manager/views.py @@ -170,7 +170,10 @@ def display_video_results(request, video_id): print("Processing video at path:", video_path) frame_interval = video.user_video_frame_preference.frame_interval if video.user_video_frame_preference else 1 detected_objects, misplaced_objects, output_video_path = process_video_for_misplaced_objects(video_path, frame_interval) - print + + # Delete the original uploaded video + if os.path.exists(video_path): + os.remove(video_path) response_data = { 'video_url': request.build_absolute_uri(video.video.url), @@ -187,7 +190,6 @@ def display_video_results(request, video_id): return JsonResponse({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) - def process_video_for_misplaced_objects(video_path, frame_interval): print("Starting object detection for video:", video_path) cap = cv2.VideoCapture(video_path) @@ -254,21 +256,9 @@ def process_video_for_misplaced_objects(video_path, frame_interval): - ################################################################################################# -####################################### Download Results ######################################## -@api_view(['GET']) -@permission_classes([IsAuthenticated]) -def download_image(request, file_path): - file_path = os.path.join(settings.MEDIA_ROOT, file_path) - if os.path.exists(file_path): - with open(file_path, 'rb') as f: - response = HttpResponse(f.read(), content_type="application/force-download") - response['Content-Disposition'] = f'attachment; filename="{os.path.basename(file_path)}"' - return response - else: - raise Http404 - +################################## Delete Video/Images ########################################## + @api_view(['DELETE']) @@ -290,4 +280,42 @@ def delete_image(request, image_name): return Response({'error': 'Image not found'}, status=status.HTTP_404_NOT_FOUND) except Exception as e: print(f"Error deleting image {image_name}: {str(e)}") - return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) \ No newline at end of file + return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + + + + +@api_view(['DELETE']) +@permission_classes([IsAuthenticated]) +def delete_video(request, video_name): + try: + print(f"Attempting to delete video: {video_name}") + video_path = os.path.join(settings.MEDIA_ROOT, 'videos', video_name) + if os.path.exists(video_path): + os.remove(video_path) + print(f"Video {video_name} deleted successfully.") + return Response(status=status.HTTP_204_NO_CONTENT) + else: + print(f"Video {video_name} not found.") + return Response({'error': 'Video not found'}, status=status.HTTP_404_NOT_FOUND) + except Exception as e: + print(f"Error deleting video {video_name}: {str(e)}") + return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + +################################################################################################# +####################################### Download Results ######################################## +@api_view(['GET']) +@permission_classes([IsAuthenticated]) +def download_image(request, file_path): + file_path = os.path.join(settings.MEDIA_ROOT, file_path) + if os.path.exists(file_path): + with open(file_path, 'rb') as f: + response = HttpResponse(f.read(), content_type="application/force-download") + response['Content-Disposition'] = f'attachment; filename="{os.path.basename(file_path)}"' + return response + else: + raise Http404 + + diff --git a/frontend/src/pages/Video/VideoDetectionPage.js b/frontend/src/pages/Video/VideoDetectionPage.js index 26af3d81b5c15aaf9fb01fd12db0e43aca5f3a1a..35ae564a6bfdd330071a05131da3b3a0a0d94d06 100644 --- a/frontend/src/pages/Video/VideoDetectionPage.js +++ b/frontend/src/pages/Video/VideoDetectionPage.js @@ -1,7 +1,8 @@ // src/pages/VideoDetection/VideoDetectionPage.js -import React, { useState } from 'react'; -import { uploadVideo, getVideoResults } from '../../services/processMisplacedManagerApi'; +import React, { useState, useEffect } from 'react'; +import { useNavigate, useLocation } from 'react-router-dom'; +import { uploadVideo, getVideoResults, deleteVideo } from '../../services/processMisplacedManagerApi'; import '../../styles/main.css'; import LoadingIndicator from '../../components/detection/LoadingIndicator'; import DetectionResults from '../../components/detection/DetectionResults'; @@ -10,9 +11,58 @@ import DetectionContainer from '../../components/detection/DetectionContainer'; const VideoDetectionPage = () => { const [videoFile, setVideoFile] = useState(null); - const [frameInterval, setFrameInterval] = useState(1); // Added state for frame interval + const [frameInterval, setFrameInterval] = useState(1); const [result, setResult] = useState(null); const [isLoading, setIsLoading] = useState(false); + const [videoName, setVideoName] = useState(null); + const [annotatedVideoName, setAnnotatedVideoName] = useState(null); + const navigate = useNavigate(); + const location = useLocation(); + const [isDeleting, setIsDeleting] = useState(false); + + useEffect(() => { + const handleUnload = async () => { + if (annotatedVideoName && !isDeleting) { + setIsDeleting(true); + console.log('Navigation event detected:'); + console.log('Annotated video name detected:', annotatedVideoName); + try { + const response = await deleteVideo(annotatedVideoName); + console.log('Delete video response:', response); + } catch (error) { + console.error('Error deleting video:', error); + } + setIsDeleting(false); + } + }; + + window.addEventListener('beforeunload', handleUnload); + + return () => { + window.removeEventListener('beforeunload', handleUnload); + }; + }, [annotatedVideoName, isDeleting]); + + useEffect(() => { + const handleRouteChange = async () => { + if (annotatedVideoName && !isDeleting) { + setIsDeleting(true); + console.log('Route change detected:'); + console.log('Annotated video name detected:', annotatedVideoName); + try { + const response = await deleteVideo(annotatedVideoName); + console.log('Delete video response:', response); + } catch (error) { + console.error('Error deleting video:', error); + } + setIsDeleting(false); + } + }; + + return () => { + handleRouteChange(); + }; + }, [annotatedVideoName, isDeleting, location]); const handleFileChange = (event) => { setVideoFile(event.target.files[0]); @@ -28,9 +78,7 @@ const VideoDetectionPage = () => { setIsLoading(true); const formData = new FormData(); formData.append('video', videoFile); - formData.append('frame_interval', frameInterval); // Added frame interval to form data - - console.log('Uploading video file:', videoFile); + formData.append('frame_interval', frameInterval); try { const uploadResponse = await uploadVideo(formData); @@ -38,8 +86,10 @@ const VideoDetectionPage = () => { if (uploadResponse.id) { const videoResults = await getVideoResults(uploadResponse.id); - console.log('Video results:', videoResults); // Added log for video results + console.log('Video results:', videoResults); setResult(videoResults); + setVideoName(uploadResponse.video.split('/').pop()); // Extract original video name from the response + setAnnotatedVideoName(videoResults.output_video_url.split('/').pop()); // Extract annotated video name from the results } else { throw new Error('Upload response did not contain video ID.'); } diff --git a/frontend/src/services/processMisplacedManagerApi.js b/frontend/src/services/processMisplacedManagerApi.js index ed241314d4828e954594bd92469b1e68df1ac708..89d9029900eaaae218306cd931b7263904717579 100644 --- a/frontend/src/services/processMisplacedManagerApi.js +++ b/frontend/src/services/processMisplacedManagerApi.js @@ -143,4 +143,16 @@ export const deleteImageByName = async (imageName) => { console.error(`Error deleting image with name ${imageName}:`, error); throw error; } -}; \ No newline at end of file +}; + +// Function to delete a video +export const deleteVideo = async (videoName) => { + try { + const response = await api.delete(`/api/process_misplaced_manager/delete-video/${videoName}/`); + return response.data; + } catch (error) { + console.error(`Error deleting video ${videoName}:`, error); + throw error; + } +}; +