mirror of
https://github.com/sassanix/Warracker.git
synced 2026-01-06 05:29:39 -06:00
### Major Features - **Public Global Warranty View:** All authenticated users can now view global warranties. Admins retain full control; regular users get read-only access to others’ warranties. - **Global View Admin Controls:** Admins can now toggle global view availability and limit it to admins only via site settings. - **Global Status Dashboard View:** Extended global view to warranty statistics and dashboards with full permissions enforcement. - **Apprise Push Notifications:** Integrated Apprise for multi-platform warranty alerts with extensive backend and frontend support (80+ services). - **Warranty Type Filtering/Sorting:** Introduced dynamic, case-insensitive filtering and sorting by warranty type on the main page. - **Admin Global Warranty View:** Dedicated admin tools and UI for viewing all warranties with enhanced styling and user info. ### UX/UI Enhancements - **Product Photo Thumbnails:** Added interactive, responsive photo previews on warranty cards across all views. - **Updated Footer Links:** All "Powered by Warracker" footers now link to the official website (`https://warracker.com`). ### Fixes and Stability Improvements - **Status Dashboard Chart Fixes:** Resolved canvas reuse errors and chart switching issues. - **CSS Cache Busting:** Ensured consistent styling across domain/IP access by versioning CSS/JS and updating service worker. - **Settings Access Fixes:** Regular users can now access the settings page without triggering admin-only API calls. - **Settings Persistence Fixes:** Addressed major frontend/backend issues preventing correct saving/loading of user preferences. - **Notification Timing Overhaul:** Rewrote logic for precise notification delivery and implemented duplicate prevention. ### Security and Technical Enhancements - Global view maintains secure ownership enforcement. - Improved permission checks, graceful degradation, and responsive design across all new features.
103 lines
4.0 KiB
JavaScript
103 lines
4.0 KiB
JavaScript
/**
|
|
* Footer Width Fix - Universal
|
|
* Ensures the Warracker footer spans full width across all pages
|
|
* Handles both light and dark themes automatically
|
|
*/
|
|
|
|
(function() {
|
|
'use strict';
|
|
|
|
// Apply footer styles based on theme
|
|
function applyFooterStyles() {
|
|
const footer = document.getElementById('warrackerFooter');
|
|
const link = document.getElementById('warrackerFooterLink');
|
|
|
|
if (!footer) return; // Exit if footer doesn't exist on this page
|
|
|
|
// Detect dark mode
|
|
const isDarkMode = document.documentElement.getAttribute('data-theme') === 'dark' ||
|
|
document.documentElement.classList.contains('dark-mode') ||
|
|
document.body.classList.contains('dark-mode');
|
|
|
|
if (isDarkMode) {
|
|
// Dark mode styles with full width override
|
|
footer.style.cssText = `
|
|
width: 100vw !important;
|
|
margin-top: 50px !important;
|
|
margin-left: calc(-50vw + 50%) !important;
|
|
margin-right: calc(-50vw + 50%) !important;
|
|
padding: 20px !important;
|
|
text-align: center !important;
|
|
border-top: 1px solid #444 !important;
|
|
background-color: #2d2d2d !important;
|
|
color: #e0e0e0 !important;
|
|
font-size: 0.9rem !important;
|
|
position: relative !important;
|
|
left: 0 !important;
|
|
right: 0 !important;
|
|
max-width: none !important;
|
|
box-sizing: border-box !important;
|
|
`;
|
|
if (link) {
|
|
link.style.cssText = 'color: #4dabf7 !important; text-decoration: none !important; font-weight: 500 !important;';
|
|
}
|
|
} else {
|
|
// Light mode styles with full width override
|
|
footer.style.cssText = `
|
|
width: 100vw !important;
|
|
margin-top: 50px !important;
|
|
margin-left: calc(-50vw + 50%) !important;
|
|
margin-right: calc(-50vw + 50%) !important;
|
|
padding: 20px !important;
|
|
text-align: center !important;
|
|
border-top: 1px solid #e0e0e0 !important;
|
|
background-color: #ffffff !important;
|
|
color: #333333 !important;
|
|
font-size: 0.9rem !important;
|
|
position: relative !important;
|
|
left: 0 !important;
|
|
right: 0 !important;
|
|
max-width: none !important;
|
|
box-sizing: border-box !important;
|
|
`;
|
|
if (link) {
|
|
link.style.cssText = 'color: #3498db !important; text-decoration: none !important; font-weight: 500 !important;';
|
|
}
|
|
}
|
|
}
|
|
|
|
// Initialize footer styles when DOM is ready
|
|
function initFooterFix() {
|
|
applyFooterStyles();
|
|
|
|
// Watch for theme changes on document.documentElement
|
|
const observer = new MutationObserver(applyFooterStyles);
|
|
observer.observe(document.documentElement, {
|
|
attributes: true,
|
|
attributeFilter: ['data-theme', 'class']
|
|
});
|
|
|
|
// Also watch body for theme changes (fallback)
|
|
observer.observe(document.body, {
|
|
attributes: true,
|
|
attributeFilter: ['class']
|
|
});
|
|
|
|
// Listen for custom theme change events if they exist
|
|
document.addEventListener('themeChanged', applyFooterStyles);
|
|
window.addEventListener('themeChanged', applyFooterStyles);
|
|
}
|
|
|
|
// Auto-initialize when DOM is loaded
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', initFooterFix);
|
|
} else {
|
|
// DOM is already loaded
|
|
initFooterFix();
|
|
}
|
|
|
|
// Expose function globally in case manual calls are needed
|
|
window.applyFooterFix = applyFooterStyles;
|
|
|
|
console.log('Footer Fix loaded - Footer will span full width on all pages');
|
|
})();
|