feat: Refonte UI Notion-complete — sidebar, topbar, multi-vues, dark mode
CI / test (push) Failing after 10s
CI / lint (push) Failing after 4s

- Layout 3 zones (sidebar 240px + topbar 44px + contenu)
- Sidebar: sections hiérarchiques, hover states, menu contextuel
- CSS design system Notion: #191919/#222/#333, Inter, coins 4-6px
- Vues: Kanban (groupes+colonnes), Dashboard Notion-style
- Templates: base.html refondu, card.html partial, board.html v2
- Backend: données sidebar + board Notion (groups/cards)
- Docs: ROADMAP v0.4→v1.0, WORKLOAD.md, README
- Backward compatible: conserve _issue_column pour api.py
- Images de référence + resized (analyse 2026-07-08)
This commit is contained in:
2026-07-08 14:13:41 -04:00
parent d0818f48de
commit cc680a46c2
12 changed files with 2601 additions and 1018 deletions
+70 -48
View File
@@ -1,58 +1,80 @@
{% extends "base.html" %}
{% block page_icon %}🏠{% endblock %}
{% block page_title %}Home{% endblock %}
{% block content %}
<div class="dashboard" x-data="{search: '{{ search }}', showArchived: {{ 'true' if show_archived else 'false' }}}">
<div class="dashboard-header">
<h1>Projets</h1>
<div class="dashboard-controls">
<input
type="text"
x-model="search"
placeholder="Rechercher un projet..."
class="search-input"
hx-get="/?show_archived=${showArchived}"
hx-trigger="keyup changed delay:300ms"
hx-target=".project-list"
hx-include="[name='search'], [name='show_archived']"
name="search"
autocomplete="off"
>
<label class="toggle-label">
<input type="checkbox" name="show_archived" x-model="showArchived"
hx-get="/"
hx-trigger="change"
hx-target=".project-list"
hx-include="[name='search'], [name='show_archived']">
<span>Archivés</span>
</label>
</div>
<div class="page-title-area" style="padding-top: 24px;">
<div class="page-title">
<h1>Projects</h1>
</div>
</div>
<div class="stats-bar">
<span>{{ repos|length }} projet(s)</span>
</div>
<div class="view-toolbar">
<input class="search-input" type="text" name="search" placeholder="Search projects..."
value="{{ search }}"
hx-get="/" hx-trigger="keyup changed delay:300ms" hx-target="#project-list"
hx-swap="outerHTML"
style="background:var(--bg-tertiary); border:1px solid var(--border);
color:var(--text-primary); padding:6px 12px; border-radius:6px;
font-size:14px; width:300px; outline:none;">
<div class="project-list">
{% if repos %}
{% for repo in repos %}
<a href="/board/{{ repo.owner.login }}/{{ repo.name }}" class="project-card">
<div class="project-card-header">
<span class="project-org">{{ repo.owner.login }}</span>
<span class="project-name">{{ repo.name }}</span>
{% if repo.archived %}<span class="badge archived">archivé</span>{% endif %}
{% if repo.private %}<span class="badge private">privé</span>{% endif %}
<label class="text-sm text-dim" style="display:flex;align-items:center;gap:6px;cursor:pointer;">
<input type="checkbox" hx-get="/" hx-target="#project-list" hx-swap="outerHTML"
name="show_archived" value="1"
{% if show_archived %}checked{% endif %}
hx-trigger="change" style="accent-color:var(--blue);">
Show archived
</label>
<div class="view-toolbar-spacer"></div>
<div class="text-sm text-dim">{{ repos|length }} projects</div>
</div>
<!-- Project list -->
<div id="project-list" style="padding: 0 24px;">
<div style="display:flex; flex-direction:column; gap: 4px;">
{% for repo in repos %}
<a href="/board/{{ repo.full_name }}"
class="project-card-notion"
style="display:flex; align-items:center; gap:12px; padding: 10px 12px;
border-radius: 6px; transition: background 0.15s; cursor: pointer; color: var(--text-primary); text-decoration: none;"
onmouseover="this.style.background='var(--bg-hover)'"
onmouseout="this.style.background='transparent'">
<span style="font-size:18px;">📁</span>
<div style="flex:1; min-width:0;">
<div style="font-weight:500; font-size:14px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">
{{ repo.name }}
</div>
{% if repo.description %}
<p class="project-desc">{{ repo.description[:120] }}{% if repo.description|length > 120 %}...{% endif %}</p>
<div style="font-size:12px; color: var(--text-secondary);">
{{ repo.owner.login if repo.owner else '?' }}/{{ repo.name }}
{% if repo.description %} — {{ repo.description[:60] }}{% endif %}
</div>
</div>
<div style="display:flex; align-items:center; gap:8px; flex-shrink:0;">
{% if repo.language %}
<span style="font-size:12px; color: var(--text-dim);">🟡 {{ repo.language }}</span>
{% endif %}
<div class="project-meta">
{% if repo.language %}<span class="meta-lang">{{ repo.language }}</span>{% endif %}
<span class="meta-stars">⭐ {{ repo.stars_count or 0 }}</span>
<span class="meta-updated">Mis à jour {{ repo.updated_at[:10] if repo.updated_at else '' }}</span>
</div>
</a>
{% endfor %}
{% else %}
<p class="empty">Aucun projet trouvé.</p>
{% if repo.private %}
<span style="font-size:12px; color: var(--text-dim);">🔒</span>
{% endif %}
<span style="font-size:12px; color: var(--text-dim);">→</span>
</div>
</a>
{% endfor %}
{% if not repos %}
<div style="text-align:center; padding:48px; color:var(--text-dim);">
<div style="font-size:48px; margin-bottom:16px;">📭</div>
<h3 style="color:var(--text-secondary);">Aucun projet trouvé</h3>
<p style="margin-top:8px;">
{% if search %}
Aucun résultat pour "{{ search }}".
{% else %}
Créez un repo sur <a href="https://git.dracodev.net" style="color:var(--blue);">Gitea</a>.
{% endif %}
</p>
</div>
{% endif %}
</div>
</div>