CI / test (push) Successful in 2m26s
- Barre de filtres en carte : recherche texte (titre, projet, #numéro, étiquettes ; accents/casse ignorés, raccourci /), listes Projet et Étiquette avec compteurs, chips de colonnes colorées multi-sélection, 4 tris. - Facettes calculées côté serveur ; filtrage instantané côté client (attributs data-*), compteur en direct, compteurs de section, état vide + réinitialisation. - Filtres structurels persistés en localStorage. - 281 tests verts (3 nouveaux, palier 22) ; vérifié en Chromium réel sur les vraies données (467 issues : recherche 'agent' -> 24 résultats instantanés).
106 lines
5.6 KiB
HTML
106 lines
5.6 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="fr" data-theme="dark">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Mes issues — Kanbante</title>
|
|
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>👤</text></svg>">
|
|
<link rel="stylesheet" href="/static/css/style.css?v={{ version }}">
|
|
</head>
|
|
<body>
|
|
{% include "_header.html" %}
|
|
|
|
<main class="focus-main">
|
|
{% if not user %}
|
|
<div class="empty-state">🔑 Aucun utilisateur Gitea résolu : définissez <code>GITEA_TOKEN</code> pour voir les issues qui vous sont assignées.</div>
|
|
{% else %}
|
|
<p class="focus-intro">Issues ouvertes assignées à <strong>{{ user.login }}</strong>, tous projets confondus — {{ total }} au total.</p>
|
|
|
|
{% if groups %}
|
|
<div class="my-filters" id="my-filters">
|
|
<div class="my-filters-row">
|
|
<div class="my-search-wrap">
|
|
<span class="my-search-icon" aria-hidden="true">🔍</span>
|
|
<input type="search" id="my-search" autocomplete="off"
|
|
placeholder="Rechercher un titre, un projet, un #numéro, une étiquette… ( / )">
|
|
</div>
|
|
<select id="my-repo" title="Filtrer par projet">
|
|
<option value="">Tous les projets</option>
|
|
{% for f in repo_facets %}
|
|
<option value="{{ f.full_name }}">{{ f.full_name }} ({{ f.count }})</option>
|
|
{% endfor %}
|
|
</select>
|
|
<select id="my-label" title="Filtrer par étiquette">
|
|
<option value="">Toutes les étiquettes</option>
|
|
{% for f in label_facets %}
|
|
<option value="{{ f.name }}">{{ f.name }} ({{ f.count }})</option>
|
|
{% endfor %}
|
|
</select>
|
|
<select id="my-sort" title="Trier les résultats">
|
|
<option value="recent">Activité récente d'abord</option>
|
|
<option value="oldest">Plus anciennes d'abord</option>
|
|
<option value="title">Titre (A → Z)</option>
|
|
<option value="repo">Projet (A → Z)</option>
|
|
</select>
|
|
</div>
|
|
<div class="my-filters-row my-filters-meta">
|
|
<div class="my-col-chips" id="my-col-chips" role="group" aria-label="Filtrer par colonne">
|
|
<button type="button" class="filter-chip on" data-col="">Toutes les colonnes</button>
|
|
{% for f in column_facets %}
|
|
<button type="button" class="filter-chip" data-col="{{ f.key }}" aria-pressed="false">
|
|
<span class="filter-chip-dot" style="background: {{ column_colors[f.key] }}"></span>{{ column_labels[f.key] }} <span class="filter-chip-count">{{ f.count }}</span>
|
|
</button>
|
|
{% endfor %}
|
|
</div>
|
|
<span class="my-count" id="my-count" role="status"></span>
|
|
<button type="button" id="my-reset" class="btn-sm" hidden>↺ Réinitialiser les filtres</button>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="empty-state" id="my-empty" hidden>🔍 Aucune issue ne correspond à ces filtres.
|
|
<button type="button" id="my-empty-reset" class="btn-sm">↺ Réinitialiser les filtres</button>
|
|
</div>
|
|
{% if not groups %}
|
|
<div class="empty-state">🎉 Aucune issue ne vous est assignée pour le moment.</div>
|
|
{% endif %}
|
|
{% for group in groups %}
|
|
<section class="focus-group" data-repo="{{ group.full_name }}">
|
|
<h2><a href="/board/{{ group.full_name }}">{{ group.full_name }}</a>
|
|
<span class="badge secondary" data-group-count>{{ group.rows|length }}</span></h2>
|
|
<div class="issue-results">
|
|
{% for row in group.rows %}
|
|
{% set issue = row.issue %}
|
|
<div class="issue-row"
|
|
data-column="{{ row.column }}"
|
|
data-labels="{{ (issue.labels or [])|map(attribute='name')|join(' ') }}"
|
|
data-updated="{{ issue.updated_at or '' }}"
|
|
data-title="{{ issue.title }}"
|
|
data-search="#{{ issue.number }} {{ issue.title }} {{ group.full_name }} {{ (issue.labels or [])|map(attribute='name')|join(' ') }}">
|
|
<span class="issue-state">🟢</span>
|
|
<a class="issue-main" href="/board/{{ group.full_name }}">
|
|
<span class="card-id">#{{ issue.number }}</span> {{ issue.title }}
|
|
</a>
|
|
<span class="col-chip" style="background: {{ column_colors[row.column] }}20; color: {{ column_colors[row.column] }}">{{ column_labels[row.column] }}</span>
|
|
{% for label in issue.labels or [] %}
|
|
<span class="label-tag" style="background: #{{ label.color }}30; color: #{{ label.color }}">{{ label.name }}</span>
|
|
{% endfor %}
|
|
<span class="activity-date">{{ (issue.updated_at or '')[:10] }}</span>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</section>
|
|
{% endfor %}
|
|
{% endif %}
|
|
</main>
|
|
|
|
<footer>
|
|
Kanbante v{{ version }} · mes issues
|
|
</footer>
|
|
<script src="/static/js/my.js?v={{ version }}" defer></script>
|
|
<script src="/static/js/live.js" defer></script>
|
|
{% include "_palette.html" %}
|
|
<script src="/static/js/palette.js" defer></script>
|
|
</body>
|
|
</html>
|