UI- Verbesserung

Dieser Commit ist enthalten in:
2025-06-10 01:45:24 +02:00
Ursprung 231383f266
Commit 99724d8362
9 geänderte Dateien mit 286 neuen und 112 gelöschten Zeilen

Datei anzeigen

@@ -3820,6 +3820,69 @@ def check_resource_availability():
return jsonify(availability)
@app.route('/api/global-search', methods=['GET'])
@login_required
def global_search():
"""Global search API endpoint for searching customers and licenses"""
query = request.args.get('q', '').strip()
if not query or len(query) < 2:
return jsonify({'customers': [], 'licenses': []})
conn = get_connection()
cur = conn.cursor()
# Search pattern with wildcards
search_pattern = f'%{query}%'
# Search customers
cur.execute("""
SELECT id, name, email, company_name
FROM customers
WHERE (LOWER(name) LIKE LOWER(%s)
OR LOWER(email) LIKE LOWER(%s)
OR LOWER(company_name) LIKE LOWER(%s))
AND is_test = FALSE
ORDER BY name
LIMIT 5
""", (search_pattern, search_pattern, search_pattern))
customers = []
for row in cur.fetchall():
customers.append({
'id': row[0],
'name': row[1],
'email': row[2],
'company_name': row[3]
})
# Search licenses
cur.execute("""
SELECT l.id, l.license_key, c.name as customer_name
FROM licenses l
JOIN customers c ON l.customer_id = c.id
WHERE LOWER(l.license_key) LIKE LOWER(%s)
AND l.is_test = FALSE
ORDER BY l.created_at DESC
LIMIT 5
""", (search_pattern,))
licenses = []
for row in cur.fetchall():
licenses.append({
'id': row[0],
'license_key': row[1],
'customer_name': row[2]
})
cur.close()
conn.close()
return jsonify({
'customers': customers,
'licenses': licenses
})
@app.route('/resources/history/<int:resource_id>')
@login_required
def resource_history(resource_id):

Datei anzeigen

@@ -17,6 +17,8 @@
--status-danger: #dc3545;
--status-inactive: #6c757d;
--status-info: #17a2b8;
--sidebar-width: 250px;
--sidebar-collapsed: 60px;
}
/* Status Classes - Global */
@@ -218,6 +220,111 @@
.sort-indicator.active {
color: var(--bs-primary);
}
/* Sidebar Navigation */
.sidebar {
position: fixed;
top: 56px;
left: 0;
height: calc(100vh - 56px);
width: var(--sidebar-width);
background-color: #f8f9fa;
border-right: 1px solid #dee2e6;
overflow-y: auto;
transition: all 0.3s;
z-index: 100;
}
.sidebar.collapsed {
width: var(--sidebar-collapsed);
}
.sidebar-header {
padding: 1rem;
background-color: #e9ecef;
border-bottom: 1px solid #dee2e6;
font-weight: 600;
}
.sidebar-nav {
list-style: none;
padding: 0;
margin: 0;
}
.sidebar-nav .nav-item {
border-bottom: 1px solid #e9ecef;
}
.sidebar-nav .nav-link {
display: flex;
align-items: center;
padding: 0.75rem 1rem;
color: #495057;
text-decoration: none;
transition: all 0.2s;
}
.sidebar-nav .nav-link:hover {
background-color: #e9ecef;
color: #212529;
}
.sidebar-nav .nav-link.active {
background-color: var(--bs-primary);
color: white;
}
.sidebar-nav .nav-link i {
margin-right: 0.5rem;
font-size: 1.2rem;
width: 24px;
text-align: center;
}
.sidebar.collapsed .sidebar-nav .nav-link span {
display: none;
}
.sidebar-submenu {
list-style: none;
padding: 0;
margin: 0;
background-color: #f1f3f4;
}
.sidebar-submenu .nav-link {
padding-left: 2.5rem;
font-size: 0.9rem;
}
/* Main Content with Sidebar */
.main-content {
margin-left: var(--sidebar-width);
transition: all 0.3s;
min-height: calc(100vh - 56px);
}
.main-content.expanded {
margin-left: var(--sidebar-collapsed);
}
/* Responsive Adjustments */
@media (max-width: 768px) {
.sidebar {
transform: translateX(-100%);
}
.sidebar.show {
transform: translateX(0);
}
.main-content {
margin-left: 0;
}
}
</style>
</head>
<body class="bg-light">
@@ -229,7 +336,7 @@
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<!-- Navigation Links entfernt - Zugriff über Dashboard -->
<!-- Navigation removed - access via sidebar -->
</ul>
<div class="d-flex align-items-center">
<div id="session-timer" class="timer-normal me-3">
@@ -243,7 +350,103 @@
</div>
</nav>
<!-- Sidebar Navigation -->
<aside class="sidebar" id="sidebar">
<ul class="sidebar-nav">
<li class="nav-item">
<a class="nav-link {% if request.endpoint == 'dashboard' %}active{% endif %}" href="/">
<i class="bi bi-speedometer2"></i>
<span>Dashboard</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if request.endpoint in ['customers_licenses', 'edit_customer', 'create_customer', 'edit_license', 'create_license'] %}active{% endif %}" href="/customers-licenses">
<i class="bi bi-people"></i>
<span>Kunden & Lizenzen</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if request.endpoint == 'create_customer' %}active{% endif %}" href="/customer/create">
<i class="bi bi-person-plus"></i>
<span>Neuer Kunde</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if request.endpoint == 'create_license' %}active{% endif %}" href="/create">
<i class="bi bi-plus-circle"></i>
<span>Neue Lizenz</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if request.endpoint == 'batch_licenses' %}active{% endif %}" href="/batch">
<i class="bi bi-stack"></i>
<span>Batch-Erstellung</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if request.endpoint == 'resources' %}active{% endif %}" href="/resources">
<i class="bi bi-box-seam"></i>
<span>Resource Pool</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if request.endpoint == 'add_resources' %}active{% endif %}" href="/resources/add">
<i class="bi bi-plus-square"></i>
<span>Ressourcen hinzufügen</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if request.endpoint == 'audit_log' %}active{% endif %}" href="/audit">
<i class="bi bi-journal-text"></i>
<span>Audit-Log</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if request.endpoint == 'sessions' %}active{% endif %}" href="/sessions">
<i class="bi bi-people"></i>
<span>Sitzungen</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if request.endpoint == 'backups' %}active{% endif %}" href="/backups">
<i class="bi bi-cloud-download"></i>
<span>Backups</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if request.endpoint == 'blocked_ips' %}active{% endif %}" href="/security/blocked-ips">
<i class="bi bi-shield-lock"></i>
<span>Sicherheit</span>
</a>
</li>
</ul>
<div class="sidebar-header mt-4">
<i class="bi bi-download"></i> Export
</div>
<ul class="sidebar-nav">
<li class="nav-item">
<a class="nav-link" href="/export/licenses?format=excel">
<i class="bi bi-file-earmark-excel"></i>
<span>Excel Export</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/export/licenses?format=csv">
<i class="bi bi-file-earmark-text"></i>
<span>CSV Export</span>
</a>
</li>
</ul>
</aside>
<!-- Main Content Area -->
<div class="main-content" id="main-content">
<!-- Page Content -->
<div class="container-fluid p-4">
{% block content %}{% endblock %}
</div>
</div>
<!-- Session Warning Modal -->
<div id="session-warning" class="session-warning-modal" style="display: none;">

