Compare commits

..

2 commits

10 changed files with 353 additions and 97 deletions

Binary file not shown.

Binary file not shown.

View file

@ -2,7 +2,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: wira-risk-management\n" "Project-Id-Version: wira-risk-management\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-09-09 21:18+0200\n" "POT-Creation-Date: 2025-09-10 08:16+0200\n"
"PO-Revision-Date: 2025-09-09 13:45+0200\n" "PO-Revision-Date: 2025-09-09 13:45+0200\n"
"Last-Translator: Kevin Heyer <kevin@example.com>\n" "Last-Translator: Kevin Heyer <kevin@example.com>\n"
"Language-Team: German\n" "Language-Team: German\n"
@ -36,11 +36,14 @@ msgstr "Verantwortlich für Maßnahmen"
msgid "Risk Management" msgid "Risk Management"
msgstr "Risikomanagement" msgstr "Risikomanagement"
#: risks/models.py:35 #: risks/models.py:35 templates/risks/list_risks.html:18
#: templates/risks/list_risks.html:83
msgid "Risk" msgid "Risk"
msgstr "Risiko" msgstr "Risiko"
#: risks/models.py:36 templates/risks/dashboard.html:85 #: risks/models.py:36 templates/risks/dashboard.html:75
#: templates/risks/dashboard.html:80 templates/risks/dashboard.html:85
#: templates/risks/list_risks.html:76
msgid "Risks" msgid "Risks"
msgstr "Risiken" msgstr "Risiken"
@ -108,7 +111,7 @@ msgstr "Asset"
msgid "Process" msgid "Process"
msgstr "Prozess" msgstr "Prozess"
#: risks/models.py:62 #: risks/models.py:62 templates/risks/list_risks.html:85
msgid "Category" msgid "Category"
msgstr "Kategorie" msgstr "Kategorie"
@ -132,7 +135,7 @@ msgstr "Restrisiken"
msgid "Control" msgid "Control"
msgstr "Maßnahme" msgstr "Maßnahme"
#: risks/models.py:176 #: risks/models.py:176 templates/risks/list_risks.html:37
msgid "Controls" msgid "Controls"
msgstr "Maßnahmen" msgstr "Maßnahmen"
@ -202,7 +205,7 @@ msgstr "Übersicht der Risiken, Maßnahmen und Vorfälle"
#: templates/risks/dashboard.html:25 #: templates/risks/dashboard.html:25
msgid "Total Risks" msgid "Total Risks"
msgstr "Restrisiken" msgstr "Risiken"
#: templates/risks/dashboard.html:33 #: templates/risks/dashboard.html:33
msgid "Residual Risks Needing Review" msgid "Residual Risks Needing Review"
@ -223,3 +226,40 @@ msgstr "Vorfälle nach Status"
#: templates/risks/dashboard.html:68 #: templates/risks/dashboard.html:68
msgid "Risks by CIA" msgid "Risks by CIA"
msgstr "CIA Risiken" msgstr "CIA Risiken"
#: templates/risks/list_risks.html:4
msgid "Risk analysis"
msgstr "Risikoanalyse"
#: templates/risks/list_risks.html:9
msgid "Filter"
msgstr "Filter"
#: templates/risks/list_risks.html:22 templates/risks/list_risks.html:41
#: templates/risks/list_risks.html:60
msgid "All"
msgstr "Alle"
#: templates/risks/list_risks.html:56 templates/risks/list_risks.html:90
msgid "Risk Owner"
msgstr "Risikoeigner"
#: templates/risks/list_risks.html:84
msgid "Asset / Process"
msgstr "Asset / Prozess"
#: templates/risks/list_risks.html:86
msgid "Likelihood"
msgstr "Eintritt"
#: templates/risks/list_risks.html:87
msgid "Impact"
msgstr "Schaden"
#: templates/risks/list_risks.html:88
msgid "Score"
msgstr "Score"
#: templates/risks/list_risks.html:89
msgid "Level"
msgstr "Stufe"

