feat: module toggles in POS config and Instance Manager
- Add GET/PUT /pos/api/config/modules endpoints in POS config_bp.py - Update sidebar.js to filter nav items based on enabled modules - Add Modules section to POS config.html with toggles for WhatsApp, Marketplace, MercadoLibre - Add module load/save logic to POS config.js - Preload modules in app-init.js for sidebar caching - Add tenant module management to Instance Manager - get_tenant_modules / update_tenant_modules in tenant_service.py - GET/PUT /api/tenants/<id>/modules endpoints in tenants_bp.py - Add modules modal to manager index.html - Add module editing UI and logic to manager.js - Add toggle-switch CSS to manager.css
This commit is contained in:
@@ -188,6 +188,7 @@ async function loadDemos() {
|
||||
<td><a href="https://${escapeHtml(d.subdomain)}.nexusautoparts.com.mx/pos/login" target="_blank" style="color:var(--accent)">${escapeHtml(d.subdomain)}</a></td>
|
||||
<td>${d.demo_days_left !== null ? d.demo_days_left + " días" : "N/A"}</td>
|
||||
<td>
|
||||
<button class="btn-icon" onclick="openModulesModal(${d.id}, '${escapeHtml(d.name)}')" title="Módulos"><i class="fas fa-cubes" style="color:var(--accent)"></i></button>
|
||||
<button class="btn-icon" onclick="resetTenant(${d.id})" title="Resetear"><i class="fas fa-undo"></i></button>
|
||||
<button class="btn-icon" onclick="toggleTenant(${d.id}, ${!d.is_active})" title="${d.is_active ? "Desactivar" : "Activar"}"><i class="fas fa-${d.is_active ? "pause" : "play"}"></i></button>
|
||||
<button class="btn-icon" onclick="confirmDelete(${d.id}, '${escapeHtml(d.name)}')" title="Eliminar"><i class="fas fa-trash" style="color:var(--danger)"></i></button>
|
||||
@@ -254,6 +255,7 @@ async function loadTenants(withStats = false) {
|
||||
<td>${t.is_active ? tag("Activo", "success") : tag("Inactivo", "danger")}</td>
|
||||
<td>${formatDate(t.created_at)}</td>
|
||||
<td>
|
||||
<button class="btn-icon" onclick="openModulesModal(${t.id}, '${escapeHtml(t.name)}')" title="Módulos"><i class="fas fa-cubes" style="color:var(--accent)"></i></button>
|
||||
<button class="btn-icon" onclick="resetTenant(${t.id})" title="Resetear datos"><i class="fas fa-undo"></i></button>
|
||||
<button class="btn-icon" onclick="toggleTenant(${t.id}, ${!t.is_active})" title="${t.is_active ? "Desactivar" : "Activar"}"><i class="fas fa-${t.is_active ? "pause" : "play"}"></i></button>
|
||||
<button class="btn-icon" onclick="confirmDelete(${t.id}, '${escapeHtml(t.name)}')" title="Eliminar"><i class="fas fa-trash" style="color:var(--danger)"></i></button>
|
||||
@@ -475,5 +477,59 @@ function copyText(text) {
|
||||
navigator.clipboard.writeText(text).then(() => toast("Copiado al portapapeles", "success"));
|
||||
}
|
||||
|
||||
// ─── Modules ───────────────────────────────────────────────────────────────
|
||||
let currentModulesTenantId = null;
|
||||
|
||||
async function openModulesModal(tenantId, name) {
|
||||
currentModulesTenantId = tenantId;
|
||||
document.getElementById("modules-modal-title").textContent = `Módulos — ${escapeHtml(name)}`;
|
||||
document.getElementById("modules-modal").style.display = "flex";
|
||||
|
||||
// Load current state
|
||||
const res = await api(`/api/tenants/${tenantId}/modules`);
|
||||
if (res && res.status === 200) {
|
||||
const m = res.data.data;
|
||||
document.getElementById("mod-whatsapp").checked = m.whatsapp !== false;
|
||||
document.getElementById("mod-marketplace").checked = m.marketplace !== false;
|
||||
document.getElementById("mod-meli").checked = m.meli !== false;
|
||||
} else {
|
||||
toast("Error al cargar módulos", "error");
|
||||
}
|
||||
}
|
||||
|
||||
function closeModulesModal() {
|
||||
document.getElementById("modules-modal").style.display = "none";
|
||||
currentModulesTenantId = null;
|
||||
}
|
||||
|
||||
async function saveModules() {
|
||||
if (!currentModulesTenantId) return;
|
||||
const btn = document.getElementById("modules-save-btn");
|
||||
const originalText = btn.innerHTML;
|
||||
btn.innerHTML = `<i class="fas fa-spinner fa-spin"></i> Guardando...`;
|
||||
btn.disabled = true;
|
||||
|
||||
const payload = {
|
||||
whatsapp: document.getElementById("mod-whatsapp").checked,
|
||||
marketplace: document.getElementById("mod-marketplace").checked,
|
||||
meli: document.getElementById("mod-meli").checked,
|
||||
};
|
||||
|
||||
const res = await api(`/api/tenants/${currentModulesTenantId}/modules`, {
|
||||
method: "PUT",
|
||||
body: payload
|
||||
});
|
||||
|
||||
if (res && res.status === 200) {
|
||||
toast("Módulos actualizados", "success");
|
||||
closeModulesModal();
|
||||
} else {
|
||||
toast(res?.data?.error || "Error al guardar", "error");
|
||||
}
|
||||
|
||||
btn.innerHTML = originalText;
|
||||
btn.disabled = false;
|
||||
}
|
||||
|
||||
// ─── Init ──────────────────────────────────────────────────────────────────
|
||||
document.addEventListener("DOMContentLoaded", initAuth);
|
||||
|
||||
Reference in New Issue
Block a user