282 lines
12 KiB
HTML
282 lines
12 KiB
HTML
{% extends "base.html" %}
|
||
{% load i18n risk_extras %}
|
||
|
||
{% block crumbs %}
|
||
<li><a href="{% url 'risks:list_risks' %}">{% trans "Risk analysis" %}</a></li>
|
||
<li><a href="{% url 'risks:show_risk' risk.id %}">{% trans "Risk" %}: {{ risk.title }}</a></li>
|
||
{% endblock %}
|
||
{% block content %}
|
||
|
||
<!-- ERP-style tabs under breadcrumb -->
|
||
<div class="erp-tabs">
|
||
<a class="is-active" data-tab="overview">{% trans "Overview" %}</a>
|
||
<a data-tab="measures">{% trans "Measures" %}</a>
|
||
<a data-tab="incidents">{% trans "Incidents" %}</a>
|
||
<a data-tab="history">{% trans "History" %}</a>
|
||
<!-- Action Icons -->
|
||
<div class="buttons">
|
||
<a href="{% url 'admin:risks_risk_change' risk.pk %}" class="button is-small is-warning" title="{% trans 'Edit Risk' %}">
|
||
<span class="icon"><i class="fas fa-edit"></i> </span> {% trans 'Edit Risk' %}
|
||
</a>
|
||
<a href="{% url 'admin:risks_risk_delete' risk.pk %}" class="button is-small is-danger" title="{% trans 'Delete Risk' %}">
|
||
<span class="icon"><i class="fas fa-trash"></i></span> {% trans 'Delete Risk' %}
|
||
</a>
|
||
<a href="{% url 'risks:mark_risk_reviewed' risk.pk %}"
|
||
class="button is-small is-success"
|
||
title="{% trans 'Mark Risk as reviewed' %}">
|
||
<span class="icon"><i class="fas fa-check"></i></span> {% trans 'Mark Risk as reviewed' %}
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tab: Overview -->
|
||
<div class="tab-panel" data-tab="overview">
|
||
<div class="card">
|
||
<div class="card-content">
|
||
|
||
<!-- General info -->
|
||
<div class="columns is-multiline">
|
||
<div class="column is-half">
|
||
<p><strong>{% trans "Asset" %}:</strong> {{ risk.asset|default:"-" }}</p>
|
||
<p><strong>{% trans "Process" %}:</strong> {{ risk.process|default:"-" }}</p>
|
||
<p><strong>{% trans "Category" %}:</strong> {{ risk.category|default:"-" }}</p>
|
||
<p>
|
||
<strong>{% trans "Protection goals" %}:</strong>
|
||
{% if risk.cia %}
|
||
{{ risk.get_cia_display }}
|
||
{% else %}
|
||
<span class="has-text-grey">{% trans "Not yet assigned" %}</span>
|
||
{% endif %}
|
||
</p>
|
||
<p><strong>{% trans "Status" %}:</strong> {{ risk.get_status_display }}</p>
|
||
</div>
|
||
<div class="column is-half">
|
||
<p><strong>{% trans "Risk owner" %}:</strong> {{ risk.owner|user_display|default:"-" }}</p>
|
||
<p><strong>{% trans "Created at" %}:</strong> {{ risk.created_at|date:'d.m.Y H:i' }}</p>
|
||
<p><strong>{% trans "Updated at" %}:</strong> {{ risk.updated_at|date:'d.m.Y H:i' }}</p>
|
||
<p><strong>{% trans "Resubmission" %}:</strong> {{ risk.follow_up|date:'d.m.Y' }}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Effects -->
|
||
<section>
|
||
<h3 class="title is-6">{% trans "Effects" %}</h3>
|
||
<p>{{ risk.effects|default:"–" }}</p>
|
||
</section>
|
||
|
||
<!-- Risk assessment -->
|
||
<section class="hero has-text-centered is-small">
|
||
<div class="hero-body">
|
||
<p class="title">{% trans "Risk assessment" %}</p>
|
||
</div>
|
||
</section>
|
||
|
||
<div class="columns is-multiline">
|
||
|
||
<!-- Gross risk -->
|
||
<div class="column is-full-mobile is-half-desktop has-text-centered is-flex">
|
||
<div class="box is-flex is-flex-direction-column is-flex-grow-1">
|
||
<h4 class="title is-6">{% trans "Gross (before measures)" %}</h4>
|
||
<div class="columns is-multiline">
|
||
|
||
<!-- Likelihood -->
|
||
<div class="column is-half">
|
||
<button class="risk-chip {{ risk.likelihood|likelihood_class }}" type="button">
|
||
<span class="chip-head">{% trans "Likelihood" %}</span>
|
||
<span class="chip-id">{{ risk.likelihood }}</span>
|
||
<span class="chip-label">{{ risk.get_likelihood_display }}</span>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Impact -->
|
||
<div class="column is-half">
|
||
<button class="risk-chip {{ risk.impact|impact_class }}" type="button">
|
||
<span class="chip-head">{% trans "Impact" %}</span>
|
||
<span class="chip-id">{{ risk.impact }}</span>
|
||
<span class="chip-label">{{ risk.get_impact_display }}</span>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Level -->
|
||
<div class="column is-half">
|
||
<button class="risk-chip {{ risk.level|level_class }}" type="button">
|
||
<span class="chip-head">{% trans "Level" %}</span>
|
||
<span class="chip-id">{{ risk.level|level_id }}</span>
|
||
<span class="chip-label">{{ risk.level }}</span>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Score -->
|
||
<div class="column is-half">
|
||
<button class="risk-chip {{ risk.score|score_class }}" type="button">
|
||
<span class="chip-head">{% trans "Score" %}</span>
|
||
<span class="chip-id">{{ risk.score }}</span>
|
||
<span class="chip-label">Max. 20</span>
|
||
</button>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div><!-- Gross risk End -->
|
||
|
||
<!-- Net risk -->
|
||
<div class="column is-full-mobile is-half-desktop has-text-centered is-flex">
|
||
<div class="box is-flex is-flex-direction-column is-flex-grow-1">
|
||
<h4 class="title is-6">{% trans "Net (after measures)" %}</h4>
|
||
<div class="columns is-multiline">
|
||
{% if risk.residual_risk %}
|
||
<!-- Likelihood -->
|
||
<div class="column is-half">
|
||
<button class="risk-chip {{ risk.residual_risk.likelihood|likelihood_class }}" type="button">
|
||
<span class="chip-head">{% trans "Likelihood" %}</span>
|
||
<span class="chip-id">{{ risk.residual_risk.likelihood }}</span>
|
||
<span class="chip-label">{{ risk.residual_risk.get_likelihood_display }}</span>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Impact -->
|
||
<div class="column is-half">
|
||
<button class="risk-chip {{ risk.residual_risk.impact|impact_class }}" type="button">
|
||
<span class="chip-head">{% trans "Impact" %}</span>
|
||
<span class="chip-id">{{ risk.residual_risk.impact }}</span>
|
||
<span class="chip-label">{{ risk.residual_risk.get_impact_display }}</span>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Level -->
|
||
<div class="column is-half">
|
||
<button class="risk-chip {{ risk.residual_risk.level|level_class }}" type="button">
|
||
<span class="chip-head">{% trans "Level" %}</span>
|
||
<span class="chip-id">{{ risk.residual_risk.level|level_id }}</span>
|
||
<span class="chip-label">{{ risk.residual_risk.level }}</span>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Score -->
|
||
<div class="column is-half">
|
||
<button class="risk-chip {{ risk.residual_risk.score|score_class }}" type="button">
|
||
<span class="chip-head">{% trans "Score" %}</span>
|
||
<span class="chip-id">{{ risk.residual_risk.score }}</span>
|
||
<span class="chip-label">Max. 20</span>
|
||
</button>
|
||
</div>
|
||
|
||
{% else %}
|
||
<div class="column is-vcentered is-centered">
|
||
<a href="{% url 'admin:risks_residualrisk_add' %}?risk={{ risk.pk }}"
|
||
class="button is-success is-focused">
|
||
<span class="icon"><i class="fas fa-add"></i></span>
|
||
<span>{% trans "Add net Risk" %}</span>
|
||
</a>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
</div><!-- Net risk End -->
|
||
|
||
</div><!-- Risk assessment End -->
|
||
</div>
|
||
</div>
|
||
</div><!-- Overview Tab End -->
|
||
|
||
<!-- Tab: Measures -->
|
||
<div class="tab-panel is-hidden" data-tab="measures">
|
||
<div class="table-container">
|
||
<table class="table is-bordered is-striped is-narrow is-hoverable is-fullwidth">
|
||
<thead>
|
||
<tr class="has-background-prosoft">
|
||
<th class="has-text-centered">{% trans "Title" %}</th>
|
||
<th class="has-text-centered">{% trans "Status" %}</th>
|
||
<th class="has-text-centered">{% trans "Deadline" %}</th>
|
||
<th class="has-text-centered">{% trans "Responsible" %}</th>
|
||
<th class="has-text-centered">{% trans "Link" %}</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for control in risk.controls.all %}
|
||
<tr onclick="window.location.href='/risks/controls/{{ control.id }}';" style="cursor:pointer;">
|
||
<td>{{ control.title }}</td>
|
||
<td class="has-text-centered">{{ control.get_status_display }}</td>
|
||
<td class="has-text-centered">{{ control.due_date|date:"d.m.Y"|default:"–" }}</td>
|
||
<td class="has-text-centered">{{ control.responsible.get_full_name|default:control.responsible.username|default:"–" }}</td>
|
||
<td class="has-text-centered">{% if control.wiki_link %}<a href="{{ control.wiki_link }}" target="_blank">🔗</a>{% else %}–{% endif %}</td>
|
||
</tr>
|
||
{% empty %}
|
||
<tr><td colspan="5" class="has-text-grey has-text-centered">{% trans "No measures recorded." %}</td></tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div><!-- Measures Tab End -->
|
||
|
||
<!-- Tab: Incidents -->
|
||
<div class="tab-panel is-hidden" data-tab="incidents">
|
||
<div class="table-container">
|
||
<table class="table is-bordered is-striped is-narrow is-hoverable is-fullwidth">
|
||
<thead>
|
||
<tr class="has-background-prosoft">
|
||
<th class="has-text-centered">{% trans "Incident" %}</th>
|
||
<th class="has-text-centered">{% trans "Status" %}</th>
|
||
<th class="has-text-centered">{% trans "Reported on" %}</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for i in risk.incidents.all %}
|
||
<tr onclick="window.location.href='/risks/incidents/{{ i.id }}';" style="cursor:pointer;">
|
||
<td>{{ i.title }}</td>
|
||
<td class="has-text-centered">{{ i.get_status_display }}</td>
|
||
<td class="has-text-centered">{{ i.created_at|date:"d.m.Y H:i" }}</td>
|
||
</tr>
|
||
{% empty %}
|
||
<tr><td class="has-text-centered"><a href="{% url 'admin:risks_incident_add' %}?related_risks={{ risk.id }}"><span class="icon breadcrumb-add-icon"><i class="fas fa-add"></i></span></a></td><td colspan="3" class="has-text-grey has-text-centered">{% trans "No incidents recorded." %}</td></tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div><!-- Incidents Tab End -->
|
||
|
||
<!-- Tab: History -->
|
||
<div class="tab-panel is-hidden" data-tab="history">
|
||
<div class="table-container">
|
||
<table class="table is-bordered is-striped is-narrow is-hoverable is-fullwidth">
|
||
<thead>
|
||
<tr class="has-background-prosoft">
|
||
<th class="has-text-centered">{% trans "Time" %}</th>
|
||
<th class="has-text-centered">{% trans "User" %}</th>
|
||
<th class="has-text-centered">{% trans "Action" %}</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for log in logs %}
|
||
<tr>
|
||
<td class="has-text-centered">{{ log.action_time|date:"d.m.Y H:i" }}</td>
|
||
<td class="has-text-centered">{{ log.user.get_full_name|default:log.user.username }}</td>
|
||
<td>{{ log.get_change_message }}</td>
|
||
</tr>
|
||
{% empty %}
|
||
<tr><td colspan="3" class="has-text-grey has-text-centered">{% trans "No history found." %}</td></tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div><!-- History Tab End -->
|
||
|
||
<!-- Tab switching script -->
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
const tabs = document.querySelectorAll('.erp-tabs a[data-tab]');
|
||
const panels = document.querySelectorAll('.tab-panel');
|
||
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');
|
||
});
|
||
});
|
||
});
|
||
</script>
|
||
{% endblock %}
|