Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions webui/assets/css/customize.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,40 @@
top: 80px;
right: 10px;
z-index: 999;
min-width: 400px;
max-width: 600px;
}

/* Estilos para mensajes de error en el toast */
.toast .toast-body {
font-size: 0.9rem;
line-height: 1.4;
}

.toast .toast-body strong {
color: inherit;
}

.toast .toast-body code {
background-color: rgba(255, 255, 255, 0.2);
padding: 2px 4px;
border-radius: 3px;
font-family: 'Courier New', monospace;
}

.toast .toast-body small {
opacity: 0.8;
font-size: 0.85rem;
}

/* Toast de advertencia con mejor legibilidad */
.toast.bg-warning .toast-body {
color: #000 !important;
}

.toast.bg-warning .toast-body code {
background-color: rgba(0, 0, 0, 0.1);
color: #000;
}

.offcanvas.offcanvas-start {
Expand Down
135 changes: 106 additions & 29 deletions webui/assets/js/site.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,11 @@ function GetPresentNode(){
success: function (data) {
ShowProgress();
let CandidateHtml = EMPTYSTR;
data.candidates.forEach((element) => {
CandidateHtml = `${CandidateHtml}<span class="badge bg-secondary rounded-pill" id="cdr-bucket">${element}</span>`;
});
if (data.candidates && Array.isArray(data.candidates)) {
data.candidates.forEach((element) => {
CandidateHtml = `${CandidateHtml}<span class="badge bg-secondary rounded-pill" id="cdr-bucket">${element}</span>`;
});
}
document.getElementById('node-info').innerHTML = `
<li class="list-group-item d-flex justify-content-between align-items-center">
Software Version <span class="badge bg-success rounded-pill">${data.swversion}</span>
Expand All @@ -339,9 +341,8 @@ function GetPresentNode(){
<div>${CandidateHtml}</div></li>`;
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
document.getElementById('node-info').innerHTML = EMPTYSTR;
ShowToast(jqXHR.responseJSON.error);
ShowAPIError(jqXHR, textStatus, errorThrown);
}
});