View file

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-09-09 21:18+0200\n" "POT-Creation-Date: 2025-09-10 08:16+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -42,11 +42,14 @@ msgstr ""
msgid "Risk Management" msgid "Risk Management"
msgstr "" msgstr ""
#: risks/models.py:35 #: risks/models.py:35 templates/risks/list_risks.html:18
#: templates/risks/list_risks.html:83
msgid "Risk" msgid "Risk"
msgstr "" msgstr ""
#: risks/models.py:36 templates/risks/dashboard.html:85 #: risks/models.py:36 templates/risks/dashboard.html:75
#: templates/risks/dashboard.html:80 templates/risks/dashboard.html:85
#: templates/risks/list_risks.html:76
msgid "Risks" msgid "Risks"
msgstr "" msgstr ""
@ -114,7 +117,7 @@ msgstr ""
msgid "Process" msgid "Process"
msgstr "" msgstr ""
#: risks/models.py:62 #: risks/models.py:62 templates/risks/list_risks.html:85
msgid "Category" msgid "Category"
msgstr "" msgstr ""
@ -138,7 +141,7 @@ msgstr ""
msgid "Control" msgid "Control"
msgstr "" msgstr ""
#: risks/models.py:176 #: risks/models.py:176 templates/risks/list_risks.html:37
msgid "Controls" msgid "Controls"
msgstr "" msgstr ""
@ -229,3 +232,40 @@ msgstr ""
#: templates/risks/dashboard.html:68 #: templates/risks/dashboard.html:68
msgid "Risks by CIA" msgid "Risks by CIA"
msgstr "" msgstr ""
#: templates/risks/list_risks.html:4
msgid "Risk analysis"
msgstr ""
#: templates/risks/list_risks.html:9
msgid "Filter"
msgstr ""
#: templates/risks/list_risks.html:22 templates/risks/list_risks.html:41
#: templates/risks/list_risks.html:60
msgid "All"
msgstr ""
#: templates/risks/list_risks.html:56 templates/risks/list_risks.html:90
msgid "Risk Owner"
msgstr ""
#: templates/risks/list_risks.html:84
msgid "Asset / Process"
msgstr ""
#: templates/risks/list_risks.html:86
msgid "Likelihood"
msgstr ""
#: templates/risks/list_risks.html:87
msgid "Impact"
msgstr ""
#: templates/risks/list_risks.html:88
msgid "Score"
msgstr ""
#: templates/risks/list_risks.html:89
msgid "Level"
msgstr ""

View file

@ -43,13 +43,19 @@ class ControlRisksInline(admin.TabularInline):
class RiskAdmin(admin.ModelAdmin): class RiskAdmin(admin.ModelAdmin):
list_display = ( list_display = (
"title", "title",
"owner", "owner_name",
"score", "score",
"level", "level",
"likelihood", "likelihood",
"impact", "impact",
"follow_up", "follow_up",
) )
def owner_name(self, obj):
if not obj.owner:
return "-"
return obj.owner.get_full_name() or obj.owner.username
list_filter = ("level", "likelihood", "impact", "owner") list_filter = ("level", "likelihood", "impact", "owner")
search_fields = ("title", "asset", "process", "category") search_fields = ("title", "asset", "process", "category")
inlines = [ResidualRiskInline, ControlRisksInline] inlines = [ResidualRiskInline, ControlRisksInline]

View file

