Files
vgui-cicd/dokumente/templates/standards/standard_list.html

201 lines
6.9 KiB
HTML

{% extends "base.html" %}
{% block title %}Standards Informatiksicherheit{% endblock %}
{% block breadcrumb_items %}
<li class="breadcrumb-item active" aria-current="page">Standards</li>
{% endblock %}
{% block content %}
<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 %}
<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 %}
</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 %}