{% extends 'netbox_rack_design/design_editor.html' %} {% load i18n %} {% load rack_design %} {# ------------------------------------------------------------------------- #} {# The BLADE LAYER (spec §10.3). #} {# #} {# Deliberately EXTENDS the rack editor rather than forking it: the drawer, #} {# the legend/role/tenant toolbar and Save are identical, because a chassis #} {# IS a rack here -- bays in place of units. Only three things differ, and #} {# each is an override block on the parent template: #} {# #} {# rd_canvas chassis columns instead of rack blocks #} {# rd_scope_panel a Chassis panel instead of the Racks panel #} {# rd_layer_switch a way back to the rack view #} {# #} {# The palette itself is filtered to child device types by editor.js, which #} {# reads data-rd-blade-layer on the root -- so a non-child type can never be #} {# offered as a blade in the first place. #} {# ------------------------------------------------------------------------- #} {# The drawer's third section holds chassis here, not racks. #} {% block rd_scope_section_label %}{% trans "Chassis" %}{% endblock %} {% block rd_layer_switch %} {# Not labelled "Racks": the drawer already has a Racks/Chassis section toggle #} {# and two identical labels in one button row is unreadable. #} {% trans "Rack view" %} {% endblock rd_layer_switch %} {% block rd_scope_panel %}

{% trans "Chassis" %}

{# Same show/hide contract as the Racks panel: HIDDEN state is stored, so a #} {# chassis with no row is visible. Toggling never touches the design. #}
{% for row in chassis_rows %}
{{ row.label }}
{{ row.rack }} · {{ row.used }}/{{ row.bay_count }} {% trans "bays used" %} {% if not row.device %}· {% trans "planned" %}{% endif %}
{# A PLANNED chassis has no device row, so there is nothing to persist a #} {# hidden state against -- and hiding what you just added would be #} {# unhelpful anyway. It is always visible. #} {% if row.device %} {% endif %}
{% empty %}
{% trans "No chassis in this design's scope." %}
{% endfor %}
{% endblock rd_scope_panel %} {% block rd_canvas %}
{% for col in chassis_columns %} {# ------------------------------------------------------------------------ #} {# A chassis column is a DEGENERATE RACK, deliberately satisfying the exact #} {# DOM contract initRack() already consumes, so the editor drives it with NO #} {# changes at all (spec §10.3: a chassis IS a rack). #} {# #} {# .nbx-rd-rack-block + data-rack-id -> a synthetic per-column id #} {# data-u-height = bay count (one grid row per bay) #} {# data-desc-units="true" so gsYToUPosition() returns gsY+1 -- i.e. the #} {# 1-based BAY INDEX -- with no arithmetic of its own #} {# one data-face="front" grid; no rear, no tray (a chassis has neither) #} {# #rd-editor-data- the widget JSON, same shape as a rack's #} {# #} {# The rack-only machinery (full-depth shadows, opposite-face hatches, the #} {# tray) never fires here: no blade is full-depth and there is no second #} {# face for a shadow to land on. data-real-rack-id / data-chassis-* carry #} {# what buildLayoutPayload needs to translate this column's items into the #} {# `bays` bucket the save contract expects (§10.6). #} {# ------------------------------------------------------------------------ #}
{# Two short lines rather than one long one: the header must never be what #} {# decides the column's width. Rack and type live in the tooltip. #}
{% if col.device %}{{ col.label }} {% else %}{{ col.label }} {% trans "planned" %}{% endif %}
{{ col.used }}/{{ col.bay_count }} {% trans "used" %} · {{ col.rack }}
{% for slot in col.slots %}{% if slot.label %}
{% if editable_layer %}{% endif %} {{ slot.label }}
{% endif %}{% endfor %}
{% if editable_layer %}{% with eid="rd-editor-data-"|add:col.grid_id_str %}{{ col.widgets|json_script:eid }}{% endwith %}{% endif %} {% empty %}

{% trans "No chassis in this design's scope — add a parent device in the rack view first." %}

{% endfor %}
{% endblock rd_canvas %}