The layout was capped at 1200px and listed links in a single column. Drop the cap and lay the cards out in a grid: three per row on wide screens, two from 1000px, one below that. To make the narrower cards work, shorten the edit action to an icon button so the title and URL keep their room, and let the edit form's field and button rows wrap. Also fixes pre-existing horizontal overflow on phone widths by stacking the sidebar above the content and letting the add-link form wrap. Grid tracks use minmax(0, 1fr) so cards can shrink below their content's intrinsic width instead of pushing the page wider. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
111 lines
4.5 KiB
HTML
111 lines
4.5 KiB
HTML
{% extends "base.html" %}
|
||
{% block title %}Meine Links · LinkVault{% endblock %}
|
||
{% block body %}
|
||
<header class="topbar">
|
||
<div class="brand">Link<span>Vault</span></div>
|
||
<div class="user-info">
|
||
{% if not ai_enabled %}
|
||
<span title="Kein OPENAI_API_KEY gesetzt – Auto-Kategorisierung deaktiviert">
|
||
⚠️ KI aus
|
||
</span>
|
||
{% endif %}
|
||
<span>{{ user.email }}</span>
|
||
<form method="post" action="/logout" style="margin:0;">
|
||
<button class="ghost" type="submit">Abmelden</button>
|
||
</form>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="layout">
|
||
<aside class="sidebar">
|
||
<div class="panel">
|
||
<a href="/?sort={{ sort }}" class="facet {% if not active_category and not active_manufacturer %}active{% endif %}">
|
||
<span>📚 Alle Links</span>
|
||
</a>
|
||
|
||
<div class="facet-group">
|
||
<h3>Kategorien</h3>
|
||
{% for name, count in facets.categories %}
|
||
<a href="/?category={{ name | urlencode }}&sort={{ sort }}"
|
||
class="facet {% if active_category == name %}active{% endif %}">
|
||
<span>{{ name }}</span><span class="count">{{ count }}</span>
|
||
</a>
|
||
{% else %}
|
||
<div class="muted" style="font-size:.85rem; padding:4px 8px;">noch keine</div>
|
||
{% endfor %}
|
||
</div>
|
||
|
||
<div class="facet-group">
|
||
<h3>Hersteller / Quellen</h3>
|
||
{% for name, count in facets.manufacturers %}
|
||
<a href="/?manufacturer={{ name | urlencode }}&sort={{ sort }}"
|
||
class="facet {% if active_manufacturer == name %}active{% endif %}">
|
||
<span>{{ name }}</span><span class="count">{{ count }}</span>
|
||
</a>
|
||
{% else %}
|
||
<div class="muted" style="font-size:.85rem; padding:4px 8px;">noch keine</div>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
|
||
<main class="main">
|
||
<div class="panel">
|
||
<form hx-post="/links" hx-target="#links" hx-swap="afterbegin"
|
||
hx-disabled-elt="button"
|
||
hx-on::after-request="if(event.detail.successful){this.reset(); var e=document.getElementById('empty-state'); if(e) e.remove();}">
|
||
<div style="display:flex; gap:8px; flex-wrap:wrap;">
|
||
<input type="url" name="url" placeholder="Link einfügen, z.B. https://hersteller.de/produkt" required
|
||
style="flex:1 1 220px; width:auto;">
|
||
<button type="submit" style="white-space:nowrap;">
|
||
<span class="htmx-indicator">⏳</span> Hinzufügen
|
||
</button>
|
||
</div>
|
||
<div class="muted" style="font-size:.8rem; margin-top:6px;">
|
||
Der Link wird automatisch geladen, zusammengefasst und einsortiert.
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<div class="panel">
|
||
<form id="searchform" onsubmit="return false;" style="margin:0;">
|
||
<input type="hidden" name="category" value="{{ active_category }}">
|
||
<input type="hidden" name="manufacturer" value="{{ active_manufacturer }}">
|
||
<input type="text" name="q" value="{{ q }}"
|
||
placeholder="🔍 Suche in Titel, Zusammenfassung, Tags..."
|
||
hx-get="/search" hx-target="#links" hx-swap="innerHTML"
|
||
hx-trigger="keyup changed delay:400ms, search"
|
||
hx-include="#searchform">
|
||
<div style="display:flex; justify-content:space-between; align-items:center; gap:12px; margin-top:10px; flex-wrap:wrap;">
|
||
{% if ai_enabled %}
|
||
<label class="muted" style="display:inline-flex; align-items:center; gap:6px; font-size:.85rem;">
|
||
<input type="checkbox" name="semantic" value="1" {% if semantic %}checked{% endif %}
|
||
hx-get="/search" hx-target="#links" hx-swap="innerHTML"
|
||
hx-trigger="change" hx-include="#searchform" style="width:auto;">
|
||
KI-Suche (findet auch sinnverwandte Treffer)
|
||
</label>
|
||
{% else %}
|
||
<span></span>
|
||
{% endif %}
|
||
|
||
<label class="muted" style="display:inline-flex; align-items:center; gap:6px; font-size:.85rem;">
|
||
Sortierung:
|
||
<select name="sort"
|
||
hx-get="/search" hx-target="#links" hx-swap="innerHTML"
|
||
hx-trigger="change" hx-include="#searchform">
|
||
{% for value, label in sort_options.items() %}
|
||
<option value="{{ value }}" {% if sort == value %}selected{% endif %}>{{ label }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
</label>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<div id="links">
|
||
{% include "_links_list.html" %}
|
||
</div>
|
||
</main>
|
||
</div>
|
||
{% endblock %}
|