IT Risk Dashboard

Overall Risk Score

0

Open Risks

0

High-Impact Risks

0

Overdue Mitigations

0

Risk Matrix

Open Risks by Category

Risk Register

IDRisk DescriptionCategoryImpactLikelihoodOwnerStatus

Log a New IT Risk

All Logged Risks

IDDescriptionStatusAction

Error: A required library is missing.

'; return; } // --- DATA MANAGEMENT --- let risks = JSON.parse(localStorage.getItem('itr_risks')) || []; const getSampleData = () => [ { id: 'R001', desc: 'Single point of failure in primary datacenter power supply.', category: 'Infrastructure', impact: 'Critical', likelihood: 'Low', owner: 'J. Smith', status: 'Mitigating' }, { id: 'R002', desc: 'Phishing attack targeting finance department credentials.', category: 'Cybersecurity', impact: 'High', likelihood: 'Medium', owner: 'S. Davis', status: 'Open' }, { id: 'R003', desc: 'Key software vendor (CRM) may not be GDPR compliant.', category: 'Compliance', impact: 'High', likelihood: 'Medium', owner: 'E. White', status: 'Open' }, { id: 'R004', desc: 'Outdated server OS no longer receiving security patches.', category: 'Infrastructure', impact: 'High', likelihood: 'High', owner: 'J. Smith', status: 'Mitigating' }, { id: 'R005', desc: 'Insider threat from disgruntled employee.', category: 'Cybersecurity', impact: 'Critical', likelihood: 'Low', owner: 'M. Chen', status: 'Accepted' }, { id: 'R006', desc: 'Lack of disaster recovery plan for customer database.', category: 'Operational', impact: 'High', likelihood: 'Low', owner: 'J. Smith', status: 'Open' }, { id: 'R007', desc: 'Third-party API for shipping quotes is unreliable.', category: 'Operational', impact: 'Medium', likelihood: 'High', owner: 'M. Chen', status: 'Closed' }, ]; if (risks.length === 0) risks = getSampleData(); const saveState = () => localStorage.setItem('itr_risks', JSON.stringify(risks)); // --- CHART INSTANCES & UTILITIES --- let riskMatrixChart, categoryChart; const tabButtons = document.querySelectorAll('.itr-tab-button'); const tabContents = document.querySelectorAll('.itr-tab-content'); const nextBtn = document.getElementById('itr-next-btn'); const prevBtn = document.getElementById('itr-prev-btn'); const IMPACT_MAP = { 'Low': 1, 'Medium': 2, 'High': 3, 'Critical': 4 }; const LIKELIHOOD_MAP = { 'Low': 1, 'Medium': 2, 'High': 3, 'Very High': 4 }; // --- RENDER FUNCTIONS --- const renderAll = () => { try { const openRisks = risks.filter(r => r.status !== 'Closed'); renderKPIs(openRisks); renderRiskMatrix(openRisks); renderCategoryChart(openRisks); renderRiskTable(openRisks); renderManageTable(); updateNavButtons(); } catch(error) { console.error("Dashboard rendering failed:", error); } }; const renderKPIs = (data) => { const riskScores = data.map(r => IMPACT_MAP[r.impact] * LIKELIHOOD_MAP[r.likelihood]); const avgRiskScore = data.length > 0 ? riskScores.reduce((s,v) => s+v, 0) / data.length : 0; document.getElementById('itr-risk-score-kpi').textContent = avgRiskScore.toFixed(1); document.getElementById('itr-open-risks-kpi').textContent = data.length; document.getElementById('itr-high-impact-kpi').textContent = data.filter(r => r.impact === 'High' || r.impact === 'Critical').length; document.getElementById('itr-overdue-kpi').textContent = '2'; // Static for demo }; const renderRiskMatrix = (data) => { const seriesData = Object.keys(LIKELIHOOD_MAP).map(lh => { const counts = Object.keys(IMPACT_MAP).map(im => { return data.filter(r => r.likelihood === lh && r.impact === im).length; }); return { name: lh, data: counts }; }); const options = { chart: { type: 'heatmap', height: 350 }, series: seriesData, xaxis: { categories: Object.keys(IMPACT_MAP), title: { text: 'Impact' } }, yaxis: { title: { text: 'Likelihood' } }, plotOptions: { heatmap: { colorScale: { ranges: [ { from: 0, to: 0, name: 'None', color: '#f0f0f0' }, { from: 1, to: 2, name: 'Low', color: '#27ae60' }, { from: 3, to: 4, name: 'Medium', color: '#f39c12' }, { from: 5, to: 20, name: 'High', color: '#c0392b' } ] } } }, dataLabels: { enabled: true } }; if(riskMatrixChart) riskMatrixChart.destroy(); document.querySelector("#itr-risk-matrix-chart").innerHTML = ''; riskMatrixChart = new ApexCharts(document.querySelector("#itr-risk-matrix-chart"), options); riskMatrixChart.render(); }; const renderCategoryChart = (data) => { const byCategory = data.reduce((acc, r) => { acc[r.category] = (acc[r.category] || 0) + 1; return acc; }, {}); const options = { chart: { type: 'donut', height: 350 }, series: Object.values(byCategory), labels: Object.keys(byCategory), legend: { position: 'bottom' } }; if(categoryChart) categoryChart.destroy(); document.querySelector("#itr-category-chart").innerHTML = ''; categoryChart = new ApexCharts(document.querySelector("#itr-category-chart"), options); categoryChart.render(); }; const renderRiskTable = (data) => { const tbody = document.getElementById('itr-risk-tbody'); tbody.innerHTML = ''; data.sort((a,b) => (IMPACT_MAP[b.impact] * LIKELIHOOD_MAP[b.likelihood]) - (IMPACT_MAP[a.impact] * LIKELIHOOD_MAP[a.likelihood])) .forEach(r => { tbody.innerHTML += ` ${r.id}${r.desc}${r.category}${r.impact}${r.likelihood}${r.owner}${r.status}`; }); }; const renderManageTable = () => { const tbody = document.getElementById('itr-manage-tbody'); tbody.innerHTML = ''; risks.forEach(r => { tbody.innerHTML += `${r.id}${r.desc}${r.status}`; }); const categories = [...new Set(risks.map(r => r.category))]; document.getElementById('itr-category-list').innerHTML = categories.map(c=>``).join(''); }; // --- EVENT HANDLING --- const switchTab = (tabId) => { tabContents.forEach(c => c.style.display = 'none'); tabButtons.forEach(b => b.classList.remove('active')); const activeContent = document.getElementById(tabId); const activeButton = document.querySelector(`.itr-tab-button[data-tab="${tabId}"]`); if (activeContent && activeButton) { activeContent.style.display = 'block'; activeButton.classList.add('active'); } updateNavButtons(); }; const updateNavButtons = () => { const i = [...tabButtons].findIndex(b => b.classList.contains('active')); prevBtn.disabled = i === 0; nextBtn.disabled = i === tabButtons.length - 1; }; tabButtons.forEach(b => b.addEventListener('click', () => switchTab(b.dataset.tab))); nextBtn.addEventListener('click', () => { const i = [...tabButtons].findIndex(b=>b.classList.contains('active')); if (i < tabButtons.length - 1) switchTab(tabButtons[i+1].dataset.tab); }); prevBtn.addEventListener('click', () => { const i = [...tabButtons].findIndex(b=>b.classList.contains('active')); if (i > 0) switchTab(tabButtons[i-1].dataset.tab); }); document.getElementById('itr-risk-form').addEventListener('submit', e => { e.preventDefault(); risks.push({ id: 'R' + String(Math.floor(Math.random() * 900) + 100).padStart(3, '0'), desc: document.getElementById('itr-form-desc').value, category: document.getElementById('itr-form-category').value, owner: document.getElementById('itr-form-owner').value, impact: document.getElementById('itr-form-impact').value, likelihood: document.getElementById('itr-form-likelihood').value, status: document.getElementById('itr-form-status').value }); saveState(); renderAll(); e.target.reset(); switchTab('itr-dashboard-tab'); }); document.getElementById('itr-manage-tbody').addEventListener('click', e => { if(e.target.tagName === 'BUTTON') { if(confirm('Are you sure?')) { risks = risks.filter(r => r.id !== e.target.dataset.id); saveState(); renderAll(); } } }); // --- PDF EXPORT --- document.getElementById('itr-download-pdf-btn').addEventListener('click', function() { const btn = this; btn.textContent = 'Generating...'; btn.disabled = true; const pdfCaptureArea = document.getElementById('itr-pdf-capture-area'); html2canvas(pdfCaptureArea, { scale: 2 }).then(canvas => { const doc = new jsPDF(); const imgData = canvas.toDataURL('image/png'); doc.setFontSize(18); doc.text('IT Risk Dashboard Summary', 14, 22); const imgWidth = doc.internal.pageSize.getWidth() - 28; const imgHeight = (canvas.height * imgWidth) / canvas.width; doc.addImage(imgData, 'PNG', 14, 30, imgWidth, imgHeight); doc.addPage(); doc.autoTable({ html: '.itr-table', startY: 15, theme: 'striped' }); doc.save('IT_Risk_Report.pdf'); }).finally(() => { btn.textContent = 'Download Report'; btn.disabled = false; }); }); // --- INITIALIZATION --- renderAll(); });
Scroll to Top