Datei anzeigen

@@ -4,13 +4,8 @@
{% block content %}
<div class="container py-5">
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="mb-4">
<h2>🔑 Batch-Lizenzen erstellen</h2>
<div>
<a href="/create" class="btn btn-secondary"> Einzellizenz</a>
<a href="/licenses" class="btn btn-secondary">📋 Lizenzen</a>
<a href="/customers" class="btn btn-secondary">👥 Kunden</a>
</div>
</div>
<div class="alert alert-info">

Datei anzeigen

@@ -25,25 +25,8 @@
{% block content %}
<div class="container py-5">
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="mb-4">
<h2>Kundenverwaltung</h2>
<div>
<a href="/customers-licenses" class="btn btn-success">
<i class="bi bi-layout-split"></i> Kombinierte Ansicht
</a>
<a href="/customer/create" class="btn btn-primary">👤 Neuer Kunde</a>
<a href="/create" class="btn btn-primary"> Neue Lizenz</a>
<a href="/batch" class="btn btn-primary">🔑 Batch-Lizenzen</a>
<div class="btn-group">
<button type="button" class="btn btn-info dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
📥 Export
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="/export/customers?format=excel">📊 Excel (.xlsx)</a></li>
<li><a class="dropdown-item" href="/export/customers?format=csv">📄 CSV (.csv)</a></li>
</ul>
</div>
</div>
</div>
<!-- Suchformular -->

Datei anzeigen

@@ -2,25 +2,11 @@
{% block title %}Kunden & Lizenzen - AccountForger Admin{% endblock %}
{% block content %}
<div class="container py-5">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2>👥 Kunden & Lizenzen</h2>
<div>
<a href="/customer/create" class="btn btn-primary">👤 Neuer Kunde</a>
<a href="/create" class="btn btn-success"> Neue Lizenz</a>
<a href="/batch" class="btn btn-primary">🔑 Batch-Lizenzen</a>
<div class="btn-group">
<button type="button" class="btn btn-info dropdown-toggle" data-bs-toggle="dropdown">
📥 Export
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="/export/licenses?format=excel">📊 Excel (.xlsx)</a></li>
<li><a class="dropdown-item" href="/export/licenses?format=csv">📄 CSV (.csv)</a></li>
</ul>
</div>
</div>
</div>
<div class="container-fluid">
<h2 class="mb-4">Kunden & Lizenzen</h2>
<div class="row">
<!-- Kundenliste (Links) -->
@@ -103,9 +89,6 @@
<a href="/customer/edit/{{ selected_customer[0] }}?ref=customers-licenses{% if request.args.get('show_test') %}&show_test=true{% endif %}" class="btn btn-sm btn-outline-primary">
<i class="bi bi-pencil"></i> Bearbeiten
</a>
<button class="btn btn-sm btn-success" onclick="showNewLicenseModal({{ selected_customer[0] }})">
<i class="bi bi-plus"></i> Neue Lizenz
</button>
</div>
</div>
{% else %}

