Design suggestion from AI. Not very useable
This commit is contained in:
@@ -1,110 +1,403 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}{{ standard }}{% endblock %}
|
||||
{% block title %}{{ standard.nummer }} – {{ standard.name }}{% endblock %}
|
||||
{% block breadcrumb_items %}
|
||||
<li class="breadcrumb-item"><a href="{% url 'standard_list' %}">Standards</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">{{ standard.nummer }}</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{{ standard.nummer }} – {{ standard.name }}</h1>
|
||||
{% if standard.history == True %}
|
||||
<h2>Version vom {{ standard.check_date }}</h2>
|
||||
{% endif %}
|
||||
<!-- Autoren, Prüfende etc. -->
|
||||
<p><strong>Autoren:</strong> {{ standard.autoren.all|join:", " }}</p>
|
||||
<p><strong>Prüfende:</strong> {{ standard.pruefende.all|join:", " }}</p>
|
||||
<p><strong>Gültigkeit:</strong> {{ standard.gueltigkeit_von }} bis {{ standard.gueltigkeit_bis|default_if_none:"auf weiteres" }}</p>
|
||||
<p><a href="{% url 'standard_json' standard.nummer %}" class="button" download="{{ standard.nummer }}.json">JSON herunterladen</a></p>
|
||||
|
||||
<!-- Start Einleitung -->
|
||||
{% if standard.einleitung_html %}
|
||||
<h2>Einleitung</h2>
|
||||
{% for typ, html in standard.einleitung_html %}
|
||||
<div>{{ html|safe }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<!-- End Einleitung -->
|
||||
|
||||
<!-- Start Geltungsbereich -->
|
||||
{% if standard.geltungsbereich_html %}
|
||||
<h2>Geltungsbereich</h2>
|
||||
{% for typ, html in standard.geltungsbereich_html %}
|
||||
<div>{{ html|safe }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<!-- End Geltungsbereich -->
|
||||
|
||||
<h2>Vorgaben</h2>
|
||||
{% for vorgabe in vorgaben %}
|
||||
<!-- Start Vorgabe -->
|
||||
{% if standard.history == True or vorgabe.long_status == "active" %}
|
||||
<a id="{{ vorgabe.Vorgabennummer }}"></a><div class="card mb-4">
|
||||
{% if vorgabe.long_status == "active"%}
|
||||
<div class="card-header d-flex justify-content-between align-items-center bg-secondary text-light">
|
||||
{% elif standard.history == True %}
|
||||
<div class="card-header d-flex justify-content-between align-items-center bg-danger-subtle">
|
||||
{% endif %}
|
||||
<h3 class="h5 m-0">{{ vorgabe.Vorgabennummer }} – {{ vorgabe.titel }}
|
||||
{% if vorgabe.long_status != "active" and standard.history == True %}<span class="text-danger"> ({{ vorgabe.long_status}})</span>{% endif %}
|
||||
</h3>
|
||||
{% if vorgabe.relevanzset %}
|
||||
<span class="badge bg-light text-black"> Relevanz:
|
||||
{{ vorgabe.relevanzset|join:", " }}
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
<span class="badge bg-light text-black">{{ vorgabe.thema }}</span>
|
||||
<div class="row">
|
||||
<!-- Main Content -->
|
||||
<div class="col-lg-8">
|
||||
<!-- Standard Header -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<h1 class="h2 mb-2">{{ standard.nummer }} – {{ standard.name }}</h1>
|
||||
{% if standard.history == True %}
|
||||
<p class="mb-0 opacity-75">Version vom {{ standard.check_date|date:"d.m.Y" }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
{% if not standard.aktiv %}
|
||||
<span class="badge bg-danger">Inaktiv</span>
|
||||
{% else %}
|
||||
<span class="badge bg-success">Aktiv</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h6 class="text-muted mb-2">📅 Gültigkeit</h6>
|
||||
<p class="mb-3">
|
||||
<strong>Von:</strong> {{ standard.gueltigkeit_von|default_if_none:"-" }}<br>
|
||||
<strong>Bis:</strong> {{ standard.gueltigkeit_bis|default_if_none:"Auf weiteres" }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h6 class="text-muted mb-2">👥 Verantwortlich</h6>
|
||||
{% if standard.autoren.all %}
|
||||
<p class="mb-1"><strong>Autoren:</strong><br>
|
||||
{% for autor in standard.autoren.all %}
|
||||
<span class="badge bg-light text-dark me-1">{{ autor }}</span>
|
||||
{% endfor %}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if standard.pruefende.all %}
|
||||
<p class="mb-3"><strong>Prüfende:</strong><br>
|
||||
{% for pruefender in standard.pruefende.all %}
|
||||
<span class="badge bg-light text-dark me-1">{{ pruefender }}</span>
|
||||
{% endfor %}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<a href="{% url 'standard_json' standard.nummer %}" class="btn btn-outline btn-sm" download="{{ standard.nummer }}.json">
|
||||
📄 JSON herunterladen
|
||||
</a>
|
||||
<button class="btn btn-outline btn-sm" onclick="window.print()">
|
||||
🖨️ Drucken
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body p-0">
|
||||
<!-- Start Kurztext -->
|
||||
{% comment %} KURZTEXT BLOCK {% endcomment %}
|
||||
{% if vorgabe.kurztext_html.0.1 %}
|
||||
<div class="p-3 mb-3 bg-light border-3" style="width: 100%;">
|
||||
{% for typ, html in vorgabe.kurztext_html %}
|
||||
{% if html %}
|
||||
<div class="mb-2">{{ html|safe }}</div>
|
||||
<!-- Table of Contents -->
|
||||
<div class="toc mb-4" id="table-of-contents">
|
||||
<h3>📋 Inhaltsverzeichnis</h3>
|
||||
<ul class="list-unstyled">
|
||||
{% if standard.einleitung_html %}
|
||||
<li><a href="#einleitung">Einleitung</a></li>
|
||||
{% endif %}
|
||||
{% if standard.geltungsbereich_html %}
|
||||
<li><a href="#geltungsbereich">Geltungsbereich</a></li>
|
||||
{% endif %}
|
||||
<li><a href="#vorgaben">Vorgaben ({{ vorgaben|length }})</a>
|
||||
<ul class="ms-3 mt-1">
|
||||
{% for vorgabe in vorgaben %}
|
||||
{% if standard.history == True or vorgabe.long_status == "active" %}
|
||||
<li><a href="#{{ vorgabe.Vorgabennummer }}">{{ vorgabe.Vorgabennummer }} – {{ vorgabe.titel|truncatechars:50 }}</a></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Einleitung -->
|
||||
{% if standard.einleitung_html %}
|
||||
<section id="einleitung" class="mb-5">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2 class="h4 mb-0">📖 Einleitung</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% for typ, html in standard.einleitung_html %}
|
||||
<div class="content-section">{{ html|safe }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
<!-- Geltungsbereich -->
|
||||
{% if standard.geltungsbereich_html %}
|
||||
<section id="geltungsbereich" class="mb-5">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2 class="h4 mb-0">🎯 Geltungsbereich</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% for typ, html in standard.geltungsbereich_html %}
|
||||
<div class="content-section">{{ html|safe }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
<!-- Vorgaben -->
|
||||
<section id="vorgaben" class="mb-5">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2 class="h4 mb-0">📝 Vorgaben</h2>
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-outline btn-sm" onclick="toggleAllVorgaben(true)">Alle ausklappen</button>
|
||||
<button type="button" class="btn btn-outline btn-sm" onclick="toggleAllVorgaben(false)">Alle einklappen</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% for vorgabe in vorgaben %}
|
||||
{% if standard.history == True or vorgabe.long_status == "active" %}
|
||||
<div class="card mb-4 vorgabe-card" id="{{ vorgabe.Vorgabennummer }}">
|
||||
<div class="card-header {% if vorgabe.long_status == "active" %}bg-success text-white{% else %}bg-secondary text-white{% endif %}"
|
||||
style="cursor: pointer;"
|
||||
onclick="toggleVorgabe('{{ vorgabe.Vorgabennummer }}')">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="toggle-icon me-2">▼</span>
|
||||
<h3 class="h5 m-0">
|
||||
{{ vorgabe.Vorgabennummer }} – {{ vorgabe.titel }}
|
||||
{% if vorgabe.long_status != "active" and standard.history == True %}
|
||||
<span class="badge bg-warning text-dark ms-2">{{ vorgabe.long_status }}</span>
|
||||
{% endif %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
{% if vorgabe.relevanzset %}
|
||||
<span class="badge bg-light text-dark">
|
||||
🔥 {{ vorgabe.relevanzset|join:", " }}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if vorgabe.thema %}
|
||||
<span class="badge bg-info">{{ vorgabe.thema }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body vorgabe-content" id="content-{{ vorgabe.Vorgabennummer }}">
|
||||
<!-- Kurztext -->
|
||||
{% if vorgabe.kurztext_html.0.1 %}
|
||||
<div class="alert alert-info mb-3">
|
||||
<h6 class="alert-heading">📌 Kurztext</h6>
|
||||
{% for typ, html in vorgabe.kurztext_html %}
|
||||
{% if html %}
|
||||
<div class="mb-2">{{ html|safe }}</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<!-- Langtext -->
|
||||
<div class="mb-4">
|
||||
{% for typ, html in vorgabe.langtext_html %}
|
||||
{% if html %}
|
||||
<div class="content-section mb-3">{{ html|safe }}</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<!-- Checklistenfragen -->
|
||||
<div class="mb-4">
|
||||
<h6 class="mb-3">✅ Checklistenfragen</h6>
|
||||
{% if vorgabe.checklistenfragen.all %}
|
||||
<div class="list-group">
|
||||
{% for frage in vorgabe.checklistenfragen.all %}
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex align-items-start">
|
||||
<input type="checkbox" class="form-check-input me-2 mt-1" id="check-{{ forloop.counter }}">
|
||||
<label class="form-check-label" for="check-{{ forloop.counter }}">
|
||||
{{ frage.frage }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="text-muted"><em>Keine Checklistenfragen vorhanden</em></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Metadaten -->
|
||||
<div class="border-top pt-3">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h6 class="text-muted mb-2">🏷️ Stichworte</h6>
|
||||
{% if vorgabe.stichworte.all %}
|
||||
<div>
|
||||
{% for s in vorgabe.stichworte.all %}
|
||||
<a href="{% url 'stichwort_detail' stichwort=s %}" class="badge bg-light text-dark text-decoration-none me-1 mb-1">
|
||||
{{ s }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="text-muted small mb-0">Keine Stichworte</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h6 class="text-muted mb-2">🔗 Referenzen</h6>
|
||||
{% if vorgabe.referenzpfade %}
|
||||
<div class="small">
|
||||
{% for ref in vorgabe.referenzpfade %}
|
||||
<div class="mb-1">{{ ref|safe }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="text-muted small mb-0">Keine Referenzen</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<!-- Langtext -->
|
||||
<div class="p-3 mb-3">
|
||||
{% comment %} LANGTEXT BLOCK {% endcomment %}
|
||||
{# <h5>Langtext</h5> #}
|
||||
{% for typ, html in vorgabe.langtext_html %}
|
||||
{% if html %}<div class="mb-3">{{ html|safe }}</div>{% endif %}
|
||||
{% endfor %}
|
||||
<!-- Checklistenfragen -->
|
||||
{% comment %} CHECKLISTENFRAGEN BLOCK {% endcomment %}
|
||||
<h5>Checklistenfragen</h5>
|
||||
{% if vorgabe.checklistenfragen.all %}
|
||||
<ul class="list-group">
|
||||
{% for frage in vorgabe.checklistenfragen.all %}
|
||||
<li class="list-group-item">{{ frage.frage }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<p><em>Keine Checklistenfragen</em></p>
|
||||
{% endif %}
|
||||
{% comment %} STICHWORTE + REFERENZEN AT BOTTOM {% endcomment %}
|
||||
<div class="mt-4 small text-muted">
|
||||
<strong>Stichworte:</strong>
|
||||
{% if vorgabe.stichworte.all %}
|
||||
{% for s in vorgabe.stichworte.all %}
|
||||
<a href="{% url 'stichwort_detail' stichwort=s %}">{{ s }}</a>{% if not forloop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<em>Keine</em>
|
||||
{% endif %}
|
||||
<br>
|
||||
<strong>Referenzen:</strong>
|
||||
{% if vorgabe.referenzpfade %}
|
||||
{% for ref in vorgabe.referenzpfade %}
|
||||
{{ ref|safe }}{% if not forloop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<em>Keine</em>
|
||||
{% endif %}
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="col-lg-4">
|
||||
<!-- Quick Actions -->
|
||||
<div class="card mb-4 sticky-top" style="top: 1rem;">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">⚡ Schnellaktionen</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="d-grid gap-2">
|
||||
<button class="btn btn-outline btn-sm" onclick="scrollToSection('einleitung')">
|
||||
📖 Zur Einleitung
|
||||
</button>
|
||||
<button class="btn btn-outline btn-sm" onclick="scrollToSection('geltungsbereich')">
|
||||
🎯 Zum Geltungsbereich
|
||||
</button>
|
||||
<button class="btn btn-outline btn-sm" onclick="scrollToSection('vorgaben')">
|
||||
📝 Zu den Vorgaben
|
||||
</button>
|
||||
<hr>
|
||||
<a href="{% url 'standard_list' %}" class="btn btn-outline btn-sm">
|
||||
← Zurück zur Liste
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Statistics -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">📊 Statistiken</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row text-center">
|
||||
<div class="col-6">
|
||||
<div class="border-end">
|
||||
<h4 class="text-primary mb-1">{{ vorgaben|length }}</h4>
|
||||
<small class="text-muted">Vorgaben</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h4 class="text-success mb-1">
|
||||
{% for vorgabe in vorgaben %}
|
||||
{% if vorgabe.long_status == "active" %}
|
||||
{% if forloop.first %}1{% else %}{{ forloop.counter }}{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</h4>
|
||||
<small class="text-muted">Aktiv</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<!-- JavaScript -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Update active TOC item on scroll
|
||||
const sections = document.querySelectorAll('section[id]');
|
||||
const tocLinks = document.querySelectorAll('.toc a');
|
||||
|
||||
function updateActiveTOC() {
|
||||
let current = '';
|
||||
sections.forEach(section => {
|
||||
const sectionTop = section.offsetTop;
|
||||
const sectionHeight = section.clientHeight;
|
||||
if (pageYOffset >= sectionTop - 100) {
|
||||
current = section.getAttribute('id');
|
||||
}
|
||||
});
|
||||
|
||||
tocLinks.forEach(link => {
|
||||
link.classList.remove('active');
|
||||
if (link.getAttribute('href') === '#' + current) {
|
||||
link.classList.add('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', updateActiveTOC);
|
||||
updateActiveTOC();
|
||||
});
|
||||
|
||||
function toggleVorgabe(vorgabeId) {
|
||||
const content = document.getElementById('content-' + vorgabeId);
|
||||
const icon = document.querySelector('#' + vorgabeId + ' .toggle-icon');
|
||||
|
||||
if (content.style.display === 'none') {
|
||||
content.style.display = 'block';
|
||||
icon.textContent = '▼';
|
||||
} else {
|
||||
content.style.display = 'none';
|
||||
icon.textContent = '▶';
|
||||
}
|
||||
}
|
||||
|
||||
function toggleAllVorgaben(expand) {
|
||||
const contents = document.querySelectorAll('.vorgabe-content');
|
||||
const icons = document.querySelectorAll('.toggle-icon');
|
||||
|
||||
contents.forEach(content => {
|
||||
content.style.display = expand ? 'block' : 'none';
|
||||
});
|
||||
|
||||
icons.forEach(icon => {
|
||||
icon.textContent = expand ? '▼' : '▶';
|
||||
});
|
||||
}
|
||||
|
||||
function scrollToSection(sectionId) {
|
||||
const element = document.getElementById(sectionId);
|
||||
if (element) {
|
||||
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.content-section {
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.content-section h1, .content-section h2, .content-section h3 {
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.content-section ul, .content-section ol {
|
||||
margin-bottom: 1rem;
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
.content-section li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.vorgabe-card {
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.vorgabe-card:hover {
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.toc a.active {
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
@media print {
|
||||
.vorgabe-content {
|
||||
display: block !important;
|
||||
}
|
||||
.toggle-icon {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,13 +1,201 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Standards Informatiksicherheit{% endblock %}
|
||||
{% block breadcrumb_items %}
|
||||
<li class="breadcrumb-item active" aria-current="page">Standards</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Standards Informatiksicherheit</h1>
|
||||
<ul>
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Standards Informatiksicherheit</h1>
|
||||
<div class="d-flex gap-2">
|
||||
<span class="badge bg-primary">{{ dokumente|length }} Standards</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filter and Search Section -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label for="filter-search" class="form-label">Suchen</label>
|
||||
<input type="text" class="form-control" id="filter-search" placeholder="Standard durchsuchen...">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="filter-status" class="form-label">Status</label>
|
||||
<select class="form-select" id="filter-status">
|
||||
<option value="">Alle</option>
|
||||
<option value="active">Aktiv</option>
|
||||
<option value="inactive">Inaktiv</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="filter-sort" class="form-label">Sortieren</label>
|
||||
<select class="form-select" id="filter-sort">
|
||||
<option value="nummer">Nummer</option>
|
||||
<option value="name">Name</option>
|
||||
<option value="gueltigkeit">Gültigkeit</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Standards Grid -->
|
||||
<div class="row" id="standards-container">
|
||||
{% for dokument in dokumente %}
|
||||
<li>
|
||||
<a href="{% url 'standard_detail' nummer=dokument.nummer %}">
|
||||
{{ dokument.nummer }} – {{ dokument.name }}
|
||||
</a>
|
||||
</li>
|
||||
<div class="col-lg-6 col-xl-4 mb-4 standard-item"
|
||||
data-nummer="{{ dokument.nummer|lower }}"
|
||||
data-name="{{ dokument.name|lower }}"
|
||||
data-status="{% if dokument.aktiv %}active{% else %}inactive{% endif %}">
|
||||
<div class="card standard-card h-100">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<span class="standard-number">{{ dokument.nummer }}</span>
|
||||
{% if not dokument.aktiv %}
|
||||
<span class="badge badge-status-inactive ms-2">Inaktiv</span>
|
||||
{% else %}
|
||||
<span class="badge badge-status-active ms-2">Aktiv</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-sm btn-outline" type="button" data-bs-toggle="dropdown">
|
||||
⋮
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="{% url 'standard_detail' nummer=dokument.nummer %}">Details anzeigen</a></li>
|
||||
<li><a class="dropdown-item" href="{% url 'standard_json' dokument.nummer %}" download="{{ dokument.nummer }}.json">JSON herunterladen</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">
|
||||
<a href="{% url 'standard_detail' nummer=dokument.nummer %}" class="text-decoration-none">
|
||||
{{ dokument.name }}
|
||||
</a>
|
||||
</h5>
|
||||
|
||||
<div class="standard-meta mb-3">
|
||||
<div class="row g-2">
|
||||
<div class="col-6">
|
||||
<small class="text-muted">
|
||||
<strong>Gültig von:</strong><br>
|
||||
{{ dokument.gueltigkeit_von|default_if_none:"-" }}
|
||||
</small>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<small class="text-muted">
|
||||
<strong>Gültig bis:</strong><br>
|
||||
{{ dokument.gueltigkeit_bis|default_if_none:"Auf weiteres" }}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if dokument.autoren.all %}
|
||||
<div class="mb-2">
|
||||
<small class="text-muted">
|
||||
<strong>Autoren:</strong>
|
||||
{% for autor in dokument.autoren.all %}
|
||||
{{ autor }}{% if not forloop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
</small>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if dokument.pruefende.all %}
|
||||
<div class="mb-3">
|
||||
<small class="text-muted">
|
||||
<strong>Prüfende:</strong>
|
||||
{% for pruefender in dokument.pruefende.all %}
|
||||
{{ pruefender }}{% if not forloop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
</small>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<a href="{% url 'standard_detail' nummer=dokument.nummer %}" class="btn btn-primary btn-sm">
|
||||
Details anzeigen
|
||||
</a>
|
||||
<div class="text-muted">
|
||||
<small>
|
||||
{% if dokument.history %}
|
||||
Version vom {{ dokument.check_date|date:"d.m.Y" }}
|
||||
{% endif %}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<div class="col-12">
|
||||
<div class="text-center py-5">
|
||||
<h3 class="text-muted">Keine Standards gefunden</h3>
|
||||
<p class="text-muted">Es wurden keine Standards gefunden, die Ihren Kriterien entsprechen.</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- JavaScript for filtering and sorting -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const searchInput = document.getElementById('filter-search');
|
||||
const statusSelect = document.getElementById('filter-status');
|
||||
const sortSelect = document.getElementById('filter-sort');
|
||||
const container = document.getElementById('standards-container');
|
||||
|
||||
function filterAndSort() {
|
||||
const searchTerm = searchInput.value.toLowerCase();
|
||||
const statusFilter = statusSelect.value;
|
||||
const sortBy = sortSelect.value;
|
||||
|
||||
let items = Array.from(container.querySelectorAll('.standard-item'));
|
||||
|
||||
// Filter
|
||||
items = items.filter(item => {
|
||||
const nummer = item.dataset.nummer;
|
||||
const name = item.dataset.name;
|
||||
const status = item.dataset.status;
|
||||
|
||||
const matchesSearch = !searchTerm ||
|
||||
nummer.includes(searchTerm) ||
|
||||
name.includes(searchTerm);
|
||||
|
||||
const matchesStatus = !statusFilter || status === statusFilter;
|
||||
|
||||
return matchesSearch && matchesStatus;
|
||||
});
|
||||
|
||||
// Sort
|
||||
items.sort((a, b) => {
|
||||
switch(sortBy) {
|
||||
case 'nummer':
|
||||
return a.dataset.nummer.localeCompare(b.dataset.nummer);
|
||||
case 'name':
|
||||
return a.dataset.name.localeCompare(b.dataset.name);
|
||||
case 'gueltigkeit':
|
||||
// This would need additional data attributes for proper sorting
|
||||
return a.dataset.nummer.localeCompare(b.dataset.nummer);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
// Reorder DOM
|
||||
items.forEach(item => container.appendChild(item));
|
||||
|
||||
// Show/hide no results message
|
||||
const noResults = container.querySelector('.col-12 .text-center');
|
||||
if (noResults) {
|
||||
noResults.parentElement.style.display = items.length === 0 ? 'block' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
searchInput.addEventListener('input', filterAndSort);
|
||||
statusSelect.addEventListener('change', filterAndSort);
|
||||
sortSelect.addEventListener('change', filterAndSort);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user