Files
gandalf/templates/device.html
T
jaredandClaude Opus 5.5 051e70b82b
Lint / JS (eslint) (push) Successful in 10s
Lint / Python (flake8) (push) Successful in 57s
Lint / Notify on failure (push) Skipped
Lint / Deploy (push) Skipped
Security / Python Security (bandit) (push) Successful in 1m7s
Lint / Python (flake8) (pull_request) Successful in 59s
Test / Python Tests (pytest) (push) Successful in 1m22s
Lint / JS (eslint) (pull_request) Successful in 11s
Lint / Notify on failure (pull_request) Skipped
Lint / Deploy (pull_request) Skipped
Security / Python Security (bandit) (pull_request) Successful in 1m7s
Test / Python Tests (pytest) (pull_request) Successful in 1m28s
Draw realistic front panels for every device model
Replace the port blocks on device pages with SVG faceplates traced from
reference images: Dream Machine Pro, USW Pro 24 PoE, USW Aggregation,
USW Flex, USW Flex Mini, USP PDU Pro and UPS 2U Pro. Port LEDs use each
model's documented colors, and ports show a cable or module when up.

Remove SWITCH_LAYOUTS, which had wrong data: the aggregation switch was
numbered across the rows instead of odd over even, and the USW Flex had
an SFP cage it doesn't have. Models without a faceplate use plain blocks.

Show PDU and UPS outlets with on/off state and auto power-cycle, and let
the UPS page show its panel even though it reports no ports.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 11:11:48 -05:00

57 lines
2.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}{{ device_name }} – GANDALF{% endblock %}
{% block content %}
<div class="lt-page-header">
<div>
<p class="g-page-sub"><a href="{{ url_for('index') }}">← Dashboard</a></p>
<h1 class="lt-page-title device-title">
<span id="device-dot" class="dot-unknown"></span>
<span>{{ device_name }}</span>
</h1>
<p class="g-page-sub" id="device-subtitle"></p>
</div>
<div id="device-actions" class="device-actions"></div>
</div>
<div id="device-root"><div class="link-loading">Loading device</div></div>
<!-- Outside device-root: auto-refresh must not reset the filter or port panel -->
<section class="g-section" id="device-ports" hidden>
<div class="g-section-header"><h2 class="g-section-title" id="device-ports-title">Ports</h2></div>
<div class="device-inspector" id="device-inspector">
<div class="device-chassis" id="device-chassis" role="region" aria-label="Front panel"></div>
<div class="inspector-panel" id="inspector-panel" role="complementary" aria-label="Port detail panel">
<div class="inspector-panel-inner" id="inspector-panel-inner"></div>
</div>
<div class="lt-frame device-port-table">
<span class="lt-frame-bl">&#x255A;</span>
<span class="lt-frame-br">&#x255D;</span>
<div class="lt-toolbar device-toolbar">
<div class="lt-toolbar-left">
<div class="lt-search">
<input type="search" class="lt-input lt-search-input lt-search-input--sm" id="device-table-search"
placeholder="Filter…" autocomplete="off" aria-label="Filter ports">
</div>
<div class="sev-pills" role="group" aria-label="Filter by state">
<button type="button" class="pill active" data-device-filter="all" aria-pressed="true">All</button>
<button type="button" class="pill" data-device-filter="up" aria-pressed="false">Up</button>
<button type="button" class="pill" data-device-filter="problems" aria-pressed="false">Errors (<span id="device-error-count">0</span>)</button>
</div>
</div>
</div>
<div id="device-table-wrap"></div>
</div>
</div>
</section>
{% include "_modem_panel.html" %}
{% endblock %}
{% block scripts %}
<script>const DEVICE_NAME = {{ device_name | tojson }};</script>
<script src="{{ url_for('static', filename='faceplates.js') }}"></script>
<script src="{{ url_for('static', filename='port-inspector.js') }}"></script>
<script src="{{ url_for('static', filename='device.js') }}"></script>
{% endblock %}