feat(audit): surface log path + /logs link in Help popover

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) <noreply@anthropic.com>
This commit is contained in:
2026-05-19 21:26:53 +00:00
parent 7c9139f199
commit c16e2a5e29
3 changed files with 35 additions and 0 deletions

View File

@@ -1596,8 +1596,27 @@ def render_sticky_footer() -> None:
f'{_html.escape(support_email)}</a>',
)
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'<div class="dt-help-row"><span class="dt-help-key">'
f'{logs_label}:</span></div>'
f'<div class="dt-help-row dt-help-sub">'
f'<code class="dt-help-path">{_html.escape(log_path_str)}</code></div>'
f'<div class="dt-help-row">'
f'<a href="./logs" target="_self">{logs_link_text}</a></div>'
)
# 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'<div class="dt-help-title">{help_title}</div>'
f'<div class="dt-help-row">{help_version}</div>'
f'{license_html}'
f'{logs_html}'
f'<div class="dt-help-row">{help_support_html}</div>'
f'<button type="button" class="dt-help-dismiss">{help_dismiss}</button>'
)
@@ -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;

View File

@@ -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"
}
}

View File

@@ -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"
}
}