Files
flowdeck/app/templates/team_load.html
T
bruno afbc236cc2
FlowDeck CI / docker (push) Successful in 1m51s
FlowDeck CI / lint (push) Successful in 1m57s
FlowDeck CI / test (push) Successful in 15m16s
fix: navigation partielle Alpine sans course + scripts de page idempotents (v7.45.2)
- app.js : x-ignore sur .main-wrapper au swap fdLoad (nœud remplacé
  uniquement), démontage unique quand tous les <script src> ont exécuté
  (load/error + filet 4s) via Alpine.initTree idempotent (_x_marker) —
  fini les cascades « Undefined variable » (éditeur) et « reading 'has' »
  ($store.fdCtx) : la zone s'initialisait avant composants et stores.
- 5 scripts de page gardés contre la ré-exécution (SyntaxError
  « Identifier 'LW' has already been declared » à la 2e visite
  partielle) : local_workspace, board, settings, database_table,
  page_editor_realtime.
- if (window.Alpine) → Alpine.data immédiat sinon listener alpine:init
  (déjà passé sur swap) : 8 scripts + 7 templates inline.
- app.css : purge des 7 blocs @font-face Inter orphelins (fichiers
  inexistants → 302 HTML → « Failed to decode downloaded font »).
- Gates : e2e/regression_editor_mount + e2e/regression_partial_nav
  (7 pages x complet/1er/2e passage) + regression_logout_dnd + smoke
  = 6/6 verts sur l'image rebuildée · pytest 1094 passed · ruff OK ·
  OpenAPI 7.45.2.
2026-10-02 21:29:46 -04:00

57 lines
2.4 KiB
HTML

{% from '_icons.html' import fd_icon %}
<!-- Team Load — Notion-style stacked bar chart -->
<div id="view-content" x-data="teamLoad()" class="team-load">
{% for member in team_data %}
<div class="team-member">
<div class="team-count">{{ member.total }}</div>
<div class="team-bar-stack" style="height: {{ member.total * 32 }}px; min-height: 40px;">
{% if member.complete > 0 %}
<div class="team-bar-segment done"
style="height: {{ (member.complete / member.total * 100)|round }}%;"
title="Complete: {{ member.complete }}"></div>
{% endif %}
{% if member.progress > 0 %}
<div class="team-bar-segment progress"
style="height: {{ (member.progress / member.total * 100)|round }}%;"
title="In progress: {{ member.progress }}"></div>
{% endif %}
{% if member.todo > 0 %}
<div class="team-bar-segment todo"
style="height: {{ (member.todo / member.total * 100)|round }}%;"
title="To-do: {{ member.todo }}"></div>
{% endif %}
</div>
<div class="team-avatar" title="{{ member.name }}">{{ member.initial }}</div>
<div style="font-size:12px; color:var(--text-secondary); text-align:center; max-width:60px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">
{{ member.name }}
</div>
</div>
{% endfor %}
{% if not team_data %}
<div style="text-align:center; padding:48px; width:100%; color:var(--text-dim);">
<div style="margin-bottom:16px;">{{ fd_icon("users",48) }}</div>
<h3>No team data</h3>
<p style="margin-top:8px;">Assign issues to team members to see their workload.</p>
</div>
{% endif %}
</div>
<div class="status-legend" style="justify-content:center; padding: 0 24px 24px;">
<div class="legend-item"><span class="legend-dot" style="background:var(--blue);"></span> To-do</div>
<div class="legend-item"><span class="legend-dot" style="background:var(--orange);"></span> In progress</div>
<div class="legend-item"><span class="legend-dot" style="background:var(--green);"></span> Complete</div>
</div>
<script nonce="{{ csp_nonce() }}">
// A20 phase 3 : registre Alpine.data (le build CSP ne résout pas les
// globales window — probe « Undefined variable: teamLoad »).
if (window.Alpine) { Alpine.data('teamLoad', teamLoad); }
else document.addEventListener('alpine:init', function () { Alpine.data('teamLoad', teamLoad); });
function teamLoad() {
return {};
}
</script>