Error: Could not load required libraries.
';
return;
}
let iac_statusChart, iac_costChart;
const TABS = ['dashboardTab', 'configTab'];
let iac_currentTabIndex = 0;
const ICONS = {
aws: `
`,
azure: `
`,
gcp: `
`
};
const STATUS_CONFIG = {
Synced: { bg: '#dcfce7', text: '#166534', color: '#22c55e' },
Drifted: { bg: '#fef9c3', text: '#854d0e', color: '#f59e0b' },
Error: { bg: '#fee2e2', text: '#991b1b', color: '#ef4444' }
};
const sampleData = [
{ stackName: "prod-us-east-1-main-app", provider: "aws", status: "Synced", resources: 125, cost: 5500, lastSync: "2025-07-08" },
{ stackName: "prod-us-west-2-analytics-db", provider: "aws", status: "Synced", resources: 15, cost: 2300, lastSync: "2025-07-08" },
{ stackName: "staging-central-us-api", provider: "azure", status: "Drifted", resources: 75, cost: 1200, lastSync: "2025-07-07" },
{ stackName: "dev-gcp-europe-west-1-testing", provider: "gcp", status: "Synced", resources: 30, cost: 450, lastSync: "2025-07-09" },
{ stackName: "shared-services-networking", provider: "aws", status: "Error", resources: 40, cost: 800, lastSync: "2025-07-05" },
];
function iac_initialize() {
sampleData.forEach(d => iac_add_row(d));
iac_updateDashboard();
iac_updateNavButtons();
}
window.iac_add_row = function(data = {}) {
const tableBody = document.getElementById('iac-input-table-body');
const row = tableBody.insertRow();
row.innerHTML = `
|
|
|
|
|
|
|
`;
}
function iac_collectData() {
const rows = document.getElementById('iac-input-table-body').rows;
let data = [];
for (let row of rows) {
data.push({
stackName: row.querySelector('.stackName').value,
provider: row.querySelector('.provider').value,
status: row.querySelector('.status').value,
resources: parseInt(row.querySelector('.resources').value) || 0,
cost: parseInt(row.querySelector('.cost').value) || 0,
lastSync: row.querySelector('.lastSync').value,
});
}
return data;
}
window.iac_updateDashboard = function() {
const data = iac_collectData();
iac_updateSummaryMetrics(data);
iac_updateStatusChart(data);
iac_updateCostChart(data);
iac_renderTable(data);
iac_changeTab('dashboardTab');
}
function iac_updateSummaryMetrics(data) {
document.getElementById('summary-stacks').textContent = data.length;
document.getElementById('summary-resources').textContent = data.reduce((sum, s) => sum + s.resources, 0).toLocaleString();
const totalCost = data.reduce((sum, s) => sum + s.cost, 0);
document.getElementById('summary-cost').textContent = `$${totalCost.toLocaleString()}`;
}
function iac_updateStatusChart(data) {
const ctx = document.getElementById('iac-status-chart');
if (iac_statusChart) iac_statusChart.destroy();
const statusCounts = data.reduce((acc, s) => {
acc[s.status] = (acc[s.status] || 0) + 1;
return acc;
}, {});
const labels = Object.keys(STATUS_CONFIG);
const chartData = labels.map(label => statusCounts[label] || 0);
const colors = labels.map(label => STATUS_CONFIG[label].color);
iac_statusChart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: labels,
datasets: [{
data: chartData,
backgroundColor: colors,
borderColor: '#ffffff',
borderWidth: 2,
}]
},
options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'top' } } }
});
}
function iac_updateCostChart(data) {
const ctx = document.getElementById('iac-cost-chart');
if (iac_costChart) iac_costChart.destroy();
const sortedData = [...data].sort((a,b) => b.cost - a.cost);
iac_costChart = new Chart(ctx, {
type: 'bar',
data: {
labels: sortedData.map(d => d.stackName),
datasets: [{
label: 'Monthly Cost ($)',
data: sortedData.map(d => d.cost),
backgroundColor: '#60a5fa',
borderColor: '#2563eb',
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: { y: { beginAtZero: true, ticks: { callback: (v) => '$' + v.toLocaleString() } } },
plugins: { legend: { display: false } }
}
});
}
function iac_renderTable(data) {
const tableBody = document.getElementById('iac-table-body');
tableBody.innerHTML = '';
data.forEach(s => {
const row = tableBody.insertRow();
row.innerHTML = `
${s.stackName} |
${ICONS[s.provider] || ''} ${s.provider.toUpperCase()} |
${s.status} |
${s.resources.toLocaleString()} |
$${s.cost.toLocaleString()} |
${s.lastSync} |
`;
});
}
window.iac_downloadPDF = function() {
const { jsPDF } = window.jspdf;
const doc = new jsPDF('landscape');
const data = iac_collectData();
doc.setFontSize(20);
doc.text("Infrastructure as Code (IaC) Report", 148, 20, { align: 'center' });
const statusCanvas = document.getElementById('iac-status-chart').toDataURL('image/png', 1.0);
const costCanvas = document.getElementById('iac-cost-chart').toDataURL('image/png', 1.0);
doc.addImage(statusCanvas, 'PNG', 20, 35, 80, 80);
doc.addImage(costCanvas, 'PNG', 110, 35, 170, 80);
const tableHead = [['Stack/Environment', 'Provider', 'Status', 'Resources', 'Monthly Cost', 'Last Sync']];
const tableBody = data.map(s => [s.stackName, s.provider.toUpperCase(), s.status, s.resources, `$${s.cost.toLocaleString()}`, s.lastSync]);
doc.autoTable({
head: tableHead,
body: tableBody,
startY: 120,
theme: 'grid',
headStyles: { fillColor: '#111827' }
});
doc.save('IaC_Dashboard_Report.pdf');
}
// --- TABBING & NAVIGATION ---
window.iac_changeTab = function(tabId) {
document.querySelectorAll('.iac-tab-content').forEach(c => c.classList.remove('active'));
document.querySelectorAll('.iac-tab-button').forEach(b => b.classList.remove('active'));
document.getElementById(tabId).classList.add('active');
const activeButton = Array.from(document.querySelectorAll('.iac-tab-button')).find(btn => btn.getAttribute('onclick').includes(tabId));
if (activeButton) activeButton.classList.add('active');
iac_currentTabIndex = TABS.indexOf(tabId);
iac_updateNavButtons();
}
window.iac_navigateTabs = function(direction) {
let newIndex = iac_currentTabIndex;
if (direction === 'next') newIndex = Math.min(newIndex + 1, TABS.length - 1);
else if (direction === 'prev') newIndex = Math.max(newIndex - 1, 0);
iac_changeTab(TABS[newIndex]);
}
function iac_updateNavButtons() {
const prevBtn = document.getElementById('iac-prev-btn');
const nextBtn = document.getElementById('iac-next-btn');
if(prevBtn) prevBtn.disabled = iac_currentTabIndex === 0;
if(nextBtn) nextBtn.disabled = iac_currentTabIndex === TABS.length - 1;
}
iac_initialize();
});