Initial commit
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
/**
|
||||
* Toast Notification System
|
||||
* Provides consistent, user-friendly notifications across the application
|
||||
* Uses Toastr library with Bootstrap 5 theming
|
||||
*/
|
||||
|
||||
// Configure Toastr global options
|
||||
toastr.options = {
|
||||
"closeButton": true,
|
||||
"debug": false,
|
||||
"newestOnTop": true,
|
||||
"progressBar": true,
|
||||
"positionClass": "toast-top-right",
|
||||
"preventDuplicates": true,
|
||||
"onclick": null,
|
||||
"showDuration": "300",
|
||||
"hideDuration": "1000",
|
||||
"timeOut": "5000",
|
||||
"extendedTimeOut": "1000",
|
||||
"showEasing": "swing",
|
||||
"hideEasing": "linear",
|
||||
"showMethod": "fadeIn",
|
||||
"hideMethod": "fadeOut"
|
||||
};
|
||||
|
||||
/**
|
||||
* Show success toast notification
|
||||
* @param {string} message - The success message to display
|
||||
* @param {string} title - Optional title for the toast
|
||||
*/
|
||||
function showSuccess(message, title = 'Success') {
|
||||
toastr.success(message, title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show error toast notification
|
||||
* @param {string} message - The error message to display
|
||||
* @param {string} title - Optional title for the toast
|
||||
*/
|
||||
function showError(message, title = 'Error') {
|
||||
toastr.error(message, title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show warning toast notification
|
||||
* @param {string} message - The warning message to display
|
||||
* @param {string} title - Optional title for the toast
|
||||
*/
|
||||
function showWarning(message, title = 'Warning') {
|
||||
toastr.warning(message, title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show info toast notification
|
||||
* @param {string} message - The info message to display
|
||||
* @param {string} title - Optional title for the toast
|
||||
*/
|
||||
function showInfo(message, title = 'Info') {
|
||||
toastr.info(message, title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show validation errors from ModelState
|
||||
* @param {Array<string>} errors - Array of validation error messages
|
||||
*/
|
||||
function showValidationErrors(errors) {
|
||||
if (!errors || errors.length === 0) return;
|
||||
|
||||
// If single error, show it directly
|
||||
if (errors.length === 1) {
|
||||
showError(errors[0], 'Validation Error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Multiple errors - show as a list
|
||||
const errorList = '<ul class="mb-0 ps-3">' +
|
||||
errors.map(err => `<li>${escapeHtml(err)}</li>`).join('') +
|
||||
'</ul>';
|
||||
|
||||
toastr.error(errorList, `${errors.length} Validation Errors`, {
|
||||
timeOut: 8000,
|
||||
extendedTimeOut: 2000
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Display TempData messages automatically on page load
|
||||
* Expects TempData keys: Success, Error, Warning, Info
|
||||
*/
|
||||
function displayTempDataMessages() {
|
||||
// Success message
|
||||
const successMsg = document.getElementById('tempdata-success-message');
|
||||
if (successMsg && successMsg.textContent.trim()) {
|
||||
showSuccess(successMsg.textContent.trim());
|
||||
}
|
||||
|
||||
// Error message
|
||||
const errorMsg = document.getElementById('tempdata-error-message');
|
||||
if (errorMsg && errorMsg.textContent.trim()) {
|
||||
showError(errorMsg.textContent.trim());
|
||||
}
|
||||
|
||||
// Permanent success — no auto-dismiss
|
||||
const successPerm = document.getElementById('tempdata-success-permanent-message');
|
||||
if (successPerm && successPerm.textContent.trim()) {
|
||||
toastr.success(successPerm.textContent.trim(), 'Success', { timeOut: 0, extendedTimeOut: 0 });
|
||||
}
|
||||
|
||||
// Permanent error — no auto-dismiss
|
||||
const errorPerm = document.getElementById('tempdata-error-permanent-message');
|
||||
if (errorPerm && errorPerm.textContent.trim()) {
|
||||
toastr.error(errorPerm.textContent.trim(), 'Error', { timeOut: 0, extendedTimeOut: 0 });
|
||||
}
|
||||
|
||||
// Warning message
|
||||
const warningMsg = document.getElementById('tempdata-warning-message');
|
||||
if (warningMsg && warningMsg.textContent.trim()) {
|
||||
showWarning(warningMsg.textContent.trim());
|
||||
}
|
||||
|
||||
// Info message
|
||||
const infoMsg = document.getElementById('tempdata-info-message');
|
||||
if (infoMsg && infoMsg.textContent.trim()) {
|
||||
showInfo(infoMsg.textContent.trim());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display ModelState validation errors on page load
|
||||
* Expects a hidden div with id 'modelstate-errors' containing JSON array of errors
|
||||
*/
|
||||
function displayModelStateErrors() {
|
||||
const errorContainer = document.getElementById('modelstate-errors');
|
||||
if (errorContainer && errorContainer.textContent.trim()) {
|
||||
try {
|
||||
const errors = JSON.parse(errorContainer.textContent);
|
||||
showValidationErrors(errors);
|
||||
} catch (e) {
|
||||
console.error('Failed to parse ModelState errors:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape HTML to prevent XSS
|
||||
* @param {string} text - Text to escape
|
||||
* @returns {string} - Escaped text
|
||||
*/
|
||||
function escapeHtml(text) {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all toasts
|
||||
*/
|
||||
function clearAllToasts() {
|
||||
toastr.clear();
|
||||
}
|
||||
|
||||
// Auto-initialize on page load
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
displayTempDataMessages();
|
||||
displayModelStateErrors();
|
||||
});
|
||||
|
||||
// Make functions globally available
|
||||
window.showSuccess = showSuccess;
|
||||
window.showError = showError;
|
||||
window.showWarning = showWarning;
|
||||
window.showInfo = showInfo;
|
||||
window.showValidationErrors = showValidationErrors;
|
||||
window.clearAllToasts = clearAllToasts;
|
||||
Reference in New Issue
Block a user