@ -1,8 +1,64 @@
from django import template from django import template
from ..models import Risk from django.utils.html import format_html
from ..models import Control, Incident, Risk
register = template.Library() register = template.Library()
_CONTROL_STATUS_MAP = dict(Control.STATUS_CHOICES)
_INCIDENT_STATUS_MAP = dict(Incident.STATUS_CHOICES)
_LIKELIHOOD_LABELS = dict(Risk.LIKELIHOOD_CHOICES)
_IMPACT_LABELS = dict(Risk.IMPACT_CHOICES)
LEVEL_ID_MAP = {"Low": 1, "Medium": 2, "High": 3, "Critical": 4}
@register.filter
def level_id(level):
return LEVEL_ID_MAP.get(str(level), "")
@register.filter
def user_display(user):
if not user:
return ""
full = user.get_full_name()
return full if full else user.username
def _short(label: str) -> str:
"""First Segment of - from Impact and Likelihood"""
if not label:
return ""
for sep in (" ", " - ", "("):
if sep in label:
return label.split(sep, 1)[0].strip()
return label.strip()
@register.filter
def likelihood_id_label(val):
try:
i = int(val)
except (TypeError, ValueError):
return ""
label = _LIKELIHOOD_LABELS.get(i, "")
short = _short(str(label)) if label else ""
return format_html("{}<br>({})", i, short) if label else format_html("{}", i)
@register.filter
def impact_id_label(val):
try:
i = int(val)
except (TypeError, ValueError):
return ""
label = _IMPACT_LABELS.get(i, "")
short = _short(str(label)) if label else ""
return format_html("{}<br>({})", i, short) if label else format_html("{}", i)
@register.filter
def control_status_label(code):
return _CONTROL_STATUS_MAP.get(code, code)
@register.filter
def incident_status_label(code):
return _INCIDENT_STATUS_MAP.get(code, code)
@register.filter @register.filter
def cia_label(value): def cia_label(value):
mapping = dict(Risk.CIA_CHOICES) mapping = dict(Risk.CIA_CHOICES)
@ -63,4 +119,16 @@ def score_class(score):
return "is-control-mid" return "is-control-mid"
if s <= 16: if s <= 16:
return "is-control-high" return "is-control-high"
return "is-control-veryhigh" return "is-control-veryhigh"
@register.filter
def to_bg(css_class: str):
"""
Wandelt is-control-foo -> has-background-control-foo um.
Für Tabellenzellen-Hintergrundfarben.
"""
try:
css = str(css_class)
except Exception:
return ""
return css.replace("is-control-", "has-background-control-") if css.startswith("is-control-") else css

View file

