Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mark required fields on the Sync Devices from Network job #281

Merged
merged 7 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/243.changed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Sync Devices From Network job form now highlights required fields.
6 changes: 4 additions & 2 deletions nautobot_device_onboarding/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ class Meta:
csv_file = FileVar(
label="CSV File",
required=False,
description="If a file is provided all the options below will be ignored.",
description="If a file is provided, all the options in the manual input tab will be disabled.",
)
location = ObjectVar(
model=Location,
Expand Down Expand Up @@ -337,6 +337,8 @@ class Meta:
description="Device platform. Define ONLY to override auto-recognition of platform.",
)

template_name = "nautobot_device_onboarding/ssot_sync_devices.html"

def load_source_adapter(self):
"""Load onboarding network adapter."""
self.source_adapter = SyncDevicesNetworkAdapter(job=self, sync=self.sync)
Expand Down Expand Up @@ -502,7 +504,7 @@ def run(
raise ValidationError(message="CSV check failed. No devices will be synced.")

else:
# Verify that all requried form inputs have been provided
# Verify that all required form inputs have been provided, this is here in case the form is not used
required_inputs = {
"location": location,
"namespace": namespace,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{% extends 'extras/job.html' %}
{% load form_helpers %}

{% block job_form %}

{% render_form job_form excluded_fields="['location', 'namespace', 'ip_addresses', 'device_role', 'device_status', 'interface_status', 'ip_address_status', 'port', 'timeout', 'secrets_group', 'platform', 'set_mgmt_only', 'update_devices_without_primary_ip', 'csv_file']" %}

{% with csv_tab_active=form.initial.csv_input %}
<ul class="nav nav-tabs" role="tablist">
<li role="presentation"{% if not csv_tab_active %} class="active"{% endif %}>
<a href="#job_manual_input" role="tab" data-toggle="tab">Manual Input</a>
</li>
<li role="presentation"{% if csv_tab_active %} class="active"{% endif %}>
<a href="#job_csv_input" role="tab" data-toggle="tab">CSV Input</a>
</li>
</ul>
<div class="tab-content">
<div id="job_manual_input" class="tab-pane{% if not csv_tab_active %} active{% endif %}">
{% render_field job_form.location %}
{% render_field job_form.namespace %}
{% render_field job_form.ip_addresses %}
{% render_field job_form.port %}
{% render_field job_form.timeout %}
{% render_field job_form.set_mgmt_only %}
{% render_field job_form.update_devices_without_primary_ip %}
{% render_field job_form.device_role %}
{% render_field job_form.device_status %}
{% render_field job_form.interface_status %}
{% render_field job_form.ip_address_status %}
{% render_field job_form.secrets_group %}
{% render_field job_form.platform %}
</div>
<div id="job_csv_input" class="tab-pane{% if csv_tab_active %} active{% endif %}">
{% render_field job_form.csv_file %}
</div>
</div>
{% endwith %}

{% endblock job_form %}

{% block javascript %}
{{ block.super }}
<script>
const csvInput = document.getElementById('id_csv_file');
const manualRequiredFields = [
"id_location", "id_namespace", "id_ip_addresses", "id_device_role",
"id_device_status", "id_interface_status", "id_ip_address_status",
"id_port", "id_timeout", "id_secrets_group"
];

function setFieldRequired(fieldId, isRequired) {
const element = document.getElementById(fieldId);
element.required = isRequired;
const label = document.querySelector(`label[for="${fieldId}"]`);
if (isRequired) {
label.classList.add('required');
} else {
label.classList.remove('required');
}
}

document.addEventListener("DOMContentLoaded", function() {
manualRequiredFields.forEach(field => setFieldRequired(field, true));

$('.nav-tabs a').on('shown.bs.tab', function(e) {
const activeTab = $(e.target).attr('href');
const isManualInputTab = activeTab === '#job_manual_input';

csvInput.value = '';
csvInput.required = !isManualInputTab;
document.querySelector('label[for="id_csv_file"]').classList.toggle('required', !isManualInputTab);

manualRequiredFields.forEach(field => setFieldRequired(field, isManualInputTab));
});
});
</script>
{% endblock javascript %}