Compare commits

..

2 Commits

Author SHA1 Message Date
7e4d2fa29b Changed edge case in date validation for Vorgaben 2025-11-03 13:21:47 +01:00
d14d9eba4c Deploy 940 2025-11-01 01:29:13 +01:00
7 changed files with 48 additions and 270 deletions

View File

@@ -1,102 +0,0 @@
/* 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;
}

View File

@@ -1,25 +0,0 @@
(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(' <span class="toggle-hint">(klicken zum umschalten)</span>');
$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);

View File

@@ -25,7 +25,7 @@ spec:
mountPath: /data mountPath: /data
containers: containers:
- name: web - name: web
image: git.baumann.gr/adebaumann/vui:0.939 image: git.baumann.gr/adebaumann/vui:0.940
imagePullPolicy: Always imagePullPolicy: Always
ports: ports:
- containerPort: 8000 - containerPort: 8000

View File

@@ -21,75 +21,45 @@ from referenzen.models import Referenz
# 'frage': forms.Textarea(attrs={'rows': 1, 'cols': 100}), # 'frage': forms.Textarea(attrs={'rows': 1, 'cols': 100}),
# } # }
class ChecklistenfragenInline(NestedStackedInline): class ChecklistenfragenInline(NestedTabularInline):
model=Checklistenfrage model=Checklistenfrage
extra=0 extra=0
fk_name="vorgabe" fk_name="vorgabe"
# form=ChecklistenForm
classes = ['collapse'] classes = ['collapse']
verbose_name_plural = "Checklistenfragen"
fieldsets = (
(None, {
'fields': ('frage',),
'classes': ('wide',),
}),
)
class VorgabeKurztextInline(NestedStackedInline): class VorgabeKurztextInline(NestedTabularInline):
model=VorgabeKurztext model=VorgabeKurztext
extra=0 extra=0
sortable_field_name = "order" sortable_field_name = "order"
show_change_link=True show_change_link=True
classes = ['collapse'] classes = ['collapse']
verbose_name_plural = "Kurztext-Abschnitte" #inline=inhalt
fieldsets = (
(None, {
'fields': ('abschnitttyp', 'inhalt', 'order'),
'classes': ('wide',),
}),
)
class VorgabeLangtextInline(NestedStackedInline): class VorgabeLangtextInline(NestedTabularInline):
model=VorgabeLangtext model=VorgabeLangtext
extra=0 extra=0
sortable_field_name = "order" sortable_field_name = "order"
show_change_link=True show_change_link=True
classes = ['collapse'] classes = ['collapse']
verbose_name_plural = "Langtext-Abschnitte" #inline=inhalt
fieldsets = (
(None, {
'fields': ('abschnitttyp', 'inhalt', 'order'),
'classes': ('wide',),
}),
)
class GeltungsbereichInline(NestedStackedInline): class GeltungsbereichInline(NestedTabularInline):
model=Geltungsbereich model=Geltungsbereich
extra=0 extra=0
sortable_field_name = "order" sortable_field_name = "order"
show_change_link=True show_change_link=True
classes = ['collapse'] classes = ['collapse']
verbose_name_plural = "Geltungsbereich-Abschnitte"
fieldsets = (
(None, {
'fields': ('abschnitttyp', 'inhalt', 'order'),
'classes': ('wide',),
}),
)
class EinleitungInline(NestedStackedInline):
model = Einleitung
extra = 0
sortable_field_name = "order"
show_change_link = True
classes = ['collapse'] classes = ['collapse']
verbose_name_plural = "Einleitungs-Abschnitte" #inline=inhalt
fieldsets = (
(None, { class EinleitungInline(NestedTabularInline):
'fields': ('abschnitttyp', 'inhalt', 'order'), model = Einleitung
'classes': ('wide',), extra = 0
}), sortable_field_name = "order"
) show_change_link = True
classes = ['collapse']
class VorgabeForm(forms.ModelForm): class VorgabeForm(forms.ModelForm):
referenzen = TreeNodeMultipleChoiceField(queryset=Referenz.objects.all(), required=False) referenzen = TreeNodeMultipleChoiceField(queryset=Referenz.objects.all(), required=False)
@@ -97,31 +67,17 @@ class VorgabeForm(forms.ModelForm):
model = Vorgabe model = Vorgabe
fields = '__all__' fields = '__all__'
class VorgabeInline(SortableInlineAdminMixin, NestedStackedInline): class VorgabeInline(SortableInlineAdminMixin, NestedTabularInline): # or StackedInline for more vertical layout
model = Vorgabe model = Vorgabe
form = VorgabeForm form = VorgabeForm
extra = 0 extra = 0
sortable_field_name = "order" sortable_field_name = "order" # Add this - make sure your Vorgabe model has an 'order' field
show_change_link = False #show_change_link = True
can_delete = False inlines = [VorgabeKurztextInline,VorgabeLangtextInline,ChecklistenfragenInline]
inlines = [VorgabeKurztextInline, VorgabeLangtextInline, ChecklistenfragenInline]
autocomplete_fields = ['stichworte','referenzen','relevanz'] autocomplete_fields = ['stichworte','referenzen','relevanz']
# Remove collapse class so Vorgaben show by default #search_fields=['nummer','name']ModelAdmin.
list_filter=['stichworte']
fieldsets = ( #classes=["collapse"]
('Grunddaten', {
'fields': (('order', 'nummer'), ('thema', 'titel')),
'classes': ('wide',),
}),
('Gültigkeit', {
'fields': (('gueltigkeit_von', 'gueltigkeit_bis'),),
'classes': ('wide',),
}),
('Verknüpfungen', {
'fields': (('referenzen', 'stichworte', 'relevanz'),),
'classes': ('wide',),
}),
)
class StichworterklaerungInline(NestedTabularInline): class StichworterklaerungInline(NestedTabularInline):
model=Stichworterklaerung model=Stichworterklaerung
@@ -148,31 +104,16 @@ class PersonAdmin(admin.ModelAdmin):
@admin.register(Dokument) @admin.register(Dokument)
class DokumentAdmin(SortableAdminBase, NestedModelAdmin): class DokumentAdmin(SortableAdminBase, NestedModelAdmin):
actions_on_top=True actions_on_top=True
inlines = [EinleitungInline, GeltungsbereichInline, VorgabeInline] inlines = [EinleitungInline,GeltungsbereichInline,VorgabeInline]
filter_horizontal=['autoren','pruefende'] #filter_horizontal=['autoren','pruefende']
list_display=['nummer','name','dokumententyp','gueltigkeit_von','gueltigkeit_bis','aktiv'] list_display=['nummer','name','dokumententyp']
search_fields=['nummer','name'] search_fields=['nummer','name']
list_filter=['dokumententyp','aktiv','gueltigkeit_von']
fieldsets = (
('Grunddaten', {
'fields': ('nummer', 'name', 'dokumententyp', 'aktiv'),
'classes': ('wide',),
}),
('Verantwortlichkeiten', {
'fields': ('autoren', 'pruefende'),
'classes': ('wide', 'collapse'),
}),
('Gültigkeit & Metadaten', {
'fields': ('gueltigkeit_von', 'gueltigkeit_bis', 'signatur_cso', 'anhaenge'),
'classes': ('wide', 'collapse'),
}),
)
class Media: class Media:
js = ('admin/js/vorgabe_collapse.js',) # js = ('admin/js/vorgabe_collapse.js',)
css = { css = {
'all': ('admin/css/vorgabe_border.css',) 'all': ('admin/css/vorgabe_border.css',
# 'admin/css/vorgabe_collapse.css',
)
} }

View File

@@ -78,7 +78,7 @@ class Vorgabe(models.Model):
if not self.gueltigkeit_bis: if not self.gueltigkeit_bis:
return "active" return "active"
if self.gueltigkeit_bis > check_date: if self.gueltigkeit_bis >= check_date:
return "active" return "active"
return "expired" if not verbose else "Ist seit dem "+self.gueltigkeit_bis.strftime('%d.%m.%Y')+" nicht mehr in Kraft." return "expired" if not verbose else "Ist seit dem "+self.gueltigkeit_bis.strftime('%d.%m.%Y')+" nicht mehr in Kraft."

View File

@@ -5,6 +5,7 @@
border-radius: 8px; border-radius: 8px;
padding: 15px; padding: 15px;
margin-bottom: 50px; margin-bottom: 50px;
background-color: #f9f9f9;
box-shadow: 0 2px 5px rgba(0,0,0,0.1); box-shadow: 0 2px 5px rgba(0,0,0,0.1);
} }
@@ -37,4 +38,4 @@ tbody.djn-dynamic-form-dokumente-vorgabe td.original p {
margin-top: 10px; margin-top: 10px;
padding-left: 10px; padding-left: 10px;
border-left: 2px dashed #ccc; border-left: 2px dashed #ccc;
} }

View File

@@ -1,58 +1,21 @@
window.addEventListener('load', function () { window.addEventListener('load', function () {
setTimeout(() => { setTimeout(() => {
// Try different selectors for nested admin vorgabe elements const vorgabenBlocks = document.querySelectorAll('.djn-dynamic-form-Standards-vorgabe');
const selectors = [ console.log("Found", vorgabenBlocks.length, "Vorgaben blocks");
'.djn-dynamic-form-dokumente-vorgabe',
'.djn-dynamic-form-Standards-vorgabe',
'.inline-related[data-inline-type="stacked"]',
'.nested-inline'
];
let vorgabenBlocks = [];
for (const selector of selectors) {
vorgabenBlocks = document.querySelectorAll(selector);
if (vorgabenBlocks.length > 0) {
console.log("Found", vorgabenBlocks.length, "Vorgaben blocks with selector:", selector);
break;
}
}
if (vorgabenBlocks.length === 0) {
console.log("No Vorgaben blocks found, trying fallback...");
// Fallback: look for any inline with vorgabe in the class
vorgabenBlocks = document.querySelectorAll('[class*="vorgabe"]');
}
vorgabenBlocks.forEach((block, index) => { vorgabenBlocks.forEach((block, index) => {
// Find the existing title/header within the vorgabe block const header = document.createElement('div');
const existingHeader = block.querySelector('h3, .inline-label, .module h2, .djn-inline-header'); header.className = 'vorgabe-toggle-header';
header.innerHTML = `▼ Vorgabe ${index + 1}`;
if (existingHeader) { header.style.cursor = 'pointer';
// Make the existing header clickable for collapse/expand
existingHeader.style.cursor = 'pointer'; block.parentNode.insertBefore(header, block);
existingHeader.addEventListener('click', (e) => {
e.preventDefault(); header.addEventListener('click', () => {
e.stopPropagation(); const isHidden = block.style.display === 'none';
block.style.display = isHidden ? '' : 'none';
// Find all content to collapse - everything except the header itself header.innerHTML = `${isHidden ? '▼' : '▶'} Vorgabe ${index + 1}`;
const allChildren = Array.from(block.children); });
const contentElements = allChildren.filter(child => child !== existingHeader && !child.contains(existingHeader));
contentElements.forEach(element => {
const isHidden = element.style.display === 'none';
element.style.display = isHidden ? '' : 'none';
});
// Update the header text to show collapse state
const originalText = existingHeader.textContent.replace(/[▼▶]\s*/, '');
const anyHidden = contentElements.some(el => el.style.display === 'none');
existingHeader.innerHTML = `${anyHidden ? '▶' : '▼'} ${originalText}`;
});
// Add initial collapse indicator
const originalText = existingHeader.textContent;
existingHeader.innerHTML = `${originalText}`;
}
}); });
}, 1000); // wait longer to allow nested inlines to render }, 500); // wait 500ms to allow nested inlines to render
}); });