feat(server-detail): cap inline console to 20 newest; modal keeps 50

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
mwiegand 2026-05-20 22:49:12 +02:00
parent 39963db2e3
commit 35dfb6dd1f
No known key found for this signature in database
3 changed files with 59 additions and 1 deletions

View file

@ -328,6 +328,7 @@ def server_detail(server_id: int):
).all() ).all()
) )
) )
console_history_overview = console_history[-20:]
connect_host = request.host.split(":")[0] connect_host = request.host.split(":")[0]
file_tree_root_entries, file_tree_truncated_count = _root_server_file_tree(server_id) file_tree_root_entries, file_tree_truncated_count = _root_server_file_tree(server_id)
@ -343,6 +344,7 @@ def server_detail(server_id: int):
else False, else False,
file_tree_truncated_count=file_tree_truncated_count, file_tree_truncated_count=file_tree_truncated_count,
console_history=console_history, console_history=console_history,
console_history_overview=console_history_overview,
**ctx, **ctx,
) )

View file

@ -63,7 +63,7 @@
<div role="tabpanel" data-tab="console" class="tab-pane" hidden> <div role="tabpanel" data-tab="console" class="tab-pane" hidden>
<div id="console-transcript-inline-{{ server.id }}" class="console-transcript" data-autoscroll> <div id="console-transcript-inline-{{ server.id }}" class="console-transcript" data-autoscroll>
{% for h in console_history %} {% for h in console_history_overview %}
{% with command=h.command, reply=h.reply, is_error=h.is_error %} {% with command=h.command, reply=h.reply, is_error=h.is_error %}
{% include "_console_line.html" %} {% include "_console_line.html" %}
{% endwith %} {% endwith %}

View file

@ -855,3 +855,59 @@ def test_server_detail_renders_state_cluster_and_inspection_strip(user_client_wi
assert 'id="files-modal"' in html assert 'id="files-modal"' in html
assert 'id="recent-players-modal"' in html assert 'id="recent-players-modal"' in html
assert 'id="job-log-modal"' in html assert 'id="job-log-modal"' in html
def test_server_detail_inline_console_caps_at_20_modal_keeps_all(user_client_with_blueprints) -> None:
"""When > 20 CommandHistory rows exist for the server, the inline
Console transcript renders only the 20 newest (chronological order),
while the modal transcript renders the full set (capped at the
route-level 50)."""
import re
from datetime import UTC, datetime, timedelta
from l4d2web.models import CommandHistory, Server
client, data = user_client_with_blueprints
with session_scope() as db:
server = Server(
user_id=data["user_id"],
blueprint_id=data["blueprint_id"],
name="console-cap",
port=27123,
rcon_password="x",
)
db.add(server)
db.flush()
sid = server.id
for i in range(35):
db.add(CommandHistory(
user_id=data["user_id"],
server_id=sid,
command=f"cmd_{i:02d}",
reply=f"reply {i}",
is_error=False,
created_at=datetime.now(UTC) - timedelta(minutes=40 - i),
))
resp = client.get(f"/servers/{sid}")
assert resp.status_code == 200
body = resp.get_data(as_text=True)
inline_match = re.search(
rf'<div id="console-transcript-inline-{sid}"[^>]*>(.*?)</div>\s*<form',
body,
re.DOTALL,
)
assert inline_match, "inline transcript container not found"
inline_lines = inline_match.group(1).count('class="console-line')
assert inline_lines == 20, f"inline expected 20, got {inline_lines}"
modal_match = re.search(
rf'<div id="console-transcript-modal-{sid}"[^>]*>(.*?)</div>\s*<form',
body,
re.DOTALL,
)
assert modal_match, "modal transcript container not found"
modal_lines = modal_match.group(1).count('class="console-line')
assert modal_lines == 35, f"modal expected 35, got {modal_lines}"