Files
hostpanel/templates/ssh_manager/projeler.html
ilkeral f4ee7a2d0b yeni
2025-08-08 07:24:25 +03:00

881 lines
37 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% extends 'ssh_manager/base.html' %}
{% block title %}Projeler - Hosting Yönetim Paneli{% endblock %}
{% block content %}
<!-- Projeler Header -->
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<h3 class="mb-1">
<i class="bi bi-folder-fill me-2"></i>Projeler
</h3>
<small class="text-muted">Tüm hosting projeleri ve yönetim işlemleri</small>
</div>
<div class="d-flex gap-2">
<select id="statusFilter" class="form-select" style="max-width: 180px;">
<option value="">Tüm Projeler</option>
<option value="active">🟢 Aktif Projeler</option>
<option value="inactive">🔴 Pasif Projeler</option>
<option value="unknown">⚫ Bilinmeyen Durumlar</option>
<option value="no-url">🔘 URL'siz Projeler</option>
</select>
<input type="text" id="projectSearch" class="form-control" style="max-width: 250px;" placeholder="Proje ara...">
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addProjectModal">
<i class="bi bi-plus-circle"></i>
</button>
</div>
</div>
<!-- Projeler Tablosu -->
<div class="table-responsive">
<table class="table table-dark table-striped">
<thead>
<tr>
<th>#</th>
<th>Proje Bilgileri</th>
<th>Klasör & Disk</th>
<th>Site Durumu</th>
<th>Host Yenileme</th>
<th>Son Yedekleme</th>
<th class="actions">İşlemler</th>
</tr>
</thead>
<tbody>
{% for project in projects %}
<tr>
<td>{{ forloop.counter }}</td>
<td style="line-height: 1.3;">
<div class="fw-bold">{{ project.name }}</div>
{% if project.customer %}
<small class="text-info">
<i class="bi bi-person me-1"></i>{{ project.customer.get_display_name }}
</small><br>
{% endif %}
{% if project.ssh_credential %}
<small class="text-muted">
<i class="bi bi-server me-1"></i>{{ project.ssh_credential.hostname }}
</small>
{% else %}
<small class="text-danger">SSH credential yok</small>
{% endif %}
</td>
<td style="line-height: 1.3;">
<div class="fw-bold">{{ project.folder_name }}</div>
{% if project.disk_usage %}
<small class="text-muted">
<i class="bi bi-hdd me-1"></i>{{ project.disk_usage }}
</small>
{% else %}
<small class="text-muted">-</small>
{% endif %}
</td>
<td>
{% if project.url %}
<div class="d-flex align-items-center mb-1">
{% if project.is_site_active %}
<span class="badge bg-success me-2" title="Site aktif">
<i class="bi bi-check-circle"></i> Aktif
</span>
{% elif project.last_site_check %}
<span class="badge bg-danger me-2" title="Site pasif">
<i class="bi bi-x-circle"></i> Pasif
</span>
{% else %}
<span class="badge bg-secondary me-2" title="Kontrol edilmemiş">
<i class="bi bi-question-circle"></i> Bilinmiyor
</span>
{% endif %}
</div>
<a href="{% if not project.url|slice:':4' == 'http' %}http://{% endif %}{{ project.url }}" target="_blank" class="text-decoration-none small" style="color: #4fc3f7;">
<i class="bi bi-globe me-1"></i>{{ project.url }}
</a>
{% else %}
<span class="text-muted">URL tanımlanmamış</span>
{% endif %}
</td>
<td>
{% if project.host_renewal_date %}
{% if project.host_renewal_date <= today %}
<small class="text-danger fw-bold">{{ project.host_renewal_date|date:"d.m.Y" }}</small>
<br><span class="badge bg-danger">Süresi Dolmuş</span>
{% elif project.host_renewal_date <= warning_date %}
<small>{{ project.host_renewal_date|date:"d.m.Y" }}</small>
<br><span class="badge bg-warning">Yaklaşıyor</span>
{% else %}
<small>{{ project.host_renewal_date|date:"d.m.Y" }}</small>
{% endif %}
{% else %}
<span class="text-muted">Tarih yok</span>
{% endif %}
</td>
<td>
{% if project.last_backup %}
<small>{{ project.last_backup|date:"d.m.Y H:i" }}</small>
{% else %}
<span class="text-warning">Yedek alınmamış</span>
{% endif %}
</td>
<td class="actions">
<i class="action-icon edit bi bi-pencil" onclick="ProjectManager.editProject({{ project.id }})" title="Düzenle"></i>
<i class="action-icon delete bi bi-trash" onclick="ProjectManager.deleteProject({{ project.id }})" title="Sil"></i>
<i class="action-icon renewal bi bi-calendar-plus" onclick="ProjectManager.renewHost({{ project.id }})" title="Domain Expiration Tarihi Sorgula ve Host Yenile"></i>
<i class="action-icon backup bi bi-cloud-arrow-up" onclick="ProjectManager.backupProject({{ project.id }})" title="Yedekle"></i>
<i class="action-icon logs bi bi-journal-text" onclick="ProjectManager.showLogsByProject({{ project.id }})" title="Loglar"></i>
{% if project.url %}
<i class="action-icon site bi bi-globe-americas" onclick="ProjectManager.checkSiteStatus({{ project.id }})" title="Site Kontrol"></i>
<i class="action-icon meta bi bi-key" onclick="ProjectManager.showMetaKey({{ project.id }})" title="Meta Key"></i>
{% endif %}
</td>
</tr>
{% empty %}
<tr>
<td colspan="6" class="text-center text-muted py-4">
<i class="bi bi-folder" style="font-size: 2rem;"></i>
<div class="mt-2">Henüz proje eklenmemiş</div>
<button class="btn btn-sm btn-outline-primary mt-2" data-bs-toggle="modal" data-bs-target="#addProjectModal">
İlk projeyi ekle
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Proje Ekleme/Düzenleme Modal -->
<div class="modal fade" id="addProjectModal" tabindex="-1" aria-labelledby="addProjectModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content">
<form id="projectForm">
<input type="hidden" id="projectId" name="id" value="">
<div class="modal-header">
<h5 class="modal-title" id="addProjectModalLabel">Yeni Proje Ekle</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Kapat"></button>
</div>
<div class="modal-body">
<input type="hidden" id="projectId" name="projectId">
<!-- Proje Bilgileri -->
<div class="mb-4">
<h6 class="text-muted mb-3">
<i class="bi bi-folder me-1"></i>Proje Bilgileri
</h6>
<div class="row g-3">
<div class="col-md-6">
<label for="name" class="form-label">Proje Adı *</label>
<input type="text" class="form-control" id="name" name="name" required placeholder="Proje adı">
</div>
<div class="col-md-6">
<label for="folder_name" class="form-label">Klasör Adı *</label>
<input type="text" class="form-control" id="folder_name" name="folder_name" required placeholder="Sunucudaki klasör adı">
</div>
<div class="col-md-6">
<label for="customer" class="form-label">Müşteri</label>
<select class="form-select" id="customer" name="customer">
<option value="">Müşteri Seçiniz (Opsiyonel)</option>
{% for customer in customers %}
<option value="{{ customer.id }}">{{ customer.get_display_name }} ({{ customer.get_customer_type_display }})</option>
{% endfor %}
</select>
</div>
<div class="col-md-6">
<label for="ssh_credential" class="form-label">Host *</label>
<select class="form-select" id="ssh_credential" name="ssh_credential" required>
<option value="">Host Seçiniz</option>
{% for host in ssh_credentials %}
<option value="{{ host.id }}">{{ host.name|default:host.hostname }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
<!-- Site Bilgileri -->
<div class="mb-3">
<h6 class="text-muted mb-3">
<i class="bi bi-globe me-1"></i>Site Bilgileri
</h6>
<div class="row g-3">
<div class="col-md-8">
<label for="url" class="form-label">Site URL'i</label>
<input type="text" class="form-control" id="url" name="url" placeholder="https://example.com">
<small class="text-muted">Site aktiflik kontrolü için gerekli</small>
</div>
<div class="col-md-4">
<label for="host_renewal_date" class="form-label">Host Yenileme Tarihi</label>
<input type="date" class="form-control" id="host_renewal_date" name="host_renewal_date">
<small class="text-muted">Hosting paketi yenileme tarihi</small>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Kapat</button>
<button type="submit" class="btn btn-primary">Kaydet</button>
</div>
</form>
</div>
</div>
</div>
<!-- Log Modal -->
<div class="modal fade" id="logsModal" tabindex="-1" aria-labelledby="logsModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="logsModalLabel">
<i class="bi bi-journal-text me-2"></i>Proje Logları
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Kapat"></button>
</div>
<div class="modal-body" id="logsContent">
<div class="text-center">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Yükleniyor...</span>
</div>
<p class="mt-2">Loglar yükleniyor...</p>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" id="clearLogsBtn" onclick="ProjectManager.clearProjectLogs()" style="display: none;">
<i class="bi bi-trash"></i> Logları Temizle
</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Kapat</button>
</div>
</div>
</div>
</div>
<!-- Meta Key Modal -->
<div class="modal fade" id="metaKeyModal" tabindex="-1" aria-labelledby="metaKeyModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content bg-dark text-light">
<div class="modal-header border-secondary">
<h5 class="modal-title" id="metaKeyModalLabel">
<i class="bi bi-key me-2"></i>Site Doğrulama Meta Key
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Kapat"></button>
</div>
<div class="modal-body" id="metaKeyContent">
<div class="text-center">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Yükleniyor...</span>
</div>
<p class="mt-2">Meta key bilgileri yükleniyor...</p>
</div>
</div>
<div class="modal-footer border-secondary">
<button type="button" class="btn btn-outline-light" data-bs-dismiss="modal">Kapat</button>
</div>
</div>
</div>
</div>
<script>
// Version: 2025-08-08-v4-{{ "now"|date:"YmdHis" }} - Fixed function definitions
// Ensure DOM is loaded before running scripts
document.addEventListener('DOMContentLoaded', function() {
console.log('DOM loaded, initializing project management functions...');
// CSRF Token almak için utility fonksiyon
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
// Toast bildirim fonksiyonu
function showToast(message, type = 'info', duration = 3000) {
// Toast container oluştur (eğer yoksa)
let toastContainer = document.getElementById('toast-container');
if (!toastContainer) {
toastContainer = document.createElement('div');
toastContainer.id = 'toast-container';
toastContainer.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
z-index: 9999;
max-width: 350px;
`;
document.body.appendChild(toastContainer);
}
// Toast elementi oluştur
const toast = document.createElement('div');
const bgClass = type === 'success' ? 'bg-success' :
type === 'error' ? 'bg-danger' :
type === 'warning' ? 'bg-warning' : 'bg-info';
toast.className = `alert ${bgClass} text-white mb-2`;
toast.style.cssText = `
opacity: 0;
transform: translateX(100%);
transition: all 0.3s ease;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
`;
toast.innerHTML = message;
// Toast'u container'a ekle
toastContainer.appendChild(toast);
// Animasyonla göster
setTimeout(() => {
toast.style.opacity = '1';
toast.style.transform = 'translateX(0)';
}, 100);
// Belirtilen süre sonra kaldır
setTimeout(() => {
toast.style.opacity = '0';
toast.style.transform = 'translateX(100%)';
setTimeout(() => {
if (toast.parentNode) {
toast.parentNode.removeChild(toast);
}
}, 300);
}, duration);
}
// ============= PROJE YÖNETİM FONKSİYONLARI =============
// Proje düzenleme fonksiyonu
function editProject(id) {
console.log('editProject called with ID:', id);
fetch(`/get-project-details/${id}/`)
.then(r => r.json())
.then(data => {
console.log('Project details response:', data);
if (data.success) {
document.getElementById('projectId').value = id;
document.getElementById('name').value = data.project.name;
document.getElementById('folder_name').value = data.project.folder_name;
// URL değerini ayarla - mevcut URL'yi olduğu gibi göster
const urlValue = data.project.url || '';
document.getElementById('url').value = urlValue;
// Host yenileme tarihini ayarla
const renewalDate = data.project.host_renewal_date || '';
document.getElementById('host_renewal_date').value = renewalDate;
document.getElementById('ssh_credential').value = data.project.ssh_credential_id || '';
document.getElementById('customer').value = data.project.customer_id || '';
document.getElementById('addProjectModalLabel').innerText = 'Proje Düzenle';
const modal = new bootstrap.Modal(document.getElementById('addProjectModal'));
modal.show();
} else {
showToast('❌ Proje bilgisi alınamadı!', 'error');
}
})
.catch(error => {
console.error('editProject error:', error);
showToast('❌ Proje bilgisi alınırken hata oluştu!', 'error');
});
}
function editProject(id) {
console.log('editProject called with ID:', id);
fetch(`/get-project-details/${id}/`)
.then(r => r.json())
.then data => {
console.log('Project details response:', data);
if (data.success) {
document.getElementById('projectId').value = id;
document.getElementById('name').value = data.project.name;
document.getElementById('folder_name').value = data.project.folder_name;
// URL değerini ayarla - mevcut URL'yi olduğu gibi göster
const urlValue = data.project.url || '';
document.getElementById('url').value = urlValue;
// Host yenileme tarihini ayarla
const renewalDate = data.project.host_renewal_date || '';
document.getElementById('host_renewal_date').value = renewalDate;
document.getElementById('ssh_credential').value = data.project.ssh_credential_id || '';
document.getElementById('customer').value = data.project.customer_id || '';
document.getElementById('addProjectModalLabel').innerText = 'Proje Düzenle';
const modal = new bootstrap.Modal(document.getElementById('addProjectModal'));
modal.show();
} else {
showToast('❌ Proje bilgisi alınamadı!', 'error');
}
})
.catch(error => {
console.error('editProject error:', error);
showToast('❌ Proje bilgisi alınırken hata oluştu!', 'error');
});
}
// Proje Sil
function deleteProject(id) {
if (confirm('Projeyi silmek istediğinize emin misiniz?')) {
fetch(`/delete_project/${id}/`, {
method: 'POST',
headers: { 'X-CSRFToken': getCookie('csrftoken') }
})
.then(r => r.json())
.then(data => {
if (data.success) {
showToast('✅ Proje başarıyla silindi', 'success');
setTimeout(() => location.reload(), 1200);
} else {
showToast(`${data.message}`, 'error');
}
});
}
}
// Proje Yedekle
function backupProject(id) {
showToast('🔄 Proje yedekleniyor...', 'info');
fetch(`/backup-project/${id}/`, {
method: 'POST',
headers: {
'X-CSRFToken': getCookie('csrftoken'),
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
showToast('✅ Proje başarıyla yedeklendi!', 'success');
} else {
showToast(`${data.message}`, 'error');
}
})
.catch(error => {
console.error('Backup error:', error);
showToast('❌ Yedekleme sırasında hata oluştu!', 'error');
});
}
// Log görüntüleme
function showLogsByProject(id) {
// Modal'ı
const logsModal = new bootstrap.Modal(document.getElementById('logsModal'));
logsModal.show();
// Loading durumunu göster
document.getElementById('logsContent').innerHTML = `
<div class="text-center">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Yükleniyor...</span>
</div>
<p class="mt-2">Loglar yükleniyor...</p>
</div>
`;
// Clear logs butonunu gizle
document.getElementById('clearLogsBtn').style.display = 'none';
fetch(`/project/${id}/backup-logs/`)
.then(response => response.json())
.then(data => {
if (data.success) {
console.log('Logs:', data.logs);
if (data.logs.length > 0) {
let logsHtml = '<div class="logs-container">';
data.logs.forEach(log => {
const statusIcon = log.status === 'success' ?
'<i class="bi bi-check-circle-fill text-success me-2"></i>' :
'<i class="bi bi-x-circle-fill text-danger me-2"></i>';
const logTypeIcon = log.log_type === 'backup' ?
'<i class="bi bi-cloud-arrow-up me-1"></i>' :
'<i class="bi bi-terminal me-1"></i>';
logsHtml += `
<div class="card mb-3 ${log.status === 'success' ? 'border-success' : 'border-danger'}">
<div class="card-header d-flex justify-content-between align-items-center py-2">
<div>
${statusIcon}
${logTypeIcon}
<small class="text-muted">${log.created_at}</small>
</div>
<span class="badge ${log.status === 'success' ? 'bg-success' : 'bg-danger'}">${log.status}</span>
</div>
<div class="card-body py-2">
<p class="mb-2"><strong>Komut:</strong></p>
<code class="d-block bg-dark text-light p-2 rounded mb-2">${log.command}</code>
<p class="mb-2"><strong>Çıktı:</strong></p>
<pre class="bg-light p-2 rounded text-dark" style="max-height: 200px; overflow-y: auto; font-size: 0.85rem;">${log.output}</pre>
</div>
</div>
`;
});
logsHtml += '</div>';
document.getElementById('logsContent').innerHTML = logsHtml;
// Clear logs butonunu göster
document.getElementById('clearLogsBtn').style.display = 'inline-block';
} else {
document.getElementById('logsContent').innerHTML = `
<div class="text-center text-muted py-4">
<i class="bi bi-journal-text" style="font-size: 3rem;"></i>
<h5 class="mt-3">Bu proje için henüz log kaydı bulunmuyor</h5>
<p class="text-muted">Yedekleme veya site kontrol işlemleri yapıldığında loglar burada görünecektir.</p>
</div>
`;
}
} else {
document.getElementById('logsContent').innerHTML = `
<div class="alert alert-danger">
<i class="bi bi-exclamation-triangle me-2"></i>
${data.message}
</div>
`;
}
})
.catch(error => {
console.error('Logs error:', error);
document.getElementById('logsContent').innerHTML = `
<div class="alert alert-danger">
<i class="bi bi-exclamation-triangle me-2"></i>
Loglar yüklenirken hata oluştu!
</div>
`;
});
}
// Site durumu kontrol
function checkSiteStatus(id) {
showToast('🔄 Site durumu kontrol ediliyor...', 'info');
fetch(`/project/${id}/check-site/`, {
method: 'POST',
headers: {
'X-CSRFToken': getCookie('csrftoken'),
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
showToast('✅ Site kontrol tamamlandı!', 'success');
setTimeout(() => window.location.reload(), 1500);
} else {
showToast(`${data.message}`, 'error');
}
})
.catch(error => {
console.error('Site check error:', error);
showToast('❌ Site kontrol sırasında hata oluştu!', 'error');
});
}
// Meta Key Göster
function showMetaKey(id) {
// Modal'ı
const metaKeyModal = new bootstrap.Modal(document.getElementById('metaKeyModal'));
metaKeyModal.show();
// Loading durumunu göster
document.getElementById('metaKeyContent').innerHTML = `
<div class="text-center">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Yükleniyor...</span>
</div>
<p class="mt-2">Meta key bilgileri yükleniyor...</p>
</div>
`;
fetch(`/project/${id}/meta-key/`)
.then(response => response.json())
.then(data => {
if (data.success) {
console.log('Meta key:', data);
let metaKeyHtml = `
<div class="mb-4">
<h6 class="text-warning mb-3">
<i class="bi bi-info-circle me-2"></i>Site Doğrulama Talimatları
</h6>
<div class="alert alert-info">
<p class="mb-2">Sitenizin doğrulanması için aşağıdaki meta tag'i HTML'inizin &lt;head&gt; bölümüne ekleyin:</p>
<ol class="mb-0">
<li>Site yönetici paneline giriş yapın</li>
<li>Tema düzenleyicisini açın (header.php veya index.html)</li>
<li>Aşağıdaki meta tag'i &lt;head&gt; bölümüne ekleyin</li>
<li>Değişiklikleri kaydedin</li>
<li>"Site Doğrula" butonuna tıklayın</li>
</ol>
</div>
</div>
<div class="mb-4">
<label class="form-label text-warning fw-bold">Meta Verification Tag:</label>
<div class="input-group">
<input type="text" class="form-control bg-dark text-light border-secondary"
value='${data.meta_key}' readonly id="metaKeyInput">
<button class="btn btn-outline-info" type="button" onclick="ProjectManager.copyToClipboard('${data.meta_key}')">>
<i class="bi bi-clipboard"></i> Kopyala
</button>
</div>
<small class="text-muted">Bu meta tag'i sitenizin &lt;head&gt; bölümüne ekleyin</small>
</div>
<div class="mb-4">
<h6 class="text-warning mb-3">
<i class="bi bi-check-circle me-2"></i>Doğrulama İşlemi
</h6>
<div class="d-grid">
<button class="btn btn-success btn-lg" onclick="ProjectManager.verifySite(${id})">>
<i class="bi bi-shield-check me-2"></i>Site Doğrula
</button>
</div>
<small class="text-muted d-block text-center mt-2">
Meta tag'i ekledikten sonra bu butona tıklayın
</small>
</div>
<div class="alert alert-warning">
<i class="bi bi-exclamation-triangle me-2"></i>
<strong>Önemli:</strong> Meta tag'i eklemeden önce doğrulama yapmayın.
Tag eklendikten sonra 2-3 dakika bekleyip doğrulama yapın.
</div>
`;
document.getElementById('metaKeyContent').innerHTML = metaKeyHtml;
} else {
document.getElementById('metaKeyContent').innerHTML = `
<div class="alert alert-danger">
<i class="bi bi-exclamation-triangle me-2"></i>
${data.message}
</div>
`;
}
})
.catch(error => {
console.error('Meta key error:', error);
document.getElementById('metaKeyContent').innerHTML = `
<div class="alert alert-danger">
<i class="bi bi-exclamation-triangle me-2"></i>
Meta key alınırken hata oluştu!
</div>
`;
});
}
// Clipboard'a kopyala
function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(() => {
showToast('✅ Panoya kopyalandı!', 'success');
}).catch(err => {
console.error('Copy error:', err);
showToast('❌ Kopyalama hatası!', 'error');
});
}
// Site doğrula
function verifySite(projectId) {
showToast('🔄 Site doğrulama tamamlandı!', 'success');
fetch(`/project/${projectId}/check-site/`, {
method: 'POST',
headers: {
'X-CSRFToken': getCookie('csrftoken'),
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
showToast('✅ Site doğrulama tamamlandı!', 'success');
} else {
showToast(`${data.message}`, 'error');
}
})
.catch(error => {
console.error('Site doğrulama hatası:', error);
showToast('❌ Site doğrulama hatası!', 'error');
});
}
// Proje loglarını temizle
function clearProjectLogs() {
if (confirm('Tüm proje loglarını temizlemek istediğinize emin misiniz?')) {
showToast('🔄 Loglar temizleniyor...', 'info');
fetch('/logs/clear/', {
method: 'POST',
headers: {
'X-CSRFToken': getCookie('csrftoken'),
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
showToast('✅ Loglar temizlendi!', 'success');
setTimeout(() => window.location.reload(), 1500);
} else {
showToast(`${data.message}`, 'error');
}
})
.catch(error => {
console.error('Clear logs error:', error);
showToast('❌ Log temizleme hatası!', 'error');
});
}
}
// Proje Form Submit
document.getElementById('projectForm').addEventListener('submit', function(e) {
e.preventDefault();
const id = document.getElementById('projectId').value;
const url = id ? `/update-project/${id}/` : '/project/create/';
const formData = new FormData(this);
fetch(url, {
method: 'POST',
headers: { 'X-CSRFToken': getCookie('csrftoken') },
body: formData
})
.then(r => r.json())
.then(data => {
if (data.success) {
showToast('✅ Proje başarıyla kaydedildi', 'success');
const modal = bootstrap.Modal.getInstance(document.getElementById('addProjectModal'));
if (modal) modal.hide();
setTimeout(() => location.reload(), 1200);
} else {
showToast(`${data.message}`, 'error');
}
});
});
// Durum Filtresi
document.getElementById('statusFilter').addEventListener('change', function() {
const filterValue = this.value;
const projectRows = document.querySelectorAll('tbody tr');
projectRows.forEach(row => {
if (row.cells.length > 1) {
const siteStatusCell = row.cells[3]; // Site Durumu sütunu
let shouldShow = false;
if (filterValue === '') {
// Tüm projeler
shouldShow = true;
} else if (filterValue === 'active') {
// Aktif projeler - success badge'i olanlar
shouldShow = siteStatusCell.querySelector('.badge.bg-success') !== null;
} else if (filterValue === 'inactive') {
// Pasif projeler - danger badge'i olanlar
shouldShow = siteStatusCell.querySelector('.badge.bg-danger') !== null;
} else if (filterValue === 'unknown') {
// Bilinmeyen durum - secondary badge'i olanlar
shouldShow = siteStatusCell.querySelector('.badge.bg-secondary') !== null;
} else if (filterValue === 'no-url') {
// URL'siz projeler - "URL tanımlanmamış" yazısı olanlar
shouldShow = siteStatusCell.textContent.includes('URL tanımlanmamış');
}
row.style.display = shouldShow ? '' : 'none';
}
});
// Filtreleme sonucunda gösterilen proje sayısını güncelle
updateProjectCount();
});
// Proje sayısını güncelleme fonksiyonu
function updateProjectCount() {
const visibleRows = document.querySelectorAll('tbody tr[style=""], tbody tr:not([style])');
const totalRows = document.querySelectorAll('tbody tr').length;
// Eğer empty state row varsa onu sayma
const actualVisibleRows = Array.from(visibleRows).filter(row => row.cells.length > 1);
const actualTotalRows = Array.from(document.querySelectorAll('tbody tr')).filter(row => row.cells.length > 1);
// Başlığı güncelle
const headerText = document.querySelector('h3');
const originalText = headerText.textContent.split(' (')[0]; // Mevcut sayı bilgisini temizle
if (actualTotalRows.length > 0) {
if (actualVisibleRows.length !== actualTotalRows.length) {
headerText.innerHTML = `<i class="bi bi-folder-fill me-2"></i>Projeler (${actualVisibleRows.length}/${actualTotalRows.length})`;
} else {
headerText.innerHTML = `<i class="bi bi-folder-fill me-2"></i>Projeler (${actualTotalRows.length})`;
}
} else {
headerText.innerHTML = `<i class="bi bi-folder-fill me-2"></i>Projeler`;
}
}
// Proje Arama (güncellenmiş versiyon - filtreleme ile uyumlu)
document.getElementById('projectSearch').addEventListener('keyup', function() {
const searchTerm = this.value.toLowerCase().trim();
const statusFilter = document.getElementById('statusFilter').value;
const projectRows = document.querySelectorAll('tbody tr');
projectRows.forEach(row => {
if (row.cells.length > 1) {
let shouldShow = true;
// Önce arama terimine göre kontrol et
if (searchTerm.length >= 2) {
const projectInfo = row.cells[1].textContent.toLowerCase();
const folderInfo = row.cells[2].textContent.toLowerCase();
const siteInfo = row.cells[3].textContent.toLowerCase();
shouldShow = projectInfo.includes(searchTerm) ||
folderInfo.includes(searchTerm) ||
siteInfo.includes(searchTerm);
}
// Sonra durum filtresine göre kontrol et
if (shouldShow && statusFilter !== '') {
const siteStatusCell = row.cells[3];
if (statusFilter === 'active') {
shouldShow = siteStatusCell.querySelector('.badge.bg-success') !== null;
} else if (statusFilter === 'inactive') {
shouldShow = siteStatusCell.querySelector('.badge.bg-danger') !== null;
} else if (statusFilter === 'unknown') {
shouldShow = siteStatusCell.querySelector('.badge.bg-secondary') !== null;
} else if (statusFilter === 'no-url') {
shouldShow = siteStatusCell.textContent.includes('URL tanımlanmamış');
}
}
row.style.display = shouldShow ? '' : 'none';
}
});
// Proje sayısını güncelle
updateProjectCount();
});
// Proje Arama (eski kod - kaldırıldı)
// Modal reset
document.getElementById('addProjectModal').addEventListener('hidden.bs.modal', function () {
document.getElementById('projectForm').reset();
document.getElementById('projectId').value = '';
document.getElementById('addProjectModalLabel').textContent = 'Yeni Proje Ekle';
});
// Sayfa yüklendiğinde proje sayısını göster
updateProjectCount();
}); // DOMContentLoaded end
</script>
{% endblock %}