Metadata Dashboard

Metadata Dashboard

Overview

Total Metadata Entries

--

Unique Metadata Types

--

Average Completeness Score

--%

Entries with Missing Data

--

Metadata Entries by Type

Metadata Completeness by Type

Recent Metadata Activities & Alerts

No recent activities or alerts to display.

No recent activities or alerts to display.

'; } else { dashboardData.recentActivity.forEach(item => { const activityDiv = document.createElement('div'); activityDiv.className = 'bg-white p-3 rounded-md shadow-sm text-gray-800'; activityDiv.textContent = item.text; recentActivityListElement.appendChild(activityDiv); }); } } // Render Metadata List in its tab renderMetadataManagement(); } // Function to render the metadata management table function renderMetadataManagement() { const metadataTableBody = document.querySelector('#metadata-table tbody'); if (metadataTableBody) { metadataTableBody.innerHTML = ''; // Clear existing rows if (dashboardData.metadataEntries.length === 0) { metadataTableBody.innerHTML = 'No metadata entries added yet.'; } else { dashboardData.metadataEntries.forEach(entry => { const row = metadataTableBody.insertRow(); row.innerHTML = ` ${entry.name} ${entry.type} ${entry.completeness}% ${entry.creationDate} ${entry.description} `; }); } } } // Function to populate data configuration inputs function populateConfigInputs() { const inputTotalMetadataEntries = document.getElementById('input-total-metadata-entries'); const inputUniqueMetadataTypes = document.getElementById('input-unique-metadata-types'); const inputAverageCompleteness = document.getElementById('input-average-completeness'); const inputMissingDataEntries = document.getElementById('input-missing-data-entries'); const inputMetadataTypeCounts = document.getElementById('input-metadata-type-counts'); const inputCompletenessByType = document.getElementById('input-completeness-by-type'); const inputRecentActivity = document.getElementById('input-recent-activity'); if (inputTotalMetadataEntries) inputTotalMetadataEntries.value = dashboardData.totalMetadataEntries; if (inputUniqueMetadataTypes) inputUniqueMetadataTypes.value = dashboardData.uniqueMetadataTypes; if (inputAverageCompleteness) inputAverageCompleteness.value = dashboardData.averageCompleteness.toFixed(0); if (inputMissingDataEntries) inputMissingDataEntries.value = dashboardData.missingDataEntries; if (inputMetadataTypeCounts) { const typeEntries = Object.entries(dashboardData.metadataTypeCounts).map(([type, count]) => `${type}:${count}`).join(','); inputMetadataTypeCounts.value = typeEntries; } if (inputCompletenessByType) { const completenessEntries = Object.entries(dashboardData.completenessByType).map(([type, percent]) => `${type}:${percent}`).join(','); inputCompletenessByType.value = completenessEntries; } if (inputRecentActivity) inputRecentActivity.value = dashboardData.recentActivity.map(a => a.text).join('\n'); } // Initial render of the dashboard and populate config inputs renderDashboard(); populateConfigInputs(); // Make functions globally accessible for onclick attributes window.showTab = function(tabId) { const tabs = ['dashboard', 'metadata-management', 'data-config']; tabs.forEach(id => { const tabContent = document.getElementById(`${id}-tab-content`); const tabButton = document.getElementById(`${id}-tab-button`); if (tabContent && tabButton) { if (id === tabId) { tabContent.classList.remove('hidden'); tabButton.classList.add('active'); } else { tabContent.classList.add('hidden'); tabButton.classList.remove('active'); } } }); updateTabNavigationButtons(tabId); }; // Function to navigate tabs using Next/Previous buttons window.navigateTabs = function(direction) { const tabs = ['dashboard', 'metadata-management', 'data-config']; let currentTabIndex = -1; tabs.forEach((id, index) => { const tabContent = document.getElementById(`${id}-tab-content`); if (tabContent && !tabContent.classList.contains('hidden')) { currentTabIndex = index; } }); let nextTabIndex = currentTabIndex; if (direction === 'next') { nextTabIndex = Math.min(currentTabIndex + 1, tabs.length - 1); } else if (direction === 'prev') { nextTabIndex = Math.max(currentTabIndex - 1, 0); } if (nextTabIndex !== currentTabIndex) { showTab(tabs[nextTabIndex]); } }; // Function to update the visibility of Next/Previous buttons function updateTabNavigationButtons(activeTabId) { const prevButton = document.getElementById('prev-tab-button'); const nextButton = document.getElementById('next-tab-button'); if (prevButton && nextButton) { if (activeTabId === 'dashboard') { prevButton.classList.add('hidden'); nextButton.classList.remove('hidden'); } else if (activeTabId === 'data-config') { prevButton.classList.remove('hidden'); nextButton.classList.add('hidden'); } else { // For intermediate tabs, both buttons are visible prevButton.classList.remove('hidden'); nextButton.classList.remove('hidden'); } } } // Initial state for tab navigation buttons updateTabNavigationButtons('dashboard'); // Function to add a new metadata entry window.addMetadataEntry = function() { const newMetadataName = document.getElementById('new-metadata-name'); const newMetadataType = document.getElementById('new-metadata-type'); const newMetadataCompleteness = document.getElementById('new-metadata-completeness'); const newMetadataCreationDate = document.getElementById('new-metadata-creation-date'); const newMetadataDescription = document.getElementById('new-metadata-description'); if (!newMetadataName || !newMetadataType || !newMetadataCompleteness || !newMetadataCreationDate || !newMetadataDescription) { console.error("One or more new metadata input fields not found."); return; } const name = newMetadataName.value.trim(); const type = newMetadataType.value; const completeness = parseInt(newMetadataCompleteness.value) || 0; const creationDate = newMetadataCreationDate.value; const description = newMetadataDescription.value.trim(); if (name && type && creationDate) { const newId = dashboardData.metadataEntries.length > 0 ? Math.max(...dashboardData.metadataEntries.map(e => e.id)) + 1 : 1; dashboardData.metadataEntries.push({ id: newId, name, type, completeness, creationDate, description }); renderMetadataManagement(); // Clear form fields newMetadataName.value = ''; newMetadataType.value = 'Document'; // Reset to default newMetadataCompleteness.value = '100'; newMetadataCreationDate.value = ''; newMetadataDescription.value = ''; // Re-render dashboard to update charts and metrics that depend on metadata list renderDashboard(); populateConfigInputs(); // Update config inputs as well } else { alert('Please fill in Name, Type, and Creation Date for the metadata entry.'); // Using alert as per previous code, but typically would use a custom modal } }; // Function to edit a metadata entry (simplified: could open a modal for editing) window.editMetadataEntry = function(id) { const entry = dashboardData.metadataEntries.find(e => e.id === id); if (entry) { document.getElementById('new-metadata-name').value = entry.name; document.getElementById('new-metadata-type').value = entry.type; document.getElementById('new-metadata-completeness').value = entry.completeness; document.getElementById('new-metadata-creation-date').value = entry.creationDate; document.getElementById('new-metadata-description').value = entry.description; deleteMetadataEntry(id); // Remove the old entry after pre-filling for a "replace" action alert('Metadata fields pre-filled for editing. Please adjust and click "Add Metadata Entry" to save changes.'); } }; // Function to delete a metadata entry window.deleteMetadataEntry = function(id) { dashboardData.metadataEntries = dashboardData.metadataEntries.filter(entry => entry.id !== id); renderMetadataManagement(); renderDashboard(); // Re-render dashboard to update charts and metrics populateConfigInputs(); // Update config inputs as well }; // Function to update dashboard data from input fields window.updateDashboardData = function() { const inputTotalMetadataEntries = document.getElementById('input-total-metadata-entries'); const inputUniqueMetadataTypes = document.getElementById('input-unique-metadata-types'); const inputAverageCompleteness = document.getElementById('input-average-completeness'); const inputMissingDataEntries = document.getElementById('input-missing-data-entries'); const inputMetadataTypeCounts = document.getElementById('input-metadata-type-counts'); const inputCompletenessByType = document.getElementById('input-completeness-by-type'); const inputRecentActivity = document.getElementById('input-recent-activity'); // Perform null checks for all elements if (inputTotalMetadataEntries) dashboardData.totalMetadataEntries = parseInt(inputTotalMetadataEntries.value) || 0; if (inputUniqueMetadataTypes) dashboardData.uniqueMetadataTypes = parseInt(inputUniqueMetadataTypes.value) || 0; if (inputAverageCompleteness) dashboardData.averageCompleteness = parseFloat(inputAverageCompleteness.value) || 0; if (inputMissingDataEntries) dashboardData.missingDataEntries = parseInt(inputMissingDataEntries.value) || 0; if (inputMetadataTypeCounts) { const typeMap = {}; inputMetadataTypeCounts.value.split(',').forEach(entry => { const parts = entry.split(':'); if (parts.length === 2) { const type = parts[0].trim(); const count = parseInt(parts[1].trim()); if (type && !isNaN(count)) { typeMap[type] = count; } } }); dashboardData.metadataTypeCounts = typeMap; } if (inputCompletenessByType) { const completenessMap = {}; inputCompletenessByType.value.split(',').forEach(entry => { const parts = entry.split(':'); if (parts.length === 2) { const type = parts[0].trim(); const percent = parseFloat(parts[1].trim()); if (type && !isNaN(percent)) { completenessMap[type] = percent; } } }); dashboardData.completenessByType = completenessMap; } if (inputRecentActivity) { const activityComments = inputRecentActivity.value.split('\n').map(comment => comment.trim()).filter(comment => comment.length > 0); dashboardData.recentActivity = activityComments.map((comment, index) => ({ id: index + 1, text: comment })); } renderDashboard(); // Re-render dashboard with new data showTab('dashboard'); // Switch back to dashboard tab after saving }; // Function to download dashboard as PDF window.downloadDashboardPdf = async function() { const dashboardContent = document.getElementById('dashboard-tab-content'); // Get the dashboard content div if (!dashboardContent) { console.error("Dashboard content element not found for PDF generation."); return; } // Temporarily hide elements not needed in PDF const elementsToHide = [ document.getElementById('prev-tab-button'), document.getElementById('next-tab-button'), document.getElementById('download-pdf-button'), document.querySelector('.flex.flex-wrap.border-b') // Tab navigation buttons container ]; elementsToHide.forEach(el => { if (el) el.style.display = 'none'; }); // Set a temporary background color for the PDF capture if needed, then revert const originalBg = document.body.style.backgroundColor; document.body.style.backgroundColor = '#ffffff'; // Ensure white background for PDF // Use html2canvas to capture the dashboard content const canvas = await html2canvas(dashboardContent, { scale: 2, // Increase scale for better resolution in PDF useCORS: true, // Important for images if any, though none are used here logging: false, // Disable logging for cleaner console backgroundColor: '#ffffff' // Ensure white background for the captured image }); // Revert hidden elements and background elementsToHide.forEach(el => { if (el) el.style.display = ''; // Revert to original display }); document.body.style.backgroundColor = originalBg; // Create a new jsPDF instance let jsPDF_lib; if (window.jspdf && typeof window.jspdf.jsPDF === 'function') { jsPDF_lib = window.jspdf.jsPDF; } else { console.error("jsPDF library (window.jspdf.jsPDF) not found or not a function."); return; // Cannot proceed without jsPDF } const pdf = new jsPDF_lib('p', 'mm', 'a4'); // 'p' for portrait, 'mm' for millimeters, 'a4' size const imgData = canvas.toDataURL('image/png'); const imgWidth = 210; // A4 width in mm const pageHeight = 297; // A4 height in mm const imgHeight = canvas.height * imgWidth / canvas.width; let heightLeft = imgHeight; let position = 0; // Add title to PDF pdf.setFontSize(22); pdf.text('Metadata Dashboard Report', pdf.internal.pageSize.getWidth() / 2, 15, { align: 'center' }); pdf.setFontSize(10); pdf.text(`Report Date: ${new Date().toLocaleDateString('en-US')}`, pdf.internal.pageSize.getWidth() / 2, 25, { align: 'center' }); // Add a small margin after the title position = 35; // Add image to PDF, handling multiple pages if content is too long pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight); heightLeft -= pageHeight - position; while (heightLeft >= 0) { position = heightLeft - imgHeight + 5; // Add a small margin at the top of new page pdf.addPage(); pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight); heightLeft -= pageHeight; } pdf.save('Metadata_Dashboard.pdf'); }; });
Scroll to Top