Add Geschichte (History) wiki-style feature with reorganized navigation

🆕 NEW FEATURES:
- Wiki-style Geschichte (History) section with rich text editor
- Image upload support for history pages
- Quill.js rich text editor with formatting options
- Slug-based URLs for SEO-friendly history pages
- Image galleries with descriptions and alt-text support

🔧 MODELS:
- GeschichteSeite: Main history pages with rich content
- GeschichteBild: Image attachments for history pages
- Auto-generated slugs, sorting, publishing controls

📝 TEMPLATES:
- geschichte/liste.html: Card-based overview of all history pages
- geschichte/detail.html: Full page view with image gallery
- geschichte/form.html: Rich text editor for creating/editing pages
- geschichte/bild_form.html: Image upload interface

🎨 UI IMPROVEMENTS:
- Reorganized navigation menu into logical groups:
  * Menschen & Finanzen (People & Finance)
  * Immobilien & Land (Real Estate & Land)
  * Verwaltung (Administration)
  * Geschichte (History)
- More compact menu design saving horizontal space
- Better grouping with dropdown headers

🛠️ TECHNICAL:
- Rich text editor with Quill.js integration
- Image upload with validation and optimization
- Permission-based access controls
- Responsive design for all screen sizes
- Proper breadcrumb navigation
- Auto-slug generation from titles
This commit is contained in:
2025-10-02 21:49:12 +02:00
parent 390bf697ee
commit 2961f376c3
10 changed files with 900 additions and 18 deletions

View File

@@ -2856,3 +2856,87 @@ class VierteljahresNachweis(models.Model):
except VierteljahresNachweis.DoesNotExist:
pass
return None
class GeschichteSeite(models.Model):
"""Wiki-style pages for foundation history"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
titel = models.CharField(max_length=200, verbose_name="Titel")
slug = models.SlugField(max_length=200, unique=True, verbose_name="URL-Slug")
inhalt = models.TextField(verbose_name="Inhalt")
# Metadata
erstellt_am = models.DateTimeField(auto_now_add=True, verbose_name="Erstellt am")
aktualisiert_am = models.DateTimeField(auto_now=True, verbose_name="Aktualisiert am")
erstellt_von = models.ForeignKey(
'auth.User',
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='geschichte_seiten_erstellt',
verbose_name="Erstellt von"
)
aktualisiert_von = models.ForeignKey(
'auth.User',
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='geschichte_seiten_aktualisiert',
verbose_name="Aktualisiert von"
)
# Options
ist_veroeffentlicht = models.BooleanField(default=True, verbose_name="Veröffentlicht")
sortierung = models.IntegerField(default=0, verbose_name="Sortierung")
class Meta:
verbose_name = "Geschichte Seite"
verbose_name_plural = "Geschichte Seiten"
ordering = ['sortierung', 'titel']
def __str__(self):
return self.titel
def get_absolute_url(self):
from django.urls import reverse
return reverse('stiftung:geschichte_detail', kwargs={'slug': self.slug})
class GeschichteBild(models.Model):
"""Images for history pages"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
seite = models.ForeignKey(
GeschichteSeite,
on_delete=models.CASCADE,
related_name='bilder',
verbose_name="Geschichte Seite"
)
titel = models.CharField(max_length=200, verbose_name="Bildtitel")
bild = models.ImageField(
upload_to='geschichte/bilder/%Y/%m/',
verbose_name="Bild"
)
beschreibung = models.TextField(blank=True, verbose_name="Beschreibung")
alt_text = models.CharField(max_length=200, blank=True, verbose_name="Alt-Text")
# Metadata
hochgeladen_am = models.DateTimeField(auto_now_add=True, verbose_name="Hochgeladen am")
hochgeladen_von = models.ForeignKey(
'auth.User',
on_delete=models.SET_NULL,
null=True,
blank=True,
verbose_name="Hochgeladen von"
)
sortierung = models.IntegerField(default=0, verbose_name="Sortierung")
class Meta:
verbose_name = "Geschichte Bild"
verbose_name_plural = "Geschichte Bilder"
ordering = ['sortierung', 'titel']
def __str__(self):
return f"{self.titel} ({self.seite.titel})"