{# SPDX-License-Identifier: Apache-2.0 #} {# Copyright (C) 2025 Marcin Zieba #} {% extends 'base/layout.html' %} {% block title %}Import Preview{% endblock %} {% block content %}
{# Header #}
Import Preview — Step 2 of 3
{{ filename }}
{# Summary bar #}
{% with c=result.counts %} {{ c.racks_created|default:0 }} rack{{ c.racks_created|default:0|pluralize }} to create {{ c.devices_created|default:0 }} device{{ c.devices_created|default:0|pluralize }} to create {% if c.racks_updated or c.devices_updated %} {{ c.racks_updated|default:0|add:c.devices_updated|default:0 }} to update {% endif %} {% if c.skipped %} {{ c.skipped }} skipped {% endif %} {% if c.ignored %} {{ c.ignored }} ignored {% endif %} {% if c.errors %} {{ c.errors }} error{{ c.errors|pluralize }} {% endif %} {% endwith %}
{# Action buttons #}
Back {% if view_mode == 'racks' %} Row view {% else %} Rack view {% endif %} {% if profile_id %} {# Auto-match existing devices #}
{% csrf_token %}
{% endif %} {% if result.counts.errors == 0 %}
{% csrf_token %}
{% else %} {% endif %}
{% if result.counts.errors %}
{{ result.counts.errors }} row{{ result.counts.errors|pluralize }} need attention. Use the buttons in the last column to add mappings, link existing devices, or ignore rows. The preview refreshes automatically after each fix.
{% endif %}
{% if view_mode == 'racks' %} {# Rack view #}
{% for rack_name, group in result.rack_groups.items %}
{{ rack_name }} {% if group.rack_row %} {% if group.rack_row.action == 'create' %}Create {% elif group.rack_row.action == 'update' %}Update {% elif group.rack_row.action == 'skip' %}Existing {% elif group.rack_row.action == 'error' %}Error {% endif %} {% else %} No rack row {% endif %}
{% if group.devices %}
    {% for dev in group.devices %}
  • {% if dev.action == 'create' %}+ {% elif dev.action == 'update' %}~ {% elif dev.action == 'skip' %} {% elif dev.action == 'error' %}! {% elif dev.action == 'ignore' %} {% endif %} {{ dev.name }} {% if dev.action != 'ignore' %} U{{ dev.detail|truncatechars:20 }} {% endif %}
  • {% endfor %}
{% else %}

No devices

{% endif %}
{% empty %}

No racks found in preview.

{% endfor %}
{% else %} {# Per-row table (default) #}
Row-by-row preview ({{ result.rows|length }} row{{ result.rows|length|pluralize }})
{% for row in result.rows %} {% empty %} {% endfor %}
# Source ID Name Type Action Detail
{{ row.row_number }} {{ row.source_id|default:"—" }} {% if row.netbox_url %}{{ row.name|default:"—" }} {% else %}{{ row.name|default:"—" }}{% endif %} {# Show source make/model for device rows #} {% if row.object_type == 'device' and row.extra_data.source_make %}
{{ row.extra_data.source_make }} / {{ row.extra_data.source_model }}
{% endif %}
{% if row.object_type == 'rack' %} Rack {% elif row.object_type == 'device' %} Device {% elif row.object_type == 'manufacturer' %} Manufacturer {% elif row.object_type == 'device_type' %} Device type {% else %} {{ row.object_type|default:"?" }} {% endif %} {% if row.action == 'create' %} Create {% elif row.action == 'update' %} Update {% elif row.action == 'skip' %} Skip {% elif row.action == 'error' %} Error {% elif row.action == 'ignore' %} Ignored {% endif %} {{ row.detail }} {% if row.object_type == 'manufacturer' and row.action == 'create' and profile_id %} {# Manufacturer: create now OR map to existing #}
{% csrf_token %}
{% elif row.object_type == 'device_type' and row.action in 'create,error' and profile_id %} {# Device type: map to existing OR create now (both open same modal) #} {% elif row.action == 'error' and row.object_type == 'rack' and profile_id %} {# Rack error — offer ignore #}
{% csrf_token %}
{% elif row.action == 'error' and row.object_type == 'device' and profile_id %} {# Device error — show class mapping button if we have source_class #} {% if row.extra_data.source_class %} {% endif %} {# Link to existing device #} {# Ignore button #}
{% csrf_token %}
{% elif row.action == 'create' and row.object_type == 'device' and row.source_id and profile_id %} {# Device will be created — allow linking to existing device instead #} {# Ignore button #}
{% csrf_token %}
{% elif row.action == 'ignore' and row.object_type == 'device' and row.source_id and profile_id %} {# Unignore button #}
{% csrf_token %}
{% endif %} {# Split button: show on device rows where name contains ' - ' #} {% if row.object_type == 'device' and row.source_id and profile_id and ' - ' in row.name %} {% endif %}
No rows found in file.
{% endif %}
{# Improved split-name modal #} {# Device Type Mapping Modal #} {# Class Mapping Modal #} {# Device Match Modal #} {# Manufacturer Mapping Modal #} {% endblock %}