modified: config.json new file: projects_webserver.json new file: public_projects_list.json modified: templates/available_projects.html new file: templates/available_projects_new.html modified: templates/docker_status.html
694 lines
27 KiB
HTML
694 lines
27 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Docker Status - {{ super() }}{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h2><i class="fas fa-docker me-2"></i>Docker Status & Diagnose</h2>
|
|
<div>
|
|
<button class="btn btn-outline-secondary me-2" onclick="reconnectDocker()">
|
|
<i class="fas fa-sync-alt"></i> Neu verbinden
|
|
</button>
|
|
<button class="btn btn-primary" onclick="runDiagnose()">
|
|
<i class="fas fa-stethoscope"></i> Diagnose ausführen
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Docker Status Cards -->
|
|
<div class="row mb-4">
|
|
<div class="col-md-3">
|
|
<div class="card">
|
|
<div class="card-body text-center">
|
|
<div class="stat-item">
|
|
<i class="fas fa-docker fa-2x mb-2" id="dockerIcon"></i>
|
|
<div class="stat-number" id="dockerStatus">Prüfung...</div>
|
|
<div class="text-muted">Docker Status</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="card">
|
|
<div class="card-body text-center">
|
|
<div class="stat-item">
|
|
<i class="fas fa-server fa-2x mb-2" id="daemonIcon"></i>
|
|
<div class="stat-number" id="daemonStatus">Prüfung...</div>
|
|
<div class="text-muted">Daemon Status</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="card">
|
|
<div class="card-body text-center">
|
|
<div class="stat-item">
|
|
<i class="fas fa-box fa-2x mb-2" id="containerIcon"></i>
|
|
<div class="stat-number" id="containerCount">-</div>
|
|
<div class="text-muted">Container</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="card">
|
|
<div class="card-body text-center">
|
|
<div class="stat-item">
|
|
<i class="fas fa-layer-group fa-2x mb-2" id="imageIcon"></i>
|
|
<div class="stat-number" id="imageCount">-</div>
|
|
<div class="text-muted">Images</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Diagnose Ergebnisse -->
|
|
<div class="row">
|
|
<div class="col-lg-8">
|
|
<div class="card">
|
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-clipboard-list me-2"></i>Diagnose Ergebnisse
|
|
</h5>
|
|
<span class="badge bg-secondary" id="lastUpdate">Noch nicht ausgeführt</span>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="diagnoseResults">
|
|
<div class="text-center text-muted py-4">
|
|
<i class="fas fa-info-circle fa-2x mb-3"></i>
|
|
<p>Klicken Sie auf "Diagnose ausführen" um Docker zu überprüfen.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Docker Logs -->
|
|
<div class="card mt-4">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-terminal me-2"></i>Docker System Logs
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="dockerLogs" class="bg-dark text-light p-3 rounded font-monospace small" style="height: 300px; overflow-y: auto;">
|
|
<div class="text-center text-muted">
|
|
Docker Logs werden geladen...
|
|
</div>
|
|
</div>
|
|
<div class="mt-2">
|
|
<button class="btn btn-outline-info btn-sm" onclick="refreshDockerLogs()">
|
|
<i class="fas fa-sync-alt"></i> Logs aktualisieren
|
|
</button>
|
|
<button class="btn btn-outline-warning btn-sm" onclick="clearDockerLogs()">
|
|
<i class="fas fa-broom"></i> Logs leeren
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-lg-4">
|
|
<!-- Schnellaktionen -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-bolt me-2"></i>Docker Aktionen
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-grid gap-2">
|
|
<button class="btn btn-success" onclick="startDockerDesktop()">
|
|
<i class="fas fa-play"></i> Docker Desktop starten
|
|
</button>
|
|
<button class="btn btn-warning" onclick="restartDockerDesktop()">
|
|
<i class="fas fa-redo"></i> Docker Desktop neustarten
|
|
</button>
|
|
<button class="btn btn-info" onclick="pullHelloWorld()">
|
|
<i class="fas fa-download"></i> Test Image herunterladen
|
|
</button>
|
|
<button class="btn btn-outline-secondary" onclick="openDockerDesktop()">
|
|
<i class="fas fa-external-link-alt"></i> Docker Desktop öffnen
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Systemanforderungen -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-clipboard-check me-2"></i>Systemanforderungen
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="requirements-list">
|
|
<div class="requirement-item mb-2">
|
|
<i class="fas fa-check text-success me-2"></i>
|
|
<span>Windows 10/11 (64-bit)</span>
|
|
</div>
|
|
<div class="requirement-item mb-2">
|
|
<i class="fas fa-check text-success me-2"></i>
|
|
<span>Hyper-V oder WSL2</span>
|
|
</div>
|
|
<div class="requirement-item mb-2">
|
|
<i class="fas fa-question text-warning me-2" id="ramCheck"></i>
|
|
<span>4GB+ RAM empfohlen</span>
|
|
</div>
|
|
<div class="requirement-item mb-2">
|
|
<i class="fas fa-question text-warning me-2" id="diskCheck"></i>
|
|
<span>20GB+ freier Speicher</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Hilfe & Ressourcen -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-question-circle me-2"></i>Hilfe & Ressourcen
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-grid gap-2">
|
|
<a href="https://docs.docker.com/desktop/windows/" target="_blank" class="btn btn-outline-primary btn-sm">
|
|
<i class="fas fa-book"></i> Docker Desktop Docs
|
|
</a>
|
|
<a href="https://docs.docker.com/desktop/troubleshoot/" target="_blank" class="btn btn-outline-info btn-sm">
|
|
<i class="fas fa-wrench"></i> Troubleshooting Guide
|
|
</a>
|
|
<a href="https://www.docker.com/products/docker-desktop/" target="_blank" class="btn btn-outline-success btn-sm">
|
|
<i class="fas fa-download"></i> Docker Desktop Download
|
|
</a>
|
|
<button class="btn btn-outline-warning btn-sm" onclick="exportDiagnose()">
|
|
<i class="fas fa-file-export"></i> Diagnose exportieren
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Installation Modal -->
|
|
<div class="modal fade" id="installModal" tabindex="-1">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Docker Desktop Installation</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<h6>Installationsschritte:</h6>
|
|
<ol>
|
|
<li>Laden Sie Docker Desktop von <a href="https://www.docker.com/products/docker-desktop/" target="_blank">docker.com</a> herunter</li>
|
|
<li>Führen Sie die Installationsdatei als Administrator aus</li>
|
|
<li>Folgen Sie dem Installationsassistenten</li>
|
|
<li>Starten Sie Ihren Computer neu</li>
|
|
<li>Starten Sie Docker Desktop</li>
|
|
<li>Warten Sie bis Docker vollständig geladen ist</li>
|
|
</ol>
|
|
|
|
<div class="alert alert-info">
|
|
<i class="fas fa-info-circle me-2"></i>
|
|
<strong>Hinweis:</strong> Docker Desktop erfordert Hyper-V oder WSL2.
|
|
Diese werden automatisch aktiviert falls nötig.
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Schließen</button>
|
|
<a href="https://www.docker.com/products/docker-desktop/" target="_blank" class="btn btn-primary">
|
|
<i class="fas fa-download"></i> Docker Desktop herunterladen
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script>
|
|
let lastDiagnoseData = null;
|
|
|
|
// Führe Diagnose aus
|
|
function runDiagnose() {
|
|
const button = event.target;
|
|
const originalText = button.innerHTML;
|
|
button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Läuft...';
|
|
button.disabled = true;
|
|
|
|
fetch('/api/docker_diagnose')
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
}
|
|
return response.json();
|
|
})
|
|
.then(data => {
|
|
if (data.error) {
|
|
throw new Error(data.error);
|
|
}
|
|
|
|
lastDiagnoseData = data;
|
|
displayDiagnoseResults(data);
|
|
updateStatusCards(data);
|
|
|
|
if (data.timestamp) {
|
|
try {
|
|
const timestamp = new Date(data.timestamp).toLocaleString();
|
|
document.getElementById('lastUpdate').textContent = timestamp;
|
|
} catch {
|
|
document.getElementById('lastUpdate').textContent = 'Gerade eben';
|
|
}
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Diagnose-Fehler:', error);
|
|
document.getElementById('diagnoseResults').innerHTML = `
|
|
<div class="alert alert-danger">
|
|
<i class="fas fa-exclamation-triangle me-2"></i>
|
|
Fehler bei der Diagnose: ${error.message || error}
|
|
<br><small class="text-muted mt-2 d-block">
|
|
Stellen Sie sicher, dass Docker läuft und versuchen Sie es erneut.
|
|
<a href="#" onclick="reconnectDocker(); return false;">Docker-Verbindung wiederherstellen</a>
|
|
</small>
|
|
</div>
|
|
`;
|
|
setDefaultCardStates();
|
|
})
|
|
.finally(() => {
|
|
button.innerHTML = originalText;
|
|
button.disabled = false;
|
|
});
|
|
}
|
|
|
|
// Zeige Diagnose-Ergebnisse
|
|
function displayDiagnoseResults(data) {
|
|
const container = document.getElementById('diagnoseResults');
|
|
|
|
if (!data || !data.checks || typeof data.checks !== 'object') {
|
|
container.innerHTML = `
|
|
<div class="alert alert-warning">
|
|
<i class="fas fa-exclamation-triangle me-2"></i>
|
|
Keine Diagnose-Daten verfügbar.
|
|
</div>
|
|
`;
|
|
return;
|
|
}
|
|
|
|
let html = '';
|
|
|
|
try {
|
|
for (const [checkName, result] of Object.entries(data.checks)) {
|
|
if (!result || typeof result !== 'object') {
|
|
continue;
|
|
}
|
|
|
|
const icon = result.success ? 'fa-check text-success' : 'fa-times text-danger';
|
|
const title = formatCheckName(checkName);
|
|
const output = result.output || 'Keine Ausgabe';
|
|
const details = result.details || '';
|
|
|
|
html += `
|
|
<div class="d-flex align-items-start mb-3">
|
|
<i class="fas ${icon} me-3 mt-1"></i>
|
|
<div class="flex-grow-1">
|
|
<h6 class="mb-1">${title}</h6>
|
|
<p class="mb-0 text-muted small">${output}</p>
|
|
${details ? `<small class="text-muted">${details}</small>` : ''}
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// Zeige Empfehlungen falls vorhanden
|
|
if (data.recommendations && Array.isArray(data.recommendations) && data.recommendations.length > 0) {
|
|
html += `
|
|
<hr>
|
|
<h6 class="text-primary"><i class="fas fa-lightbulb me-2"></i>Empfehlungen:</h6>
|
|
<ul class="list-unstyled">
|
|
`;
|
|
|
|
data.recommendations.forEach(rec => {
|
|
if (typeof rec === 'string' && rec.trim()) {
|
|
html += `<li class="text-muted small"><i class="fas fa-arrow-right me-2"></i>${rec}</li>`;
|
|
}
|
|
});
|
|
|
|
html += '</ul>';
|
|
}
|
|
|
|
} catch (e) {
|
|
console.error('Fehler beim Anzeigen der Diagnose-Ergebnisse:', e);
|
|
html = `
|
|
<div class="alert alert-danger">
|
|
<i class="fas fa-exclamation-triangle me-2"></i>
|
|
Fehler beim Verarbeiten der Diagnose-Daten.
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
if (!html) {
|
|
html = '<div class="text-center text-muted">Keine Diagnose-Daten verfügbar.</div>';
|
|
}
|
|
|
|
container.innerHTML = html;
|
|
}
|
|
|
|
// Formatiere Check-Namen
|
|
function formatCheckName(name) {
|
|
const names = {
|
|
'docker_version': 'Docker Version',
|
|
'docker_daemon': 'Docker Daemon',
|
|
'containers': 'Container Status',
|
|
'images': 'Docker Images'
|
|
};
|
|
return names[name] || name;
|
|
}
|
|
|
|
// Update Status-Cards
|
|
function updateStatusCards(data) {
|
|
// Sicherheitscheck für data.checks
|
|
if (!data || !data.checks || typeof data.checks !== 'object') {
|
|
console.warn('Fehlende oder ungültige Diagnose-Daten:', data);
|
|
setDefaultCardStates();
|
|
return;
|
|
}
|
|
|
|
// Docker Status
|
|
try {
|
|
if (data.checks.docker_version) {
|
|
const dockerIcon = document.getElementById('dockerIcon');
|
|
const dockerStatus = document.getElementById('dockerStatus');
|
|
|
|
if (dockerIcon && dockerStatus) {
|
|
if (data.checks.docker_version.success) {
|
|
dockerIcon.className = 'fas fa-cube fa-2x mb-2 text-success';
|
|
dockerStatus.textContent = 'Installiert';
|
|
dockerStatus.className = 'stat-number text-success';
|
|
} else {
|
|
dockerIcon.className = 'fas fa-cube fa-2x mb-2 text-danger';
|
|
dockerStatus.textContent = 'Nicht verfügbar';
|
|
dockerStatus.className = 'stat-number text-danger';
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.error('Fehler beim Update Docker Status:', e);
|
|
}
|
|
|
|
// Daemon Status
|
|
try {
|
|
if (data.checks.docker_daemon) {
|
|
const daemonIcon = document.getElementById('daemonIcon');
|
|
const daemonStatus = document.getElementById('daemonStatus');
|
|
|
|
if (daemonIcon && daemonStatus) {
|
|
if (data.checks.docker_daemon.success) {
|
|
daemonIcon.className = 'fas fa-server fa-2x mb-2 text-success';
|
|
daemonStatus.textContent = 'Läuft';
|
|
daemonStatus.className = 'stat-number text-success';
|
|
} else {
|
|
daemonIcon.className = 'fas fa-server fa-2x mb-2 text-danger';
|
|
daemonStatus.textContent = 'Gestoppt';
|
|
daemonStatus.className = 'stat-number text-danger';
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.error('Fehler beim Update Daemon Status:', e);
|
|
}
|
|
|
|
// Container Count - mit Sicherheitschecks
|
|
try {
|
|
if (data.checks.containers) {
|
|
const containerCount = document.getElementById('containerCount');
|
|
const containerIcon = document.getElementById('containerIcon');
|
|
|
|
if (containerCount && containerIcon) {
|
|
if (data.checks.containers.success &&
|
|
data.checks.containers.containers &&
|
|
Array.isArray(data.checks.containers.containers)) {
|
|
|
|
const containers = data.checks.containers.containers;
|
|
const count = containers.length;
|
|
containerCount.textContent = count;
|
|
|
|
// Zähle laufende Container sicher
|
|
const running = containers.filter(c => {
|
|
try {
|
|
return c && (c.State === 'running' || c.status === 'running');
|
|
} catch {
|
|
return false;
|
|
}
|
|
}).length;
|
|
|
|
containerCount.title = `${running} laufend, ${count - running} gestoppt`;
|
|
|
|
if (count > 0) {
|
|
containerIcon.className = 'fas fa-box fa-2x mb-2 text-success';
|
|
} else {
|
|
containerIcon.className = 'fas fa-box fa-2x mb-2 text-secondary';
|
|
}
|
|
} else {
|
|
containerCount.textContent = '0';
|
|
containerIcon.className = 'fas fa-box fa-2x mb-2 text-danger';
|
|
containerCount.title = 'Container können nicht gelesen werden';
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.error('Fehler beim Update Container Status:', e);
|
|
}
|
|
|
|
// Image Count - mit Sicherheitschecks
|
|
try {
|
|
if (data.checks.images) {
|
|
const imageCount = document.getElementById('imageCount');
|
|
const imageIcon = document.getElementById('imageIcon');
|
|
|
|
if (imageCount && imageIcon) {
|
|
if (data.checks.images.success && data.checks.images.output) {
|
|
// Extrahiere Anzahl aus output-Text (z.B. "5 Images")
|
|
const match = data.checks.images.output.match(/(\d+)/);
|
|
const count = match ? parseInt(match[1], 10) : 0;
|
|
imageCount.textContent = count;
|
|
|
|
if (count > 0) {
|
|
imageIcon.className = 'fas fa-layer-group fa-2x mb-2 text-success';
|
|
} else {
|
|
imageIcon.className = 'fas fa-layer-group fa-2x mb-2 text-warning';
|
|
}
|
|
} else {
|
|
imageCount.textContent = '0';
|
|
imageIcon.className = 'fas fa-layer-group fa-2x mb-2 text-danger';
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.error('Fehler beim Update Image Status:', e);
|
|
}
|
|
}
|
|
|
|
function setDefaultCardStates() {
|
|
// Setze alle Cards auf einen sicheren Default-Zustand
|
|
try {
|
|
const elements = [
|
|
{icon: 'dockerIcon', status: 'dockerStatus', iconClass: 'fas fa-cube fa-2x mb-2 text-secondary', text: 'Unbekannt'},
|
|
{icon: 'daemonIcon', status: 'daemonStatus', iconClass: 'fas fa-server fa-2x mb-2 text-secondary', text: 'Unbekannt'},
|
|
{icon: 'containerIcon', status: 'containerCount', iconClass: 'fas fa-box fa-2x mb-2 text-secondary', text: '-'},
|
|
{icon: 'imageIcon', status: 'imageCount', iconClass: 'fas fa-layer-group fa-2x mb-2 text-secondary', text: '-'}
|
|
];
|
|
|
|
elements.forEach(el => {
|
|
const iconEl = document.getElementById(el.icon);
|
|
const statusEl = document.getElementById(el.status);
|
|
|
|
if (iconEl) iconEl.className = el.iconClass;
|
|
if (statusEl) {
|
|
statusEl.textContent = el.text;
|
|
statusEl.className = 'stat-number text-muted';
|
|
}
|
|
});
|
|
} catch (e) {
|
|
console.error('Fehler beim Setzen der Default-Zustände:', e);
|
|
}
|
|
}
|
|
|
|
// Docker Reconnect
|
|
function reconnectDocker() {
|
|
const button = event.target.closest('button');
|
|
const originalText = button.innerHTML;
|
|
button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Verbinde...';
|
|
button.disabled = true;
|
|
|
|
fetch('/api/docker_reconnect', {
|
|
method: 'POST'
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
showToast('success', 'Docker-Verbindung wiederhergestellt');
|
|
// Diagnose automatisch neu ausführen
|
|
setTimeout(() => runDiagnose(), 500);
|
|
} else {
|
|
showToast('error', `Fehler beim Verbinden: ${data.error}`);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Docker Reconnect Fehler:', error);
|
|
showToast('error', 'Netzwerkfehler beim Reconnect');
|
|
})
|
|
.finally(() => {
|
|
button.innerHTML = originalText;
|
|
button.disabled = false;
|
|
});
|
|
}
|
|
|
|
// Toast-Funktion für Benachrichtigungen
|
|
function showToast(type, message) {
|
|
const toastContainer = getOrCreateToastContainer();
|
|
|
|
const toastId = 'toast-' + Date.now();
|
|
const toastClass = type === 'success' ? 'bg-success' : type === 'error' ? 'bg-danger' : 'bg-info';
|
|
const iconClass = type === 'success' ? 'fas fa-check' : type === 'error' ? 'fas fa-exclamation-triangle' : 'fas fa-info-circle';
|
|
|
|
const toastHtml = `
|
|
<div id="${toastId}" class="toast ${toastClass} text-white" role="alert" data-bs-delay="5000">
|
|
<div class="toast-header ${toastClass} text-white border-0">
|
|
<i class="${iconClass} me-2"></i>
|
|
<strong class="me-auto">${type === 'success' ? 'Erfolg' : type === 'error' ? 'Fehler' : 'Info'}</strong>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="toast"></button>
|
|
</div>
|
|
<div class="toast-body">
|
|
${message}
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
toastContainer.insertAdjacentHTML('beforeend', toastHtml);
|
|
|
|
const toastElement = document.getElementById(toastId);
|
|
const toast = new bootstrap.Toast(toastElement);
|
|
toast.show();
|
|
|
|
// Automatisch entfernen nach dem Ausblenden
|
|
toastElement.addEventListener('hidden.bs.toast', () => {
|
|
toastElement.remove();
|
|
});
|
|
}
|
|
|
|
function getOrCreateToastContainer() {
|
|
let container = document.getElementById('toast-container');
|
|
if (!container) {
|
|
container = document.createElement('div');
|
|
container.id = 'toast-container';
|
|
container.className = 'toast-container position-fixed top-0 end-0 p-3';
|
|
container.style.zIndex = '9999';
|
|
document.body.appendChild(container);
|
|
}
|
|
return container;
|
|
}
|
|
|
|
// Docker Desktop Aktionen
|
|
function startDockerDesktop() {
|
|
alert('Bitte starten Sie Docker Desktop manuell über das Startmenü.');
|
|
}
|
|
|
|
function restartDockerDesktop() {
|
|
if (confirm('Docker Desktop neustarten? Dies kann einige Minuten dauern.')) {
|
|
alert('Bitte starten Sie Docker Desktop manuell neu:\n1. Docker Desktop schließen\n2. Docker Desktop wieder öffnen\n3. Warten bis vollständig geladen');
|
|
}
|
|
}
|
|
|
|
function pullHelloWorld() {
|
|
const button = event.target;
|
|
const originalText = button.innerHTML;
|
|
button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Lädt...';
|
|
button.disabled = true;
|
|
|
|
// Simuliere Docker Pull (in echter Implementation würde hier eine API-Call erfolgen)
|
|
setTimeout(() => {
|
|
alert('Test abgeschlossen. Prüfen Sie die Diagnose für Details.');
|
|
button.innerHTML = originalText;
|
|
button.disabled = false;
|
|
runDiagnose();
|
|
}, 3000);
|
|
}
|
|
|
|
function openDockerDesktop() {
|
|
// Versuche Docker Desktop zu öffnen
|
|
alert('Suchen Sie nach "Docker Desktop" im Startmenü oder klicken Sie auf das Docker-Symbol in der Taskleiste.');
|
|
}
|
|
|
|
// Docker Logs
|
|
function refreshDockerLogs() {
|
|
const logsContainer = document.getElementById('dockerLogs');
|
|
logsContainer.innerHTML = '<div class="text-center text-muted">Docker Logs werden geladen...</div>';
|
|
|
|
// Simuliere Log-Abruf
|
|
setTimeout(() => {
|
|
const logs = `[${new Date().toISOString()}] Docker Desktop starting...
|
|
[${new Date().toISOString()}] Hyper-V backend initialized
|
|
[${new Date().toISOString()}] WSL2 engine started
|
|
[${new Date().toISOString()}] Docker daemon started
|
|
[${new Date().toISOString()}] Ready for connections`;
|
|
|
|
logsContainer.innerHTML = `<pre class="mb-0">${logs}</pre>`;
|
|
logsContainer.scrollTop = logsContainer.scrollHeight;
|
|
}, 1000);
|
|
}
|
|
|
|
function clearDockerLogs() {
|
|
if (confirm('Docker Logs leeren?')) {
|
|
document.getElementById('dockerLogs').innerHTML = '<div class="text-center text-muted">Logs geleert</div>';
|
|
}
|
|
}
|
|
|
|
// Export Diagnose
|
|
function exportDiagnose() {
|
|
if (!lastDiagnoseData) {
|
|
alert('Bitte führen Sie zuerst eine Diagnose aus.');
|
|
return;
|
|
}
|
|
|
|
const dataStr = JSON.stringify(lastDiagnoseData, null, 2);
|
|
const blob = new Blob([dataStr], {type: 'application/json'});
|
|
const url = URL.createObjectURL(blob);
|
|
|
|
const a = document.createElement('a');
|
|
a.href = url;
|
|
a.download = `docker_diagnose_${new Date().toISOString().split('T')[0]}.json`;
|
|
a.click();
|
|
|
|
URL.revokeObjectURL(url);
|
|
}
|
|
|
|
// Auto-Diagnose beim Laden
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Führe automatische Icon-Reparatur aus
|
|
setTimeout(() => {
|
|
const dockerIcon = document.getElementById('dockerIcon');
|
|
if (dockerIcon) {
|
|
const computed = window.getComputedStyle(dockerIcon);
|
|
const content = computed.getPropertyValue('content');
|
|
|
|
// Wenn Icon nicht lädt, verwende Fallback
|
|
if (content === 'none' || content === '"\\f2dc"' || content === '"\\f1c0"') {
|
|
console.log('Docker Icon wird repariert...');
|
|
dockerIcon.className = 'bi bi-cube fs-1 mb-2';
|
|
dockerIcon.style.color = '#007bff';
|
|
}
|
|
}
|
|
}, 500);
|
|
|
|
runDiagnose();
|
|
refreshDockerLogs();
|
|
});
|
|
</script>
|
|
{% endblock %}
|