Compare commits

..

2 commits

Author SHA1 Message Date
Kevin Heyer
9c1fa2afa9 . 2025-09-15 11:08:06 +02:00
Kevin Heyer
fe54e08de2 Change UI 2025-09-15 11:06:33 +02:00
8 changed files with 100 additions and 7 deletions

View file

@ -94,7 +94,7 @@ class RedirectOnSaveMixin:
@admin.register(Risk) @admin.register(Risk)
class RiskAdmin(ChangedByMixin, RedirectOnSaveMixin, admin.ModelAdmin): class RiskAdmin(ChangedByMixin, RedirectOnSaveMixin, admin.ModelAdmin):
redirect_url_name = "risks:show_risk" redirect_url_name = "risks:show_risk"
list_display = ("title", "owner_name", "status", "score", "level", "likelihood", "impact", "follow_up") list_display = ("title", "owner_name", "score", "level", "likelihood", "impact", "follow_up", "status")
list_filter = ("status", "level", "likelihood", "impact", "owner") list_filter = ("status", "level", "likelihood", "impact", "owner")
search_fields = ("title", "asset", "process", "category") search_fields = ("title", "asset", "process", "category")
inlines = [ResidualRiskInline, ControlRisksInline] inlines = [ResidualRiskInline, ControlRisksInline]
@ -139,6 +139,13 @@ class IncidentAdmin(ChangedByMixin, RedirectOnSaveMixin, admin.ModelAdmin):
autocomplete_fields = ("related_risks",) autocomplete_fields = ("related_risks",)
filter_horizontal = ("related_risks",) filter_horizontal = ("related_risks",)
def get_changeform_initial_data(self, request):
initial = super().get_changeform_initial_data(request)
risk_id = request.GET.get("related_risks")
if risk_id:
initial["related_risks"] = [risk_id]
return initial
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Notification # Notification

View file

@ -1,4 +1,5 @@
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers from rest_framework import serializers
from .models import Risk, Control, ResidualRisk, AuditLog, Incident from .models import Risk, Control, ResidualRisk, AuditLog, Incident

View file

@ -17,6 +17,7 @@ urlpatterns = [
path("risks/risks/<int:id>", views.show_risk, name="show_risk"), path("risks/risks/<int:id>", views.show_risk, name="show_risk"),
path("risks/risk_matrix", views.risk_matrix, name="risk_matrix"), path("risks/risk_matrix", views.risk_matrix, name="risk_matrix"),
path("risks/<int:id>/status", views.update_risk_status, name="update_risk_status"), path("risks/<int:id>/status", views.update_risk_status, name="update_risk_status"),
path("risks/<int:pk>/mark_reviewed/", views.mark_risk_reviewed, name="mark_risk_reviewed"),
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# Controls # Controls

View file

@ -0,0 +1,13 @@
{% extends "admin/change_form.html" %}
{% load i18n %}
{% block submit_buttons_bottom %}
{{ block.super }}
{% if original and original.pk %}
<a href="{% url 'risks:show_risk' original.pk %}"
class="button is-light">
{% trans "Schließen" %}
</a>
{% endif %}
{% endblock %}

View file

@ -11,6 +11,22 @@
<link rel="stylesheet" href="{% static 'css/print.css' %}" media="print"> <link rel="stylesheet" href="{% static 'css/print.css' %}" media="print">
</head> </head>
<body> <body>
{% if messages %}
<div id="message-modal" class="modal">
<div class="modal-background"></div>
<div class="modal-content" style="max-width: 400px;">
<div class="box has-text-centered">
{% for message in messages %}
<p>{{ message }}</p>
{% endfor %}
<br>
<button class="button is-primary close">OK</button>
</div>
</div>
<button class="modal-close is-large delete" aria-label="close"></button>
</div>
{% endif %}
<header class="topbar"> <header class="topbar">
<nav class="navbar topbar-nav" role="navigation" aria-label="main navigation"> <nav class="navbar topbar-nav" role="navigation" aria-label="main navigation">
<div class="navbar-brand"> <div class="navbar-brand">
@ -165,6 +181,37 @@
menu.classList.toggle('is-active'); menu.classList.toggle('is-active');
}); });
}); });
document.addEventListener('DOMContentLoaded', () => {
const modal = document.getElementById('message-modal');
if (!modal) return;
// Funktion zum Öffnen
function openModal() {
modal.classList.add('is-active');
}
// Funktion zum Schließen
function closeModal() {
modal.classList.remove('is-active');
}
// Modal automatisch öffnen, weil eine Message da ist
openModal();
// Close-Elemente: Hintergrund, delete-Button, OK-Button
modal.querySelector('.modal-background').addEventListener('click', closeModal);
modal.querySelector('.delete').addEventListener('click', closeModal);
modal.querySelector('.close').addEventListener('click', closeModal);
// Escape drücken
document.addEventListener('keydown', (e) => {
if (e.key === "Escape" || e.key === "Esc") {
closeModal();
}
});
});
</script> </script>
</body> </body>

