- Add custom error pages (404, 403, 500) with user-friendly messages
- Add flash message system with signed cookies for security
- Add toast notifications with auto-dismiss and manual close
- Add comprehensive SEO meta tags (description, keywords, OG, Twitter)
- Add canonical URLs for SEO
- Update routes to use slug-based URLs (/posts/{slug} instead of /posts/{id})
- Add Open Graph and Twitter Card meta tags for social sharing
- Add favicon SVG
- Update all templates with proper meta tags and URLs
- Add error handlers registration in main.py
- Add flash middleware for request handling
- Install itsdangerous dependency
70 lines
1.8 KiB
JavaScript
70 lines
1.8 KiB
JavaScript
/**
|
|
* Flash messages functionality for blog application.
|
|
*
|
|
* Handles auto-dismissal and manual closing of flash messages.
|
|
*/
|
|
|
|
(function() {
|
|
'use strict';
|
|
|
|
const AUTO_DISMISS_DELAY = 5000; // 5 seconds
|
|
|
|
function initFlashMessages() {
|
|
const flashMessages = document.querySelectorAll('[data-testid^="flash-message-"]');
|
|
|
|
flashMessages.forEach(function(message) {
|
|
const closeBtn = message.querySelector('[data-testid="flash-close"]');
|
|
|
|
// Manual close
|
|
if (closeBtn) {
|
|
closeBtn.addEventListener('click', function() {
|
|
dismissMessage(message);
|
|
});
|
|
}
|
|
|
|
// Auto dismiss after delay
|
|
setTimeout(function() {
|
|
dismissMessage(message);
|
|
}, AUTO_DISMISS_DELAY);
|
|
|
|
// Pause auto-dismiss on hover
|
|
message.addEventListener('mouseenter', function() {
|
|
message.classList.add('paused');
|
|
});
|
|
|
|
message.addEventListener('mouseleave', function() {
|
|
message.classList.remove('paused');
|
|
});
|
|
});
|
|
}
|
|
|
|
function dismissMessage(message) {
|
|
if (message.classList.contains('paused')) {
|
|
// Retry after a short delay if paused
|
|
setTimeout(function() {
|
|
dismissMessage(message);
|
|
}, 1000);
|
|
return;
|
|
}
|
|
|
|
message.classList.add('fade-out');
|
|
|
|
setTimeout(function() {
|
|
message.remove();
|
|
|
|
// Remove container if empty
|
|
const container = document.querySelector('[data-testid="flash-container"]');
|
|
if (container && container.children.length === 0) {
|
|
container.remove();
|
|
}
|
|
}, 300);
|
|
}
|
|
|
|
// Initialize on DOM ready
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', initFlashMessages);
|
|
} else {
|
|
initFlashMessages();
|
|
}
|
|
})();
|