Compare commits
2 commits
8afa7363d0
...
79c977f03b
Author | SHA1 | Date | |
---|---|---|---|
![]() |
79c977f03b | ||
![]() |
f43412b2dd |
10 changed files with 353 additions and 97 deletions
BIN
db.sqlite3
BIN
db.sqlite3
Binary file not shown.
Binary file not shown.
|
@ -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"
|
||||||
|
|
|
@ -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 ""
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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)
|
||||||
|
@ -64,3 +120,15 @@ def score_class(score):
|
||||||
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
|
|
@ -161,3 +161,86 @@ body.dark-mode .box {
|
||||||
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); }
|
||||||
|
}
|
|
@ -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">
|
||||||
|
|
|
@ -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 -->
|
||||||
|
|
||||||
|
|
|
@ -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 %}
|
||||||
|
|
Loading…
Add table
Reference in a new issue