diff --git a/atlas/templates/atlas/user_uploads.html b/atlas/templates/atlas/user_uploads.html index 158c232a..d7ef461a 100644 --- a/atlas/templates/atlas/user_uploads.html +++ b/atlas/templates/atlas/user_uploads.html @@ -636,11 +636,9 @@ } const casePk = trigger.dataset.caseId || importCaseId; - if (!casePk) { - alert('Could not determine a target case for this partial import. Use an "Import remaining" button linked to a case or open this page in a case context.'); - return; - } - const confirmMsg = `Finish importing ${seriesUids.length} series${casePk ? ` into case ${casePk}` : ''}?`; + const confirmMsg = casePk + ? `Finish importing ${seriesUids.length} series into case ${casePk}?` + : `Finish importing ${seriesUids.length} series without linking to a case?`; if (!window.confirm(confirmMsg)) return; await runImport(seriesUids, casePk); diff --git a/deploy/settings_local.py b/deploy/settings_local.py index a25bc3af..6f7ccf0d 100644 --- a/deploy/settings_local.py +++ b/deploy/settings_local.py @@ -66,7 +66,7 @@ if not DEBUG: 'file': { 'level': 'DEBUG', 'class': 'logging.FileHandler', - 'filename': 'log.txt', + 'filename': 'logs/app.log', 'formatter': 'verbose', }, }, diff --git a/deploy/settings_local.py.example b/deploy/settings_local.py.example index 2d4204a0..65ec41f9 100644 --- a/deploy/settings_local.py.example +++ b/deploy/settings_local.py.example @@ -33,7 +33,7 @@ if not DEBUG: 'file': { 'level': 'DEBUG', 'class': 'logging.FileHandler', - 'filename': 'log.txt', + 'filename': 'logs/app.log', 'formatter': 'verbose', }, }, diff --git a/rad/logging_setup.py b/rad/logging_setup.py index 7171b648..68e244af 100644 --- a/rad/logging_setup.py +++ b/rad/logging_setup.py @@ -50,9 +50,13 @@ def _get_log_file_path() -> Path: pass try: - return Path(getattr(settings, "BASE_DIR", Path.cwd())) / "log.txt" + return Path(getattr(settings, "BASE_DIR", Path.cwd())) / "logs" / "app.log" except Exception: - return Path.cwd() / "log.txt" + return Path.cwd() / "logs" / "app.log" + + +def get_log_file_path() -> Path: + return _get_log_file_path() def configure_loguru() -> Path: @@ -60,7 +64,7 @@ def configure_loguru() -> Path: if _CONFIGURED: return _get_log_file_path() - log_file_path = _get_log_file_path() + log_file_path = get_log_file_path() log_file_path.parent.mkdir(parents=True, exist_ok=True) stdout_level = _get_stdout_level() log_format = "[{time:DD/MMM/YYYY HH:mm:ss}] {level} [{name}:{line}] {message}" diff --git a/rad/tests/test_logs_view.py b/rad/tests/test_logs_view.py index 827e14c6..15a5377b 100644 --- a/rad/tests/test_logs_view.py +++ b/rad/tests/test_logs_view.py @@ -24,13 +24,13 @@ def test_loguru_uses_django_file_handler_path(settings, tmp_path, monkeypatch): def test_logs_view_filters_by_date_and_can_reset_log_file(client, admin_user, monkeypatch, tmp_path): client.force_login(admin_user) - log_file = tmp_path / "log.txt" + log_file = tmp_path / "app.log" log_file.write_text( "[03/Jun/2026 10:00:00] INFO [atlas.views:10] first entry\n" "[03/Jun/2026 11:00:00] ERROR [atlas.views:11] second entry\n", encoding="utf-8", ) - monkeypatch.setattr("rad.views.settings.BASE_DIR", str(tmp_path)) + monkeypatch.setattr("rad.views.get_log_file_path", lambda: log_file) response = client.get( reverse("logs_view"), diff --git a/rad/views.py b/rad/views.py index 04770b80..7de52a0e 100644 --- a/rad/views.py +++ b/rad/views.py @@ -105,6 +105,7 @@ from django.db.models import Q from dal import autocomplete from loguru import logger +from .logging_setup import get_log_file_path import psutil @@ -295,13 +296,13 @@ def account_send_password_reset(request, slug): @user_passes_test(lambda u: u.is_superuser) def logs_view(request): - """Display production logs from log.txt with search filtering. + """Display production logs with search/filter controls. Scope: superusers only. - Functionality: reads log.txt, displays entries with optional text search filter. + Functionality: reads the configured application log file and displays entries with optional text search filter. Supports ?all=1 to show all entries without pagination limit. """ - log_file_path = os.path.join(settings.BASE_DIR, "log.txt") + log_file_path = str(get_log_file_path()) search_query = request.GET.get("q", "").strip() level_filter = request.GET.get("level", "").strip().upper() show_all = request.GET.get("all") == "1"