mirror of
https://github.com/house-of-vanity/OutFleet.git
synced 2025-08-21 14:37:16 +00:00
220 lines
8.1 KiB
HTML
220 lines
8.1 KiB
HTML
{% extends "admin/change_form.html" %}
|
|
{% load static %}
|
|
|
|
{% block content_title %}
|
|
<h1 class="h4 m-0 pr-3 mr-3 border-right">
|
|
{% if original %}
|
|
👤 User: {{ original.username }}
|
|
{% else %}
|
|
👤 Add User
|
|
{% endif %}
|
|
</h1>
|
|
{% endblock %}
|
|
|
|
{% block extrahead %}
|
|
{{ block.super }}
|
|
<style>
|
|
.user-management-section {
|
|
background: #f8f9fa;
|
|
border: 1px solid #dee2e6;
|
|
border-radius: 0.375rem;
|
|
padding: 1rem;
|
|
margin: 0.5rem 0;
|
|
}
|
|
|
|
.user-management-section h4 {
|
|
margin: 0 0 0.75rem 0;
|
|
color: #495057;
|
|
font-size: 1rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.server-section {
|
|
background: #ffffff;
|
|
border: 1px solid #e9ecef;
|
|
border-radius: 0.25rem;
|
|
padding: 1rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.link-item {
|
|
background: #f8f9fa;
|
|
border: 1px solid #e9ecef;
|
|
border-radius: 0.25rem;
|
|
padding: 0.75rem;
|
|
margin-bottom: 0.5rem;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.btn-sm-custom {
|
|
padding: 0.25rem 0.5rem;
|
|
font-size: 0.75rem;
|
|
border-radius: 0.2rem;
|
|
margin: 0 0.1rem;
|
|
}
|
|
|
|
.readonly .user-management-section {
|
|
border: none;
|
|
background: transparent;
|
|
padding: 0;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block admin_change_form_document_ready %}
|
|
{{ block.super }}
|
|
{% if original %}
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const userId = {{ original.id }};
|
|
const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;
|
|
|
|
// Show success/error messages in Django admin style
|
|
function showMessage(message, type = 'success') {
|
|
const messageClass = type === 'error' ? 'error' : 'success';
|
|
const messageHtml = `
|
|
<div class="alert alert-${messageClass} alert-dismissible" style="margin: 1rem 0;">
|
|
${message}
|
|
<button type="button" class="close" aria-label="Close" onclick="this.parentElement.remove()">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
`;
|
|
|
|
const target = document.querySelector('.card-body') || document.querySelector('.content');
|
|
if (target) {
|
|
target.insertAdjacentHTML('afterbegin', messageHtml);
|
|
setTimeout(() => {
|
|
const alert = target.querySelector('.alert');
|
|
if (alert) alert.remove();
|
|
}, 5000);
|
|
}
|
|
}
|
|
|
|
// Add new link functionality
|
|
document.querySelectorAll('.add-link-btn').forEach(btn => {
|
|
btn.addEventListener('click', async function() {
|
|
const serverId = this.dataset.serverId;
|
|
const serverName = this.dataset.serverName;
|
|
|
|
const comment = prompt(`Add comment for new link on ${serverName} (optional):`, '');
|
|
if (comment === null) return;
|
|
|
|
const originalText = this.textContent;
|
|
this.textContent = '⏳ Adding...';
|
|
this.disabled = true;
|
|
|
|
try {
|
|
const response = await fetch(`/admin/vpn/user/${userId}/add-link/`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
'X-CSRFToken': csrfToken
|
|
},
|
|
body: `server_id=${serverId}&comment=${encodeURIComponent(comment)}`
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.success) {
|
|
showMessage(`✅ New link created successfully: ${data.link}`);
|
|
setTimeout(() => window.location.reload(), 1000);
|
|
} else {
|
|
showMessage(`❌ Error: ${data.error}`, 'error');
|
|
}
|
|
} catch (error) {
|
|
showMessage(`❌ Network error: ${error.message}`, 'error');
|
|
} finally {
|
|
this.textContent = originalText;
|
|
this.disabled = false;
|
|
}
|
|
});
|
|
});
|
|
|
|
// Delete link functionality
|
|
document.querySelectorAll('.delete-link-btn').forEach(btn => {
|
|
btn.addEventListener('click', async function() {
|
|
const linkId = this.dataset.linkId;
|
|
const linkName = this.dataset.linkName;
|
|
|
|
if (!confirm(`Are you sure you want to delete link ${linkName}?`)) {
|
|
return;
|
|
}
|
|
|
|
const originalText = this.textContent;
|
|
this.textContent = '⏳ Deleting...';
|
|
this.disabled = true;
|
|
|
|
try {
|
|
const response = await fetch(`/admin/vpn/user/${userId}/delete-link/${linkId}/`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
'X-CSRFToken': csrfToken
|
|
}
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.success) {
|
|
showMessage(`✅ Link ${linkName} deleted successfully`);
|
|
this.closest('.link-item')?.remove();
|
|
} else {
|
|
showMessage(`❌ Error: ${data.error}`, 'error');
|
|
}
|
|
} catch (error) {
|
|
showMessage(`❌ Network error: ${error.message}`, 'error');
|
|
} finally {
|
|
this.textContent = originalText;
|
|
this.disabled = false;
|
|
}
|
|
});
|
|
});
|
|
|
|
// Add server access functionality
|
|
document.querySelectorAll('.add-server-btn').forEach(btn => {
|
|
btn.addEventListener('click', async function() {
|
|
const serverId = this.dataset.serverId;
|
|
const serverName = this.dataset.serverName;
|
|
|
|
if (!confirm(`Add access to server ${serverName}?`)) {
|
|
return;
|
|
}
|
|
|
|
const originalText = this.textContent;
|
|
this.textContent = '⏳ Adding...';
|
|
this.disabled = true;
|
|
|
|
try {
|
|
const response = await fetch(`/admin/vpn/user/${userId}/add-server-access/`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
'X-CSRFToken': csrfToken
|
|
},
|
|
body: `server_id=${serverId}`
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.success) {
|
|
showMessage(`✅ Access to ${serverName} added successfully`);
|
|
setTimeout(() => window.location.reload(), 1000);
|
|
} else {
|
|
showMessage(`❌ Error: ${data.error}`, 'error');
|
|
}
|
|
} catch (error) {
|
|
showMessage(`❌ Network error: ${error.message}`, 'error');
|
|
} finally {
|
|
this.textContent = originalText;
|
|
this.disabled = false;
|
|
}
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
{% endif %}
|
|
{% endblock %}
|