{% extends 'generic/object.html' %} {% load helpers %} {% block content %}

Auto-cabling

{% comment %} object-level perms: the two PORT rows come from the view already scoped to the requesting user (see views._scoped) — never straight off `object`, which the plugin permission alone would hand out for every job of the install. The two RACK rows do come straight off `object`: a rack name is an inventory label, and the Path row below lists rack names for everyone. {% endcomment %}
Source port {{ source_port|linkify|placeholder }} {% if trace_source %}Trace{% endif %}
Destination port {{ target_port|linkify|placeholder }} {% if trace_target %}Trace{% endif %}
Source rack {{ object.source_rack|linkify|placeholder }}
Target rack {{ object.target_rack|linkify|placeholder }}
Media {{ object.media }}
Status {% badge object.get_status_display bg_color=object.get_status_color %}
Path {% if object.path %}{{ object.path|join:" → " }}{% else %}—{% endif %}
Detail {{ object.reason|placeholder }}
Requested by {{ object.requested_by|placeholder }}

Cables created by this job {% comment %} object-level perms: `cable_count` counts only what THIS viewer may see (plus the ids that match no cable at all, which the warning row below accounts for). The raw `object.created_cable_ids|length` told a restricted viewer how many cables the job holds beyond the rows it is shown. Same rule as the REST payload. It stays a count of the TRACE — the header says "created by this job", which a rolled-back job did create — so it is not restated per case: the invariant cable_count == rows shown + missing is what lets the row at the bottom of the table explain the whole gap, and a badge narrowed to the surviving rows would leave that row explaining a difference no longer visible anywhere on the page. {% endcomment %} {{ cable_count }} {% if object.created_cable_ids %} ⬇ Work order (Excel) {% endif %} {% if object.created_cable_ids and object.status != 'rolled_back' %} {% comment %} the confirmation says what the button DESTROYS, so it is built from `deletable_count` (restrict(user, "delete") — the very queryset rollback deletes), never from the view-scoped badge above: delete and view are independent object permissions, and an operator granted delete without view was confirming "Delete the 0 cable(s)…" and destroying every one of them. {% endcomment %}
{% csrf_token %}
{% if deletable_count != cable_count %} {% comment %} the two numbers answer different questions; when they disagree the destructive one is spelled out on the page, so the modal is never a surprise. A count, not an identity: no row of a cable this viewer may not view is added anywhere. {% endcomment %} Rollback will delete {{ deletable_count }} cable(s). {% endif %} {% endif %}

{% for cable in cables %} {% empty %} {% endfor %} {% if missing_cables > 0 %} {% comment %} only ids matching NO cable row reach here: "no longer exist" is a statement about the database, so a cable the viewer merely may not see must never land in it. WHY they are gone is `missing_state` (views + visibility.missing_cable_state): a rollback run through the plugin deletes the cables and KEEPS the trace, so it empties this table by design — and the single warning below used to accuse the operator's install of losing the plugin's own work. The count is stated in all three cases: rows disappear from the table while the badge above still counts them (cable_count == rows shown + missing), and an operator watching them go needs to read how many and why. {% endcomment %} {% if missing_state == 'rollback' %} {% elif missing_state == 'partial' %} {% else %} {% endif %} {% endif %}
CableTypeStatus
{{ cable|linkify }} {{ cable.type }} {{ cable.status }}
No cable (job not executed or rolled back).
{{ missing_cables }} cable(s) of the job no longer exist: this job was rolled back through the plugin, which deletes the cables it created and keeps their ids as its trace. Expected — nothing was deleted behind the plugin's back.
{{ missing_cables }} cable(s) of the job no longer exist (deleted outside the plugin). A rollback allowed to delete only some of them leaves the very same trace, and the rest of the job's cables are still there — the plugin cannot tell the two apart.
{{ missing_cables }} cable(s) of the job no longer exist (deleted outside the plugin). This job is not marked rolled back, so the plugin did not delete them.
{% if channel.racks %}

Channel — locate & patch {% badge object.get_status_display bg_color=object.get_status_color %}

Per rack of the channel (source→target): the device highlighted in its native elevation (locate it), and the exact port to patch (in red). Use Trace (above) for the full physical path.

{% include 'netbox_autocabling/inc/channel_racks.html' %}
{% endif %} {% endblock %}