diff --git a/webui/assets/css/customize.css b/webui/assets/css/customize.css
index 21765c17..a45e6b68 100644
--- a/webui/assets/css/customize.css
+++ b/webui/assets/css/customize.css
@@ -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 {
diff --git a/webui/assets/js/site.js b/webui/assets/js/site.js
index acfadbb8..7fe2fe88 100644
--- a/webui/assets/js/site.js
+++ b/webui/assets/js/site.js
@@ -324,9 +324,11 @@ function GetPresentNode(){
success: function (data) {
ShowProgress();
let CandidateHtml = EMPTYSTR;
- data.candidates.forEach((element) => {
- CandidateHtml = `${CandidateHtml}${element}`;
- });
+ if (data.candidates && Array.isArray(data.candidates)) {
+ data.candidates.forEach((element) => {
+ CandidateHtml = `${CandidateHtml}${element}`;
+ });
+ }
document.getElementById('node-info').innerHTML = `
Software Version ${data.swversion}
@@ -339,9 +341,8 @@ function GetPresentNode(){
${CandidateHtml}
`;
},
error: function (jqXHR, textStatus, errorThrown) {
- console.log(jqXHR);
document.getElementById('node-info').innerHTML = EMPTYSTR;
- ShowToast(jqXHR.responseJSON.error);
+ ShowAPIError(jqXHR, textStatus, errorThrown);
}
});
@@ -351,9 +352,11 @@ function GetPresentNode(){
success: function (data) {
ShowProgress();
let MembersHtml = EMPTYSTR;
- data.members.forEach((element) => {
- MembersHtml = `${MembersHtml}${element}`;
- });
+ if (data.members && Array.isArray(data.members)) {
+ data.members.forEach((element) => {
+ MembersHtml = `${MembersHtml}${element}`;
+ });
+ }
document.getElementById('cluster-info').innerHTML = `
Cluster Name ${data.name}
@@ -378,9 +381,8 @@ function GetPresentNode(){
`;
},
error: function (jqXHR, textStatus, errorThrown) {
- console.log(jqXHR);
document.getElementById('cluster-info').innerHTML = EMPTYSTR;
- ShowToast(jqXHR.responseJSON.error);
+ ShowAPIError(jqXHR, textStatus, errorThrown);
}
});
}
@@ -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);
}
});
}
@@ -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');
+ }
}
});
}
@@ -485,8 +493,7 @@ function GeneralModify(name, SettingName){
}
},
error: function (jqXHR, textStatus, errorThrown) {
- console.log(jqXHR);
- ShowToast(jqXHR.responseJSON.error);
+ ShowAPIError(jqXHR, textStatus, errorThrown);
}
});
}
@@ -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);
}
});
}
@@ -618,9 +624,8 @@ function AccessDomainPolicyDetail(Adomain){
`;
},
error: function (jqXHR, textStatus, errorThrown) {
- console.log(jqXHR);
document.getElementById(`DetailAD${Adomain}`).innerHTML = EMPTYSTR;
- ShowToast(jqXHR.responseJSON.error);
+ ShowAPIError(jqXHR, textStatus, errorThrown);
}
});
}
@@ -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);
}
});
}
@@ -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);
}
});
}
@@ -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);
}
});
}
@@ -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);
}
});
}
@@ -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);
}
});
}
@@ -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 = '🚨 Errores de Validación:
';
+
+ 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: ${err.input})` : '';
+ let expectedValues = err.ctx && err.ctx.expected ? `
💡 Valores permitidos: ${err.ctx.expected}` : '';
+
+ errorMessage += `• ${fieldName}: ${errorMsg}${inputValue}${expectedValues}
`;
+ });
+
+ // Agregar sugerencia de ayuda
+ errorMessage += '
💡 Revisa los valores ingresados y asegúrate de que cumplan con el formato requerido.';
+ } else if (error.error) {
+ errorMessage = `❌ Error: ${error.error}`;
+ } else if (error.message) {
+ errorMessage = `❌ Error: ${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 += `
📊 Código: ${jqXHR.status} (${statusText})`;
+ }
+ } 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);
+}
+
+