feat: MercadoLibre integration + inventory bulk publish + WhatsApp bridge fixes
- Add MercadoLibre OAuth, listings, orders, webhooks and category search - New marketplace_external_bp.py, meli_service.py, marketplace_external_service.py - New marketplace_external.html/js with ML management UI - Inventory: bulk publish to ML with category autocomplete, listing type and shipping selectors - Inventory: new .btn--meli styles, select/label CSS fixes - WhatsApp bridge: rate limiting, 440/515/408 error handling, stale watchdog - DB migration v3.4_meli_integration.sql for marketplace_listings, orders, sync_queue - Add Celery tasks for ML sync and webhook processing - Sidebar: MercadoLibre navigation link
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
var activePhone = null;
|
||||
var pollTimer = null;
|
||||
var statusPollTimer = null;
|
||||
var qrPollTimer = null;
|
||||
var connectionState = 'unknown'; // 'open', 'close', 'connecting', 'unknown'
|
||||
|
||||
// -- Helpers ---------------------------------------------------------------
|
||||
@@ -88,6 +89,10 @@
|
||||
api('GET', '/status').then(function (data) {
|
||||
var state = (data.instance || data).state || data.state || 'close';
|
||||
updateConnectionUI(state);
|
||||
// If bridge already has a QR ready, show it immediately
|
||||
if (state === 'qr' || state === 'connecting') {
|
||||
fetchQR();
|
||||
}
|
||||
}).catch(function () {
|
||||
updateConnectionUI('close');
|
||||
});
|
||||
@@ -106,7 +111,8 @@
|
||||
// Load conversations + start polling on page load / reconnect
|
||||
loadConversations();
|
||||
startPolling();
|
||||
} else if (state === 'connecting') {
|
||||
stopQRPolling();
|
||||
} else if (state === 'connecting' || state === 'qr') {
|
||||
statusDot.className = 'status-dot status-dot--warn';
|
||||
statusText.textContent = 'Escaneando QR...';
|
||||
connectSection.style.display = 'flex';
|
||||
@@ -125,6 +131,7 @@
|
||||
refreshQrBtn.style.display = 'none';
|
||||
qrImg.style.display = 'none';
|
||||
qrPlaceholder.style.display = '';
|
||||
stopQRPolling();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,8 +148,15 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// Instance created, now fetch QR
|
||||
fetchQR();
|
||||
// Switch UI to connecting state immediately
|
||||
updateConnectionUI('connecting');
|
||||
qrPlaceholder.textContent = 'Iniciando conexion con WhatsApp, generando QR...';
|
||||
qrPlaceholder.style.display = '';
|
||||
qrImg.style.display = 'none';
|
||||
|
||||
// Start polling for QR; the first fetchQR may not have QR ready yet
|
||||
startStatusPolling();
|
||||
startQRPolling();
|
||||
}).catch(function () {
|
||||
connectBtn.disabled = false;
|
||||
connectBtn.textContent = 'Conectar WhatsApp';
|
||||
@@ -151,7 +165,10 @@
|
||||
}
|
||||
|
||||
function fetchQR() {
|
||||
qrPlaceholder.textContent = 'Generando QR...';
|
||||
// Only update placeholder text if we don't already have a QR image showing
|
||||
if (qrImg.style.display !== 'block') {
|
||||
qrPlaceholder.textContent = 'Generando codigo QR, espera unos segundos...';
|
||||
}
|
||||
|
||||
api('GET', '/qr').then(function (data) {
|
||||
var base64 = data.qr || data.base64 || data.qrcode || '';
|
||||
@@ -164,14 +181,18 @@
|
||||
|
||||
// Start polling for connection state while QR is shown
|
||||
startStatusPolling();
|
||||
startQRPolling();
|
||||
} else if ((data.instance && data.instance.state === 'open') || data.state === 'open') {
|
||||
// Already connected
|
||||
updateConnectionUI('open');
|
||||
loadConversations();
|
||||
} else {
|
||||
qrPlaceholder.textContent = 'No se pudo generar el QR. Intenta de nuevo.';
|
||||
qrPlaceholder.style.display = '';
|
||||
qrImg.style.display = 'none';
|
||||
// QR not ready yet — this is normal right after pressing Connect
|
||||
if (qrImg.style.display !== 'block') {
|
||||
qrPlaceholder.textContent = 'Generando codigo QR, por favor espera... (el codigo cambia cada pocos segundos, escanealo en cuanto aparezca)';
|
||||
qrPlaceholder.style.display = '';
|
||||
qrImg.style.display = 'none';
|
||||
}
|
||||
}
|
||||
}).catch(function () {
|
||||
qrPlaceholder.textContent = 'Error al obtener QR';
|
||||
@@ -208,6 +229,24 @@
|
||||
}
|
||||
}
|
||||
|
||||
function startQRPolling() {
|
||||
stopQRPolling();
|
||||
qrPollTimer = setInterval(function () {
|
||||
if (connectionState === 'connecting' || connectionState === 'qr') {
|
||||
fetchQR();
|
||||
} else {
|
||||
stopQRPolling();
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
function stopQRPolling() {
|
||||
if (qrPollTimer) {
|
||||
clearInterval(qrPollTimer);
|
||||
qrPollTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
connectBtn.addEventListener('click', doConnect);
|
||||
disconnectBtn.addEventListener('click', doDisconnect);
|
||||
refreshQrBtn.addEventListener('click', fetchQR);
|
||||
|
||||
Reference in New Issue
Block a user