// Wrap the entire code in an IIFE (Immediately Invoked Function Expression) // to create a private scope and avoid global variable conflicts (function() { // Use a local variable instead of global let directivesLoadingState = false; // Expose necessary functions to window/global scope window.loadDirectives = loadDirectives; window.handleDirectiveAction = handleDirectiveAction; window.deleteDirective = deleteDirective; window.loadAttributeChoices = loadAttributeChoices; window.switchTab = switchTab; window.submitDirective = submitDirective; // Directives Functions function loadDirectives() { // Prevent multiple simultaneous requests if (directivesLoadingState) { console.log("Already loading directives, request ignored"); return; } directivesLoadingState = true; console.log("Loading directives"); const tableBody = document.getElementById('directivesTableBody'); if (!tableBody) { console.error('Directives table body not found'); directivesLoadingState = false; return; } tableBody.innerHTML = 'Loading directives...'; fetch('integrity_check_handler.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: 'action=get_directives' }) .then(response => { console.log("Get directives response status:", response.status); if (!response.ok) { throw new Error(`Server error: ${response.status}`); } return response.text().then(text => { console.log("Raw directives response:", text); // Log the raw response try { return JSON.parse(text); } catch (e) { console.error("JSON parse error:", e); throw new Error("Invalid JSON response: " + text.substring(0, 100)); } }); }) .then(data => { directivesLoadingState = false; console.log("Directives data:", data); if (!data.success) { throw new Error(data.message || 'Failed to load directives'); } if (!data.directives || data.directives.length === 0) { tableBody.innerHTML = 'No directives found'; return; } // Group directives by attributes to identify sets created from multiple selections const directiveSets = groupDirectivesByAttributes(data.directives); // Build HTML for each directive let html = ''; for (const directive of data.directives) { // See if this directive is part of a set (created from multiple selections) const setKey = `${directive.attribute1_id}_${directive.attribute2_id}`; const setInfo = directiveSets[setKey]; const isPartOfSet = setInfo && (setInfo.attr1Choices.length > 1 || setInfo.attr2Choices.length > 1); const setDescription = isPartOfSet ? `(Part of a set: ${setInfo.attr1Choices.length} × ${setInfo.attr2Choices.length} combinations)` : ''; // Create the row HTML html += ` ${directive.id} ${directive.attribute1_name}: ${directive.choice1} ${isPartOfSet ? `
${setDescription}
` : ''} ${directive.attribute2_name}: ${directive.choice2} ${directive.status.charAt(0).toUpperCase() + directive.status.slice(1)}
${directive.status === 'pending' ? ` ` : ` `}
`; } tableBody.innerHTML = html; // Add some CSS for set info addSetInfoStyles(); }) .catch(error => { directivesLoadingState = false; console.error('Error loading directives:', error); tableBody.innerHTML = `Failed to load directives: ${error.message}`; showNotification('Failed to load directives: ' + error.message, 'error'); }); } function groupDirectivesByAttributes(directives) { const sets = {}; for (const directive of directives) { const key = `${directive.attribute1_id}_${directive.attribute2_id}`; if (!sets[key]) { sets[key] = { attribute1_id: directive.attribute1_id, attribute2_id: directive.attribute2_id, attribute1_name: directive.attribute1_name, attribute2_name: directive.attribute2_name, attr1Choices: [], attr2Choices: [] }; } // Add choices if they don't exist in the array if (!sets[key].attr1Choices.includes(directive.choice1)) { sets[key].attr1Choices.push(directive.choice1); } if (!sets[key].attr2Choices.includes(directive.choice2)) { sets[key].attr2Choices.push(directive.choice2); } } return sets; } function addSetInfoStyles() { // Check if the styles are already added if (document.getElementById('set-info-styles')) return; const style = document.createElement('style'); style.id = 'set-info-styles'; style.textContent = ` .set-info { font-size: 0.75rem; color: var(--gray-500); margin-top: 0.25rem; font-style: italic; } `; document.head.appendChild(style); } function submitDirective() { const attribute1Select = document.getElementById('attribute1'); const attribute2Select = document.getElementById('attribute2'); const choice1Select = document.getElementById('choice1'); const choice2Select = document.getElementById('choice2'); if (!attribute1Select.value || !attribute2Select.value || !choice1Select.value || !choice2Select.value) { showNotification('Please select all fields', 'error'); return; } if (attribute1Select.value === attribute2Select.value) { showNotification('Please select two different attributes', 'error'); return; } const directiveData = { attribute1_id: attribute1Select.value, attribute2_id: attribute2Select.value, choice1: choice1Select.value, choice2: choice2Select.value }; console.log("Submitting new directive:", directiveData); fetch('integrity_check_handler.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: `action=add_directive&data=${encodeURIComponent(JSON.stringify(directiveData))}` }) .then(response => { console.log("Add directive response status:", response.status); if (!response.ok) { throw new Error(`Server error: ${response.status}`); } return response.text().then(text => { console.log("Raw response:", text); // Log the raw response try { return JSON.parse(text); } catch (e) { console.error("JSON parse error:", e); throw new Error("Invalid JSON response: " + text.substring(0, 100)); } }); }) .then(data => { console.log("Add directive data:", data); if (data.success) { // Reset form attribute1Select.value = ''; attribute2Select.value = ''; choice1Select.innerHTML = ''; choice2Select.innerHTML = ''; showNotification('Directive added successfully', 'success'); loadDirectives(); } else { throw new Error(data.message || 'Failed to add directive'); } }) .catch(error => { console.error('Error in submitDirective:', error); showNotification('Failed to add directive: ' + error.message, 'error'); }); } function handleDirectiveAction(id, action) { console.log(`Handling ${action} action for directive:`, id); fetch('integrity_check_handler.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: `action=${action}_directive&directive_id=${id}` }) .then(response => { console.log(`${action} directive response status:`, response.status); if (!response.ok) { throw new Error(`Server error: ${response.status}`); } return response.text().then(text => { console.log("Raw response:", text); // Log the raw response try { return JSON.parse(text); } catch (e) { console.error("JSON parse error:", e); throw new Error("Invalid JSON response: " + text.substring(0, 100)); } }); }) .then(data => { console.log(`${action} directive data:`, data); if (data.success) { showNotification(`Directive ${action === 'approve' ? 'approved' : 'revoked'} successfully`, 'success'); loadDirectives(); // Reload the directives list } else { throw new Error(data.message || `Failed to ${action} directive`); } }) .catch(error => { console.error(`Error in ${action} directive:`, error); showNotification(error.message, 'error'); }); } function deleteDirective(id) { if (!confirm('Are you sure you want to delete this directive?')) { return; } fetch('integrity_check_handler.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: `action=delete_directive&directive_id=${id}` }) .then(response => { console.log("Delete directive response status:", response.status); if (!response.ok) { throw new Error(`Server error: ${response.status}`); } return response.text().then(text => { console.log("Raw response:", text); try { return JSON.parse(text); } catch (e) { console.error("JSON parse error:", e); throw new Error("Invalid JSON response: " + text.substring(0, 100)); } }); }) .then(data => { console.log("Delete directive data:", data); if (data.success) { showNotification('Directive deleted successfully', 'success'); loadDirectives(); } else { throw new Error(data.message || 'Failed to delete directive'); } }) .catch(error => { console.error('Error in deleteDirective:', error); showNotification(error.message, 'error'); }); } // Load choices for the selected attribute function loadAttributeChoices(attributeId, targetSelectId) { if (!attributeId) { document.getElementById(targetSelectId).innerHTML = ''; return; } fetch('get_attribute_choices.php?attribute_id=' + attributeId) .then(response => response.json()) .then(data => { if (data.success) { const select = document.getElementById(targetSelectId); select.innerHTML = ''; data.choices.forEach(choice => { const option = document.createElement('option'); option.value = choice; option.textContent = choice; select.appendChild(option); }); } else { console.error('Error loading choices:', data.message); showNotification('Error loading choices: ' + data.message, 'error'); } }) .catch(error => { console.error('Error:', error); showNotification('Error loading choices', 'error'); }); } // Helper Functions function switchTab(tab) { console.log("Switching to tab:", tab); // Find the tab elements const tabs = document.querySelectorAll('.optimaize-tab'); const contents = document.querySelectorAll('.optimaize-content'); // Deactivate all tabs tabs.forEach(t => t.classList.remove('active')); contents.forEach(c => c.style.display = 'none'); // Activate the requested tab let tabElement = null; for (const t of tabs) { if (t.getAttribute('data-tab') === tab || t.textContent.toLowerCase().includes(tab.toLowerCase())) { tabElement = t; break; } } if (tabElement) { tabElement.classList.add('active'); } // Show the corresponding content let contentElement = null; if (tab === 'directives') { contentElement = document.getElementById('directivesContent'); } if (contentElement) { contentElement.style.display = 'block'; // Load directives when switching to that tab if (tab === 'directives') { loadDirectives(); } } } // Utility function to show notifications function showNotification(message, type = 'success') { console.log(`Notification (${type}):`, message); const container = document.getElementById('notificationContainer'); if (!container) { // Create container if it doesn't exist const newContainer = document.createElement('div'); newContainer.id = 'notificationContainer'; newContainer.style.position = 'fixed'; newContainer.style.top = '20px'; newContainer.style.right = '20px'; newContainer.style.zIndex = '9999'; document.body.appendChild(newContainer); // Use the newly created container showNotification(message, type); return; } const notification = document.createElement('div'); notification.className = `notification notification-${type}`; notification.style.padding = '10px 15px'; notification.style.margin = '0 0 10px 0'; notification.style.borderRadius = '4px'; notification.style.boxShadow = '0 2px 5px rgba(0,0,0,0.2)'; notification.style.opacity = '0'; notification.style.transition = 'opacity 0.3s'; // Set background color based on type if (type === 'success') { notification.style.backgroundColor = '#4CAF50'; notification.style.color = 'white'; } else if (type === 'error') { notification.style.backgroundColor = '#F44336'; notification.style.color = 'white'; } else if (type === 'warning') { notification.style.backgroundColor = '#FF9800'; notification.style.color = 'white'; } else if (type === 'info') { notification.style.backgroundColor = '#2196F3'; notification.style.color = 'white'; } const icon = document.createElement('span'); icon.className = 'notification-icon'; icon.style.marginRight = '10px'; icon.textContent = type === 'success' ? '✓' : type === 'warning' ? '⚠' : type === 'info' ? 'ℹ' : '⨉'; const text = document.createElement('span'); text.className = 'notification-message'; text.textContent = message; notification.appendChild(icon); notification.appendChild(text); container.appendChild(notification); // Show notification with a small delay setTimeout(() => { notification.style.opacity = '1'; }, 10); // Hide and remove after 5 seconds setTimeout(() => { notification.style.opacity = '0'; setTimeout(() => notification.remove(), 300); }, 5000); } // Initialize event handlers document.addEventListener('DOMContentLoaded', function() { console.log("DOM loaded, initializing directive handlers"); // Setup tabs const directivesTab = document.querySelector('.optimaize-tab[data-tab="directives"]'); if (directivesTab) { directivesTab.addEventListener('click', (e) => { console.log("Directives tab clicked"); e.preventDefault(); switchTab('directives'); }); console.log("Directives tab handler attached"); } else { console.warn("Directives tab not found"); } // Setup attribute selection change handlers const attribute1Select = document.getElementById('attribute1'); const attribute2Select = document.getElementById('attribute2'); if (attribute1Select) { attribute1Select.addEventListener('change', function() { loadAttributeChoices(this.value, 'choice1'); }); } if (attribute2Select) { attribute2Select.addEventListener('change', function() { loadAttributeChoices(this.value, 'choice2'); }); } // Load directives by default if (document.querySelector('.optimaize-section') && document.querySelector('.optimaize-section').style.display === 'block') { console.log("Loading directives by default"); loadDirectives(); } console.log("Directive initialization complete"); }); })();