// Domain Management - Handles domain-related functionality
class DomainManager {
constructor() {
this.domains = [];
}
async checkTraefikInstallation() {
try {
const response = await fetch('/api/traefik/status');
if (response.ok) {
const data = await response.json();
return data.installed || false;
}
return false;
} catch (error) {
//console.log('DomainManager: Traefik status check failed, assuming not installed:', error.message);
return false;
}
}
async renderDomainsSection(configItems, displaySubcategory, subcategoryDescription) {
const traefikStatus = await this.checkTraefikInstallation();
let html = `
${this.generateField(newFieldId, newDomainKey, '', `Domain ${nextDomainNumber}`, '', { placeholder: 'example.com' })}
`;
// Find the domain-building-blocks container and add the new block
const domainContainer = document.querySelector('.domain-building-blocks');
if (domainContainer) {
const tempDiv = document.createElement('div');
tempDiv.innerHTML = newDomainHTML;
const newBlock = tempDiv.firstElementChild;
domainContainer.appendChild(newBlock);
// Focus on the new input field
const newInput = newBlock.querySelector('input');
if (newInput) {
newInput.focus();
}
// Update add domain button state
this.updateDomainDeleteButtons();
this.attachDnsChecks();
}
} catch (error) {
console.error('Error adding new domain:', error);
}
}
deleteDomain(domainKey, buttonElement) {
if (typeof window.DomainManager === 'undefined' || !window.DomainManager.deleteDomain) {
console.error('DomainManager not available for deleteDomain');
return;
}
//console.log(`Delete domain button clicked for: ${domainKey}`);
try {
// Find the domain-building-block and remove it
const domainBlock = buttonElement.closest('.domain-building-block');
if (domainBlock) {
// Clear the input value first
const input = domainBlock.querySelector('input');
if (input) {
input.value = '';
}
// Remove the entire building block
domainBlock.remove();
// Update delete button states
this.updateDomainDeleteButtons();
}
} catch (error) {
console.error('Error deleting domain:', error);
}
}
updateDomainDeleteButtons() {
// Find all domain building blocks
const allDomainBlocks = document.querySelectorAll('.domain-building-block');
// Find all domain numbers from existing blocks
const allDomainNumbers = [];
allDomainBlocks.forEach(block => {
const input = block.querySelector('input');
if (input) {
const inputName = input.name;
const match = inputName.match(/CFG_DOMAIN_(\d+)/);
if (match) {
allDomainNumbers.push(parseInt(match[1]));
}
}
});
// Update delete button states (only highest numbered domain can be deleted, but NEVER Domain 1)
allDomainBlocks.forEach((block, index) => {
const deleteBtn = block.querySelector('.delete-domain-btn');
if (deleteBtn) {
const input = block.querySelector('input');
if (input) {
const inputName = input.name;
const domainNum = inputName.match(/CFG_DOMAIN_(\d+)/);
const domainNumber = domainNum ? parseInt(domainNum[1]) : 0;
// Find the highest domain number among all visible blocks
const highestDomainNumber = Math.max(...allDomainNumbers);
// Only highest numbered domain can be deleted, but NEVER Domain 1
const canDelete = domainNumber === highestDomainNumber && domainNumber !== 1;
deleteBtn.disabled = !canDelete;
deleteBtn.className = `delete-domain-btn ${!canDelete ? 'disabled' : ''}`;
deleteBtn.title = canDelete ? 'Delete domain' : domainNumber === 1 ? 'Domain 1 cannot be deleted' : 'Can only delete highest numbered domain';
}
}
});
}
}
// Standalone domain management functions - immediately available
window.addDomain = function() {
//console.log('Add Domain button clicked!');
try {
// Before adding new domain, validate that all existing domains have valid format
if (!canAddNewDomain()) {
// Find the first invalid domain and focus it with flash
const allDomainInputs = document.querySelectorAll('input[id^="config-CFG_DOMAIN_"]');
for (const input of allDomainInputs) {
if (!validateDomainFormat(input, false)) { // Don't show notification here
input.style.animation = 'flash 0.5s ease-in-out 2';
input.focus();
setTimeout(() => {
input.style.animation = '';
}, 1000);
return;
}
}
return;
}
// Find the highest existing domain number
const domainInputs = document.querySelectorAll('input[name^="CFG_DOMAIN_"]');
const domainNumbers = [];
domainInputs.forEach(input => {
const match = input.name.match(/CFG_DOMAIN_(\d+)/);
if (match) {
domainNumbers.push(parseInt(match[1]));
}
});
// Check if we've reached the maximum of 9 domains
if (domainNumbers.length >= 9) {
//console.log('Maximum of 9 domains reached');
return;
}
const nextDomainNumber = domainNumbers.length > 0 ? Math.max(...domainNumbers) + 1 : 1;
const newDomainKey = `CFG_DOMAIN_${nextDomainNumber}`;
const newFieldId = `config-${newDomainKey}`;
// Create new domain building block HTML
const newDomainHTML = `
${typeof ConfigShared !== 'undefined' ? ConfigShared.generateField(newFieldId, newDomainKey, '', `Domain ${nextDomainNumber}`, '', {
placeholder: 'example.com',
className: 'domain-input',
onchange: 'validateDomainFormat(this, true)',
oninput: 'validateDomainFormat(this, true)',
onblur: 'validateDomainFormat(this, true)'
}) : ``}
`;
// Find the domain-building-blocks container and add the new block
const domainContainer = document.querySelector('.domain-building-blocks');
if (domainContainer) {
const tempDiv = document.createElement('div');
tempDiv.innerHTML = newDomainHTML;
const newBlock = tempDiv.firstElementChild;
domainContainer.appendChild(newBlock);
// Focus on the new input field
const newInput = newBlock.querySelector('input');
if (newInput) {
newInput.focus();
}
// Update add domain button state
updateDomainDeleteButtons();
updateAddDomainButton();
}
} catch (error) {
console.error('Error adding new domain:', error);
}
};
window.deleteDomain = function(domainKey, buttonElement) {
//console.log(`Delete domain button clicked for: ${domainKey}`);
try {
// Find the domain-building-block and remove it
const domainBlock = buttonElement.closest('.domain-building-block');
if (domainBlock) {
// Clear the input value first
const input = domainBlock.querySelector('input');
if (input) {
input.value = '';
}
// Remove the entire building block
domainBlock.remove();
// Update add domain button state (re-enable if we're below 9 domains)
updateDomainDeleteButtons();
updateAddDomainButton();
}
} catch (error) {
console.error('Error deleting domain:', error);
}
};
// Helper function to update delete button states
function updateDomainDeleteButtons() {
// Find all domain building blocks
const allDomainBlocks = document.querySelectorAll('.domain-building-block');
// Find all domain numbers from existing blocks
const allDomainNumbers = [];
allDomainBlocks.forEach(block => {
const input = block.querySelector('input');
if (input) {
const inputName = input.name;
const match = inputName.match(/CFG_DOMAIN_(\d+)/);
if (match) {
allDomainNumbers.push(parseInt(match[1]));
}
}
});
// Update delete button states (only highest numbered domain can be deleted, but NEVER Domain 1)
allDomainBlocks.forEach((block, index) => {
const deleteBtn = block.querySelector('.delete-domain-btn');
if (deleteBtn) {
const input = block.querySelector('input');
if (input) {
const inputName = input.name;
const domainNum = inputName.match(/CFG_DOMAIN_(\d+)/);
const domainNumber = domainNum ? parseInt(domainNum[1]) : 0;
// Find the highest domain number among all visible blocks
const highestDomainNumber = Math.max(...allDomainNumbers);
// Only highest numbered domain can be deleted, but NEVER Domain 1
const canDelete = domainNumber === highestDomainNumber && domainNumber !== 1;
deleteBtn.disabled = !canDelete;
deleteBtn.className = `delete-domain-btn ${!canDelete ? 'disabled' : ''}`;
deleteBtn.title = canDelete ? 'Delete domain' : domainNumber === 1 ? 'Domain 1 cannot be deleted' : 'Can only delete highest numbered domain';
}
}
});
}
// Helper function to update add domain button state
function updateAddDomainButton() {
const addDomainBtn = document.getElementById('add-domain-btn');
if (addDomainBtn) {
// Find all domain building blocks
const allDomainBlocks = document.querySelectorAll('.domain-building-block');
// Find all domain numbers from existing blocks
const allDomainNumbers = [];
allDomainBlocks.forEach(block => {
const input = block.querySelector('input');
if (input) {
const inputName = input.name;
const match = inputName.match(/CFG_DOMAIN_(\d+)/);
if (match) {
allDomainNumbers.push(parseInt(match[1]));
}
}
});
// Check if we've reached the maximum of 9 domains
const isMaxDomains = allDomainNumbers.length >= 9;
// Update button state
addDomainBtn.disabled = isMaxDomains;
addDomainBtn.className = `btn ${isMaxDomains ? 'btn-secondary' : 'btn-primary'}`;
addDomainBtn.innerHTML = `