Datei anzeigen

@@ -2,6 +2,8 @@
{% block title %}Dashboard{% endblock %}
{% block extra_css %}
<style>
.stat-card {
@@ -64,16 +66,8 @@
{% endblock %}
{% block content %}
<div class="container py-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h1>Dashboard</h1>
<div>
<a href="/customers-licenses{{ '?show_test=true' if request.args.get('show_test') == 'true' else '' }}" class="btn btn-success">👥 Kunden & Lizenzen</a>
<a href="/create{{ '?show_test=true' if request.args.get('show_test') == 'true' else '' }}" class="btn btn-primary"> Neue Lizenz</a>
<a href="/resources{{ '?show_test=true' if request.args.get('show_test') == 'true' else '' }}" class="btn btn-info">📦 Resource Pool</a>
<a href="/audit{{ '?show_test=true' if request.args.get('show_test') == 'true' else '' }}" class="btn btn-secondary">📝 Log</a>
</div>
</div>
<div class="container-fluid">
<h1 class="mb-4">Dashboard</h1>
<!-- Statistik-Karten -->
<div class="row g-3 mb-4">
@@ -274,14 +268,6 @@
<div class="card-header bg-primary text-white">
<h5 class="mb-0">
<i class="fas fa-server"></i> Resource Pool Status
<div class="float-end">
<a href="/resources/add{{ '?show_test=true' if request.args.get('show_test') == 'true' else '' }}" class="btn btn-sm btn-success me-1" title="Ressourcen hinzufügen">
<i class="bi bi-plus"></i> Hinzufügen
</a>
<a href="/resources{{ '?show_test=true' if request.args.get('show_test') == 'true' else '' }}" class="btn btn-sm btn-light">
Verwalten →
</a>
</div>
</h5>
</div>
<div class="card-body">

Datei anzeigen

@@ -4,15 +4,8 @@
{% block content %}
<div class="container py-5">
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="mb-4">
<h2>Neue Lizenz erstellen</h2>
<div>
<a href="/batch" class="btn btn-primary">🔑 Batch</a>
<a href="/licenses" class="btn btn-secondary">📋 Lizenzen</a>
<a href="/customers" class="btn btn-secondary">👥 Kunden</a>
<a href="/sessions" class="btn btn-secondary">🟢 Sessions</a>
<a href="/backups" class="btn btn-secondary">💾 Backups</a>
</div>
</div>
<form method="post" action="/create" accept-charset="UTF-8">

Datei anzeigen

@@ -28,24 +28,8 @@
{% block content %}
<div class="container py-5">
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="mb-4">
<h2>Lizenzübersicht</h2>
<div>
<a href="/customers-licenses" class="btn btn-success">
<i class="bi bi-layout-split"></i> Kombinierte Ansicht
</a>
<a href="/create" class="btn btn-primary"> Neue Lizenz</a>
<a href="/batch" class="btn btn-primary">🔑 Batch-Lizenzen</a>
<div class="btn-group">
<button type="button" class="btn btn-info dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
📥 Export
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="/export/licenses?format=excel">📊 Excel (.xlsx)</a></li>
<li><a class="dropdown-item" href="/export/licenses?format=csv">📄 CSV (.csv)</a></li>
</ul>
</div>
</div>
</div>
<!-- Such- und Filterformular -->

Datei anzeigen

@@ -2,6 +2,8 @@
{% block title %}Resource Pool{% endblock %}
{% block extra_css %}
<style>
/* Statistik-Karten Design wie Dashboard */
@@ -167,30 +169,12 @@
{% endblock %}
{% block content %}
<div class="container-fluid py-4">
<div class="container-fluid">
<!-- Header -->
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<div class="mb-4">
<h1 class="mb-0">Resource Pool</h1>
<p class="text-muted mb-0">Verwalten Sie Domains, IPs und Telefonnummern</p>
</div>
<div>
{% if request.referrer and 'customers-licenses' in request.referrer %}
<a href="{{ request.referrer }}" class="btn btn-outline-secondary">
<i class="bi bi-arrow-left"></i> Zurück zu Kunden
</a>
{% endif %}
<a href="{{ url_for('add_resources', show_test=show_test) }}" class="btn btn-success">
Ressourcen hinzufügen
</a>
<a href="{{ url_for('resources_metrics', show_test=show_test) }}" class="btn btn-info">
📊 Metriken
</a>
<a href="{{ url_for('resources_report', show_test=show_test) }}" class="btn btn-secondary">
📄 Report
</a>
</div>
</div>
<!-- Test/Live Mode Toggle -->
<div class="card mb-3">