gabriel / musehub public
session_rows.html html
144 lines 5.6 KB
Raw
sha256:0997d6250ae6476362f6fe2025af7789f46d03df3e9f34356d5e8ee79b201923 fix(issues): use issue number as pagination cursor, not cre… Sonnet 4.6 patch 8 days ago
1 {# fragments/session_rows.html — HTMX fragment: supercharged session cards.
2 Context:
3 sessions : list[dict] — cursor-paginated sessions (camelCase keys)
4 total : int
5 next_cursor: str | None — pass as ?cursor= to load next page; None on last page
6 base_url : str
7 #}
8 {% from "musehub/macros/pagination.html" import cursor_pagination %}
9 {% from "musehub/macros/empty_state.html" import empty_state %}
10
11 {# ── Helpers ──────────────────────────────────────────────────────────────── #}
12 {% macro pcolor(name) -%}
13 {%- set colors = ["#58a6ff","#3fb950","#a371f7","#fb8500","#2dd4bf","#d29922","#f85149","#e879f9"] -%}
14 {{ colors[(name|length) % (colors|length)] }}
15 {%- endmacro %}
16
17 {# Human-readable duration from seconds #}
18 {% macro fmt_duration(sec) -%}
19 {%- if sec is none or sec == 0 -%}—
20 {%- elif sec < 60 -%}< 1m
21 {%- elif sec < 3600 -%}{{ (sec / 60) | int }}m
22 {%- else -%}{{ (sec / 3600) | int }}h {{ ((sec % 3600) / 60) | int }}m
23 {%- endif -%}
24 {%- endmacro %}
25
26 {% if sessions %}
27 <div class="sess-card-list">
28 {% for s in sessions %}
29 {% set is_live = s.isActive %}
30 {% set dur = s.durationSeconds %}
31 {% set n_commits = s.commits | length %}
32
33 {# Age-based card colour: live=green, < 14d=blue, older=gray #}
34 {% if is_live %}
35 {% set card_cls = "sess-card-live" %}
36 {% elif s.startedAt and (s.startedAt | fmtrelative).endswith("d ago") and (s.startedAt | fmtrelative).split("d ago")[0].split(" ")[-1] | int < 15 %}
37 {% set card_cls = "sess-card-recent" %}
38 {% else %}
39 {% set card_cls = "sess-card-older" %}
40 {% endif %}
41
42 <div class="sess-card {{ card_cls }}"
43 data-status="{% if is_live %}live{% else %}ended{% endif %}"
44 data-intent="{{ s.intent | lower }}"
45 data-location="{{ s.location | lower }}"
46 id="session-{{ s.sessionId }}">
47
48 {# ── Left: status + duration ────────────────────────────────────────── #}
49 <div class="sess-card-left">
50 {% if is_live %}
51 <span class="sess-status-pill sess-pill-live">
52 <span class="session-live-dot" style="width:6px;height:6px"></span>
53 Live
54 </span>
55 <div class="sess-duration">∞</div>
56 <div class="sess-duration-label">ongoing</div>
57 {% else %}
58 <span class="sess-status-pill sess-pill-ended">Ended</span>
59 <div class="sess-duration">{{ fmt_duration(dur) }}</div>
60 <div class="sess-duration-label">duration</div>
61 {% endif %}
62 {% if n_commits > 0 %}
63 <span class="sess-commit-chip" style="margin-top:4px">
64 {{ icon("commit", 9) }}
65 {{ n_commits }}
66 </span>
67 {% endif %}
68 </div>
69
70 {# ── Body ───────────────────────────────────────────────────────────── #}
71 <div class="sess-card-body">
72 {# Title row: ID + seq label #}
73 <div class="sess-card-title-row">
74 <a href="{{ base_url }}/sessions/{{ s.sessionId }}" class="sess-id-link">
75 {{ s.sessionId | short_id }}
76 </a>
77 <span style="font-size:10px;color:var(--text-muted)">
78 {{ s.startedAt | fmtrelative }}
79 {% if s.endedAt %} · ended {{ s.endedAt | fmtrelative }}{% endif %}
80 </span>
81 </div>
82
83 {# Intent / goal #}
84 {% if s.intent %}
85 <div class="sess-intent">{{ s.intent }}</div>
86 {% endif %}
87
88 {# Notes preview #}
89 {% if s.notes %}
90 <div class="sess-notes-preview">{{ s.notes }}</div>
91 {% endif %}
92
93 {# Location + commit count meta #}
94 <div class="sess-meta-row">
95 {% if s.location %}
96 <span class="sess-location">
97 {{ icon("map-pin", 10) }}
98 {{ s.location }}
99 </span>
100 {% endif %}
101 {% if n_commits > 0 %}
102 <span>
103 {{ icon("commit", 10) }}
104 {{ n_commits }} commit{{ 's' if n_commits != 1 else '' }}
105 </span>
106 {% endif %}
107 </div>
108
109 {# Participants #}
110 {% if s.participants %}
111 <div class="sess-participants-row">
112 {% for p in s.participants %}
113 <a href="/{{ p | urlencode }}" class="sess-participant">
114 <span class="sess-participant-dot" style="background:{{ pcolor(p) }}">{{ p[0] | upper }}</span>
115 {{ p }}
116 </a>
117 {% endfor %}
118 </div>
119 {% endif %}
120 </div>
121
122 {# ── Right: actions ─────────────────────────────────────────────────── #}
123 <div class="sess-card-right">
124 <a href="{{ base_url }}/sessions/{{ s.sessionId }}" class="btn btn-secondary btn-sm">
125 {% if is_live %}Join{% else %}View{% endif %}
126 </a>
127 {% if not is_live and n_commits > 0 %}
128 <a href="{{ base_url }}/commits?session={{ s.sessionId }}" class="btn btn-secondary btn-sm">
129 Commits
130 </a>
131 {% endif %}
132 </div>
133 </div>
134 {% endfor %}
135 </div>
136 {{ cursor_pagination(next_cursor, base_url ~ '/sessions') }}
137
138 {% else %}
139 {{ empty_state(
140 title="No sessions yet",
141 desc="Start a collaboration session in Muse to capture collaborative changes and track contributions over time.",
142 icon_name="commit",
143 ) }}
144 {% endif %}
File History 1 commit
sha256:0997d6250ae6476362f6fe2025af7789f46d03df3e9f34356d5e8ee79b201923 fix(issues): use issue number as pagination cursor, not cre… Sonnet 4.6 patch 8 days ago