@ -160,4 +160,87 @@ body.dark-mode .box {
/* Optional: Buttons, Links etc. anpassen */ /* Optional: Buttons, Links etc. anpassen */
body.dark-mode a { body.dark-mode a {
color: #bb86fc; color: #bb86fc;
}
/* Ticket-Button (ID links, Text rechts) */
.risk-chip{
--chip-w: 260px;
--chip-id-w: 40px;
width: var(--chip-w);
display: inline-flex;
align-items: stretch;
border: 0;
border-radius: 8px;
overflow: hidden;
font-weight: 600;
box-shadow: 0 4px 14px rgba(0,0,0,.08);
background: var(--chip-bg, #eee);
color: var(--chip-fg, #111);
}
.risk-chip{
display:inline-flex;
flex-direction:column; /* <— neu */
}
.risk-chip .chip-head{
padding:.35rem .6rem;
font-size:.75rem;
font-weight:700;
text-transform:uppercase;
letter-spacing:.02em;
color:var(--chip-fg);
background:rgba(0,0,0,.10);
border-bottom:1px solid rgba(0,0,0,.12);
}
.risk-chip .chip-main{
display:flex;
align-items:stretch;
}
/* linke ID-Spalte mit leichter Textur */
.risk-chip .chip-id{
flex: 0 0 var(--chip-id-w);
display: grid;
place-items: center;
font-size: 1.25rem;
position: relative;
background: rgba(0,0,0,.06);
}
.risk-chip .chip-id::after{
content:"";
position: absolute; inset:0;
background:
linear-gradient( to right, rgba(255,255,255,.15), rgba(0,0,0,.08) 60% ),
repeating-linear-gradient(135deg, rgba(255,255,255,.12) 0 6px, transparent 6px 12px);
mix-blend-mode: soft-light;
opacity:.6;
}
/* rechte Text-Spalte */
.risk-chip .chip-label{
flex: 1 1 auto;
padding: .5rem .75rem;
line-height: 1.25;
display: flex;
align-items: center;
border-left: 1px solid rgba(0,0,0,.08);
min-height: 2.25rem;
}
/* Farbzuteilung aus deinen Custom-Klassen */
.risk-chip.is-control-verylow { --chip-bg: var(--c-verylow); --chip-fg: var(--c-verylow-inv); }
.risk-chip.is-control-low { --chip-bg: var(--c-low); --chip-fg: var(--c-low-inv); }
.risk-chip.is-control-mid { --chip-bg: var(--c-mid); --chip-fg: var(--c-mid-inv); }
.risk-chip.is-control-high { --chip-bg: var(--c-high); --chip-fg: var(--c-high-inv); }
.risk-chip.is-control-veryhigh{ --chip-bg: var(--c-veryhigh); --chip-fg: var(--c-veryhigh-inv); }
/* Responsiv: auf schmalen Screens volle Breite */
@media (max-width: 480px){
.risk-chip{ width: 100%; }
}
@media (max-width: 1215px) {
.risk-chip { --chip-w: 100%; width: var(--chip-w); }
} }

View file

@ -1,5 +1,5 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load i18n %} {% load i18n risk_extras %}
{% block content %} {% block content %}
<!-- Hero Section --> <!-- Hero Section -->
<section class="hero is-small is-bold"> <section class="hero is-small is-bold">
@ -26,7 +26,7 @@
</div> </div>
</div> </div>
<!-- Residual-Risiken --> <!-- Restrisiken -->
<div class="column is-one-quarter"> <div class="column is-one-quarter">
<div class="box has-text-centered {% if residual_review_required > 0 %}has-background-control-high{% else %}has-background-control-low{% endif %}"> <div class="box has-text-centered {% if residual_review_required > 0 %}has-background-control-high{% else %}has-background-control-low{% endif %}">
<h2 class="title is-4">{{ residual_review_required }}</h2> <h2 class="title is-4">{{ residual_review_required }}</h2>
@ -47,8 +47,8 @@
<div class="box"> <div class="box">
<h2 class="subtitle">{% trans "Controls by Status" %}</h2> <h2 class="subtitle">{% trans "Controls by Status" %}</h2>
<ul> <ul>
{% for status in controls_by_status %} {% for row in controls_by_status %}
<li>{{ status.status }}: {{ status.count }}</li> <li>{{ row.status|control_status_label }}: {{ row.count }}</li>
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>
@ -57,8 +57,8 @@
<div class="box"> <div class="box">
<h2 class="subtitle">{% trans "Incidents by Status" %}</h2> <h2 class="subtitle">{% trans "Incidents by Status" %}</h2>
<ul> <ul>
{% for incident in incidents_status %} {% for row in incidents_status %}
<li>{{ incident.status }}: {{ incident.count }}</li> <li>{{ row.status|incident_status_label }}: {{ row.count }}</li>
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>
@ -72,12 +72,12 @@
{% if cia == '1' %} {% if cia == '1' %}
<div class="box has-background-control-verylow has-text-centered"> <div class="box has-background-control-verylow has-text-centered">
<h3 class="title is-5">{% trans "Confidentiality" %}</h3> <h3 class="title is-5">{% trans "Confidentiality" %}</h3>
<p>{{ count }} Risks</p> <p>{{ count }} {% trans "Risks" %}</p>
</div> </div>
{% elif cia == '2' %} {% elif cia == '2' %}
<div class="box has-background-control-mid has-text-centered"> <div class="box has-background-control-mid has-text-centered">
<h3 class="title is-5">{% trans "Integrity" %}</h3> <h3 class="title is-5">{% trans "Integrity" %}</h3>
<p>{{ count }} Risks</p> <p>{{ count }} {% trans "Risks" %}</p>
</div> </div>
{% elif cia == '3' %} {% elif cia == '3' %}
<div class="box has-background-control-high has-text-centered"> <div class="box has-background-control-high has-text-centered">

View file

@ -1,5 +1,5 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load risk_extras %} {% load i18n risk_extras %}
{% block crumbs %} {% block crumbs %}
<li><a href="{% url 'risks:list_risks' %}">Risikoanalyse</a></li> <li><a href="{% url 'risks:list_risks' %}">Risikoanalyse</a></li>
<li><a href="{% url 'risks:show_risk' risk.id %}">{{ risk.title }}</a></li> <li><a href="{% url 'risks:show_risk' risk.id %}">{{ risk.title }}</a></li>
@ -32,6 +32,7 @@
<div class="column is-half"> <div class="column is-half">
<p><strong>Asset:</strong> {{ risk.asset|default:"-" }}</p> <p><strong>Asset:</strong> {{ risk.asset|default:"-" }}</p>
<p><strong>Prozess:</strong> {{ risk.process|default:"-" }}</p> <p><strong>Prozess:</strong> {{ risk.process|default:"-" }}</p>
<p><strong>Kategorie:</strong> {{ risk.category|default:"-" }}</p>
<p> <p>
<strong>Schutzziele:</strong> <strong>Schutzziele:</strong>
{% if risk.cia %} {% if risk.cia %}
@ -42,103 +43,111 @@
</p> </p>
</div> </div>
<div class="column is-half"> <div class="column is-half">
<p><strong>Kategorie:</strong> {{ risk.category|default:"-" }}</p> <p><strong>Risikoeigner:</strong> {{ risk.owner|user_display|default:"-" }}</p>
<p><strong>Risikoeigner:</strong> {{ risk.owner|default:"-" }}</p>
<p><strong>Erstellt am:</strong> {{ risk.created_at|date:'d.m.Y H:i' }}</p> <p><strong>Erstellt am:</strong> {{ risk.created_at|date:'d.m.Y H:i' }}</p>
<p><strong>Aktualisiert am:</strong> {{ risk.updated_at|date:'d.m.Y H:i' }}</p> <p><strong>Aktualisiert am:</strong> {{ risk.updated_at|date:'d.m.Y H:i' }}</p>
<p><strong>Wiedervorlage am:</strong> {{ risk.follow_up|date:'d.m.Y' }}</p>
</div> </div>
</div> </div>
<!-- Risikobewertung --> <!-- Risikobewertung -->
<h3>Risikobewertung</h3> <section class="hero has-text-centered is-small">
<div class="hero-body">
<p class="title">Risikobewertung</p>
</div>
</section>
<div class="columns is-multiline"> <div class="columns is-multiline">
<!-- Bruttorisiko --> <!-- Bruttorisiko -->
<div class="column is-half"> <div class="column is-full-mobile is-full-tablet is-half-desktop has-text-centered is-flex">
<div class="box"> <div class="box is-flex is-flex-direction-column is-flex-grow-1">
<h4>Brutto (vor Maßnahmen)</h4> <h4>Brutto (vor Maßnahmen)</h4>
<div class="columns is-multiline"> <div class="columns is-multiline">
<!-- Eintrittswahrscheinlichkeit --> <!-- Eintrittswahrscheinlichkeit -->
<div class="column is-half has-text-centered"> <div class="column is-full-mobile is-full-tablet is-half-desktop has-text-centered">
<p class="heading">Eintrittswahrscheinlichkeit</p> <button class="risk-chip {{ risk.likelihood|likelihood_class }}" type="button" aria-label="{% trans 'Likelihood' as likelihood_long_name %}">
<button class="button is-small {{ risk.likelihood|likelihood_class }}"> <span class="chip-head">Eintrittswahrscheinlichkeit</span>
{{ risk.get_likelihood_display }} <span class="chip-id">{{ risk.likelihood }}</span>
<span class="chip-label">{{ risk.get_likelihood_display }}</span>
</button> </button>
</div> <!-- Eintrittswahrscheinlichkeit Ende --> </div>
<!-- Schadensausmaß --> <!-- Schadensausmaß -->
<div class="column is-half has-text-centered"> <div class="column is-full-mobile is-full-tablet is-half-desktop has-text-centered">
<p class="heading">Schadensausmaß</p> <button class="risk-chip {{ risk.impact|impact_class }}" type="button" aria-label="{% trans 'Impact' as impact_long_name %}">
<button class="button is-small {{ risk.impact|impact_class }}"> <span class="chip-head">Schadensausmaß</span>
{{ risk.get_impact_display }} <span class="chip-id">{{ risk.impact }}</span>
<span class="chip-label">{{ risk.get_impact_display }}</span>
</button> </button>
</div> <!-- Schadensausmaß Ende --> </div>
<!-- Stufe --> <!-- Stufe -->
<div class="column is-half has-text-centered"> <div class="column is-full-mobile is-full-tablet is-half-desktop has-text-centered">
<p class="heading">Stufe</p> <button class="risk-chip {{ risk.level|level_class }}" type="button" aria-label="{% trans 'Level' %}">
<button class="button is-small {{ risk.level|level_class }}"> <span class="chip-head">Stufe</span>
{{ risk.level }} <span class="chip-id">{{ risk.level|level_id }}</span>
<span class="chip-label">{{ risk.level }}</span>
</button> </button>
</div> <!-- Stufe Ende --> </div>
<!-- Score --> <!-- Score -->
<div class="column is-half has-text-centered"> <div class="column is-full-mobile is-full-tablet is-half-desktop has-text-centered">
<p class="heading">Score</p> <button class="risk-chip {{ risk.score|score_class }}" type="button" aria-label="{% trans 'Score' %}">
<button class="button is-small {{ risk.score|score_class }}"> <span class="chip-head">Score</span>
{{ risk.score }} / 20 <span class="chip-id">{{ risk.score }}</span>
<span class="chip-label">Score (max. 20)</span>
</button> </button>
</div> <!-- Score Ende --> </div>
</div> </div>
</div> </div>
</div> <!-- Ende Bruttorisiko --> </div> <!-- Ende Bruttorisiko -->
<!-- Nettorisiko --> <!-- Nettorisiko -->
<div class="column is-half"> <div class="column is-full-mobile is-full-tablet is-half-desktop has-text-centered is-flex">
<div class="box"> <div class="box is-flex is-flex-direction-column is-flex-grow-1">
<h4>Netto (nach Maßnahmen)</h4> <h4>Netto (nach Maßnahmen)</h4>
<div class="columns is-multiline">
{% if risk.residual_risk %} {% if risk.residual_risk %}
<div class="columns is-multiline">
<!-- Eintrittswahrscheinlichkeit --> <!-- Eintrittswahrscheinlichkeit -->
<div class="column is-half has-text-centered"> <div class="column is-full-mobile is-full-tablet is-half-desktop has-text-centered">
<p class="heading">Eintrittswahrscheinlichkeit</p> <button class="risk-chip {{ risk.residual_risk.likelihood|likelihood_class }}" type="button" aria-label="{% trans 'Likelihood' as likelihood_long_name %}">
<button class="button is-small {{ risk.likelihood|likelihood_class }}"> <span class="chip-head">Eintrittswahrscheinlichkeit</span>
{{ risk.residual_risk.get_likelihood_display }} <span class="chip-id">{{ risk.residual_risk.likelihood }}</span>
<span class="chip-label">{{ risk.residual_risk.get_likelihood_display }}</span>
</button> </button>
</div> <!-- Eintrittswahrscheinlichkeit Ende --> </div>
<!-- Schadensausmaß --> <!-- Schadensausmaß -->
<div class="column is-half has-text-centered"> <div class="column is-full-mobile is-full-tablet is-half-desktop has-text-centered">
<p class="heading">Schadensausmaß</p> <button class="risk-chip {{ risk.residual_risk.impact|impact_class }}" type="button" aria-label="{% trans 'Impact' as impact_long_name %}">
<button class="button is-small {{ risk.impact|impact_class }}"> <span class="chip-head">Schadensausmaß</span>
{{ risk.residual_risk.get_impact_display }} <span class="chip-id">{{ risk.residual_risk.impact }}</span>
<span class="chip-label">{{ risk.residual_risk.get_impact_display }}</span>
</button> </button>
</div> <!-- Schadensausmaß Ende --> </div>
<!-- Stufe --> <!-- Stufe -->
<div class="column is-half has-text-centered"> <div class="column is-full-mobile is-full-tablet is-half-desktop has-text-centered">
<p class="heading">Stufe</p> <button class="risk-chip {{ risk.residual_risk.level|level_class }}" type="button" aria-label="{% trans 'Level' %}">
<button class="button is-small {{ risk.level|level_class }}"> <span class="chip-head">Stufe</span>
{{ risk.residual_risk.level }} <span class="chip-id">{{ risk.residual_risk.level|level_id }}</span>
<span class="chip-label">{{ risk.residual_risk.level }}</span>
</button> </button>
</div> <!-- Stufe Ende --> </div>
<!-- Score --> <!-- Score -->
<div class="column is-half has-text-centered"> <div class="column is-full-mobile is-full-tablet is-half-desktop has-text-centered" aria-label="{% trans 'Score' %}">
<p class="heading">Score</p> <button class="risk-chip {{ risk.residual_risk.score|score_class }}" type="button">
<button class="button is-small {{ risk.score|score_class }}"> <span class="chip-head">Score</span>
{{ risk.residual_risk.score }} / 20 <span class="chip-id">{{ risk.residual_risk.score }}</span>
<span class="chip-label">(max. 20)</span>
</button> </button>
</div> <!-- Score Ende -->
</div> </div>
{% else %} {% else %}
<p class="has-text-grey">Noch kein Nettorisiko erfasst.</p> <p class="has-text-grey">Noch kein Nettorisiko erfasst.</p>
{% endif %} {% endif %}
</div>
</div> </div>
</div> <!-- Ende Nettorisiko --> </div> <!-- Ende Nettorisiko -->

View file

@ -1,11 +1,12 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load i18n risk_extras %}
{% block crumbs %} {% block crumbs %}
<li><a href="{% url 'risks:list_risks' %}">Risikoanalyse</a></li> <li><a href="{% url 'risks:list_risks' %}">{% trans "Risk analysis" %}</a></li>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<section class="section"> <section class="section">
<div class="box"> <div class="box">
<h2 class="title is-5">Auswahl</h2> <h2 class="title is-5">{% trans "Filter" %}</h2>
<!-- Filter --> <!-- Filter -->
<form method="get"> <form method="get">
@ -14,11 +15,11 @@
<!-- Risiko Filter --> <!-- Risiko Filter -->
<div class="column is-3"> <div class="column is-3">
<div class="field"> <div class="field">
<label class="label">Risiko</label> <label class="label">{% trans "Risk" %}</label>
<div class="control"> <div class="control">
<div class="select is-fullwidth"> <div class="select is-fullwidth">
<select name="risk" onchange="this.form.submit()"> <select name="risk" onchange="this.form.submit()">
<option value="">Alle</option> <option value="">{% trans "All" %}</option>
{% for r in risks %} {% for r in risks %}
<option value="{{ r.id }}" {% if request.GET.risk == r.id|stringformat:"s" %}selected{% endif %}> <option value="{{ r.id }}" {% if request.GET.risk == r.id|stringformat:"s" %}selected{% endif %}>
{{ r.title }} {{ r.title }}
@ -33,11 +34,11 @@
<!-- Maßnahmen Filter --> <!-- Maßnahmen Filter -->
<div class="column is-3"> <div class="column is-3">
<div class="field"> <div class="field">
<label class="label">Maßnahmen</label> <label class="label">{% trans "Controls" %}</label>
<div class="control"> <div class="control">
<div class="select is-fullwidth"> <div class="select is-fullwidth">
<select name="control" onchange="this.form.submit()"> <select name="control" onchange="this.form.submit()">
<option value="">Alle</option> <option value="">{% trans "All" %}</option>
{% for c in controls %} {% for c in controls %}
<option value="{{ c.id }}" {% if request.GET.control == c.id|stringformat:"s" %}selected{% endif %}> <option value="{{ c.id }}" {% if request.GET.control == c.id|stringformat:"s" %}selected{% endif %}>
{{ c.title }} {{ c.title }}
@ -52,11 +53,11 @@
<!-- Risikoeigner Filter --> <!-- Risikoeigner Filter -->
<div class="column is-3"> <div class="column is-3">
<div class="field"> <div class="field">
<label class="label">Risikoeigner</label> <label class="label">{% trans "Risk Owner" %}</label>
<div class="control"> <div class="control">
<div class="select is-fullwidth"> <div class="select is-fullwidth">
<select name="owner" onchange="this.form.submit()"> <select name="owner" onchange="this.form.submit()">
<option value="">Alle</option> <option value="">{% trans "All" %}</option>
{% for u in owners %} {% for u in owners %}
<option value="{{ u.id }}" {% if request.GET.owner == u.id|stringformat:"s" %}selected{% endif %}> <option value="{{ u.id }}" {% if request.GET.owner == u.id|stringformat:"s" %}selected{% endif %}>
{{ u.get_full_name|default:u.username }} {{ u.get_full_name|default:u.username }}
@ -72,21 +73,21 @@
</form> </form>
<h2 class="title is-5">Risiken</h2> <h2 class="title is-5">{% trans "Risks" %}</h2>
<!-- Risiken --> <!-- Risiken -->
<div class="table-container"> <div class="table-container">
<table class="table is-bordered is-striped is-hoverable is-fullwidth"> <table class="table is-bordered is-striped is-hoverable is-fullwidth">
<thead> <thead>
<tr> <tr>
{% if request.user.is_staff %}<th></th>{% endif %} {% if request.user.is_staff %}<th></th>{% endif %}
<th>Risiko</th> <th>{% trans "Risk" %}</th>
<th>Asset / Prozes</th> <th>{% trans "Asset / Process" %}</th>
<th>Kategorie</th> <th>{% trans "Category" %}</th>
<th>Eintritt</th> <th>{% trans "Likelihood" %}</th>
<th>Schaden</th> <th>{% trans "Impact" %}</th>
<th>Score</th> <th>{% trans "Score" %}</th>
<th>Stufe</th> <th>{% trans "Level" %}</th>
<th>Risikoeigner</th> <th>{% trans "Risk Owner" %}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -125,13 +126,22 @@
{% endif %} {% endif %}
</td> </td>
<td onclick="window.location.href='{% url 'risks:show_risk' r.id %}'" style="cursor:pointer;">{{ r.category }}</td> <td onclick="window.location.href='{% url 'risks:show_risk' r.id %}'" style="cursor:pointer;">{{ r.category }}</td>
<td onclick="window.location.href='{% url 'risks:show_risk' r.id %}'" style="cursor:pointer;">{{ r.get_likelihood_display }}</td> <td onclick="window.location.href='{% url 'risks:show_risk' r.id %}'" class="has-text-centered {{ r.likelihood|likelihood_class|to_bg }}" style="cursor:pointer;">
<td onclick="window.location.href='{% url 'risks:show_risk' r.id %}'" style="cursor:pointer;">{{ r.get_impact_display }}</td> {{ r.likelihood|likelihood_id_label }}
<td onclick="window.location.href='{% url 'risks:show_risk' r.id %}'" style="cursor:pointer;">{{ r.score }}</td> </td>
<td onclick="window.location.href='{% url 'risks:show_risk' r.id %}'" style="cursor:pointer;">{{ r.level }}</td> <td onclick="window.location.href='{% url 'risks:show_risk' r.id %}'" class="has-text-centered {{ r.impact|impact_class|to_bg }}" style="cursor:pointer;">
{{ r.impact|impact_id_label }}
</td>
<td onclick="window.location.href='{% url 'risks:show_risk' r.id %}'" class="has-text-centered {{ r.score|score_class|to_bg }}" style="cursor:pointer;">
{{ r.score }}
</td>
<td onclick="window.location.href='{% url 'risks:show_risk' r.id %}'" class="has-text-centered {{ r.level|level_class|to_bg }}" style="cursor:pointer;">
{{ r.level }}
</td>
<td onclick="window.location.href='{% url 'risks:show_risk' r.id %}'" style="cursor:pointer;"> <td onclick="window.location.href='{% url 'risks:show_risk' r.id %}'" style="cursor:pointer;">
{% if r.owner %} {% if r.owner %}
{{ r.owner.get_full_name|default:r.owner.username }} {{ r.owner|user_display }}
{% else %} {% else %}
{% endif %} {% endif %}