
- Added Notification model with admin interface for managing notifications. - Created context processor to count unread notifications for the user. - Introduced forms for updating the status of Risk, Control, Incident, and ResidualRisk. - Added views for displaying and managing notifications, including marking them as read. - Updated URLs to include routes for notifications and status updates. - Enhanced templates to support notifications display and status update forms. - Improved CSS for avatar and badge display in the navbar. - Translated various static texts to support internationalization.
310 lines
No EOL
14 KiB
HTML
310 lines
No EOL
14 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 %}">{{ risk.title }}</a></li>
|
||
{% endblock %}
|
||
{% block content %}
|
||
<div class="container">
|
||
<section class="hero is-small">
|
||
<div class="hero-body">
|
||
<p class="title">{% trans "Risk" %}: {{ risk.title }}</p>
|
||
<p class="subtitle is-6">{{ risk.description }}</p>
|
||
</div>
|
||
</section>
|
||
<!-- Überblick-->
|
||
<div class="card">
|
||
<header class="card-header">
|
||
<p class="card-header-title">{% trans "Overview" %}</p>
|
||
|
||
{% if request.user.is_staff or risk.owner_id == request.user.id %}
|
||
<form method="post" action="{% url 'risks:update_risk_status' risk.id %}" class="card-header-icon" style="margin-left:auto;">
|
||
{% csrf_token %}
|
||
<div class="field has-addons">
|
||
<div class="control">
|
||
<div class="select is-small">
|
||
<select name="status">
|
||
{% for value,label in risk.STATUS_CHOICES %}
|
||
<option value="{{ value }}" {% if risk.status == value %}selected{% endif %}>{{ label }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="control">
|
||
<button class="button is-small is-link" title="{% trans 'Update status' %}">
|
||
<span class="icon"><i class="fas fa-save"></i></span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
|
||
<a class="card-header-icon has-text-warning" href="{% url 'admin:risks_risk_change' risk.pk %}" title="Risiko bearbeiten">
|
||
<span class="icon"><i class="fas fa-edit" aria-hidden="true"></i></span>
|
||
</a>
|
||
<a class="card-header-icon has-text-danger" href="{% url 'admin:risks_risk_delete' risk.pk %}" title="Risiko Löschen (WARNUNG!)">
|
||
<span class="icon"><i class="fas fa-trash" aria-hidden="true"></i></span>
|
||
</a>
|
||
{% endif %}
|
||
</header>
|
||
<!-- Inhalt Überblick-->
|
||
<div class="card-content">
|
||
<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.status }}</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>
|
||
<!-- Risikobewertung -->
|
||
<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">
|
||
|
||
<!-- Bruttorisiko -->
|
||
<div class="column is-full-mobile is-full-tablet is-half-desktop has-text-centered is-flex">
|
||
<div class="box is-flex is-flex-direction-column is-flex-grow-1">
|
||
<h4>{% trans "Gross (before measures)" %}</h4>
|
||
<div class="columns is-multiline">
|
||
|
||
<!-- Eintrittswahrscheinlichkeit -->
|
||
<div class="column is-full-mobile is-full-tablet is-half-desktop has-text-centered">
|
||
<button class="risk-chip {{ risk.likelihood|likelihood_class }}" type="button" aria-label="{% trans 'Likelihood' as likelihood_long_name %}">
|
||
<span class="chip-head">{% trans "Probability of occurrence" %}</span>
|
||
<span class="chip-id">{{ risk.likelihood }}</span>
|
||
<span class="chip-label">{{ risk.get_likelihood_display }}</span>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Schadensausmaß -->
|
||
<div class="column is-full-mobile is-full-tablet is-half-desktop has-text-centered">
|
||
<button class="risk-chip {{ risk.impact|impact_class }}" type="button" aria-label="{% trans 'Impact' as impact_long_name %}">
|
||
<span class="chip-head">{% trans "Extent of damage" %}</span>
|
||
<span class="chip-id">{{ risk.impact }}</span>
|
||
<span class="chip-label">{{ risk.get_impact_display }}</span>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Stufe -->
|
||
<div class="column is-full-mobile is-full-tablet is-half-desktop has-text-centered">
|
||
<button class="risk-chip {{ risk.level|level_class }}" type="button" aria-label="{% trans 'Level' %}">
|
||
<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-full-mobile is-full-tablet is-half-desktop has-text-centered">
|
||
<button class="risk-chip {{ risk.score|score_class }}" type="button" aria-label="{% trans 'Score' %}">
|
||
<span class="chip-head">{% trans "Score" %}</span>
|
||
<span class="chip-id">{{ risk.score }}</span>
|
||
<span class="chip-label">Score (max. 20)</span>
|
||
</button>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div> <!-- Ende Bruttorisiko -->
|
||
|
||
<!-- Nettorisiko -->
|
||
<div class="column is-full-mobile is-full-tablet is-half-desktop has-text-centered is-flex">
|
||
<div class="box is-flex is-flex-direction-column is-flex-grow-1">
|
||
<h4>{% trans "Net (after measures)" %}</h4>
|
||
<div class="columns is-multiline">
|
||
{% if risk.residual_risk %}
|
||
<!-- Eintrittswahrscheinlichkeit -->
|
||
<div class="column is-full-mobile is-full-tablet is-half-desktop has-text-centered">
|
||
<button class="risk-chip {{ risk.residual_risk.likelihood|likelihood_class }}" type="button" aria-label="{% trans 'Likelihood' as likelihood_long_name %}">
|
||
<span class="chip-head">{% trans "Probability of occurrence" %}</span>
|
||
<span class="chip-id">{{ risk.residual_risk.likelihood }}</span>
|
||
<span class="chip-label">{{ risk.residual_risk.get_likelihood_display }}</span>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Schadensausmaß -->
|
||
<div class="column is-full-mobile is-full-tablet is-half-desktop has-text-centered">
|
||
<button class="risk-chip {{ risk.residual_risk.impact|impact_class }}" type="button" aria-label="{% trans 'Impact' as impact_long_name %}">
|
||
<span class="chip-head">{% trans "Extent of damage" %}</span>
|
||
<span class="chip-id">{{ risk.residual_risk.impact }}</span>
|
||
<span class="chip-label">{{ risk.residual_risk.get_impact_display }}</span>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Stufe -->
|
||
<div class="column is-full-mobile is-full-tablet is-half-desktop has-text-centered">
|
||
<button class="risk-chip {{ risk.residual_risk.level|level_class }}" type="button" aria-label="{% trans 'Level' %}">
|
||
<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-full-mobile is-full-tablet is-half-desktop has-text-centered" aria-label="{% trans 'Score' %}">
|
||
<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 %}
|
||
<p class="has-text-grey">{% trans "No net risk recorded yet." %}</p>
|
||
{% endif %}
|
||
</div><br>
|
||
{% if request.user.is_staff or risk.owner_id == request.user.id %}
|
||
<form method="post" action="{% url 'risks:update_residual_review' risk.id %}">
|
||
{% csrf_token %}
|
||
<label class="checkbox">
|
||
<input type="checkbox" name="review_required" value="on" {% if risk.residual_risk and risk.residual_risk.review_required %}checked{% endif %}>
|
||
{% trans "Review required" %}
|
||
</label>
|
||
<button class="button is-small is-link" style="margin-left:.5rem;">
|
||
{% trans "Save" %}
|
||
</button>
|
||
</form>
|
||
{% endif %}
|
||
</div>
|
||
</div> <!-- Ende Nettorisiko -->
|
||
|
||
</div> <!-- Ende Risikobewertung -->
|
||
</div> <!-- Ende Inhalt Überblick -->
|
||
</div> <!-- Ende Überblick -->
|
||
|
||
<!-- Maßnahmen -->
|
||
<div class="card">
|
||
<header class="card-header">
|
||
<p class="card-header-title">{% trans "Measures" %}</p>
|
||
</header>
|
||
<div class="card-content">
|
||
{% if risk.controls.exists %}
|
||
<table class="table is-striped is-hoverable is-fullwidth">
|
||
<thead>
|
||
<tr>
|
||
<th>{% trans "Title" %}</th>
|
||
<th>{% trans "Status" %}</th>
|
||
<th>{% trans "Deadline" %}</th>
|
||
<th>{% trans "Responsible" %}</th>
|
||
<th>{% 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>{{ control.get_status_display }}</td>
|
||
<td>
|
||
{% if control.due_date %}
|
||
{{ control.due_date|date:"d.m.Y" }}
|
||
{% else %}
|
||
–
|
||
{% endif %}
|
||
</td>
|
||
<td>
|
||
{% if control.responsible %}
|
||
{{ control.responsible.get_full_name|default:control.responsible.username }}
|
||
{% else %}
|
||
–
|
||
{% endif %}
|
||
</td>
|
||
<td>
|
||
{% if control.wiki_link %}
|
||
<a href="{{ control.wiki_link }}" target="_blank">🔗</a>
|
||
{% else %}
|
||
–
|
||
{% endif %}
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
{% else %}
|
||
<p class="has-text-grey">{% trans "No measures recorded." %}</p>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
<!-- Ende Maßnahmen -->
|
||
|
||
<!-- Vorfälle -->
|
||
<div class="card">
|
||
<header class="card-header">
|
||
<p class="card-header-title">{% trans "Incidents" %}</p>
|
||
</header>
|
||
<div class="card-content">
|
||
{% if risk.incidents.exists %}
|
||
<table class="table is-striped is-fullwidth">
|
||
<thead>
|
||
<tr>
|
||
<th>{% trans "Incident" %}</th>
|
||
<th>{% trans "Status" %}</th>
|
||
<th>{% 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>{{ i.status }}</td>
|
||
<td>{{ i.created_at|date:"d.m.Y H:i" }}</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
{% else %}
|
||
<p class="has-text-grey">{% trans "No incidents recorded." %}</p>
|
||
{% endif %}
|
||
</div>
|
||
</div> <!-- Ende Vorfälle -->
|
||
|
||
<!-- Historie -->
|
||
<div class="card">
|
||
<header class="card-header">
|
||
<p class="card-header-title">{% trans "History" %}</p>
|
||
</header>
|
||
<div class="card-content">
|
||
{% if logs %}
|
||
<table class="table is-striped is-fullwidth">
|
||
<thead>
|
||
<tr>
|
||
<th>{% trans "Time" %}</th>
|
||
<th>{% trans "User" %}</th>
|
||
<th>{% trans "Action" %}</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for log in logs %}
|
||
<tr>
|
||
<td>{{ log.action_time|date:"d.m.Y H:i" }}</td>
|
||
<td>{{ log.user.get_full_name|default:log.user.username }}</td>
|
||
<td>{{ log.get_change_message }}</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
{% else %}
|
||
<p class="has-text-grey">{% trans "No History found." %}</p>
|
||
{% endif %}
|
||
</div>
|
||
</div> <!-- Ende Historie -->
|
||
|
||
<br><br>
|
||
|
||
</div>
|
||
{% endblock %} |