Expand All @@ -351,9 +352,11 @@ function GetPresentNode(){
success: function (data) {
ShowProgress();
let MembersHtml = EMPTYSTR;
data.members.forEach((element) => {
MembersHtml = `${MembersHtml}<span class="badge bg-dark rounded-pill" id="cdr-bucket">${element}</span>`;
});
if (data.members && Array.isArray(data.members)) {
data.members.forEach((element) => {
MembersHtml = `${MembersHtml}<span class="badge bg-dark rounded-pill" id="cdr-bucket">${element}</span>`;
});
}
document.getElementById('cluster-info').innerHTML = `
<li class="list-group-item d-flex justify-content-between align-items-center">
Cluster Name <span class="badge bg-warning text-dark rounded-pill">${data.name}</span>
Expand All @@ -378,9 +381,8 @@ function GetPresentNode(){
</div>`;
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
document.getElementById('cluster-info').innerHTML = EMPTYSTR;
ShowToast(jqXHR.responseJSON.error);
ShowAPIError(jqXHR, textStatus, errorThrown);
}
});
}
Expand All @@ -404,9 +406,8 @@ function GeneralGetPresent(SettingName){
}
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
document.getElementById(presentation).innerHTML = EMPTYSTR;
ShowToast(jqXHR.responseJSON.error);
ShowAPIError(jqXHR, textStatus, errorThrown);
}
});
}
Expand Down Expand Up @@ -459,7 +460,14 @@ function GeneralRemove(name, SettingName){
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
ShowToast(jqXHR.responseJSON.error);

// Mostrar el modal de errores si hay respuesta JSON
if (jqXHR.responseJSON) {
ShowErrorModal(jqXHR.responseJSON);
} else {
// Fallback al toast si no hay respuesta JSON
ShowToast('Error de conexión: ' + textStatus, 'danger');
}
}
});
}
Expand All @@ -485,8 +493,7 @@ function GeneralModify(name, SettingName){
}
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
ShowToast(jqXHR.responseJSON.error);
ShowAPIError(jqXHR, textStatus, errorThrown);
}
});
}
Expand Down Expand Up @@ -530,8 +537,7 @@ function GeneralSubmit(name, SettingName, method="POST"){
offcanvaspanel.hide();
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
ShowToast(jqXHR.responseJSON.error);
ShowAPIError(jqXHR, textStatus, errorThrown);
}
});
}
Expand Down Expand Up @@ -618,9 +624,8 @@ function AccessDomainPolicyDetail(Adomain){
</div>`;
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
document.getElementById(`DetailAD${Adomain}`).innerHTML = EMPTYSTR;
ShowToast(jqXHR.responseJSON.error);
ShowAPIError(jqXHR, textStatus, errorThrown);
}
});
}
Expand Down Expand Up @@ -669,9 +674,8 @@ function AccessUserDirectoryDetail(Adomain){
}
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
document.getElementById(`TableAD${Adomain}`).innerHTML = EMPTYSTR;
ShowToast(jqXHR.responseJSON.error);
ShowAPIError(jqXHR, textStatus, errorThrown);
}
});
}
Expand All @@ -689,8 +693,7 @@ function RemoveAccessUser(domain, user){
AccessUserDirectoryDetail(domain);
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
ShowToast(jqXHR.responseJSON.error);
ShowAPIError(jqXHR, textStatus, errorThrown);
}
});
}
Expand All @@ -714,8 +717,7 @@ function UpdateAccessUser(domain, user){
PresentCanvas(userdata, domain, SettingName, 'PATCH');
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
ShowToast(jqXHR.responseJSON.error);
ShowAPIError(jqXHR, textStatus, errorThrown);
}
});
}
Expand Down Expand Up @@ -829,9 +831,8 @@ function RoutingTableDetail(Rtablename){
};
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
document.getElementById("DetailRT"+Rtablename).innerHTML = EMPTYSTR;
ShowToast(jqXHR.responseJSON.error);
ShowAPIError(jqXHR, textStatus, errorThrown);
}
});
}
Expand All @@ -848,8 +849,7 @@ function RemoveRoutingRecord(tablename, match, value){
RoutingTableDetail(tablename);
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
ShowToast(jqXHR.responseJSON.error);
ShowAPIError(jqXHR, textStatus, errorThrown);
}
});
}
Expand Down Expand Up @@ -940,6 +940,83 @@ function ShowToast(message, msgtype='danger'){
ToastMsgEMLS.classList.remove('bg-warning');
ToastMsgEMLS.classList.remove('bg-success');
}

// Configurar duración del toast según el tipo de mensaje
let delay = 3500; // 3.5 segundos por defecto
if (msgtype === 'warning') {
delay = 8000; // 8 segundos para errores de validación
} else if (msgtype === 'danger') {
delay = 6000; // 6 segundos para errores críticos
}

// Configurar el delay del toast
ToastMsgEMLS.setAttribute('data-bs-delay', delay);

document.getElementById('event-message').innerHTML = message;
$('.toast').toast('show');
}

// Función mejorada para mostrar errores de la API
function ShowAPIError(jqXHR, textStatus, errorThrown) {
console.log(jqXHR);

let errorMessage = '';
let msgType = 'danger';

if (jqXHR.responseJSON) {
const error = jqXHR.responseJSON;

if (error.detail && Array.isArray(error.detail)) {
// Error de validación de Pydantic
msgType = 'warning';
errorMessage = '<strong>🚨 Errores de Validación:</strong><br>';

error.detail.forEach((err, index) => {
let fieldName = err.loc && err.loc.length > 1 ? err.loc[1] : 'Campo';
let errorMsg = err.msg || 'Error de validación';
let inputValue = err.input ? ` (Valor: <code>${err.input}</code>)` : '';
let expectedValues = err.ctx && err.ctx.expected ? `<br><small>💡 Valores permitidos: ${err.ctx.expected}</small>` : '';

errorMessage += `• <strong>${fieldName}:</strong> ${errorMsg}${inputValue}${expectedValues}<br>`;
});

// Agregar sugerencia de ayuda
errorMessage += '<br><small>💡 Revisa los valores ingresados y asegúrate de que cumplan con el formato requerido.</small>';
} else if (error.error) {
errorMessage = `<strong>❌ Error:</strong> ${error.error}`;
} else if (error.message) {
errorMessage = `<strong>❌ Error:</strong> ${error.message}`;
} else {
errorMessage = '❌ Ha ocurrido un error inesperado';
}

// Agregar código de estado si está disponible
if (jqXHR.status) {
let statusText = '';
switch(jqXHR.status) {
case 400: statusText = 'Solicitud Incorrecta'; break;
case 401: statusText = 'No Autorizado'; break;
case 403: statusText = 'Prohibido'; break;
case 404: statusText = 'No Encontrado'; break;
case 422: statusText = 'Entidad No Procesable'; break;
case 500: statusText = 'Error del Servidor'; break;
default: statusText = 'Error';
}
errorMessage += `<br><small>📊 Código: ${jqXHR.status} (${statusText})</small>`;
}
} else {
// Error de conexión
msgType = 'danger';
errorMessage = `🌐 Error de conexión: ${textStatus}`;

if (textStatus === 'timeout') {
errorMessage = '⏰ Tiempo de espera agotado. Verifica tu conexión a internet.';
} else if (textStatus === 'error') {
errorMessage = '🔌 Error de conexión. Verifica que el servidor esté disponible.';
}
}

ShowToast(errorMessage, msgType);
}