Files
gandalf/templates/rack.html
T
jaredandClaude Opus 5.5 a9de175d90
Lint / JS (eslint) (push) Successful in 8s
Lint / Python (flake8) (push) Successful in 1m0s
Lint / Notify on failure (push) Skipped
Lint / Deploy (push) Skipped
Security / Python Security (bandit) (push) Successful in 1m9s
Lint / Python (flake8) (pull_request) Successful in 57s
Test / Python Tests (pytest) (push) Successful in 1m14s
Lint / JS (eslint) (pull_request) Successful in 8s
Lint / Notify on failure (pull_request) Skipped
Lint / Deploy (pull_request) Skipped
Security / Python Security (bandit) (pull_request) Successful in 56s
Test / Python Tests (pytest) (pull_request) Successful in 1m5s
Rack: ports-facing separate from posts, three views, ZimaBoard 832 shelves to scale
Gear on the rear posts usually still faces the front (the StarTech's RPDU
and ZimaBoard shelf), so "which posts" and "which way the ports face" are
now separate fields (mount, facing). The page has three views: Front (front
posts), Rear posts (rear-post gear seen from the front, i.e. what is behind
the front gear) and Rear (from behind). An item seen from the side it
doesn't face shows its back. Facing defaults to front, so existing items
keep their meaning.

Shelves are drawn at true scale with their contents ordered by a new
"Position on shelf". The IceWhale ZimaBoard 832 is traced from IceWhale's
labelled photo of its port end (ZimaDocs): Mini-DP, two RJ45-over-USB 3.0
stacks with link/activity LEDs, DC jack, gunmetal case, gold PCB edge and
black base. Its RJ45 link lights follow the host's physical NICs and the
status glow follows the host.

New cutsheet_items columns facing and slot, added on first use.

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

94 lines
4.7 KiB
HTML

{% extends "base.html" %}
{% block title %}Rack{% endblock %}
{% block content %}
<div class="lt-page-header">
<div>
<h1 class="lt-page-title">Rack</h1>
<p class="g-page-sub">The rack front, drawn from the rack units on the cutsheet with live port state. Hover a port to light up every port on the same cable run; click it to open the port or the cable.</p>
</div>
<div class="cs-actions no-print">
<button type="button" class="lt-btn lt-btn-secondary lt-btn-sm" data-export="svg">Download SVG</button>
<button type="button" class="lt-btn lt-btn-secondary lt-btn-sm" data-export="png">Download PNG</button>
{% if can_edit %}
<button type="button" class="lt-btn lt-btn-secondary lt-btn-sm" data-action="rack-settings">Rack settings</button>
<button type="button" class="lt-btn lt-btn-secondary lt-btn-sm" data-action="add-rack">+ Rack</button>
<a class="lt-btn lt-btn-secondary lt-btn-sm" href="/cutsheet#cs-items-section">Edit positions</a>
{% endif %}
</div>
</div>
<div class="rack-bar">
<div class="rack-tabs" id="rack-tabs" role="tablist" aria-label="Racks" hidden></div>
<div class="rack-face" role="group" aria-label="Rack side">
<button type="button" class="rack-face-btn active" data-face="front" aria-pressed="true"
title="The front posts, seen from the front">Front</button>
<button type="button" class="rack-face-btn" data-face="behind" aria-pressed="false"
title="Gear on the rear posts, seen from the front (what is behind the front gear)">Rear posts</button>
<button type="button" class="rack-face-btn" data-face="rear" aria-pressed="false"
title="The rack seen from behind">Rear</button>
</div>
</div>
<div class="rack-warnings" id="rack-warnings" role="alert" hidden></div>
<section class="g-section">
<div class="g-section-header">
<h2 class="g-section-title" id="rack-title">Front</h2>
<span class="g-section-badge" id="rack-count">0</span>
</div>
<p class="rack-readout" id="rack-readout" aria-live="polite"></p>
<div class="rack-legend" aria-hidden="true">
<span><i class="rack-key rack-key-ok"></i>matches cutsheet</span>
<span><i class="rack-key rack-key-bad"></i>mismatch</span>
<span><i class="rack-key rack-key-doc"></i>documented, unconfirmed</span>
<label class="rack-toggle"><input type="checkbox" id="rack-show-empty"> Show empty units</label>
</div>
<div class="rack" id="rack"><div class="link-loading">Loading rack</div></div>
<p class="cs-hint rack-unplaced" id="rack-unplaced"></p>
</section>
{% if can_edit %}
<div id="rack-modal" class="lt-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="rack-modal-title" aria-hidden="true">
<div class="lt-modal">
<div class="lt-modal-header">
<h3 class="lt-modal-title" id="rack-modal-title">Rack settings</h3>
<button type="button" class="lt-modal-close" data-modal-close aria-label="Close">&#x2715;</button>
</div>
<form id="rack-form" autocomplete="off">
<div class="lt-modal-body">
<input type="hidden" name="id">
<input type="hidden" name="previous">
<div class="form-row">
<div class="lt-form-group">
<label class="lt-label" for="rack-name">Name <span class="required">*</span></label>
<input class="lt-input" id="rack-name" name="name" required maxlength="100" placeholder="e.g. StarTech 25U">
</div>
<div class="lt-form-group">
<label class="lt-label" for="rack-units">Height (U) <span class="required">*</span></label>
<input class="lt-input" id="rack-units" name="units" type="number" min="1" max="60" required>
</div>
</div>
<div class="lt-form-group">
<label class="lt-label" for="rack-notes">Notes</label>
<textarea class="lt-input" id="rack-notes" name="notes" rows="2" maxlength="2000" placeholder="model, location, depth"></textarea>
</div>
<p class="cs-hint">Renaming a rack moves its items with it. A rack can be deleted once it is empty.</p>
</div>
<div class="lt-modal-footer">
<button type="button" class="lt-btn lt-btn-danger" data-action="delete-rack">Delete</button>
<button type="button" class="lt-btn lt-btn-secondary" data-modal-close>Cancel</button>
<button type="submit" class="lt-btn lt-btn-primary">Save</button>
</div>
</form>
</div>
</div>
{% endif %}
{% endblock %}
{% block scripts %}
<script>const RACK_CAN_EDIT = {{ 'true' if can_edit else 'false' }};</script>
<script src="{{ url_for('static', filename='faceplates.js') }}"></script>
<script src="{{ url_for('static', filename='fronts.js') }}"></script>
<script src="{{ url_for('static', filename='rack.js') }}"></script>
{% endblock %}