feat: Ordnerstruktur, Medienupload und erweiterten Editor ergänzen

- NetBox-4.6-Verknüpfungsformular korrigieren
- hierarchische Dokumentationsordner hinzufügen
- breite Editoransicht und Fokusmodus implementieren
- sicheren direkten Bild-Upload integrieren
- Ordner über Suche und REST-API bereitstellen
This commit is contained in:
2026-07-22 11:04:10 +02:00
parent da0774b3aa
commit 59598fbd74
19 changed files with 324 additions and 47 deletions
+37
View File
@@ -15,6 +15,7 @@ class Document(NetBoxModel):
body_format = models.CharField(max_length=10, choices=BODY_FORMAT_CHOICES, default="html")
summary = models.CharField(max_length=500, blank=True)
is_published = models.BooleanField(default=True)
category = models.ForeignKey("DocumentCategory", on_delete=models.SET_NULL, null=True, blank=True, related_name="documents")
class Meta:
ordering = ("title",)
@@ -56,6 +57,42 @@ class Document(NetBoxModel):
return bleach.clean(value, tags=tags, attributes=attributes, protocols=("http", "https", "mailto"), css_sanitizer=css)
class DocumentCategory(NetBoxModel):
name = models.CharField(max_length=100)
slug = models.SlugField(max_length=100)
parent = models.ForeignKey("self", on_delete=models.CASCADE, null=True, blank=True, related_name="children")
description = models.CharField(max_length=500, blank=True)
class Meta:
ordering = ("name",)
constraints = [models.UniqueConstraint(fields=("parent", "slug"), name="%(app_label)s_%(class)s_unique_parent_slug")]
verbose_name_plural = "document categories"
def __str__(self):
names = [self.name]
parent = self.parent
seen = {self.pk}
while parent and parent.pk not in seen:
names.append(parent.name)
seen.add(parent.pk)
parent = parent.parent
return " / ".join(reversed(names))
def get_absolute_url(self):
return reverse("plugins:netbox_documentation:documentcategory", args=[self.pk])
def clean(self):
super().clean()
from django.core.exceptions import ValidationError
parent = self.parent
seen = {self.pk} if self.pk else set()
while parent:
if parent.pk in seen:
raise ValidationError({"parent": "Ein Ordner kann nicht sich selbst oder einem Unterordner untergeordnet werden."})
seen.add(parent.pk)
parent = parent.parent
class DocumentAssignment(NetBoxModel):
document = models.ForeignKey(Document, on_delete=models.CASCADE, related_name="assignments")
assigned_object_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)