left4me/l4d2web/templates/base.html
mwiegand a11d030edd
feat(l4d2-web): overlay detail Files section with HTMX file tree + downloads
Adds a server-rendered collapsible file tree section to the overlay
detail page so users can verify what their script/workshop overlays
produced and pull individual artifacts (VPKs, configs) without SSH.
HTMX-driven lazy folder expansion with click-to-download via send_file;
symlinks land anywhere under LEFT4ME_ROOT (so workshop addons stream
from the shared cache) but escapes are refused. Same access rule as the
rest of the page (admin or owner). 39 new tests; full web suite green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 20:16:25 +02:00

45 lines
2 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ session.get('csrf_token', '') }}">
<title>{% block title %}left4me{% endblock %}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/tokens.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/layout.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/components.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/logs.css') }}">
</head>
<body>
<header class="site-header">
<div class="site-header-inner">
<nav class="primary-nav" aria-label="Main navigation">
<a class="brand" href="{{ '/dashboard' if g.user else '/login' }}">left4me</a>
{% if g.user %}
<a href="/servers">servers</a>
<a href="/blueprints">blueprints</a>
<a href="/overlays">overlays</a>
{% endif %}
</nav>
{% if g.user %}
<nav class="account-nav" aria-label="Account navigation">
{% if g.user.admin %}<a href="/admin">admin</a>{% endif %}
<span class="muted">{{ g.user.username }}</span>
<form method="post" action="/logout" class="inline-form">
<input type="hidden" name="csrf_token" value="{{ session.get('csrf_token', '') }}">
<button class="link-button" type="submit">logout</button>
</form>
</nav>
{% endif %}
</div>
</header>
<main class="container">
{% block content %}{% endblock %}
</main>
<script src="{{ url_for('static', filename='vendor/htmx.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/csrf.js') }}"></script>
<script src="{{ url_for('static', filename='js/sse.js') }}"></script>
<script src="{{ url_for('static', filename='js/modal.js') }}"></script>
<script src="{{ url_for('static', filename='js/file-tree.js') }}"></script>
</body>
</html>