From b0c9b89e94d832e558e1a6a255f040b7f9ebf18e Mon Sep 17 00:00:00 2001 From: "Adrian A. Baumann" Date: Sat, 1 Nov 2025 00:18:29 +0100 Subject: [PATCH] Borders work, collapsing doesn't yet --- admin/css/vorgabe_border.css | 102 +++++++++++++++++++++++++++++++ admin/js/vorgabe_toggle.js | 25 ++++++++ dokumente/admin.py | 113 ++++++++++++++++++++++++++--------- 3 files changed, 212 insertions(+), 28 deletions(-) create mode 100644 admin/css/vorgabe_border.css create mode 100644 admin/js/vorgabe_toggle.js diff --git a/admin/css/vorgabe_border.css b/admin/css/vorgabe_border.css new file mode 100644 index 0000000..68440be --- /dev/null +++ b/admin/css/vorgabe_border.css @@ -0,0 +1,102 @@ +/* Better visual separation for Vorgaben inlines */ +.inline-group[data-inline-model="vorgabe"] { + border: 2px solid #ddd; + border-radius: 8px; + margin-bottom: 20px; + padding: 15px; + background-color: #f9f9f9; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); +} + +.inline-group[data-inline-model="vorgabe"] .inline-related { + border: 1px solid #ccc; + border-radius: 6px; + margin-bottom: 10px; + background-color: white; + padding: 10px; +} + +.inline-group[data-inline-model="vorgabe"] h3 { + background-color: #007cba; + color: white; + padding: 8px 12px; + margin: -15px -15px 10px -15px; + border-radius: 6px 6px 0 0; + font-weight: bold; +} + +.inline-group[data-inline-model="vorgabe"] .collapse .inline-related { + border-left: 3px solid #007cba; +} + +/* Better spacing for nested inlines */ +.inline-group[data-inline-model="vorgabe"] .inline-group { + margin-top: 10px; +} + +.inline-group[data-inline-model="vorgabe"] .inline-group h3 { + background-color: #f0f8ff; + color: #333; + padding: 6px 10px; + margin: 0 0 8px 0; + border-left: 3px solid #007cba; +} + +/* Highlight active/expanded vorgabe */ +.inline-group[data-inline-model="vorgabe"] .inline-related:not(.collapsed) { + border-color: #007cba; + box-shadow: 0 0 8px rgba(0,124,186,0.2); +} + +/* Highlight actively edited vorgabe */ +.inline-group[data-inline-model="vorgabe"] .inline-related.active-edit { + border-color: #28a745; + box-shadow: 0 0 12px rgba(40,167,69,0.3); + background-color: #f8fff9; +} + +/* Toggle hint styling */ +.toggle-hint { + font-size: 0.8em; + color: #666; + font-weight: normal; +} + +/* Better fieldset styling for vorgabe inlines */ +.inline-group[data-inline-model="vorgabe"] .fieldset { + border: 1px solid #e0e0e0; + border-radius: 4px; + padding: 10px; + margin-bottom: 10px; + background-color: #fafafa; +} + +.inline-group[data-inline-model="vorgabe"] .fieldset h2 { + background-color: #e3f2fd; + color: #1565c0; + padding: 5px 10px; + margin: -10px -10px 10px -10px; + border-radius: 4px 4px 0 0; + font-size: 0.9em; + font-weight: bold; +} + +/* Better form layout */ +.inline-group[data-inline-model="vorgabe"] .form-row { + border-bottom: 1px solid #eee; + padding: 8px 0; +} + +.inline-group[data-inline-model="vorgabe"] .form-row:last-child { + border-bottom: none; +} + +/* Wide fields styling */ +.inline-group[data-inline-model="vorgabe"] .wide .form-row > div { + width: 100%; +} + +.inline-group[data-inline-model="vorgabe"] .wide textarea { + width: 100%; + min-height: 80px; +} \ No newline at end of file diff --git a/admin/js/vorgabe_toggle.js b/admin/js/vorgabe_toggle.js new file mode 100644 index 0000000..b6a4168 --- /dev/null +++ b/admin/js/vorgabe_toggle.js @@ -0,0 +1,25 @@ +(function($) { + 'use strict'; + + $(document).ready(function() { + // Add toggle buttons for each vorgabe inline + $('.inline-group[data-inline-model="vorgabe"]').each(function() { + var $group = $(this); + var $headers = $group.find('h3'); + + $headers.css('cursor', 'pointer').append(' (klicken zum umschalten)'); + + $headers.on('click', function(e) { + e.preventDefault(); + var $inline = $(this).closest('.inline-related'); + $inline.find('.collapse').toggleClass('collapsed'); + }); + }); + + // Highlight active vorgabe when editing + $('.inline-group[data-inline-model="vorgabe"] .inline-related').on('click', function() { + $('.inline-group[data-inline-model="vorgabe"] .inline-related').removeClass('active-edit'); + $(this).addClass('active-edit'); + }); + }); +})(django.jQuery); \ No newline at end of file diff --git a/dokumente/admin.py b/dokumente/admin.py index 3fb238a..81f5928 100644 --- a/dokumente/admin.py +++ b/dokumente/admin.py @@ -21,45 +21,75 @@ from referenzen.models import Referenz # 'frage': forms.Textarea(attrs={'rows': 1, 'cols': 100}), # } -class ChecklistenfragenInline(NestedTabularInline): +class ChecklistenfragenInline(NestedStackedInline): model=Checklistenfrage extra=0 fk_name="vorgabe" -# form=ChecklistenForm classes = ['collapse'] + verbose_name_plural = "Checklistenfragen" + fieldsets = ( + (None, { + 'fields': ('frage',), + 'classes': ('wide',), + }), + ) -class VorgabeKurztextInline(NestedTabularInline): +class VorgabeKurztextInline(NestedStackedInline): model=VorgabeKurztext extra=0 sortable_field_name = "order" show_change_link=True classes = ['collapse'] - #inline=inhalt + verbose_name_plural = "Kurztext-Abschnitte" + fieldsets = ( + (None, { + 'fields': ('abschnitttyp', 'inhalt', 'order'), + 'classes': ('wide',), + }), + ) -class VorgabeLangtextInline(NestedTabularInline): +class VorgabeLangtextInline(NestedStackedInline): model=VorgabeLangtext extra=0 sortable_field_name = "order" show_change_link=True classes = ['collapse'] - #inline=inhalt + verbose_name_plural = "Langtext-Abschnitte" + fieldsets = ( + (None, { + 'fields': ('abschnitttyp', 'inhalt', 'order'), + 'classes': ('wide',), + }), + ) -class GeltungsbereichInline(NestedTabularInline): +class GeltungsbereichInline(NestedStackedInline): model=Geltungsbereich extra=0 sortable_field_name = "order" show_change_link=True classes = ['collapse'] - classes = ['collapse'] - #inline=inhalt + verbose_name_plural = "Geltungsbereich-Abschnitte" + fieldsets = ( + (None, { + 'fields': ('abschnitttyp', 'inhalt', 'order'), + 'classes': ('wide',), + }), + ) -class EinleitungInline(NestedTabularInline): - model = Einleitung - extra = 0 - sortable_field_name = "order" - show_change_link = True - classes = ['collapse'] +class EinleitungInline(NestedStackedInline): + model = Einleitung + extra = 0 + sortable_field_name = "order" + show_change_link = True + classes = ['collapse'] + verbose_name_plural = "Einleitungs-Abschnitte" + fieldsets = ( + (None, { + 'fields': ('abschnitttyp', 'inhalt', 'order'), + 'classes': ('wide',), + }), + ) class VorgabeForm(forms.ModelForm): referenzen = TreeNodeMultipleChoiceField(queryset=Referenz.objects.all(), required=False) @@ -67,17 +97,30 @@ class VorgabeForm(forms.ModelForm): model = Vorgabe fields = '__all__' -class VorgabeInline(SortableInlineAdminMixin, NestedTabularInline): # or StackedInline for more vertical layout +class VorgabeInline(SortableInlineAdminMixin, NestedStackedInline): # Changed to StackedInline for better box separation model = Vorgabe form = VorgabeForm extra = 0 sortable_field_name = "order" # Add this - make sure your Vorgabe model has an 'order' field - #show_change_link = True - inlines = [VorgabeKurztextInline,VorgabeLangtextInline,ChecklistenfragenInline] + show_change_link = True + inlines = [VorgabeKurztextInline, VorgabeLangtextInline, ChecklistenfragenInline] autocomplete_fields = ['stichworte','referenzen','relevanz'] - #search_fields=['nummer','name']ModelAdmin. - list_filter=['stichworte'] - #classes=["collapse"] + classes = ["collapse"] # Start collapsed for better overview + + fieldsets = ( + ('Grunddaten', { + 'fields': ('order', 'nummer', 'thema', 'titel'), + 'classes': ('wide',), + }), + ('Gültigkeit', { + 'fields': ('gueltigkeit_von', 'gueltigkeit_bis'), + 'classes': ('wide', 'collapse'), + }), + ('Verknüpfungen', { + 'fields': ('referenzen', 'stichworte', 'relevanz'), + 'classes': ('wide', 'collapse'), + }), + ) class StichworterklaerungInline(NestedTabularInline): model=Stichworterklaerung @@ -104,16 +147,30 @@ class PersonAdmin(admin.ModelAdmin): @admin.register(Dokument) class DokumentAdmin(SortableAdminBase, NestedModelAdmin): actions_on_top=True - inlines = [EinleitungInline,GeltungsbereichInline,VorgabeInline] - #filter_horizontal=['autoren','pruefende'] - list_display=['nummer','name','dokumententyp'] + inlines = [EinleitungInline, GeltungsbereichInline, VorgabeInline] + filter_horizontal=['autoren','pruefende'] + list_display=['nummer','name','dokumententyp','gueltigkeit_von','gueltigkeit_bis','aktiv'] search_fields=['nummer','name'] + list_filter=['dokumententyp','aktiv','gueltigkeit_von'] + + fieldsets = ( + ('Grunddaten', { + 'fields': ('nummer', 'name', 'dokumententyp', 'aktiv') + }), + ('Verantwortlichkeiten', { + 'fields': ('autoren', 'pruefende'), + 'classes': ('collapse',), + }), + ('Gültigkeit & Metadaten', { + 'fields': ('gueltigkeit_von', 'gueltigkeit_bis', 'signatur_cso', 'anhaenge'), + 'classes': ('collapse',), + }), + ) + class Media: -# js = ('admin/js/vorgabe_collapse.js',) + js = ('admin/js/vorgabe_toggle.js',) css = { - 'all': ('admin/css/vorgabe_border.css', -# 'admin/css/vorgabe_collapse.css', - ) + 'all': ('admin/css/vorgabe_border.css',) }