Design suggestion from AI. Not very useable
This commit is contained in:
@@ -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