285 lines
14 KiB
HTML
285 lines
14 KiB
HTML
{% set lang = request.cookies.get('panel_lang', 'es') %}
|
|
<!DOCTYPE html>
|
|
<html lang="{{ lang }}">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>{{ "Canales de Discord - Bots de Traducción" | translate(lang) }}</title>
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
|
|
<style>
|
|
.channel-item {
|
|
border-left: 4px solid #6f42c1;
|
|
transition: all 0.3s ease;
|
|
}
|
|
.channel-item:hover {
|
|
border-left-color: #563d7c;
|
|
background-color: #f8f9fa;
|
|
}
|
|
.channel-inactive {
|
|
border-left-color: #dc3545;
|
|
opacity: 0.7;
|
|
}
|
|
.server-card {
|
|
border: 1px solid #dee2e6;
|
|
border-radius: 8px;
|
|
margin-bottom: 20px;
|
|
}
|
|
.server-header {
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
color: white;
|
|
padding: 15px;
|
|
border-radius: 8px 8px 0 0;
|
|
}
|
|
.toggle-switch {
|
|
position: relative;
|
|
display: inline-block;
|
|
width: 50px;
|
|
height: 24px;
|
|
}
|
|
.toggle-switch input {
|
|
opacity: 0;
|
|
width: 0;
|
|
height: 0;
|
|
}
|
|
.slider {
|
|
position: absolute;
|
|
cursor: pointer;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background-color: #ccc;
|
|
transition: .4s;
|
|
border-radius: 24px;
|
|
}
|
|
.slider:before {
|
|
position: absolute;
|
|
content: "";
|
|
height: 18px;
|
|
width: 18px;
|
|
left: 3px;
|
|
bottom: 3px;
|
|
background-color: white;
|
|
transition: .4s;
|
|
border-radius: 50%;
|
|
}
|
|
input:checked + .slider {
|
|
background-color: #28a745;
|
|
}
|
|
input:checked + .slider:before {
|
|
transform: translateX(26px);
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
|
<div class="container-fluid">
|
|
<a class="navbar-brand" href="/dashboard">
|
|
<i class="bi bi-translate"></i> {{ "Bots de Traducción" | translate(lang) }}
|
|
</a>
|
|
<div class="d-flex align-items-center">
|
|
<div class="dropdown me-3">
|
|
<button class="btn btn-outline-light btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown">
|
|
<i class="bi bi-translate"></i>
|
|
</button>
|
|
<ul class="dropdown-menu dropdown-menu-end">
|
|
<li><a class="dropdown-item {{ 'active' if lang == 'es' }}" href="/set-lang/es">Español</a></li>
|
|
<li><a class="dropdown-item {{ 'active' if lang == 'en' }}" href="/set-lang/en">English</a></li>
|
|
<li><a class="dropdown-item {{ 'active' if lang == 'pt' }}" href="/set-lang/pt">Português</a></li>
|
|
</ul>
|
|
</div>
|
|
<a href="/dashboard" class="btn btn-outline-light btn-sm me-2">{{ "Dashboard" | translate(lang) }}</a>
|
|
<a href="/logout" class="btn btn-outline-light btn-sm">{{ "Cerrar Sesión" | translate(lang) }}</a>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="container mt-5">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h2>📱 {{ "Canales de Discord" | translate(lang) }}</h2>
|
|
<div>
|
|
<a href="/diagnosis" class="btn btn-outline-secondary me-2">
|
|
<i class="bi bi-bug"></i> {{ "Diagnóstico" | translate(lang) }}
|
|
</a>
|
|
<form method="post" action="/discord-channels/sync" class="d-inline" id="syncForm">
|
|
<button type="button" class="btn btn-primary" id="syncBtn" onclick="handleSync()">
|
|
<i class="bi bi-arrow-repeat" id="syncIcon"></i> <span id="syncText">{{ "Sincronizar" | translate(lang) }}</span>
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
{% if success %}
|
|
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
|
<i class="bi bi-check-circle"></i> {{ "Configuración actualizada correctamente." | translate(lang) }}
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
|
</div>
|
|
{% endif %}
|
|
{% if synced %}
|
|
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
|
<i class="bi bi-check-circle"></i> {{ "Servidores y canales sincronizados desde Discord." | translate(lang) }}
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
|
</div>
|
|
{% endif %}
|
|
{% if error %}
|
|
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
|
<i class="bi bi-exclamation-circle"></i> {{ "Error al realizar la operación. Verifica la configuración del bot." | translate(lang) }}
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if servers_with_channels|length == 0 %}
|
|
<div class="alert alert-info">
|
|
<i class="bi bi-info-circle"></i> {{ "No hay servidores sincronizados. Usa el botón 'Sincronizar' para obtener los servidores y canales de Discord." | translate(lang) }}
|
|
</div>
|
|
{% else %}
|
|
{% for server_id, server_data in servers_with_channels.items() %}
|
|
<div class="card mb-4">
|
|
<div class="card-header bg-dark text-white">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<h5 class="mb-0">
|
|
<i class="bi bi-server"></i> {{ server_data.server_info.server_name }}
|
|
<small class="text-muted">({{ server_data.server_info.server_id }})</small>
|
|
</h5>
|
|
<form method="post" action="/discord-channels/delete-server" class="d-inline">
|
|
<input type="hidden" name="server_id" value="{{ server_id }}">
|
|
<button type="submit" class="btn btn-sm btn-outline-danger"
|
|
onclick="return confirm('{{ '¿Eliminar este servidor y todos sus canales?' | translate(lang) }}')">
|
|
<i class="bi bi-trash"></i> {{ "Eliminar" | translate(lang) }}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
{% if server_data.channels|length == 0 %}
|
|
<p class="text-muted">{{ "No hay canales en este servidor." | translate(lang) }}</p>
|
|
{% else %}
|
|
<form method="post" action="/discord-channels/bulk-toggle">
|
|
<input type="hidden" name="server_id" value="{{ server_id }}">
|
|
<div class="table-responsive">
|
|
<table class="table table-hover">
|
|
<thead>
|
|
<tr>
|
|
<th width="50px">
|
|
<input type="checkbox" class="form-check-input" id="selectAll_{{ server_id }}"
|
|
onchange="toggleAllChannels({{ server_id }})">
|
|
</th>
|
|
<th>{{ "Canal" | translate(lang) }}</th>
|
|
<th>{{ "ID" | translate(lang) }}</th>
|
|
<th width="100px">{{ "Estado" | translate(lang) }}</th>
|
|
<th width="120px">{{ "Acciones" | translate(lang) }}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for channel in server_data.channels %}
|
|
<tr>
|
|
<td>
|
|
<input type="checkbox" class="form-check-input channel-checkbox"
|
|
name="channel_ids" value="{{ channel.channel_id }}"
|
|
data-server="{{ server_id }}">
|
|
</td>
|
|
<td>
|
|
<i class="bi bi-hash"></i> {{ channel.channel_name }}
|
|
</td>
|
|
<td><code>{{ channel.channel_id }}</code></td>
|
|
<td>
|
|
{% if channel.is_active %}
|
|
<span class="badge bg-success">{{ "Activo" | translate(lang) }}</span>
|
|
{% else %}
|
|
<span class="badge bg-secondary">{{ "Inactivo" | translate(lang) }}</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
<div class="btn-group btn-group-sm" role="group">
|
|
<form method="post" action="/discord-channels/toggle" class="d-inline">
|
|
<input type="hidden" name="channel_id" value="{{ channel.channel_id }}">
|
|
<input type="hidden" name="is_active" value="{{ 'false' if channel.is_active else 'true' }}">
|
|
<button type="submit" class="btn {% if channel.is_active %}btn-warning{% else %}btn-success{% endif %} btn-sm"
|
|
title="{{ 'Desactivar' if channel.is_active else 'Activar' | translate(lang) }}">
|
|
<i class="bi bi-{% if channel.is_active %}pause{% else %}play{% endif %}"></i>
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="mt-3">
|
|
<button type="submit" name="bulk_action" value="activate"
|
|
class="btn btn-success btn-sm me-2" disabled>
|
|
<i class="bi bi-play"></i> {{ "Activar seleccionados" | translate(lang) }}
|
|
</button>
|
|
<button type="submit" name="bulk_action" value="deactivate"
|
|
class="btn btn-warning btn-sm" disabled>
|
|
<i class="bi bi-pause"></i> {{ "Desactivar seleccionados" | translate(lang) }}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
{% endif %}
|
|
</div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script>
|
|
function toggleAllChannels(serverId) {
|
|
const selectAll = document.getElementById('selectAll_' + serverId);
|
|
const checkboxes = document.querySelectorAll('.channel-checkbox[data-server="' + serverId + '"]');
|
|
const bulkButtons = selectAll.closest('form').querySelectorAll('button[type="submit"][name="bulk_action"]');
|
|
|
|
checkboxes.forEach(checkbox => {
|
|
checkbox.checked = selectAll.checked;
|
|
});
|
|
|
|
// Habilitar/deshabilitar botones bulk
|
|
const anyChecked = document.querySelectorAll('.channel-checkbox:checked').length > 0;
|
|
bulkButtons.forEach(btn => btn.disabled = !anyChecked);
|
|
}
|
|
|
|
function updateBulkButtons() {
|
|
const anyChecked = document.querySelectorAll('.channel-checkbox:checked').length > 0;
|
|
document.querySelectorAll('button[type="submit"][name="bulk_action"]').forEach(btn => {
|
|
btn.disabled = !anyChecked;
|
|
});
|
|
|
|
// Actualizar checkboxes de "seleccionar todo"
|
|
document.querySelectorAll('[id^="selectAll_"]').forEach(selectAll => {
|
|
const serverId = selectAll.id.replace('selectAll_', '');
|
|
const checkboxes = document.querySelectorAll('.channel-checkbox[data-server="' + serverId + '"]');
|
|
const allChecked = Array.from(checkboxes).every(cb => cb.checked);
|
|
const anyChecked = Array.from(checkboxes).some(cb => cb.checked);
|
|
|
|
selectAll.checked = allChecked;
|
|
selectAll.indeterminate = anyChecked && !allChecked;
|
|
});
|
|
}
|
|
|
|
// Agregar event listeners a todos los checkboxes
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
document.querySelectorAll('.channel-checkbox').forEach(checkbox => {
|
|
checkbox.addEventListener('change', updateBulkButtons);
|
|
});
|
|
});
|
|
|
|
function handleSync() {
|
|
if (confirm('{{ "¿Sincronizar servidores y canales desde Discord?" | translate(lang) }}')) {
|
|
const btn = document.getElementById('syncBtn');
|
|
const icon = document.getElementById('syncIcon');
|
|
const text = document.getElementById('syncText');
|
|
|
|
btn.disabled = true;
|
|
icon.className = 'spinner-border spinner-border-sm';
|
|
text.innerText = ' {{ "Sincronizando..." | translate(lang) }}';
|
|
|
|
document.getElementById('syncForm').submit();
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|