Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions backend_py/src/routes/recordings.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def delete_recording(request: Request, recording_path: str) -> list[RecordingInf
recordings_service: RecordingsService = request.app.state.recordings_service

response = recordings_service.delete_recording(recording_path)
if not response:
if response is None:
raise HTTPException(
status_code=404, detail="Recording not found or could not be deleted"
)
Expand All @@ -187,13 +187,7 @@ def bulk_delete_recording(
) -> list[RecordingInfo]:
recordings_service: RecordingsService = request.app.state.recordings_service

response = recordings_service.bulk_delete_recordings(filenames)
if not response:
raise HTTPException(
status_code=404, detail="Recordings not found or could not be deleted"
)

return response
return recordings_service.bulk_delete_recordings(filenames)


@recordings_router.patch("/{old_name}/{new_name}", summary="Rename a recording")
Expand Down
33 changes: 17 additions & 16 deletions backend_py/src/services/recordings/recordings_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,28 +132,29 @@ def get_recording(self, filename: str) -> RecordingInfo | None:
return recording
return None

def _remove_recording_file(self, filename: str) -> bool:
# Caller must hold recordings_lock
recording_path = os.path.join(self.recordings_path, filename)
self.durations.pop(recording_path, None)

if not os.path.exists(recording_path):
return False

os.remove(recording_path)
self.recordings = [rec for rec in self.recordings if rec.path != recording_path]
return True

def delete_recording(self, filename: str) -> list[RecordingInfo] | None:
if filename in self.durations:
self.durations.pop(filename, None)
with self.recordings_lock:
if not self._remove_recording_file(filename):
return None

recording_path = os.path.join(self.recordings_path, filename)
if os.path.exists(recording_path):
os.remove(recording_path)
self.recordings = [
rec for rec in self.recordings if rec.path != recording_path
]
return self.recordings
return None
return self.get_recordings()

def bulk_delete_recordings(self, filenames: list[str]) -> list[RecordingInfo]:
with self.recordings_lock:
for filename in filenames:
if filename in self.durations:
self.durations.pop(filename, None)

recording_path = os.path.join(self.recordings_path, filename)
if os.path.exists(recording_path):
os.remove(recording_path)
self._remove_recording_file(filename)

return self.get_recordings()

Expand Down
22 changes: 13 additions & 9 deletions frontend/src/components/dwe/recordings/store/recording-store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -305,16 +305,20 @@ export const recordingsActions = {
body: targetNames,
});

if (result.data) {
recordingsState.recordings = result.data;
recordingsActions.setSelectedNames([]);

toast.success(
deleteTargets.length > 1
? `Deleted ${deleteTargets.length} recordings`
: `Recording deleted: ${deleteTargets[0].name}`,
);
if (result.error || !result.data) {
console.error(result.error);
toast.error("Failed to delete recording");
return;
}

recordingsState.recordings = result.data;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot this still used valtio...

recordingsActions.setSelectedNames([]);

toast.success(
deleteTargets.length > 1
? `Deleted ${deleteTargets.length} recordings`
: `Recording deleted: ${deleteTargets[0].name}`,
);
} catch (error) {
console.error(error);
toast.error("Failed to delete recording");
Expand Down
11 changes: 8 additions & 3 deletions run_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
from contextlib import asynccontextmanager

import socketio
from fastapi import FastAPI, HTTPException, Request
from fastapi import FastAPI, Request
from fastapi.exception_handlers import http_exception_handler
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse, JSONResponse
from fastapi.responses import FileResponse, JSONResponse, Response
from fastapi.staticfiles import StaticFiles
from starlette.exceptions import HTTPException as StarletteHTTPException

from backend_py.src import FeatureSupport, Server

Expand Down Expand Up @@ -95,8 +97,11 @@ async def register_service() -> JSONResponse:
app.mount("/", StaticFiles(directory=FRONTEND_DIR, html=True), name="static")

@app.exception_handler(404)
async def not_found(request: Request, exc: HTTPException) -> FileResponse:
async def not_found(request: Request, exc: StarletteHTTPException) -> Response:
"""Serve index.html for any unknown paths (Frontend Routing Support)"""
# API 404s keep their JSON error, so the frontend can tell they failed
if request.url.path.startswith("/api/"):
return await http_exception_handler(request, exc)
return FileResponse(os.path.join(FRONTEND_DIR, "index.html"))

async def main() -> None:
Expand Down
Loading