From c16e2a5e29bd158e5d83ec8e3e8184f4f181c75f Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 19 May 2026 21:26:53 +0000 Subject: [PATCH] feat(audit): surface log path + /logs link in Help popover MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a "Log file" section to the sticky-footer Help popover with two affordances: 1. The current audit-log path rendered as monospace text with ``user-select: all`` so a single click selects the whole path for copy-paste into a file manager. Works on every platform — no subprocess required. 2. A "View all logs →" link to the new ``/logs`` page (added in the previous commit) for download/inspection of today's and prior days' files. i18n keys ``footer.help_logs_label`` + ``footer.help_logs_link`` added to en + es packs, matching the existing ``footer.help_*`` naming. ``audit_log_path()`` is wrapped in try/except because a broken audit module MUST NOT take the footer down — falls back to "—". Same defensive pattern the license section uses. Rollback: ``git revert HEAD`` removes the section; the popover and its layout return to the prior shape with zero coupling to the audit module. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/gui/components/_legacy.py | 31 +++++++++++++++++++++++++++++++ src/i18n/packs/en.json | 2 ++ src/i18n/packs/es.json | 2 ++ 3 files changed, 35 insertions(+) diff --git a/src/gui/components/_legacy.py b/src/gui/components/_legacy.py index ec65670..5719be8 100644 --- a/src/gui/components/_legacy.py +++ b/src/gui/components/_legacy.py @@ -1596,8 +1596,27 @@ def render_sticky_footer() -> None: f'{_html.escape(support_email)}', ) license_label = _html.escape(_t("footer.help_license_label")) + logs_label = _html.escape(_t("footer.help_logs_label")) + logs_link_text = _html.escape(_t("footer.help_logs_link")) help_dismiss = _html.escape(_t("footer.help_dismiss")) + # Logs section — surface today's audit log path as copyable text + # plus a link to the /logs page. Wrapped because a broken audit + # log MUST NOT stop the footer from rendering; fall back to "—". + try: + from src.audit import audit_log_path + log_path_str = str(audit_log_path()) + except Exception: + log_path_str = "—" + logs_html = ( + f'
' + f'{logs_label}:
' + f'
' + f'{_html.escape(log_path_str)}
' + f'' + ) + # License section — read state and branch on activated/valid. The # query is wrapped because a corrupted license file MUST NOT stop # the footer from rendering; in that case we fall back to the @@ -1639,6 +1658,7 @@ def render_sticky_footer() -> None: f'
{help_title}
' f'
{help_version}
' f'{license_html}' + f'{logs_html}' f'
{help_support_html}
' f'' ) @@ -1766,6 +1786,17 @@ def render_sticky_footer() -> None: color: rgb(90, 95, 110) !important; font-weight: 500 !important; } +#datatools-help-popover .dt-help-path { + display: block !important; + font-family: var(--font-mono, ui-monospace, Menlo, Consolas, monospace) !important; + font-size: 11px !important; + color: rgb(38, 39, 48) !important; + background: rgba(0, 0, 0, 0.04) !important; + padding: 2px 6px !important; + border-radius: 3px !important; + word-break: break-all !important; + user-select: all !important; +} #datatools-help-popover .dt-help-row a { color: rgb(0, 102, 204) !important; text-decoration: none !important; diff --git a/src/i18n/packs/en.json b/src/i18n/packs/en.json index ace964e..762ec86 100644 --- a/src/i18n/packs/en.json +++ b/src/i18n/packs/en.json @@ -185,6 +185,8 @@ "help_license_expires": "Expires {date} ({days} days)", "help_activate_link": "Activate now →", "help_manage_link": "Manage license →", + "help_logs_label": "Log file", + "help_logs_link": "View all logs →", "help_dismiss": "Close" } } diff --git a/src/i18n/packs/es.json b/src/i18n/packs/es.json index 16b9b29..768e966 100644 --- a/src/i18n/packs/es.json +++ b/src/i18n/packs/es.json @@ -185,6 +185,8 @@ "help_license_expires": "Caduca {date} ({days} días)", "help_activate_link": "Activar ahora →", "help_manage_link": "Gestionar licencia →", + "help_logs_label": "Archivo de registro", + "help_logs_link": "Ver todos los registros →", "help_dismiss": "Cerrar" } }