Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
159
resources/js/modules/spa-router/index.js
Normal file
159
resources/js/modules/spa-router/index.js
Normal file
@@ -0,0 +1,159 @@
|
||||
import { Logger } from '../../core/logger.js';
|
||||
import { SPARouter } from './SPARouter.js';
|
||||
import { getAdaptiveTransition, fastTransition } from './transition-config.js';
|
||||
|
||||
/**
|
||||
* SPA Router Module
|
||||
*
|
||||
* Provides Single Page Application navigation:
|
||||
* - Intercepts internal links and loads content via AJAX
|
||||
* - Updates only the <main> element, keeping header/footer unchanged
|
||||
* - Manages browser history (back/forward buttons work)
|
||||
* - Shows skeleton loading states during navigation
|
||||
* - Progressive enhancement (falls back to normal navigation on errors)
|
||||
*
|
||||
* Features:
|
||||
* - Automatic link interception for all internal links (href="/...")
|
||||
* - Opt-out via data-spa="false"
|
||||
* - Browser history management with pushState
|
||||
* - Loading states and smooth transitions
|
||||
* - Module re-initialization after content changes
|
||||
* - Skeleton loading animation
|
||||
*
|
||||
* Backend Integration:
|
||||
* - Sends X-SPA-Request header to signal SPA navigation
|
||||
* - Backend can return only <main> content for SPA requests
|
||||
* - Falls back to full page load if SPA request fails
|
||||
*/
|
||||
|
||||
const SPARouterModule = {
|
||||
name: 'spa-router',
|
||||
router: null,
|
||||
initialized: false,
|
||||
|
||||
init(config = {}) {
|
||||
// Prevent multiple initialization
|
||||
if (this.initialized && this.router) {
|
||||
Logger.warn('[SPARouterModule] SPA Router already initialized, returning existing instance');
|
||||
return this.router;
|
||||
}
|
||||
|
||||
Logger.info('[SPARouterModule] Initializing SPA Router');
|
||||
|
||||
// Default configuration mit schnelleren Transitions
|
||||
const defaultConfig = {
|
||||
containerSelector: 'main',
|
||||
linkSelector: 'a[href^="/"]',
|
||||
excludeSelector: '[data-spa="false"], [download], [target="_blank"], [href^="mailto:"], [href^="tel:"], [href^="#"]',
|
||||
enableSkeletonLoading: true,
|
||||
...fastTransition, // Verwende schnelle Transitions als Standard
|
||||
...getAdaptiveTransition() // Überschreibe mit adaptiven Einstellungen
|
||||
};
|
||||
|
||||
const options = { ...defaultConfig, ...config };
|
||||
|
||||
// Initialize router
|
||||
this.router = SPARouter.create(options);
|
||||
this.initialized = true;
|
||||
|
||||
// Set up global access
|
||||
if (typeof window !== 'undefined') {
|
||||
window.spaRouter = this.router;
|
||||
}
|
||||
|
||||
// Listen for module re-initialization events
|
||||
document.addEventListener('spa:reinit-module', this.handleModuleReinit.bind(this));
|
||||
|
||||
// Listen for navigation events for debugging
|
||||
document.addEventListener('spa:navigated', this.handleNavigation.bind(this));
|
||||
|
||||
Logger.info('[SPARouterModule] SPA Router initialized successfully');
|
||||
|
||||
return this.router;
|
||||
},
|
||||
|
||||
handleModuleReinit(event) {
|
||||
const { element, moduleName } = event.detail;
|
||||
|
||||
Logger.info(`[SPARouterModule] Re-initializing module: ${moduleName}`, element);
|
||||
|
||||
// This would need access to the main module system
|
||||
// For now, we'll just log and let the main init system handle it
|
||||
|
||||
// Trigger a custom event that the main module system can listen to
|
||||
const reinitEvent = new CustomEvent('module:reinit-needed', {
|
||||
detail: { element, moduleName },
|
||||
bubbles: true
|
||||
});
|
||||
|
||||
document.dispatchEvent(reinitEvent);
|
||||
},
|
||||
|
||||
handleNavigation(event) {
|
||||
const { url, timestamp } = event.detail;
|
||||
|
||||
Logger.info(`[SPARouterModule] Navigation completed to: ${url}`);
|
||||
|
||||
// Re-run auto form enhancement for new content
|
||||
if (typeof window.initAutoFormHandling === 'function') {
|
||||
// Only re-initialize forms that are not already enhanced
|
||||
setTimeout(() => {
|
||||
window.initAutoFormHandling();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// Trigger analytics or other tracking if needed
|
||||
if (typeof window.gtag === 'function') {
|
||||
window.gtag('config', 'GA_TRACKING_ID', {
|
||||
page_path: new URL(url).pathname
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// Public API methods
|
||||
navigateTo(url, title) {
|
||||
if (this.router) {
|
||||
return this.router.navigateTo(url, title);
|
||||
}
|
||||
Logger.warn('[SPARouterModule] Router not initialized');
|
||||
},
|
||||
|
||||
getCurrentUrl() {
|
||||
return this.router?.getCurrentUrl() || window.location.href;
|
||||
},
|
||||
|
||||
isNavigating() {
|
||||
return this.router?.isNavigating() || false;
|
||||
},
|
||||
|
||||
destroy() {
|
||||
if (this.router) {
|
||||
this.router.destroy();
|
||||
this.router = null;
|
||||
}
|
||||
|
||||
this.initialized = false;
|
||||
|
||||
// Remove global reference
|
||||
if (typeof window !== 'undefined' && window.spaRouter) {
|
||||
delete window.spaRouter;
|
||||
}
|
||||
|
||||
document.removeEventListener('spa:reinit-module', this.handleModuleReinit);
|
||||
document.removeEventListener('spa:navigated', this.handleNavigation);
|
||||
|
||||
Logger.info('[SPARouterModule] SPA Router destroyed');
|
||||
}
|
||||
};
|
||||
|
||||
// Export the router class for direct usage
|
||||
export { SPARouter };
|
||||
|
||||
// Export as default for module system
|
||||
export default SPARouterModule;
|
||||
|
||||
// Export init function directly for compatibility with module system
|
||||
export const init = SPARouterModule.init.bind(SPARouterModule);
|
||||
|
||||
// Also export named for direct usage
|
||||
export { SPARouterModule };
|
||||
Reference in New Issue
Block a user