247 lines
No EOL
9.2 KiB
HTML
247 lines
No EOL
9.2 KiB
HTML
{% extends "layout.html" %}
|
|
|
|
{% block content %}
|
|
<div class="container-xl">
|
|
<div class="page-header d-print-none">
|
|
<div class="row align-items-center">
|
|
<div class="col">
|
|
<h2 class="page-title">
|
|
{% if subnet %}Edit Subnet{% else %}New Subnet{% endif %}
|
|
</h2>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card mt-3">
|
|
<div class="card-body">
|
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
|
{% if messages %}
|
|
{% for category, message in messages %}
|
|
<div class="alert alert-{{ category }} alert-dismissible fade show" role="alert">
|
|
{{ message }}
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
</div>
|
|
{% endfor %}
|
|
{% endif %}
|
|
{% endwith %}
|
|
|
|
<form method="POST"
|
|
action="{% if subnet %}{{ url_for('ipam.subnet_edit', subnet_id=subnet.id) }}{% else %}{{ url_for('ipam.subnet_new') }}{% endif %}">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
|
|
|
<!-- IP Address and Prefix Selection -->
|
|
<div class="row mb-3">
|
|
<div class="col-md-8">
|
|
<label class="form-label required">IP Address</label>
|
|
<input type="text" class="form-control" id="ip-address" placeholder="192.168.1.0" required
|
|
value="{% if subnet %}{{ subnet.cidr.split('/')[0] }}{% endif %}">
|
|
</div>
|
|
<div class="col-md-4">
|
|
<label class="form-label required">Prefix</label>
|
|
<select class="form-select" id="prefix" required>
|
|
{% for i in range(8, 31) %}
|
|
<option value="{{ i }}" {% if subnet and subnet.cidr.split('/')[1]|int==i %}selected{% endif %}>
|
|
{{ i }} ({{ 2**(32-i) }} hosts)
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Hidden CIDR field to submit combined value -->
|
|
<input type="hidden" name="cidr" id="cidr-value" value="{% if subnet %}{{ subnet.cidr }}{% endif %}">
|
|
|
|
<div class="mb-3">
|
|
<div class="d-flex align-items-center">
|
|
<div class="flex-grow-1">
|
|
<label for="location_id" class="form-label required">Location</label>
|
|
<select class="form-select" id="location_id" name="location_id" required>
|
|
<option value="">Select a location</option>
|
|
{% for location in locations %}
|
|
<option value="{{ location.id }}" {% if subnet and subnet.location_id==location.id %}selected{% endif
|
|
%}>
|
|
{{ location.name }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
<div class="ms-2 pt-4">
|
|
<button type="button" class="btn btn-outline-primary btn-icon" data-bs-toggle="modal"
|
|
data-bs-target="#add-location-modal">
|
|
<span class="ti ti-plus"></span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" name="auto_scan" id="auto_scan" {% if subnet and
|
|
subnet.auto_scan %}checked{% endif %}>
|
|
<label class="form-check-label" for="auto_scan">
|
|
Auto-scan for active hosts
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-footer">
|
|
<button type="submit" class="btn btn-primary">Save</button>
|
|
<a href="{% if subnet %}{{ url_for('ipam.subnet_view', subnet_id=subnet.id) }}{% else %}{{ url_for('ipam.ipam_home') }}{% endif %}"
|
|
class="btn btn-outline-secondary ms-2">Cancel</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Add Location Modal -->
|
|
<div class="modal modal-blur fade" id="add-location-modal" tabindex="-1" role="dialog" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Add New Location</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form id="add-location-form">
|
|
<div class="mb-3">
|
|
<label class="form-label required">Location Name</label>
|
|
<input type="text" class="form-control" id="new-location-name" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Description</label>
|
|
<textarea class="form-control" id="new-location-description" rows="3"></textarea>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-link link-secondary" data-bs-dismiss="modal">
|
|
Cancel
|
|
</button>
|
|
<button type="button" class="btn btn-primary ms-auto" id="save-location-btn">
|
|
<span class="ti ti-plus me-2"></span>
|
|
Add Location
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
// Handle CIDR combination
|
|
const ipAddressInput = document.getElementById('ip-address');
|
|
const prefixSelect = document.getElementById('prefix');
|
|
const cidrValue = document.getElementById('cidr-value');
|
|
|
|
function updateCIDR() {
|
|
const ip = ipAddressInput.value.trim();
|
|
const prefix = prefixSelect.value;
|
|
if (ip) {
|
|
cidrValue.value = `${ip}/${prefix}`;
|
|
}
|
|
}
|
|
|
|
if (ipAddressInput && prefixSelect && cidrValue) {
|
|
ipAddressInput.addEventListener('input', updateCIDR);
|
|
prefixSelect.addEventListener('change', updateCIDR);
|
|
}
|
|
|
|
// Add location functionality
|
|
const saveLocationBtn = document.getElementById('save-location-btn');
|
|
const locationSelect = document.getElementById('location_id');
|
|
const addLocationModal = document.getElementById('add-location-modal');
|
|
|
|
if (saveLocationBtn && locationSelect && addLocationModal) {
|
|
const bsModal = new bootstrap.Modal(addLocationModal);
|
|
|
|
saveLocationBtn.addEventListener('click', function () {
|
|
const name = document.getElementById('new-location-name').value.trim();
|
|
const description = document.getElementById('new-location-description').value.trim();
|
|
const csrfToken = document.querySelector('input[name="csrf_token"]').value;
|
|
|
|
if (!name) {
|
|
alert('Location name is required');
|
|
return;
|
|
}
|
|
|
|
apiFunctions.createLocation(name, description, csrfToken)
|
|
.then(data => {
|
|
// Add new option to select dropdown
|
|
const newOption = new Option(data.name, data.id, true, true);
|
|
locationSelect.add(newOption);
|
|
|
|
// Reset form and close modal
|
|
document.getElementById('new-location-name').value = '';
|
|
document.getElementById('new-location-description').value = '';
|
|
bsModal.hide();
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert('Failed to create location: ' + error.message);
|
|
});
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
// Handle CIDR combination
|
|
const ipAddressInput = document.getElementById('ip-address');
|
|
const prefixSelect = document.getElementById('prefix');
|
|
const cidrValue = document.getElementById('cidr-value');
|
|
|
|
function updateCIDR() {
|
|
const ip = ipAddressInput.value.trim();
|
|
const prefix = prefixSelect.value;
|
|
if (ip) {
|
|
cidrValue.value = `${ip}/${prefix}`;
|
|
}
|
|
}
|
|
|
|
if (ipAddressInput && prefixSelect && cidrValue) {
|
|
ipAddressInput.addEventListener('input', updateCIDR);
|
|
prefixSelect.addEventListener('change', updateCIDR);
|
|
}
|
|
|
|
// Add location functionality
|
|
const saveLocationBtn = document.getElementById('save-location-btn');
|
|
const locationSelect = document.getElementById('location_id');
|
|
const addLocationModal = document.getElementById('add-location-modal');
|
|
|
|
if (saveLocationBtn && locationSelect && addLocationModal) {
|
|
const bsModal = new bootstrap.Modal(addLocationModal);
|
|
|
|
saveLocationBtn.addEventListener('click', function () {
|
|
const name = document.getElementById('new-location-name').value.trim();
|
|
const description = document.getElementById('new-location-description').value.trim();
|
|
const csrfToken = document.querySelector('input[name="csrf_token"]').value;
|
|
|
|
if (!name) {
|
|
alert('Location name is required');
|
|
return;
|
|
}
|
|
|
|
apiFunctions.createLocation(name, description, csrfToken)
|
|
.then(data => {
|
|
// Add new option to select dropdown
|
|
const newOption = new Option(data.name, data.id, true, true);
|
|
locationSelect.add(newOption);
|
|
|
|
// Reset form and close modal
|
|
document.getElementById('new-location-name').value = '';
|
|
document.getElementById('new-location-description').value = '';
|
|
bsModal.hide();
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert('Failed to create location: ' + error.message);
|
|
});
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
{% endblock %} |