2025-09-11 10:22:20 +02:00
|
|
|
|
{% extends "base.html" %}
|
|
|
|
|
{% load i18n risk_extras %}
|
|
|
|
|
{% block crumbs %}
|
|
|
|
|
<li><a href="{% url 'risks:risk_matrix' %}">{% trans "Risk Matrix" %}</a></li>
|
|
|
|
|
{% endblock %}
|
|
|
|
|
{% block content %}
|
2025-09-11 15:02:29 +02:00
|
|
|
|
<div class="erp-tabs">
|
|
|
|
|
<a class="is-active" data-tab="matrix">{% trans "Risk Matrix" %}</a>
|
|
|
|
|
<a data-tab="details">{% trans "Detail View" %}</a>
|
|
|
|
|
</div>
|
|
|
|
|
<section class="section">
|
2025-09-11 10:22:20 +02:00
|
|
|
|
<div class="box">
|
2025-09-11 15:02:29 +02:00
|
|
|
|
<!-- Panel: Matrix View -->
|
|
|
|
|
<div class="tab-panel" data-tab="matrix">
|
|
|
|
|
<table class="table is-bordered is-fullwidth has-text-centered risk-matrix-table">
|
2025-09-11 10:22:20 +02:00
|
|
|
|
<thead>
|
|
|
|
|
<tr>
|
2025-09-15 11:06:33 +02:00
|
|
|
|
<th class="has-text-left">{% trans "Impact" %} * {% trans "Likelihood" %}</th>
|
2025-09-22 09:44:51 +02:00
|
|
|
|
{% for likelihood in likelihoods %}
|
2025-09-22 10:14:21 +02:00
|
|
|
|
<th class="{{ likelihood.value|likelihood_class|to_bg }}">
|
|
|
|
|
{{ likelihood.value }} ({{ likelihood.name }}) <br> {{ likelihood.description }}
|
|
|
|
|
</th>
|
2025-09-11 10:22:20 +02:00
|
|
|
|
{% endfor %}
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
2025-09-22 10:14:21 +02:00
|
|
|
|
{% for impact in impacts reversed %}
|
2025-09-11 10:22:20 +02:00
|
|
|
|
<tr>
|
2025-09-22 10:14:21 +02:00
|
|
|
|
<th class="has-text-left {{ impact.value|impact_class|to_bg }}">{{ impact.value }} - {{ impact.name }}<br>{{ impact.description }}</th>
|
2025-09-22 09:44:51 +02:00
|
|
|
|
{% for likelihood in likelihoods %}
|
2025-09-22 10:14:21 +02:00
|
|
|
|
{% with s=impact.value|mul:likelihood.value %}
|
2025-09-11 10:22:20 +02:00
|
|
|
|
<td class="risk-matrix-cell {{ s|score_bg_class }}">
|
2025-09-11 15:02:29 +02:00
|
|
|
|
<div class="is-flex is-justify-content-center is-align-items-center">
|
|
|
|
|
{% if s <= 4 %}
|
|
|
|
|
<span class="tag is-control-verylow is-light">Low ({{ s }})</span>
|
|
|
|
|
{% elif s <= 8 %}
|
|
|
|
|
<span class="tag is-control-low is-light">Medium ({{ s }})</span>
|
|
|
|
|
{% elif s <= 12 %}
|
|
|
|
|
<span class="tag is-control-mid is-light">High ({{ s }})</span>
|
|
|
|
|
{% else %}
|
|
|
|
|
<span class="tag is-control-veryhigh is-light">Critical ({{ s }})</span>
|
|
|
|
|
{% endif %}
|
2025-09-11 10:22:20 +02:00
|
|
|
|
</div>
|
|
|
|
|
</td>
|
|
|
|
|
{% endwith %}
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</tr>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
2025-09-22 09:44:51 +02:00
|
|
|
|
</div>
|
2025-09-11 15:02:29 +02:00
|
|
|
|
<!-- Panel: Details View -->
|
2025-09-11 10:22:20 +02:00
|
|
|
|
<div class="tab-panel is-hidden" data-tab="details">
|
|
|
|
|
<div class="level mb-3">
|
|
|
|
|
<div class="level-left">
|
|
|
|
|
<div class="level-item"><strong>{% trans "Show" %}:</strong></div>
|
|
|
|
|
<div class="level-item">
|
|
|
|
|
<div class="buttons has-addons">
|
|
|
|
|
<button type="button" class="button is-small is-info is-light details-toggle is-active" data-mode="gross">
|
|
|
|
|
{% trans "Gross" %}
|
|
|
|
|
</button>
|
|
|
|
|
<button type="button" class="button is-small is-info is-light details-toggle" data-mode="net">
|
|
|
|
|
{% trans "Net" %}
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-09-22 09:44:51 +02:00
|
|
|
|
</div>
|
2025-09-11 15:02:29 +02:00
|
|
|
|
<!-- Gross Risk List -->
|
2025-09-11 10:22:20 +02:00
|
|
|
|
<div class="details-table" data-mode="gross">
|
2025-09-11 15:02:29 +02:00
|
|
|
|
<table class="table is-bordered is-fullwidth has-text-centered risk-matrix-table">
|
2025-09-11 10:22:20 +02:00
|
|
|
|
<thead>
|
|
|
|
|
<tr>
|
|
|
|
|
<th class="has-text-left">{% trans "Impact" %} / {% trans "Likelihood" %}</th>
|
2025-09-22 09:44:51 +02:00
|
|
|
|
{% for likelihood in likelihoods %}
|
2025-09-22 10:14:21 +02:00
|
|
|
|
<th class="{{ likelihood.value|likelihood_class|to_bg }}">{{ likelihood.value }} ({{ likelihood.name }}) <br> {{ likelihood.description }}</th>
|
2025-09-11 10:22:20 +02:00
|
|
|
|
{% endfor %}
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
2025-09-22 10:14:21 +02:00
|
|
|
|
{% for impact in impacts reversed %}
|
2025-09-11 10:22:20 +02:00
|
|
|
|
<tr>
|
2025-09-22 10:14:21 +02:00
|
|
|
|
<th class="has-text-left {{ impact.value|impact_class|to_bg }}">{{ impact.value }} - {{ impact.name }}<br>{{ impact.description }}</th>
|
2025-09-22 09:44:51 +02:00
|
|
|
|
{% for likelihood in likelihoods %}
|
2025-09-22 10:14:21 +02:00
|
|
|
|
{% with row=gross_matrix|dict_get:impact.value %}
|
2025-09-22 09:44:51 +02:00
|
|
|
|
{% with cell=row|dict_get:likelihood.value %}
|
2025-09-22 10:14:21 +02:00
|
|
|
|
{% with s=impact.value|mul:likelihood.value %}
|
2025-09-22 09:44:51 +02:00
|
|
|
|
<td class="risk-matrix-cell {{ likelihood|likelihood_class }}">
|
|
|
|
|
{% if cell %}
|
|
|
|
|
<ul class="risk-cell-list">
|
|
|
|
|
{% for risk in cell %}
|
|
|
|
|
<li style="list-style:none;">
|
|
|
|
|
<a href="{% url 'risks:show_risk' risk.id %}" class="tag">{{ risk.title }}</a>
|
|
|
|
|
</li>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</ul>
|
|
|
|
|
{% else %}
|
|
|
|
|
<span class="has-text-grey">–</span>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</td>
|
|
|
|
|
{% endwith %}
|
|
|
|
|
{% endwith %}
|
2025-09-11 10:22:20 +02:00
|
|
|
|
{% endwith %}
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</tr>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
2025-09-22 09:44:51 +02:00
|
|
|
|
</div>
|
2025-09-11 15:02:29 +02:00
|
|
|
|
<!-- Net Risk List -->
|
2025-09-11 10:22:20 +02:00
|
|
|
|
<div class="details-table is-hidden" data-mode="net">
|
2025-09-11 15:02:29 +02:00
|
|
|
|
<table class="table is-bordered is-fullwidth has-text-centered risk-matrix-table">
|
2025-09-11 10:22:20 +02:00
|
|
|
|
<thead>
|
|
|
|
|
<tr>
|
|
|
|
|
<th class="has-text-left">{% trans "Impact" %} / {% trans "Likelihood" %}</th>
|
2025-09-22 09:44:51 +02:00
|
|
|
|
{% for likelihood in likelihoods %}
|
2025-09-22 10:14:21 +02:00
|
|
|
|
<th class="{{ likelihood.value|likelihood_class|to_bg }}">{{ likelihood.value }} ({{ likelihood.name }}) <br> {{ likelihood.description }}</th>
|
2025-09-11 10:22:20 +02:00
|
|
|
|
{% endfor %}
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
2025-09-22 10:14:21 +02:00
|
|
|
|
{% for impact in impacts reversed %}
|
2025-09-11 10:22:20 +02:00
|
|
|
|
<tr>
|
2025-09-22 10:14:21 +02:00
|
|
|
|
<th class="has-text-left {{ impact.value|impact_class|to_bg }}">{{ impact.value }} - {{ impact.name }}<br>{{ impact.description }}</th>
|
2025-09-22 09:44:51 +02:00
|
|
|
|
{% for likelihood in likelihoods %}
|
2025-09-22 10:14:21 +02:00
|
|
|
|
{% with row=net_matrix|dict_get:impact.value %}
|
|
|
|
|
{% with cell=row|dict_get:likelihood.value %}
|
|
|
|
|
{% with s=impact.value|mul:likelihood.value %}
|
|
|
|
|
<td class="risk-matrix-cell {{ likelihood|likelihood_class }}">
|
|
|
|
|
{% if cell %}
|
|
|
|
|
<ul class="risk-cell-list">
|
|
|
|
|
{% for risk in cell %}
|
|
|
|
|
<li style="list-style:none;">
|
|
|
|
|
<a href="{% url 'risks:show_risk' risk.id %}" class="tag">{{ risk.title }}</a>
|
|
|
|
|
</li>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</ul>
|
|
|
|
|
{% else %}
|
|
|
|
|
<span class="has-text-grey">–</span>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</td>
|
|
|
|
|
{% endwith %}
|
|
|
|
|
{% endwith %}
|
2025-09-11 10:22:20 +02:00
|
|
|
|
{% endwith %}
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</tr>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
2025-09-22 09:44:51 +02:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</section>
|
2025-09-11 10:22:20 +02:00
|
|
|
|
<script>
|
2025-09-11 15:02:29 +02:00
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
|
const tabs = document.querySelectorAll('.erp-tabs a[data-tab]');
|
2025-09-11 10:22:20 +02:00
|
|
|
|
const panels = document.querySelectorAll('.tab-panel');
|
2025-09-11 15:02:29 +02:00
|
|
|
|
tabs.forEach(tab => {
|
|
|
|
|
tab.addEventListener('click', e => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
tabs.forEach(x => x.classList.remove('is-active'));
|
|
|
|
|
panels.forEach(p => p.classList.add('is-hidden'));
|
|
|
|
|
tab.classList.add('is-active');
|
|
|
|
|
const target = tab.getAttribute('data-tab');
|
|
|
|
|
const activePanel = document.querySelector(`.tab-panel[data-tab="${target}"]`);
|
|
|
|
|
if (activePanel) activePanel.classList.remove('is-hidden');
|
|
|
|
|
});
|
|
|
|
|
});
|
2025-09-11 10:22:20 +02:00
|
|
|
|
const toggles = document.querySelectorAll('.details-toggle');
|
|
|
|
|
const tables = document.querySelectorAll('.details-table');
|
2025-09-11 15:02:29 +02:00
|
|
|
|
toggles.forEach(btn => {
|
|
|
|
|
btn.addEventListener('click', () => {
|
2025-09-22 09:44:51 +02:00
|
|
|
|
const mode = btn.getAttribute('data-mode');
|
2025-09-11 15:02:29 +02:00
|
|
|
|
toggles.forEach(b => b.classList.toggle('is-active', b === btn));
|
|
|
|
|
tables.forEach(t => {
|
|
|
|
|
t.classList.toggle('is-hidden', t.getAttribute('data-mode') !== mode);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
2025-09-11 10:22:20 +02:00
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
{% endblock %}
|