feat(live-state): link player cards to their Steam profile

Wraps avatar + persona name in an a[href=steamcommunity.com/profiles/<id>]
in both the Current and Recent blocks. Steam auto-redirects to the user's
vanity URL on follow, so we don't need to store profileurl separately.

target=_blank + rel=noopener noreferrer to keep the dashboard page in
place when a link is followed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mwiegand 2026-05-12 22:51:50 +02:00
parent 674c4df360
commit 6cbe7dc9f2
No known key found for this signature in database
2 changed files with 23 additions and 12 deletions

View file

@ -21,12 +21,16 @@
<ul class="player-grid"> <ul class="player-grid">
{% for session, profile in current_players %} {% for session, profile in current_players %}
<li class="player-card"> <li class="player-card">
<a class="player-link"
href="https://steamcommunity.com/profiles/{{ session.steam_id_64 }}"
target="_blank" rel="noopener noreferrer">
{% if profile and profile.avatar_url %} {% if profile and profile.avatar_url %}
<img class="avatar" src="{{ profile.avatar_url }}" alt="" loading="lazy"> <img class="avatar" src="{{ profile.avatar_url }}" alt="" loading="lazy">
{% else %} {% else %}
<span class="avatar placeholder" aria-hidden="true"></span> <span class="avatar placeholder" aria-hidden="true"></span>
{% endif %} {% endif %}
<span class="name">{{ (profile and profile.persona_name) or session.name_at_join }}</span> <span class="name">{{ (profile and profile.persona_name) or session.name_at_join }}</span>
</a>
<span class="meta"> <span class="meta">
joined {{ ((now - session.joined_at).total_seconds() // 60) | int }}m ago joined {{ ((now - session.joined_at).total_seconds() // 60) | int }}m ago
· ping {{ session.min_ping }}-{{ session.max_ping }}ms · ping {{ session.min_ping }}-{{ session.max_ping }}ms
@ -41,12 +45,16 @@
<ul class="player-grid recent"> <ul class="player-grid recent">
{% for row in recent_players %} {% for row in recent_players %}
<li class="player-card"> <li class="player-card">
<a class="player-link"
href="https://steamcommunity.com/profiles/{{ row.steam_id_64 }}"
target="_blank" rel="noopener noreferrer">
{% if row.avatar_url %} {% if row.avatar_url %}
<img class="avatar" src="{{ row.avatar_url }}" alt="" loading="lazy"> <img class="avatar" src="{{ row.avatar_url }}" alt="" loading="lazy">
{% else %} {% else %}
<span class="avatar placeholder" aria-hidden="true"></span> <span class="avatar placeholder" aria-hidden="true"></span>
{% endif %} {% endif %}
<span class="name">{{ row.persona_name or row.name_at_join }}</span> <span class="name">{{ row.persona_name or row.name_at_join }}</span>
</a>
<span class="meta"> <span class="meta">
last seen {{ ((now - row.last_seen).total_seconds() // 60) | int }}m ago last seen {{ ((now - row.last_seen).total_seconds() // 60) | int }}m ago
</span> </span>

View file

@ -566,6 +566,9 @@ def test_live_state_fragment_renders_current_and_recent(user_client_with_bluepri
# Recent block — only OldPlayer, not MrCool42 # Recent block — only OldPlayer, not MrCool42
assert "OldPersona" in html assert "OldPersona" in html
assert "old_medium.jpg" in html assert "old_medium.jpg" in html
# Steam profile links — one for the current player, one for the recent.
assert "steamcommunity.com/profiles/76561197960828710" in html
assert "steamcommunity.com/profiles/76561198021234567" in html
def test_reset_operation_enqueues_job_and_stops_desired_state(user_client_with_blueprints) -> None: def test_reset_operation_enqueues_job_and_stops_desired_state(user_client_with_blueprints) -> None: