QueryBuilder/app/templates/dashboard.html
2025-10-14 21:27:41 +02:00

255 lines
11 KiB
HTML

{% extends "base.html" %}
{% block title %}Dashboard - Query Builder{% endblock %}
{% block content %}
<div class="row h-100">
<!-- Linke Sidebar - Tabellen -->
<div class="col-md-2 border-end bg-light">
<div class="p-3">
<!-- Datenbankauswahl Section -->
<div class="mb-4">
<h6><i class="fas fa-database"></i> Datenbankverbindung</h6>
<select id="database-selector" class="form-select form-select-sm" onchange="onDatabaseChange()">
<option value="demo">Lade Verbindungen...</option>
</select>
<button class="btn btn-sm btn-outline-info mt-2 w-100" onclick="testConnection()">
<i class="fas fa-plug"></i> Verbindung testen
</button>
</div>
<!-- Tabellen Section -->
<div class="mb-4">
<h5>
<i class="fas fa-table"></i> Tabellen
<div class="float-end">
<button class="btn btn-sm btn-outline-secondary" id="toggle-columns-btn" onclick="toggleColumnsView()" title="Spalten ein/ausblenden">
<i class="fas fa-eye"></i>
</button>
<button class="btn btn-sm btn-outline-primary" onclick="loadTables()">
<i class="fas fa-sync-alt"></i>
</button>
</div>
</h5>
<div id="tables-list">
<div class="text-muted">Lade Tabellen...</div>
</div>
</div>
</div>
</div>
<!-- Hauptbereich - Query Editor und Ergebnisse -->
<!-- Mittlere Spalte - Query Editor und Ergebnisse -->
<div class="col-md-8">
<div class="p-3">
<!-- Query Editor Section -->
<div class="mb-4">
<h5><i class="fas fa-code"></i> SQL Query Editor</h5>
<div class="card">
<div class="card-body">
<div class="position-relative">
<textarea id="query-input" class="form-control mb-3" rows="8"
placeholder="Geben Sie hier Ihre Oracle SQL-Query ein...&#10;&#10;Beispiel für Oracle:&#10;SELECT * FROM USERS WHERE ROWNUM <= 10"></textarea>
<div id="autocomplete-dropdown" class="autocomplete-dropdown"></div>
</div>
<div class="btn-group">
<button class="btn btn-primary" onclick="executeQuery()">
<i class="fas fa-play"></i> Query Ausführen
</button>
<button type="button" class="btn btn-success" id="save-query-btn">
<i class="fas fa-save"></i> Query Speichern
</button>
<button class="btn btn-secondary" onclick="clearQuery()">
<i class="fas fa-trash"></i> Löschen
</button>
</div>
</div>
</div>
</div>
<!-- Ergebnisse Section -->
<div class="mb-3">
<h5><i class="fas fa-table"></i> Query-Ergebnisse</h5>
<div id="results-container" class="card">
<div class="card-body">
<div class="text-muted text-center py-4">
Führen Sie eine Query aus, um Ergebnisse anzuzeigen
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Rechte Sidebar - Gespeicherte Queries -->
<div class="col-md-2 border-start bg-light">
<div class="p-2 h-100">
<div class="mb-3">
<h6><i class="fas fa-bookmark"></i> Gespeicherte Queries</h6>
</div>
<!-- Query-Suche -->
<div class="mb-3">
<input type="text" id="query-search" class="form-control form-control-sm"
placeholder="Query suchen..." onkeyup="filterSavedQueries()">
</div>
<!-- Gespeicherte Queries Liste -->
<div id="saved-queries-list" class="overflow-auto" style="max-height: calc(100vh - 250px);">
{% for query in saved_queries %}
<div class="card mb-2 saved-query-card" data-query-id="{{ query.id }}">
<div class="card-body p-2">
<div class="d-flex justify-content-between align-items-start">
<div class="flex-grow-1" style="cursor: pointer;" onclick="loadSavedQuery({{ query.id }})">
<h6 class="card-title mb-1 text-primary">{{ query.name }}</h6>
<small class="text-muted d-block mb-1">{{ query.created_at.strftime('%d.%m.%Y %H:%M') }}</small>
<small class="text-muted query-preview">{{ query.query[:100] }}{% if query.query|length > 100 %}...{% endif %}</small>
</div>
<div class="dropdown">
<button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown">
<i class="fas fa-ellipsis-v"></i>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" onclick="loadSavedQuery({{ query.id }})">
<i class="fas fa-play"></i> Laden
</a></li>
<li><a class="dropdown-item" href="#" onclick="editQueryName({{ query.id }})">
<i class="fas fa-edit"></i> Umbenennen
</a></li>
<li><a class="dropdown-item" href="#" onclick="duplicateQuery({{ query.id }})">
<i class="fas fa-copy"></i> Duplizieren
</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item text-danger" href="#" onclick="deleteSavedQuery({{ query.id }})">
<i class="fas fa-trash"></i> Löschen
</a></li>
</ul>
</div>
</div>
</div>
</div>
{% endfor %}
<!-- Platzhalter wenn keine Queries vorhanden -->
<div id="no-queries-placeholder" class="text-center text-muted py-4" {% if saved_queries %}style="display: none;"{% endif %}>
<i class="fas fa-bookmark fa-2x mb-2"></i>
<p>Keine gespeicherten Queries vorhanden.</p>
<small>Speichern Sie Ihre erste Query mit dem <i class="fas fa-save"></i> Button!</small>
</div>
</div>
</div>
</div>
</div>
<!-- Save Query Modal -->
<div class="modal fade" id="saveQueryModal" tabindex="-1">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Query speichern</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="query-name" class="form-label">Query-Name:</label>
<input type="text" class="form-control" id="query-name"
placeholder="z.B. Benutzer-Liste" required autofocus>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Abbrechen</button>
<button type="button" class="btn btn-success" onclick="saveQuery()">
<i class="fas fa-save"></i> Speichern
</button>
</div>
</div>
</div>
</div>
<!-- Edit Query Name Modal -->
<div class="modal fade" id="editQueryModal" tabindex="-1">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Query umbenennen</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="edit-query-name" class="form-label">Neuer Name:</label>
<input type="text" class="form-control" id="edit-query-name" required autofocus>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Abbrechen</button>
<button type="button" class="btn btn-primary" onclick="updateQueryName()">
<i class="fas fa-save"></i> Umbenennen
</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
// Verbindungen werden automatisch in app.js geladen
// currentConnection ist jetzt in app.js definiert
// Die loadConnections und onDatabaseChange Funktionen sind jetzt in app.js
// Teste Datenbankverbindung
function testConnection() {
const button = event.target;
const originalText = button.innerHTML;
button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Teste...';
button.disabled = true;
fetch(`/test_connection/${currentConnection}`)
.then(response => response.json())
.then(data => {
if (data.success) {
showAlert('success', `${data.message}`);
} else {
showAlert('danger', `${data.message}`);
}
})
.catch(error => {
showAlert('danger', `Fehler beim Testen der Verbindung: ${error}`);
})
.finally(() => {
button.innerHTML = originalText;
button.disabled = false;
});
}
// Hilfsfunktion für Alerts
function showAlert(type, message) {
// Entferne vorhandene Alerts
const existingAlert = document.querySelector('.alert');
if (existingAlert) {
existingAlert.remove();
}
// Erstelle neues Alert
const alertDiv = document.createElement('div');
alertDiv.className = `alert alert-${type} alert-dismissible fade show`;
alertDiv.innerHTML = `
${message}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
`;
// Füge Alert am Anfang des Contents ein
const content = document.querySelector('.container-fluid');
content.insertBefore(alertDiv, content.firstChild);
// Auto-hide nach 5 Sekunden
setTimeout(() => {
if (alertDiv && alertDiv.parentNode) {
alertDiv.remove();
}
}, 5000);
}
</script>
{% endblock %}