336 lines
12 KiB
HTML
336 lines
12 KiB
HTML
{% extends 'base.html' %}
|
||
|
||
{% block title %}User List{% endblock %}
|
||
|
||
{% block content %}
|
||
<h1>User List</h1>
|
||
|
||
<table border="1">
|
||
<thead>
|
||
<tr>
|
||
<th>MAC Address</th>
|
||
<th>Description</th>
|
||
<th>VLAN ID</th>
|
||
<th>Actions</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for user in results %}
|
||
<tr>
|
||
<td><input type="text" id="mac_address-{{ user.mac_address }}" value="{{ user.mac_address }}"></td>
|
||
<td><input type="text" id="description-{{ user.mac_address }}" value="{{ user.description }}"></td>
|
||
<td>
|
||
<select id="vlan_id-{{ user.mac_address }}">
|
||
{% for group in groups %}
|
||
<option value="{{ group.groupname }}" {% if user.vlan_id == group.groupname %} selected {% endif %}>
|
||
{{ group.groupname }}
|
||
</option>
|
||
{% endfor %}
|
||
</select>
|
||
</td>
|
||
<td>
|
||
<button onclick="updateUser('{{ user.mac_address }}')">✅</button>
|
||
<button onclick="location.reload()">❌</button>
|
||
<a href="/delete_user/{{ user.mac_address }}" onclick="saveScrollPosition()">🗑️</a>
|
||
<button onclick="duplicateUser('{{ user.mac_address }}')">Duplicate</button>
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
<tr>
|
||
<td colspan="4">
|
||
<button onclick="addNewUserRow()">➕ Add User</button>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<dialog id="add-user-dialog">
|
||
<div id="add-user-dialog-content">
|
||
<table border="1">
|
||
<thead>
|
||
<tr>
|
||
<th>MAC Address</th>
|
||
<th>Description</th>
|
||
<th>VLAN ID</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><input type="text" id="new-mac"></td>
|
||
<td><input type="text" id="new-description"></td>
|
||
<td>
|
||
<select id="new-vlan_id">
|
||
{% for group in groups %}
|
||
<option value="{{ group.groupname }}">
|
||
{{ group.groupname }}
|
||
</option>
|
||
{% endfor %}
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div style="display: flex; justify-content: flex-end; margin-top: 10px;">
|
||
<button id="cancel-add-user-dialog">Cancel</button>
|
||
<button id="save-new-user">Save</button>
|
||
</div>
|
||
</dialog>
|
||
|
||
<dialog id="duplicate-dialog">
|
||
<div id="duplicate-dialog-content">
|
||
<table border="1">
|
||
<thead>
|
||
<tr>
|
||
<th>MAC Address</th>
|
||
<th>Description</th>
|
||
<th>VLAN ID</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><input type="text" id="dup-mac"></td>
|
||
<td><input type="text" id="dup-description"></td>
|
||
<td>
|
||
<select id="dup-vlan_id">
|
||
{% for group in groups %}
|
||
<option value="{{ group.groupname }}">
|
||
{{ group.groupname }}
|
||
</option>
|
||
{% endfor %}
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div style="display: flex; justify-content: flex-end; margin-top: 10px;">
|
||
<button id="close-duplicate-dialog">Cancel</button>
|
||
<button id="save-duplicated-user">Save</button>
|
||
</div>
|
||
</dialog>
|
||
|
||
<style>
|
||
.merged-cell {
|
||
border: none;
|
||
}
|
||
|
||
#cancel-add-user-dialog {
|
||
border-radius: 5px;
|
||
padding: 10px;
|
||
background-color: #f44336;
|
||
color: white;
|
||
border: none;
|
||
cursor: pointer;
|
||
margin-right: 10px;
|
||
}
|
||
|
||
#cancel-add-user-dialog:hover {
|
||
background-color: #d32f2f;
|
||
}
|
||
|
||
#save-new-user {
|
||
border-radius: 5px;
|
||
padding: 10px;
|
||
background-color: #4CAF50;
|
||
color: white;
|
||
border: none;
|
||
cursor: pointer;
|
||
}
|
||
|
||
#save-new-user:hover {
|
||
background-color: #45a049;
|
||
}
|
||
|
||
#add-user-dialog-content + div {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
margin-top: 10px;
|
||
}
|
||
</style>
|
||
|
||
<script>
|
||
function updateUser(mac_address) {
|
||
const description = document.getElementById('description-' + mac_address).value;
|
||
const vlan_id = document.getElementById('vlan_id-' + mac_address).value;
|
||
const mac_address_input = document.getElementById('mac_address-' + mac_address).value; //added
|
||
|
||
fetch('/update_user', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded',
|
||
},
|
||
body: `mac_address=${mac_address}&description=${description}&vlan_id=${vlan_id}&new_mac_address=${mac_address_input}` //added new param
|
||
})
|
||
.then(response => response.text())
|
||
.then(data => {
|
||
if (data === 'success') {
|
||
location.reload();
|
||
} else {
|
||
alert('Error updating user: ' + data);
|
||
}
|
||
});
|
||
}
|
||
|
||
function saveScrollPosition() {
|
||
sessionStorage.setItem('scrollPosition', window.scrollY);
|
||
}
|
||
|
||
window.onload = function () {
|
||
const scrollPosition = sessionStorage.getItem('scrollPosition');
|
||
if (scrollPosition) {
|
||
window.scrollTo(0, scrollPosition);
|
||
sessionStorage.removeItem('scrollPosition');
|
||
}
|
||
}
|
||
|
||
|
||
|
||
function duplicateUser(mac_address) {
|
||
console.log("duplicateUser called with mac_address:", mac_address);
|
||
fetch('/duplicate_user', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded',
|
||
},
|
||
body: `mac_address=${mac_address}`
|
||
})
|
||
.then(response => {
|
||
console.log("Response status:", response.status);
|
||
console.log("Response text:", response.text());
|
||
return response.json()
|
||
})
|
||
.then(data => {
|
||
console.log("Response data:", data);
|
||
const userData = data;
|
||
if (userData) {
|
||
document.getElementById('dup-mac').value = userData.mac_address;
|
||
document.getElementById('dup-description').value = userData.description;
|
||
|
||
const vlanSelect = document.getElementById('dup-vlan_id');
|
||
vlanSelect.innerHTML = '';
|
||
{% for group in groups %}
|
||
let option = document.createElement('option');
|
||
option.value = "{{ group.groupname }}";
|
||
option.textContent = "{{ group.groupname }}";
|
||
if ("{{ group.groupname }}" === userData.vlan_id) {
|
||
option.selected = true;
|
||
}
|
||
vlanSelect.appendChild(option);
|
||
{% endfor %}
|
||
|
||
document.getElementById('duplicate-dialog').showModal();
|
||
} else {
|
||
alert("Failed to retrieve user data for duplication.");
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
document.getElementById('close-duplicate-dialog').addEventListener('click', () => {
|
||
document.getElementById('duplicate-dialog').close();
|
||
});
|
||
|
||
document.getElementById('save-duplicated-user').addEventListener('click', () => {
|
||
saveDuplicatedUser();
|
||
});
|
||
|
||
function saveDuplicatedUser() {
|
||
let mac = document.getElementById('dup-mac').value;
|
||
let description = document.getElementById('dup-description').value;
|
||
let vlan_id = document.getElementById('dup-vlan_id').value;
|
||
|
||
fetch('/add_user', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({ mac_address: mac, description: description, vlan_id: vlan_id }),
|
||
})
|
||
.then((response) => {
|
||
if (!response.ok) {
|
||
return response.text().then((text) => {
|
||
throw new Error(`HTTP error! status: ${response.status}, body: ${text}`);
|
||
});
|
||
}
|
||
return response.json();
|
||
})
|
||
.then((data) => {
|
||
console.log("Server response:", data);
|
||
if (data && data.success) {
|
||
document.getElementById('duplicate-dialog').close();
|
||
location.reload();
|
||
} else {
|
||
alert("Error adding user: " + (data && data.message ? data.message : "Unknown error"));
|
||
}
|
||
})
|
||
.catch((error) => {
|
||
console.error("Fetch error:", error);
|
||
alert("Error adding user: " + error.message);
|
||
});
|
||
}
|
||
|
||
function addNewUserRow() {
|
||
document.getElementById('add-user-dialog').showModal();
|
||
}
|
||
|
||
document.getElementById('cancel-add-user-dialog').addEventListener('click', () => {
|
||
document.getElementById('add-user-dialog').close();
|
||
});
|
||
|
||
document.getElementById('save-new-user').addEventListener('click', () => {
|
||
saveNewUser();
|
||
});
|
||
|
||
function saveNewUser() {
|
||
const mac = document.getElementById('new-mac').value;
|
||
const description = document.getElementById('new-description').value;
|
||
const vlan_id = document.getElementById('new-vlan_id').value;
|
||
|
||
if (!mac) {
|
||
alert('MAC Address cannot be empty.');
|
||
return;
|
||
}
|
||
|
||
// Construct the data as an object
|
||
const userData = {
|
||
username: mac, // Use MAC as username
|
||
password: mac, // Use MAC as password
|
||
mac_address: mac,
|
||
description: description,
|
||
vlan_id: vlan_id
|
||
};
|
||
|
||
fetch('/add_user', { // Make sure this URL is correct
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json', // Set the content type to JSON
|
||
},
|
||
body: JSON.stringify(userData), // Send the data as a JSON string
|
||
})
|
||
.then(response => {
|
||
if (!response.ok) {
|
||
// Handle HTTP errors (e.g., 400, 500)
|
||
return response.text().then(text => {
|
||
throw new Error(`HTTP error! status: ${response.status}, body: ${text}`);
|
||
});
|
||
}
|
||
return response.json(); // Expect JSON response from server
|
||
})
|
||
.then(data => {
|
||
console.log("Server response:", data);
|
||
if (data && data.success) { // Check for success property in JSON response
|
||
document.getElementById('add-user-dialog').close();
|
||
location.reload();
|
||
} else {
|
||
alert('Error adding user: ' + (data && data.message ? data.message : 'Unknown error')); // Show error from server or a generic message
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Fetch error:', error); // Log the error for debugging
|
||
alert('Error adding user: ' + error.message); // Show a user-friendly error message
|
||
});
|
||
}
|
||
</script>
|
||
{% endblock %}
|