Fix domains tab navigation to prevent page breakage
- Prevent re-initialization when clicking domains button while already on domains tab - Add navigateToTab helper function to intelligently handle tab navigation - Redirect #domains hash to index (no hash) since domains is the default tab - Update all navigation buttons to use navigateToTab helper - Handle both initial load and hashchange events to remove #domains hash This fixes the issue where navigating to or clicking the domains tab when already viewing it would break the page by clearing and re-rendering content.
This commit is contained in:
@@ -1,12 +1,23 @@
|
|||||||
// Main admin entry point - loads all modules and initializes the application
|
// Main admin entry point - loads all modules and initializes the application
|
||||||
// Load order: config -> state -> utils -> core -> notifications -> ws-client -> ui modules -> main init
|
// Load order: config -> state -> utils -> core -> notifications -> ws-client -> ui modules -> main init
|
||||||
|
|
||||||
|
// Redirect if hash is 'domains' on initial load (should use no hash for default)
|
||||||
|
if (location.hash === '#domains') {
|
||||||
|
// Replace state to remove hash without triggering hashchange
|
||||||
|
history.replaceState(null, '', location.pathname + location.search);
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize when DOM is ready
|
// Initialize when DOM is ready
|
||||||
function initializeApp() {
|
function initializeApp() {
|
||||||
// showTab function - must be defined after all modules are loaded
|
// showTab function - must be defined after all modules are loaded
|
||||||
function showTab(tabId) {
|
function showTab(tabId) {
|
||||||
document.querySelectorAll('.tab-content').forEach(el => el.classList.add('hidden'));
|
// If we're already on this tab and it's visible, don't do anything to avoid breaking the page
|
||||||
const tabEl = document.getElementById(tabId);
|
const tabEl = document.getElementById(tabId);
|
||||||
|
if (window.activeTab === tabId && tabEl && !tabEl.classList.contains('hidden')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelectorAll('.tab-content').forEach(el => el.classList.add('hidden'));
|
||||||
if (tabEl) tabEl.classList.remove('hidden');
|
if (tabEl) tabEl.classList.remove('hidden');
|
||||||
window.activeTab = tabId;
|
window.activeTab = tabId;
|
||||||
|
|
||||||
@@ -238,9 +249,53 @@ if (document.readyState === 'loading') {
|
|||||||
initializeApp();
|
initializeApp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Navigation helper function - only sets hash if not already on that tab
|
||||||
|
function navigateToTab(tabId) {
|
||||||
|
// Get current tab - check hash first, then fallback to activeTab
|
||||||
|
const currentHash = location.hash.substring(1);
|
||||||
|
let currentTab;
|
||||||
|
|
||||||
|
if (currentHash && document.getElementById(currentHash)) {
|
||||||
|
currentTab = currentHash;
|
||||||
|
} else {
|
||||||
|
// No hash or invalid hash - use activeTab or default to 'domains'
|
||||||
|
currentTab = window.activeTab || 'domains';
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're already on this tab, don't change the hash
|
||||||
|
// This prevents breaking the page when clicking the same tab button
|
||||||
|
if (currentTab === tabId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For domains tab, navigate to index with no hash (since domains is the default)
|
||||||
|
if (tabId === 'domains') {
|
||||||
|
history.replaceState(null, '', location.pathname + location.search);
|
||||||
|
if (window.showTab) {
|
||||||
|
window.showTab('domains');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only set hash if we're not already on this tab
|
||||||
|
location.hash = tabId;
|
||||||
|
}
|
||||||
|
window.navigateToTab = navigateToTab;
|
||||||
|
|
||||||
// Handle hash changes
|
// Handle hash changes
|
||||||
window.addEventListener('hashchange', () => {
|
window.addEventListener('hashchange', () => {
|
||||||
const tabId = location.hash.substring(1);
|
const tabId = location.hash.substring(1);
|
||||||
|
|
||||||
|
// Redirect if hash is 'domains' (should use no hash for default)
|
||||||
|
if (tabId === 'domains') {
|
||||||
|
history.replaceState(null, '', location.pathname + location.search);
|
||||||
|
// Show domains tab without hash
|
||||||
|
if (window.showTab) {
|
||||||
|
window.showTab('domains');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (tabId && document.getElementById(tabId) && window.showTab) {
|
if (tabId && document.getElementById(tabId) && window.showTab) {
|
||||||
window.showTab(tabId);
|
window.showTab(tabId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,23 +42,23 @@
|
|||||||
|
|
||||||
<nav class="flex justify-center mb-8 space-x-4 flex-wrap">
|
<nav class="flex justify-center mb-8 space-x-4 flex-wrap">
|
||||||
<!-- Core Management -->
|
<!-- Core Management -->
|
||||||
<button onclick="location.hash = 'domains';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Domains</button>
|
<button onclick="if(window.navigateToTab) window.navigateToTab('domains'); else location.hash = 'domains';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Domains</button>
|
||||||
<button onclick="location.hash = 'host';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Host</button>
|
<button onclick="if(window.navigateToTab) window.navigateToTab('host'); else location.hash = 'host';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Host</button>
|
||||||
<button onclick="location.hash = 'entries';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Entries</button>
|
<button onclick="if(window.navigateToTab) window.navigateToTab('entries'); else location.hash = 'entries';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Entries</button>
|
||||||
<button onclick="location.hash = 'peers';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Peers</button>
|
<button onclick="if(window.navigateToTab) window.navigateToTab('peers'); else location.hash = 'peers';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Peers</button>
|
||||||
<!-- Network -->
|
<!-- Network -->
|
||||||
<button onclick="location.hash = 'local-dns';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Local DNS</button>
|
<button onclick="if(window.navigateToTab) window.navigateToTab('local-dns'); else location.hash = 'local-dns';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Local DNS</button>
|
||||||
<button onclick="location.hash = 'interfaces';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Interfaces</button>
|
<button onclick="if(window.navigateToTab) window.navigateToTab('interfaces'); else location.hash = 'interfaces';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Interfaces</button>
|
||||||
<!-- Security -->
|
<!-- Security -->
|
||||||
<button onclick="location.hash = 'certs';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Certificates</button>
|
<button onclick="if(window.navigateToTab) window.navigateToTab('certs'); else location.hash = 'certs';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Certificates</button>
|
||||||
<!-- Monitoring -->
|
<!-- Monitoring -->
|
||||||
<button onclick="location.hash = 'stats';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Stats</button>
|
<button onclick="if(window.navigateToTab) window.navigateToTab('stats'); else location.hash = 'stats';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Stats</button>
|
||||||
<button onclick="location.hash = 'logs';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Logs</button>
|
<button onclick="if(window.navigateToTab) window.navigateToTab('logs'); else location.hash = 'logs';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Logs</button>
|
||||||
<!-- Configuration -->
|
<!-- Configuration -->
|
||||||
<button onclick="location.hash = 'backups';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Backups</button>
|
<button onclick="if(window.navigateToTab) window.navigateToTab('backups'); else location.hash = 'backups';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Backups</button>
|
||||||
<!-- Plugins -->
|
<!-- Plugins -->
|
||||||
<button onclick="location.hash = 'plugins';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Plugins</button>
|
<button onclick="if(window.navigateToTab) window.navigateToTab('plugins'); else location.hash = 'plugins';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Plugins</button>
|
||||||
<button onclick="location.hash = 'settings';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Settings</button>
|
<button onclick="if(window.navigateToTab) window.navigateToTab('settings'); else location.hash = 'settings';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Settings</button>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div id="domains" class="tab-content hidden flex flex-col" style="height: calc(100vh - 200px); max-height: calc(100vh - 200px);">
|
<div id="domains" class="tab-content hidden flex flex-col" style="height: calc(100vh - 200px); max-height: calc(100vh - 200px);">
|
||||||
|
|||||||
Reference in New Issue
Block a user