282 lines
No EOL
8.8 KiB
HTML
282 lines
No EOL
8.8 KiB
HTML
<nav class="navbar navbar-expand-lg" style="z-index: 1100;">
|
|
<div class="container-fluid">
|
|
<a class="navbar-brand d-flex align-items-center" href="{{ base_path }}/">
|
|
<i class="fas fa-users-cog me-2"></i>
|
|
<span>AgentHub</span>
|
|
</a>
|
|
|
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup"
|
|
aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
|
|
<span class="navbar-toggler-icon"></span>
|
|
</button>
|
|
|
|
<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
|
|
<div class="navbar-nav me-auto">
|
|
{% if current_user %}
|
|
<a class="nav-link" href="{{ base_path }}/profile">
|
|
<i class="fas fa-home me-1"></i>Home
|
|
</a>
|
|
{% endif %}
|
|
{% if current_user %}
|
|
{% if not current_user.is_admin %}
|
|
<a class="nav-link" href="{{ base_path }}/agent-management">
|
|
<i class="fas fa-globe me-1"></i>All Agents
|
|
</a>
|
|
<a class="nav-link" href="{{ base_path }}/agent-management?view=my">
|
|
<i class="fas fa-robot me-1"></i>My Agents
|
|
</a>
|
|
{% endif %}
|
|
{% if current_user.is_admin %}
|
|
<a class="nav-link" href="{{ base_path }}/admin">
|
|
<i class="fas fa-tachometer-alt me-1"></i>Admin
|
|
</a>
|
|
<a class="nav-link" href="{{ base_path }}/api/admin/agents/export/csv" download>
|
|
<i class="fas fa-download me-1"></i>Export CSV
|
|
</a>
|
|
<a class="nav-link" href="#" onclick="document.getElementById('csv-import-input').click(); return false;">
|
|
<i class="fas fa-file-upload me-1"></i>Import CSV
|
|
</a>
|
|
<input type="file" id="csv-import-input" accept=".csv" style="display: none;" onchange="uploadCsv(this)">
|
|
<a class="nav-link text-danger" href="#"
|
|
onclick="document.getElementById('csv-delete-input').click(); return false;">
|
|
<i class="fas fa-trash-alt me-1"></i>Delete by CSV
|
|
</a>
|
|
<input type="file" id="csv-delete-input" accept=".csv" style="display: none;" onchange="deleteCsv(this)">
|
|
{% endif %}
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="navbar-nav">
|
|
{% if current_user %}
|
|
<a class="nav-link" href="{{ base_path }}/search">
|
|
<i class="fas fa-search me-1"></i>Search
|
|
</a>
|
|
<div class="nav-item dropdown">
|
|
<a class="nav-link dropdown-toggle d-flex align-items-center" href="#" role="button"
|
|
data-bs-toggle="dropdown">
|
|
<div class="user-avatar me-2">
|
|
{{ current_user.full_name[0] if current_user.full_name else current_user.email[0] }}
|
|
</div>
|
|
{{ current_user.full_name or current_user.email.split('@')[0] }}
|
|
</a>
|
|
<ul class="dropdown-menu dropdown-menu-end">
|
|
<li>
|
|
<h6 class="dropdown-header">{{ current_user.email }}</h6>
|
|
</li>
|
|
<li>
|
|
<hr class="dropdown-divider">
|
|
</li>
|
|
<li>
|
|
<a class="dropdown-item" href="{{ base_path }}/profile">
|
|
<i class="fas fa-user me-2"></i>My Profile
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a class="dropdown-item" href="{{ base_path }}/agent-register">
|
|
<i class="fas fa-plus-circle me-2"></i>Add Agent
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a class="dropdown-item" href="{{ base_path }}/agent-management">
|
|
<i class="fas fa-list me-2"></i>My Agents
|
|
</a>
|
|
</li>
|
|
{% if current_user.is_admin %}
|
|
<li>
|
|
<a class="dropdown-item" href="{{ base_path }}/admin">
|
|
<i class="fas fa-cog me-2"></i>Admin Panel
|
|
</a>
|
|
</li>
|
|
{% endif %}
|
|
{% if current_user.get('actual_is_admin') or current_user.is_admin %}
|
|
<li>
|
|
<a class="dropdown-item" href="#" onclick="toggleAdminView(event)">
|
|
<i class="fas fa-exchange-alt me-2"></i>
|
|
{% if current_user.get('actual_is_admin') %}
|
|
Switch to Admin View
|
|
{% else %}
|
|
Switch to User View
|
|
{% endif %}
|
|
</a>
|
|
</li>
|
|
{% endif %}
|
|
<li>
|
|
<hr class="dropdown-divider">
|
|
</li>
|
|
<li>
|
|
<a class="dropdown-item text-danger" href="{{ base_path }}/logout">
|
|
<i class="fas fa-sign-out-alt me-2"></i>Logout
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
{% else %}
|
|
<a class="nav-link" href="{{ base_path }}/login">
|
|
<i class="fas fa-sign-in-alt me-1"></i>Login
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<style>
|
|
.user-avatar {
|
|
width: 28px;
|
|
height: 28px;
|
|
border-radius: 50%;
|
|
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: white;
|
|
font-size: 0.75rem;
|
|
}
|
|
|
|
.dropdown-menu {
|
|
border-radius: 12px;
|
|
border: none;
|
|
box-shadow: var(--shadow-lg);
|
|
padding: 0.5rem 0;
|
|
margin-top: 0.5rem;
|
|
z-index: 1050 !important;
|
|
position: absolute !important;
|
|
}
|
|
|
|
.dropdown-item {
|
|
padding: 0.5rem 1rem;
|
|
transition: all 0.3s ease;
|
|
border-radius: 8px;
|
|
margin: 0 0.5rem;
|
|
}
|
|
|
|
.dropdown-item:hover {
|
|
background-color: var(--bg-light);
|
|
transform: translateX(4px);
|
|
}
|
|
|
|
.navbar-toggler {
|
|
border: none;
|
|
padding: 4px 8px;
|
|
}
|
|
|
|
.navbar-toggler:focus {
|
|
box-shadow: none;
|
|
}
|
|
|
|
.navbar {
|
|
position: relative;
|
|
z-index: 1100 !important;
|
|
}
|
|
|
|
.nav-item.dropdown {
|
|
position: relative;
|
|
z-index: 1100;
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
async function toggleAdminView(event) {
|
|
event.preventDefault();
|
|
|
|
try {
|
|
const response = await fetch('{{ base_path }}/api/admin/toggle-view', {
|
|
method: 'POST',
|
|
credentials: 'include',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
}
|
|
});
|
|
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
|
|
// Redirect based on new view mode
|
|
if (data.view_mode === 'user') {
|
|
window.location.href = '{{ base_path }}/agent-management';
|
|
} else {
|
|
window.location.href = '{{ base_path }}/admin';
|
|
}
|
|
} else {
|
|
const error = await response.json();
|
|
alert('Failed to toggle view: ' + (error.detail || 'Unknown error'));
|
|
}
|
|
} catch (error) {
|
|
console.error('Error toggling admin view:', error);
|
|
alert('Failed to toggle view. Please try again.');
|
|
}
|
|
}
|
|
|
|
async function uploadCsv(input) {
|
|
if (!input.files || !input.files[0]) return;
|
|
|
|
const file = input.files[0];
|
|
const formData = new FormData();
|
|
formData.append('file', file);
|
|
|
|
try {
|
|
const response = await fetch('{{ base_path }}/api/admin/agents/import/csv', {
|
|
method: 'POST',
|
|
body: formData
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (response.ok && result.success) {
|
|
let msg = `Import complete!\nImported: ${result.imported}\nSkipped: ${result.skipped}\nErrors: ${result.errors}`;
|
|
if (result.errors > 0) {
|
|
msg += `\n\nFirst few errors:\n${result.error_details.join('\n')}`;
|
|
}
|
|
alert(msg);
|
|
window.location.reload();
|
|
} else {
|
|
alert('Import failed: ' + (result.detail || 'Unknown error'));
|
|
}
|
|
} catch (error) {
|
|
console.error('Error uploading CSV:', error);
|
|
alert('Error uploading CSV: ' + error.message);
|
|
}
|
|
|
|
// Reset input
|
|
input.value = '';
|
|
}
|
|
|
|
async function deleteCsv(input) {
|
|
if (!input.files || !input.files[0]) return;
|
|
|
|
if (!confirm("WARNING: This will permanently delete all agents found in the CSV file. Are you sure you want to proceed?")) {
|
|
input.value = '';
|
|
return;
|
|
}
|
|
|
|
const file = input.files[0];
|
|
const formData = new FormData();
|
|
formData.append('file', file);
|
|
|
|
try {
|
|
const response = await fetch('{{ base_path }}/api/admin/agents/delete/csv', {
|
|
method: 'POST',
|
|
body: formData
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (response.ok && result.success) {
|
|
let msg = `Deletion complete!\nDeleted: ${result.deleted}\nNot Found: ${result.not_found}\nErrors: ${result.errors}`;
|
|
if (result.errors > 0) {
|
|
msg += `\n\nFirst few errors:\n${result.error_details.join('\n')}`;
|
|
}
|
|
alert(msg);
|
|
window.location.reload();
|
|
} else {
|
|
alert('Deletion failed: ' + (result.detail || 'Unknown error'));
|
|
}
|
|
} catch (error) {
|
|
console.error('Error deleting via CSV:', error);
|
|
alert('Error deleting via CSV: ' + error.message);
|
|
}
|
|
|
|
// Reset input
|
|
input.value = '';
|
|
}
|
|
</script> |