Phase 3: Django-natives DMS – Paperless-NGX durch DokumentDatei ersetzt
- Neues Modell DokumentDatei mit PostgreSQL FTS (SearchVectorField, GinIndex) - Upload-Pfad: dokumente/YYYY/MM/<uuid>/dateiname - 7 DMS-Views: list, detail, download, upload (HTMX Drag&Drop), delete, edit, search_api - Templates: list, detail, edit, upload mit Drag&Drop-Zone, Partials - URLs: /dms/ komplett verdrahtet - Sidebar: DMS als Primäreintrag, Paperless als Legacy - Migrationsskript: manage.py migrate_paperless_dokumente (DokumentLink → DokumentDatei) - compose.yml: paperless-Dienst deaktiviert (Legacy-Kommentarblock) - Migration 0048 angewendet Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
119
app/templates/stiftung/dms/detail.html
Normal file
119
app/templates/stiftung/dms/detail.html
Normal file
@@ -0,0 +1,119 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}{{ dok.titel }} – DMS – Stiftungsverwaltung{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3">
|
||||
{% if dok.is_pdf %}
|
||||
<i class="fas fa-file-pdf text-danger me-2"></i>
|
||||
{% else %}
|
||||
<i class="fas fa-file text-primary me-2"></i>
|
||||
{% endif %}
|
||||
{{ dok.titel }}
|
||||
</h1>
|
||||
<div class="d-flex gap-2">
|
||||
<a href="{% url 'stiftung:dms_download' pk=dok.pk %}" class="btn btn-outline-success">
|
||||
<i class="fas fa-download me-2"></i>Herunterladen
|
||||
</a>
|
||||
<a href="{% url 'stiftung:dms_edit' pk=dok.pk %}" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-edit me-2"></i>Bearbeiten
|
||||
</a>
|
||||
<a href="{% url 'stiftung:dms_list' %}" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-arrow-left me-2"></i>Zurück
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Metadaten -->
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-header bg-dark text-white py-2">
|
||||
<span class="small fw-bold"><i class="fas fa-info-circle me-2"></i>Dokument-Informationen</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<dl class="row mb-0">
|
||||
<dt class="col-sm-4 text-muted small">Typ</dt>
|
||||
<dd class="col-sm-8"><span class="badge bg-secondary">{{ dok.get_kontext_display }}</span></dd>
|
||||
|
||||
{% if dok.beschreibung %}
|
||||
<dt class="col-sm-4 text-muted small">Beschreibung</dt>
|
||||
<dd class="col-sm-8">{{ dok.beschreibung }}</dd>
|
||||
{% endif %}
|
||||
|
||||
<dt class="col-sm-4 text-muted small">Dateiname</dt>
|
||||
<dd class="col-sm-8 font-monospace small">{{ dok.dateiname_original|default:dok.datei.name }}</dd>
|
||||
|
||||
<dt class="col-sm-4 text-muted small">Dateigröße</dt>
|
||||
<dd class="col-sm-8">{{ dok.get_human_size }}</dd>
|
||||
|
||||
<dt class="col-sm-4 text-muted small">Hochgeladen am</dt>
|
||||
<dd class="col-sm-8">{{ dok.erstellt_am|date:"d.m.Y H:i" }} Uhr</dd>
|
||||
|
||||
{% if dok.erstellt_von %}
|
||||
<dt class="col-sm-4 text-muted small">Hochgeladen von</dt>
|
||||
<dd class="col-sm-8">{{ dok.erstellt_von.get_full_name|default:dok.erstellt_von.username }}</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Zuordnungen -->
|
||||
{% if dok.destinataer or dok.land or dok.paechter or dok.verpachtung %}
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-header bg-dark text-white py-2">
|
||||
<span class="small fw-bold"><i class="fas fa-link me-2"></i>Zuordnungen</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if dok.destinataer %}
|
||||
<div class="mb-2">
|
||||
<span class="text-muted small"><i class="fas fa-user me-1"></i>Destinatär:</span>
|
||||
<a href="{% url 'stiftung:destinataer_detail' pk=dok.destinataer.pk %}" class="ms-2">
|
||||
{{ dok.destinataer.get_full_name }}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if dok.land %}
|
||||
<div class="mb-2">
|
||||
<span class="text-muted small"><i class="fas fa-map me-1"></i>Länderei:</span>
|
||||
<a href="{% url 'stiftung:land_detail' pk=dok.land.pk %}" class="ms-2">
|
||||
{{ dok.land.lfd_nr }}{% if dok.land.gemeinde %} – {{ dok.land.gemeinde }}{% endif %}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if dok.paechter %}
|
||||
<div class="mb-2">
|
||||
<span class="text-muted small"><i class="fas fa-user-tie me-1"></i>Pächter:</span>
|
||||
<a href="{% url 'stiftung:paechter_detail' pk=dok.paechter.pk %}" class="ms-2">
|
||||
{{ dok.paechter.get_full_name }}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if dok.verpachtung %}
|
||||
<div class="mb-2">
|
||||
<span class="text-muted small"><i class="fas fa-handshake me-1"></i>Verpachtung:</span>
|
||||
<a href="{% url 'stiftung:land_verpachtung_detail' pk=dok.verpachtung.pk %}" class="ms-2">
|
||||
Vertrag #{{ dok.verpachtung.pk|stringformat:'s'|slice:':8' }}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Aktionen -->
|
||||
<div class="d-flex gap-2 mt-2">
|
||||
<form method="post" action="{% url 'stiftung:dms_delete' pk=dok.pk %}"
|
||||
class="d-inline" onsubmit="return confirm('Dokument „{{ dok.titel }}" unwiderruflich löschen?')">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="next" value="{% url 'stiftung:dms_list' %}">
|
||||
<button type="submit" class="btn btn-outline-danger btn-sm">
|
||||
<i class="fas fa-trash me-2"></i>Dokument löschen
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
66
app/templates/stiftung/dms/edit.html
Normal file
66
app/templates/stiftung/dms/edit.html
Normal file
@@ -0,0 +1,66 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}{{ dok.titel }} bearbeiten – DMS – Stiftungsverwaltung{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-7">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3">
|
||||
<i class="fas fa-edit text-primary me-2"></i>
|
||||
Metadaten bearbeiten
|
||||
</h1>
|
||||
<a href="{% url 'stiftung:dms_detail' pk=dok.pk %}" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-arrow-left me-2"></i>Zurück
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card shadow">
|
||||
<div class="card-body">
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold">Titel</label>
|
||||
<input type="text" name="titel" class="form-control"
|
||||
value="{{ dok.titel }}" required maxlength="255">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold">Typ / Kontext</label>
|
||||
<select name="kontext" class="form-select">
|
||||
{% for code, label in kontext_choices %}
|
||||
<option value="{{ code }}" {% if code == dok.kontext %}selected{% endif %}>{{ label }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-semibold">Beschreibung</label>
|
||||
<textarea name="beschreibung" class="form-control" rows="3">{{ dok.beschreibung }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2 justify-content-end">
|
||||
<a href="{% url 'stiftung:dms_detail' pk=dok.pk %}" class="btn btn-outline-secondary">Abbrechen</a>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save me-2"></i>Speichern
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Datei-Info (read-only) -->
|
||||
<div class="card shadow mt-4">
|
||||
<div class="card-header bg-light py-2">
|
||||
<span class="small text-muted"><i class="fas fa-file me-2"></i>Datei (nicht änderbar)</span>
|
||||
</div>
|
||||
<div class="card-body py-2">
|
||||
<span class="font-monospace small text-muted">{{ dok.dateiname_original|default:dok.datei.name }}</span>
|
||||
<span class="text-muted small ms-3">{{ dok.get_human_size }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
153
app/templates/stiftung/dms/list.html
Normal file
153
app/templates/stiftung/dms/list.html
Normal file
@@ -0,0 +1,153 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}DMS – Dokumente – Stiftungsverwaltung{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3">
|
||||
<i class="fas fa-folder-open text-primary me-2"></i>
|
||||
Dokumentenverwaltung (DMS)
|
||||
</h1>
|
||||
<a href="{% url 'stiftung:dms_upload' %}" class="btn btn-primary">
|
||||
<i class="fas fa-upload me-2"></i>Dokument hochladen
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Suche & Filter -->
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-body py-2">
|
||||
<form method="get" class="row g-2 align-items-center">
|
||||
<div class="col-md-5">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-text"><i class="fas fa-search"></i></span>
|
||||
<input type="text" name="q" value="{{ q }}" class="form-control"
|
||||
placeholder="Volltextsuche (Titel, Beschreibung, Inhalt)"
|
||||
hx-get="{% url 'stiftung:dms_search_api' %}"
|
||||
hx-target="#search-results"
|
||||
hx-trigger="keyup changed delay:400ms"
|
||||
hx-include="[name='q']">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select name="kontext" class="form-select form-select-sm" onchange="this.form.submit()">
|
||||
<option value="">Alle Typen</option>
|
||||
{% for code, label in kontext_choices %}
|
||||
<option value="{{ code }}" {% if code == kontext_filter %}selected{% endif %}>{{ label }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button type="submit" class="btn btn-sm btn-outline-primary w-100">Suchen</button>
|
||||
</div>
|
||||
{% if q or kontext_filter %}
|
||||
<div class="col-md-2">
|
||||
<a href="{% url 'stiftung:dms_list' %}" class="btn btn-sm btn-outline-secondary w-100">Reset</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- HTMX Live-Suchergebnisse -->
|
||||
<div id="search-results"></div>
|
||||
|
||||
<!-- Dokument-Liste -->
|
||||
<div class="card shadow">
|
||||
<div class="card-header bg-dark text-white py-2 d-flex justify-content-between">
|
||||
<span class="small fw-bold"><i class="fas fa-file me-2"></i>{{ gesamt }} Dokument(e)</span>
|
||||
{% if q %}<span class="small text-warning">Suche: „{{ q }}"</span>{% endif %}
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
{% if page_obj.object_list %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-hover mb-0">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Titel</th>
|
||||
<th>Typ</th>
|
||||
<th>Zuordnung</th>
|
||||
<th>Größe</th>
|
||||
<th>Hochgeladen</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for dok in page_obj %}
|
||||
<tr>
|
||||
<td class="align-middle">
|
||||
<a href="{% url 'stiftung:dms_detail' pk=dok.pk %}" class="text-decoration-none fw-semibold">
|
||||
{% if dok.is_pdf %}<i class="fas fa-file-pdf text-danger me-1"></i>{% else %}<i class="fas fa-file text-muted me-1"></i>{% endif %}
|
||||
{{ dok.titel|truncatechars:60 }}
|
||||
</a>
|
||||
{% if dok.beschreibung %}
|
||||
<div class="small text-muted">{{ dok.beschreibung|truncatechars:80 }}</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<span class="badge bg-secondary small">{{ dok.get_kontext_display }}</span>
|
||||
</td>
|
||||
<td class="align-middle small text-muted">
|
||||
{% if dok.destinataer %}<div><i class="fas fa-user me-1"></i>{{ dok.destinataer.get_full_name }}</div>{% endif %}
|
||||
{% if dok.land %}<div><i class="fas fa-map me-1"></i>{{ dok.land.lfd_nr }}</div>{% endif %}
|
||||
{% if dok.paechter %}<div><i class="fas fa-user-tie me-1"></i>{{ dok.paechter.get_full_name }}</div>{% endif %}
|
||||
</td>
|
||||
<td class="align-middle small text-muted text-nowrap">{{ dok.get_human_size }}</td>
|
||||
<td class="align-middle small text-muted text-nowrap">
|
||||
{{ dok.erstellt_am|date:"d.m.Y" }}
|
||||
{% if dok.erstellt_von %}<br>{{ dok.erstellt_von.get_full_name|default:dok.erstellt_von.username }}{% endif %}
|
||||
</td>
|
||||
<td class="align-middle text-end">
|
||||
<a href="{% url 'stiftung:dms_download' pk=dok.pk %}" class="btn btn-xs btn-outline-success me-1" style="font-size:0.7rem;padding:2px 6px;" title="Herunterladen">
|
||||
<i class="fas fa-download"></i>
|
||||
</a>
|
||||
<a href="{% url 'stiftung:dms_edit' pk=dok.pk %}" class="btn btn-xs btn-outline-secondary me-1" style="font-size:0.7rem;padding:2px 6px;" title="Bearbeiten">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<form method="post" action="{% url 'stiftung:dms_delete' pk=dok.pk %}" class="d-inline" onsubmit="return confirm('Dokument löschen?')">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="next" value="{% url 'stiftung:dms_list' %}">
|
||||
<button type="submit" class="btn btn-xs btn-outline-danger" style="font-size:0.7rem;padding:2px 6px;" title="Löschen">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- Pagination -->
|
||||
{% if page_obj.has_other_pages %}
|
||||
<div class="d-flex justify-content-center py-3">
|
||||
<nav>
|
||||
<ul class="pagination pagination-sm mb-0">
|
||||
{% if page_obj.has_previous %}
|
||||
<li class="page-item"><a class="page-link" href="?page={{ page_obj.previous_page_number }}&q={{ q }}&kontext={{ kontext_filter }}">‹</a></li>
|
||||
{% endif %}
|
||||
<li class="page-item active"><a class="page-link">{{ page_obj.number }}/{{ page_obj.paginator.num_pages }}</a></li>
|
||||
{% if page_obj.has_next %}
|
||||
<li class="page-item"><a class="page-link" href="?page={{ page_obj.next_page_number }}&q={{ q }}&kontext={{ kontext_filter }}">›</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<div class="text-muted text-center py-5">
|
||||
<i class="fas fa-folder-open fa-3x mb-3 d-block opacity-25"></i>
|
||||
{% if q %}Keine Dokumente für „{{ q }}" gefunden.{% else %}Noch keine Dokumente vorhanden.{% endif %}
|
||||
<div class="mt-3">
|
||||
<a href="{% url 'stiftung:dms_upload' %}" class="btn btn-primary btn-sm">
|
||||
<i class="fas fa-upload me-1"></i>Erstes Dokument hochladen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
39
app/templates/stiftung/dms/partials/search_results.html
Normal file
39
app/templates/stiftung/dms/partials/search_results.html
Normal file
@@ -0,0 +1,39 @@
|
||||
{% if results %}
|
||||
<div class="card shadow mb-4 border-primary">
|
||||
<div class="card-header bg-primary text-white py-2">
|
||||
<span class="small fw-bold">
|
||||
<i class="fas fa-search me-2"></i>Live-Suche: „{{ q }}" – {{ results|length }} Treffer
|
||||
</span>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-hover mb-0">
|
||||
<tbody>
|
||||
{% for dok in results %}
|
||||
<tr>
|
||||
<td class="align-middle">
|
||||
<a href="{% url 'stiftung:dms_detail' pk=dok.pk %}" class="text-decoration-none fw-semibold">
|
||||
{% if dok.is_pdf %}<i class="fas fa-file-pdf text-danger me-1"></i>{% else %}<i class="fas fa-file text-muted me-1"></i>{% endif %}
|
||||
{{ dok.titel|truncatechars:60 }}
|
||||
</a>
|
||||
{% if dok.beschreibung %}
|
||||
<div class="small text-muted">{{ dok.beschreibung|truncatechars:80 }}</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<span class="badge bg-secondary small">{{ dok.get_kontext_display }}</span>
|
||||
</td>
|
||||
<td class="align-middle small text-muted text-nowrap">{{ dok.erstellt_am|date:"d.m.Y" }}</td>
|
||||
<td class="align-middle text-end">
|
||||
<a href="{% url 'stiftung:dms_download' pk=dok.pk %}" class="btn btn-xs btn-outline-success" style="font-size:0.7rem;padding:2px 6px;">
|
||||
<i class="fas fa-download"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
10
app/templates/stiftung/dms/partials/upload_success.html
Normal file
10
app/templates/stiftung/dms/partials/upload_success.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<div class="alert alert-success d-flex align-items-center gap-3 mt-3">
|
||||
<i class="fas fa-check-circle fa-2x"></i>
|
||||
<div>
|
||||
<strong>Erfolgreich hochgeladen!</strong>
|
||||
<div class="small">
|
||||
„{{ dok.titel }}" — {{ dok.get_human_size }}
|
||||
<a href="{% url 'stiftung:dms_detail' pk=dok.pk %}" class="ms-2">Details ansehen</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
164
app/templates/stiftung/dms/upload.html
Normal file
164
app/templates/stiftung/dms/upload.html
Normal file
@@ -0,0 +1,164 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}Dokument hochladen – Stiftungsverwaltung{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3">
|
||||
<i class="fas fa-upload text-primary me-2"></i>
|
||||
Dokument hochladen
|
||||
</h1>
|
||||
<a href="{% url 'stiftung:dms_list' %}" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-arrow-left me-2"></i>Zurück
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<form method="post" enctype="multipart/form-data" id="upload-form">
|
||||
{% csrf_token %}
|
||||
|
||||
<!-- Drag & Drop Zone -->
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-body">
|
||||
<div id="drop-zone"
|
||||
class="border border-2 border-dashed rounded p-5 text-center"
|
||||
style="border-color: #ccc !important; cursor: pointer; transition: all 0.2s;"
|
||||
onclick="document.getElementById('datei-input').click()">
|
||||
<i class="fas fa-cloud-upload-alt fa-3x text-muted mb-3 d-block"></i>
|
||||
<p class="mb-1 fw-semibold">Datei hierher ziehen oder klicken zum Auswählen</p>
|
||||
<p class="small text-muted mb-0">PDF, Word, Excel, Bilder — max. 50 MB</p>
|
||||
<div id="file-preview" class="mt-3 d-none">
|
||||
<span class="badge bg-success fs-6 px-3 py-2">
|
||||
<i class="fas fa-file me-2"></i><span id="file-name"></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="file" name="datei" id="datei-input" class="d-none" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Metadaten -->
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-header bg-dark text-white py-2">
|
||||
<span class="small fw-bold"><i class="fas fa-tag me-2"></i>Metadaten</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold">Titel</label>
|
||||
<input type="text" name="titel" class="form-control"
|
||||
placeholder="Wird automatisch aus Dateiname abgeleitet wenn leer">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold">Typ / Kontext</label>
|
||||
<select name="kontext" class="form-select">
|
||||
{% for code, label in kontext_choices %}
|
||||
<option value="{{ code }}" {% if code == initial.kontext %}selected{% endif %}>{{ label }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold">Beschreibung <span class="text-muted fw-normal">(optional)</span></label>
|
||||
<textarea name="beschreibung" class="form-control" rows="2"
|
||||
placeholder="Kurze Beschreibung des Dokuments"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Zuordnung -->
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-header bg-dark text-white py-2">
|
||||
<span class="small fw-bold"><i class="fas fa-link me-2"></i>Zuordnung <span class="fw-normal opacity-75">(optional)</span></span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small fw-semibold">Destinatär</label>
|
||||
<select name="destinataer_id" class="form-select form-select-sm">
|
||||
<option value="">– keine –</option>
|
||||
{% for d in destinataere %}
|
||||
<option value="{{ d.pk }}" {% if d.pk|stringformat:'s' == initial.destinataer_id %}selected{% endif %}>
|
||||
{{ d.get_full_name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small fw-semibold">Länderei</label>
|
||||
<select name="land_id" class="form-select form-select-sm">
|
||||
<option value="">– keine –</option>
|
||||
{% for l in laendereien %}
|
||||
<option value="{{ l.pk }}" {% if l.pk|stringformat:'s' == initial.land_id %}selected{% endif %}>
|
||||
{{ l.lfd_nr }}{% if l.gemeinde %} – {{ l.gemeinde }}{% endif %}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small fw-semibold">Pächter</label>
|
||||
<select name="paechter_id" class="form-select form-select-sm">
|
||||
<option value="">– keine –</option>
|
||||
{% for p in paechter_qs %}
|
||||
<option value="{{ p.pk }}" {% if p.pk|stringformat:'s' == initial.paechter_id %}selected{% endif %}>
|
||||
{{ p.get_full_name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2 justify-content-end">
|
||||
<a href="{% url 'stiftung:dms_list' %}" class="btn btn-outline-secondary">Abbrechen</a>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-upload me-2"></i>Hochladen
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
const dropZone = document.getElementById('drop-zone');
|
||||
const fileInput = document.getElementById('datei-input');
|
||||
const filePreview = document.getElementById('file-preview');
|
||||
const fileName = document.getElementById('file-name');
|
||||
|
||||
function showFile(file) {
|
||||
fileName.textContent = file.name;
|
||||
filePreview.classList.remove('d-none');
|
||||
dropZone.style.borderColor = '#198754 !important';
|
||||
dropZone.classList.add('border-success');
|
||||
}
|
||||
|
||||
fileInput.addEventListener('change', function () {
|
||||
if (this.files[0]) showFile(this.files[0]);
|
||||
});
|
||||
|
||||
dropZone.addEventListener('dragover', function (e) {
|
||||
e.preventDefault();
|
||||
this.style.backgroundColor = '#f0f7ff';
|
||||
this.style.borderColor = '#0d6efd';
|
||||
});
|
||||
|
||||
dropZone.addEventListener('dragleave', function () {
|
||||
this.style.backgroundColor = '';
|
||||
this.style.borderColor = '#ccc';
|
||||
});
|
||||
|
||||
dropZone.addEventListener('drop', function (e) {
|
||||
e.preventDefault();
|
||||
this.style.backgroundColor = '';
|
||||
this.style.borderColor = '#ccc';
|
||||
const files = e.dataTransfer.files;
|
||||
if (files.length > 0) {
|
||||
fileInput.files = files;
|
||||
showFile(files[0]);
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user