Wiki source code of ISMS Management Dashboard

Last modified by Lee Pedley on 2026/09/21 21:18

Show last authors
1 {{velocity}}
2 ## ISO 27001 ISMS operational dashboard. The 30-day horizon and score >=15 indicator are local management defaults.
3 #set ($riskDocs = $services.query.xwql("from doc.object('Risks.Code.RisksClass') as obj").setLimit(1000).execute())
4 #set ($treatmentDocs = $services.query.xwql("from doc.object('Risk Treatments.Code.Risk TreatmentsClass') as obj").setLimit(1000).execute())
5 #set ($controlDocs = $services.query.xwql("from doc.object('Controls and SoA.Code.Controls and SoAClass') as obj").setLimit(1000).execute())
6 #set ($evidenceDocs = $services.query.xwql("from doc.object('Evidence.Code.EvidenceClass') as obj").setLimit(1000).execute())
7 #set ($auditDocs = $services.query.xwql("from doc.object('Audits.Code.AuditsClass') as obj").setLimit(1000).execute())
8 #set ($findingDocs = $services.query.xwql("from doc.object('Findings.Code.FindingsClass') as obj").setLimit(1000).execute())
9 #set ($actionDocs = $services.query.xwql("from doc.object('Corrective Actions.Code.Corrective ActionsClass') as obj").setLimit(1000).execute())
10 #set ($controlledDocDocs = $services.query.xwql("from doc.object('Controlled Documents.Code.Controlled DocumentsClass') as obj").setLimit(1000).execute())
11
12 #set ($openRisks = 0)
13 #set ($highResidualRisks = 0)
14 #set ($openTreatments = 0)
15 #set ($overdueTreatments = 0)
16 #set ($controlsDue = 0)
17 #set ($evidenceAttention = 0)
18 #set ($activeAudits = 0)
19 #set ($openFindings = 0)
20 #set ($overdueFindings = 0)
21 #set ($overdueActions = 0)
22 #set ($documentsDue = 0)
23 #set ($alerts = [])
24
25 #foreach ($ref in $riskDocs)
26 #set ($d = $xwiki.getDocument($ref))
27 #set ($o = $d.getObject('Risks.Code.RisksClass'))
28 #if ($o)
29 #set ($st = $o.getProperty('status').getValue())
30 #if ($st != 'Closed') #set ($openRisks = $openRisks + 1) #end
31 #set ($rs = $o.getProperty('residualScore').getValue())
32 #if ($rs && $rs >= 15) #set ($highResidualRisks = $highResidualRisks + 1) #end
33 #end
34 #end
35
36 #foreach ($ref in $treatmentDocs)
37 #set ($d = $xwiki.getDocument($ref))
38 #set ($o = $d.getObject('Risk Treatments.Code.Risk TreatmentsClass'))
39 #if ($o)
40 #set ($st = $o.getProperty('status').getValue())
41 #if ($st != 'Complete' && $st != 'Cancelled')
42 #set ($openTreatments = $openTreatments + 1)
43 #set ($due = $o.getProperty('targetDate').getValue())
44 #if ($due && $datetool.whenIs($due).days < 0)
45 #set ($overdueTreatments = $overdueTreatments + 1)
46 #set ($discard = $alerts.add(['Overdue treatment',$ref,$d.displayTitle,$xwiki.formatDate($due)]))
47 #end
48 #end
49 #end
50 #end
51
52 #foreach ($ref in $controlDocs)
53 #set ($d = $xwiki.getDocument($ref))
54 #set ($o = $d.getObject('Controls and SoA.Code.Controls and SoAClass'))
55 #if ($o)
56 #set ($due = $o.getProperty('nextReviewDate').getValue())
57 #if ($due && $datetool.whenIs($due).days <= 30)
58 #set ($controlsDue = $controlsDue + 1)
59 #set ($discard = $alerts.add(['Control review',$ref,$d.displayTitle,$xwiki.formatDate($due)]))
60 #end
61 #end
62 #end
63
64 #foreach ($ref in $evidenceDocs)
65 #set ($d = $xwiki.getDocument($ref))
66 #set ($o = $d.getObject('Evidence.Code.EvidenceClass'))
67 #if ($o)
68 #set ($due = $o.getProperty('validUntil').getValue())
69 #if ($due && $datetool.whenIs($due).days <= 30)
70 #set ($evidenceAttention = $evidenceAttention + 1)
71 #set ($discard = $alerts.add(['Evidence review / expiry',$ref,$d.displayTitle,$xwiki.formatDate($due)]))
72 #end
73 #end
74 #end
75
76 #foreach ($ref in $auditDocs)
77 #set ($d = $xwiki.getDocument($ref))
78 #set ($o = $d.getObject('Audits.Code.AuditsClass'))
79 #if ($o)
80 #set ($st = $o.getProperty('status').getValue())
81 #if ($st != 'Complete' && $st != 'Cancelled') #set ($activeAudits = $activeAudits + 1) #end
82 #end
83 #end
84
85 #foreach ($ref in $findingDocs)
86 #set ($d = $xwiki.getDocument($ref))
87 #set ($o = $d.getObject('Findings.Code.FindingsClass'))
88 #if ($o)
89 #set ($st = $o.getProperty('status').getValue())
90 #if ($st != 'Closed')
91 #set ($openFindings = $openFindings + 1)
92 #set ($due = $o.getProperty('dueDate').getValue())
93 #if ($due && $datetool.whenIs($due).days < 0)
94 #set ($overdueFindings = $overdueFindings + 1)
95 #set ($discard = $alerts.add(['Overdue finding',$ref,$d.displayTitle,$xwiki.formatDate($due)]))
96 #end
97 #end
98 #end
99 #end
100
101 #foreach ($ref in $actionDocs)
102 #set ($d = $xwiki.getDocument($ref))
103 #set ($o = $d.getObject('Corrective Actions.Code.Corrective ActionsClass'))
104 #if ($o)
105 #set ($st = $o.getProperty('status').getValue())
106 #set ($due = $o.getProperty('dueDate').getValue())
107 #if ($due && $st != 'Verified' && $st != 'Cancelled' && $datetool.whenIs($due).days < 0)
108 #set ($overdueActions = $overdueActions + 1)
109 #set ($discard = $alerts.add(['Overdue corrective action',$ref,$d.displayTitle,$xwiki.formatDate($due)]))
110 #end
111 #end
112 #end
113
114 #foreach ($ref in $controlledDocDocs)
115 #set ($d = $xwiki.getDocument($ref))
116 #set ($o = $d.getObject('Controlled Documents.Code.Controlled DocumentsClass'))
117 #if ($o)
118 #set ($due = $o.getProperty('nextReviewDate').getValue())
119 #if ($due && $datetool.whenIs($due).days <= 30)
120 #set ($documentsDue = $documentsDue + 1)
121 #set ($discard = $alerts.add(['Document review',$ref,$d.displayTitle,$xwiki.formatDate($due)]))
122 #end
123 #end
124 #end
125
126 {{html wiki="true" clean="false"}}
127 <style>
128 .isms-dashboard .isms-note { margin: 0 0 1.2em 0; }
129 .isms-kpis { display:grid; grid-template-columns:repeat(auto-fit,minmax(170px,1fr)); gap:12px; margin:16px 0 24px; }
130 .isms-kpi { border:1px solid #d9dfe5; border-radius:7px; padding:14px 16px; background:#fff; min-height:92px; }
131 .isms-kpi .n { font-size:2em; font-weight:700; line-height:1.1; margin-top:6px; }
132 .isms-kpi .label { font-weight:600; }
133 .isms-kpi .sub { color:#68737d; font-size:.9em; margin-top:5px; }
134 .isms-section { margin-top:26px; }
135 .isms-links { display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr)); gap:10px; }
136 .isms-link { display:block; border:1px solid #d9dfe5; border-radius:6px; padding:12px; text-decoration:none; }
137 .isms-alerts { width:100%; border-collapse:collapse; }
138 .isms-alerts th,.isms-alerts td { border-bottom:1px solid #e4e7ea; padding:8px; text-align:left; }
139 </style>
140 <div class="isms-dashboard">
141 <div class="box infomessage isms-note"><strong>ISMS operational dashboard</strong><br/>Counts are management aids. The 30-day review window and residual score >=15 indicator are local defaults; align them with your approved risk criteria and review cycle.</div>
142 <div class="isms-kpis">
143 <div class="isms-kpi"><div class="label">Open risks</div><div class="n">$openRisks</div><div class="sub"><a href="$xwiki.getURL('Risks.WebHome','view')">Open risk register</a></div></div>
144 <div class="isms-kpi"><div class="label">Residual score >=15</div><div class="n">$highResidualRisks</div><div class="sub">Review against risk appetite</div></div>
145 <div class="isms-kpi"><div class="label">Open treatments</div><div class="n">$openTreatments</div><div class="sub">$overdueTreatments overdue</div></div>
146 <div class="isms-kpi"><div class="label">Controls due <=30 days</div><div class="n">$controlsDue</div><div class="sub"><a href="$xwiki.getURL('Controls and SoA.WebHome','view')">Open SoA</a></div></div>
147 <div class="isms-kpi"><div class="label">Evidence due / expired</div><div class="n">$evidenceAttention</div><div class="sub"><a href="$xwiki.getURL('Evidence.WebHome','view')">Open evidence</a></div></div>
148 <div class="isms-kpi"><div class="label">Open findings</div><div class="n">$openFindings</div><div class="sub">$overdueFindings overdue</div></div>
149 <div class="isms-kpi"><div class="label">Overdue corrective actions</div><div class="n">$overdueActions</div><div class="sub"><a href="$xwiki.getURL('Corrective Actions.WebHome','view')">Open actions</a></div></div>
150 <div class="isms-kpi"><div class="label">Documents due <=30 days</div><div class="n">$documentsDue</div><div class="sub"><a href="$xwiki.getURL('Controlled Documents.WebHome','view')">Open documents</a></div></div>
151 <div class="isms-kpi"><div class="label">Active audits</div><div class="n">$activeAudits</div><div class="sub"><a href="$xwiki.getURL('Audits.WebHome','view')">Open audits</a></div></div>
152 </div>
153
154 <div class="isms-section">
155 <h2>Attention queue</h2>
156 #if ($alerts.isEmpty())
157 <div class="box infomessage">No overdue or due-within-30-days items were detected in the tracked review/date fields.</div>
158 #else
159 <table class="isms-alerts"><thead><tr><th>Type</th><th>Record</th><th>Date</th></tr></thead><tbody>
160 #foreach ($item in $alerts)
161 <tr><td>$escapetool.xml($item.get(0))</td><td><a href="$xwiki.getURL($item.get(1),'view')">$escapetool.xml($item.get(2))</a></td><td>$escapetool.xml($item.get(3))</td></tr>
162 #end
163 </tbody></table>
164 #end
165 </div>
166
167 <div class="isms-section">
168 <h2>Registers</h2>
169 <div class="isms-links">
170 <a class="isms-link" href="$xwiki.getURL('Controlled Documents.WebHome','view')"><strong>Controlled Documents</strong><br/>Policies, procedures, approvals and review dates.</a>
171 <a class="isms-link" href="$xwiki.getURL('Controls and SoA.WebHome','view')"><strong>Controls &amp; SoA</strong><br/>Applicability, implementation, ownership and evidence.</a>
172 <a class="isms-link" href="$xwiki.getURL('Risks.WebHome','view')"><strong>Risks</strong><br/>Inherent/residual assessment and treatment decisions.</a>
173 <a class="isms-link" href="$xwiki.getURL('Risk Treatments.WebHome','view')"><strong>Risk Treatments</strong><br/>Treatment actions, owners, target dates and status.</a>
174 <a class="isms-link" href="$xwiki.getURL('Evidence.WebHome','view')"><strong>Evidence</strong><br/>Evidence validity and control/risk links.</a>
175 <a class="isms-link" href="$xwiki.getURL('Audits.WebHome','view')"><strong>Audits</strong><br/>Internal, external and certification assurance activity.</a>
176 <a class="isms-link" href="$xwiki.getURL('Findings.WebHome','view')"><strong>Findings</strong><br/>Audit findings, root cause and verification workflow.</a>
177 <a class="isms-link" href="$xwiki.getURL('Corrective Actions.WebHome','view')"><strong>Corrective Actions</strong><br/>Remediation, due dates and effectiveness review.</a>
178 </div>
179 </div>
180 </div>
181 {{/html}}
182 {{/velocity}}