View file

@ -16,10 +16,15 @@
<!-- Action Icons --> <!-- Action Icons -->
<div class="buttons"> <div class="buttons">
<a href="{% url 'admin:risks_risk_change' risk.pk %}" class="button is-small is-warning" title="{% trans 'Edit Risk' %}"> <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> <span class="icon"><i class="fas fa-edit"></i> </span>&nbsp;&nbsp;{% trans 'Edit Risk' %}
</a> </a>
<a href="{% url 'admin:risks_risk_delete' risk.pk %}" class="button is-small is-danger" title="{% trans 'Delete Risk' %}"> <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> <span class="icon"><i class="fas fa-trash"></i></span>&nbsp;&nbsp;{% 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>&nbsp;&nbsp;{% trans 'Mark Risk as reviewed' %}
</a> </a>
</div> </div>
</div> </div>
@ -157,7 +162,13 @@
</div> </div>
{% else %} {% else %}
<p class="has-text-grey">{% trans "No net risk recorded yet." %}</p> <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 %} {% endif %}
</div> </div>
</div> </div>
@ -217,7 +228,7 @@
<td class="has-text-centered">{{ i.created_at|date:"d.m.Y H:i" }}</td> <td class="has-text-centered">{{ i.created_at|date:"d.m.Y H:i" }}</td>
</tr> </tr>
{% empty %} {% empty %}
<tr><td colspan="3" class="has-text-grey has-text-centered">{% trans "No incidents recorded." %}</td></tr> <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 %} {% endfor %}
</tbody> </tbody>
</table> </table>

View file

@ -162,7 +162,20 @@
<td>{{ r.asset }}</td> <td>{{ r.asset }}</td>
<td>{{ r.category }}</td> <td>{{ r.category }}</td>
<td>{{ r.process }}</td> <td>{{ r.process }}</td>
<td>{{ r.get_status_display }}</td> <td>
<div class="tag
{% if r.status == 'open' %}
is-info
{% elif r.status == 'review_required' %}
is-warning
{% elif r.status == 'closed' %}
is-success
{% elif r.status == 'in_progress' %}
is-link is-light
{% endif %}
">
{{ r.get_status_display }}
</div> {% if not r.residual_risk %} / <div class="tag is-danger">Kein Restrisiko</div>{% endif %}</td>
<td>{{ r.created_at|date:"d.m.Y H:i" }}</td> <td>{{ r.created_at|date:"d.m.Y H:i" }}</td>
<td>{{ r.owner|user_display }}</td> <td>{{ r.owner|user_display }}</td>
<td>{{ r.updated_at|date:"d.m.Y H:i" }}</td> <td>{{ r.updated_at|date:"d.m.Y H:i" }}</td>

View file

@ -18,7 +18,7 @@
<table class="table is-bordered is-fullwidth has-text-centered risk-matrix-table"> <table class="table is-bordered is-fullwidth has-text-centered risk-matrix-table">
<thead> <thead>
<tr> <tr>
<th class="has-text-left">{% trans "Impact" %} / {% trans "Likelihood" %}</th> <th class="has-text-left">{% trans "Impact" %} * {% trans "Likelihood" %}</th>
{% for l_val, l_label in likelihoods %} {% for l_val, l_label in likelihoods %}
<th class="{{ l_val|likelihood_class|to_bg }}">{{ l_label }}</th> <th class="{{ l_val|likelihood_class|to_bg }}">{{ l_label }}</th>
{% endfor %} {% endfor %}