snapshot: preserve handbook, bilingual phase 2, and logo updates

This commit is contained in:
Md Bayazid Bostame
2026-03-24 12:25:43 +01:00
parent 0f285aa2cf
commit 4d3c7bdf6e
26 changed files with 625 additions and 66 deletions

View File

@@ -16,6 +16,7 @@ from django.views.decorators.http import require_POST
from django.views.decorators.csrf import ensure_csrf_cookie
from django.utils import timezone
from django.utils.translation import gettext as _, gettext_lazy
from django.utils.translation import get_language
from .forms import OffboardingRequestForm, OnboardingRequestForm
from .form_builder import (
@@ -124,6 +125,10 @@ def _form_field_labels(form_type: str) -> dict[str, str]:
return {}
def _translate_choice_list(choices):
return [(value, str(label)) for value, label in choices]
def _build_onboarding_layout(form) -> list[dict]:
ordered_names = list(form.fields.keys())
group_by_field = {}
@@ -209,12 +214,24 @@ def home(request):
)
@login_required
@user_passes_test(_is_staff)
def handbook_page(request):
return render(request, 'workflows/handbook.html')
@login_required
@user_passes_test(_is_staff)
def project_wiki_page(request):
return render(request, 'workflows/project_wiki.html')
@login_required
@user_passes_test(_is_staff)
def developer_handbook_page(request):
return render(request, 'workflows/developer_handbook.html')
@login_required
def requests_dashboard(request):
if request.method == 'POST':
@@ -416,7 +433,7 @@ def onboarding_success(request, request_id: int):
@require_POST
def generate_onboarding_intro_pdf(request, request_id: int):
obj = get_object_or_404(OnboardingRequest, id=request_id)
pdf_path = _generate_onboarding_intro_pdf(obj)
pdf_path = _generate_onboarding_intro_pdf(obj, language_code=get_language())
obj.intro_pdf_path = str(pdf_path)
obj.save(update_fields=['intro_pdf_path'])
messages.success(request, _('Einweisungs- und Übergabeprotokoll wurde erzeugt.'))
@@ -429,7 +446,11 @@ def generate_onboarding_intro_pdf(request, request_id: int):
def generate_onboarding_intro_session_pdf(request, request_id: int):
onboarding = get_object_or_404(OnboardingRequest, id=request_id)
session, _created = OnboardingIntroductionSession.objects.get_or_create(onboarding_request=onboarding)
pdf_path = _generate_onboarding_intro_session_pdf(session, admin_signature_name=_display_user_name(request.user))
pdf_path = _generate_onboarding_intro_session_pdf(
session,
admin_signature_name=_display_user_name(request.user),
language_code=get_language(),
)
session.exported_pdf_path = str(pdf_path)
session.save(update_fields=['exported_pdf_path'])
messages.success(request, _('Einweisungsprotokoll aus Live-Status wurde erzeugt.'))
@@ -441,7 +462,7 @@ def generate_onboarding_intro_session_pdf(request, request_id: int):
def onboarding_intro_session_page(request, request_id: int):
onboarding = get_object_or_404(OnboardingRequest, id=request_id)
session, _created = OnboardingIntroductionSession.objects.get_or_create(onboarding_request=onboarding)
sections = build_intro_sections_for_request(onboarding)
sections = build_intro_sections_for_request(onboarding, language_code=get_language())
if request.method == 'POST':
checked_ids = set(request.POST.getlist('checked_items'))
@@ -576,6 +597,7 @@ def offboarding_success(request, request_id: int):
@login_required
@user_passes_test(_is_staff)
def form_builder_page(request):
language_code = get_language()
form_type = request.GET.get('form_type', 'onboarding')
if form_type not in DEFAULT_FIELD_ORDER:
form_type = 'onboarding'
@@ -600,6 +622,7 @@ def form_builder_page(request):
if action == 'add_option':
category = request.POST.get('category', '').strip()
label = request.POST.get('label', '').strip()
label_en = request.POST.get('label_en', '').strip()
value = request.POST.get('value', '').strip()
if category not in option_categories:
messages.error(request, 'Ungültige Kategorie.')
@@ -612,6 +635,7 @@ def form_builder_page(request):
FormOption.objects.create(
category=category,
label=label,
label_en=label_en,
value=value or label,
sort_order=(next_sort + 1) if next_sort is not None else 0,
is_active=True,
@@ -627,17 +651,31 @@ def form_builder_page(request):
continue
next_label = request.POST.get(f'label_{option.id}', '').strip() or option.label
option.label = next_label
option.label_en = request.POST.get(f'label_en_{option.id}', '').strip()
option.value = request.POST.get(f'value_{option.id}', '').strip() or next_label
option.is_active = request.POST.get(f'active_{option.id}') == 'on'
option.sort_order = pos
try:
option.save(update_fields=['label', 'value', 'is_active', 'sort_order'])
option.save(update_fields=['label', 'label_en', 'value', 'is_active', 'sort_order'])
except IntegrityError:
messages.error(request, f'Doppelte Bezeichnung in Kategorie: {next_label}')
return redirect(f"/admin-tools/form-builder/?form_type={form_type}&option_category={option.category}")
option_category = option.category
messages.success(request, 'Optionen wurden gespeichert.')
elif action == 'save_field_texts':
field_ids = request.POST.getlist('field_ids')
for raw_id in field_ids:
cfg = FormFieldConfig.objects.filter(id=raw_id, form_type=form_type).first()
if not cfg:
continue
cfg.label_override = (request.POST.get(f'label_override_{cfg.id}') or '').strip()
cfg.label_override_en = (request.POST.get(f'label_override_en_{cfg.id}') or '').strip()
cfg.help_text_override = (request.POST.get(f'help_text_override_{cfg.id}') or '').strip()
cfg.help_text_override_en = (request.POST.get(f'help_text_override_en_{cfg.id}') or '').strip()
cfg.save(update_fields=['label_override', 'label_override_en', 'help_text_override', 'help_text_override_en'])
messages.success(request, 'Feldtexte wurden gespeichert.')
return redirect(f"/admin-tools/form-builder/?form_type={form_type}&option_category={option_category}")
default_names = list(DEFAULT_FIELD_ORDER.get(form_type, []))
@@ -676,7 +714,9 @@ def form_builder_page(request):
column_by_key[page_key]['items'].append(
{
'field_name': cfg.field_name,
'label': labels.get(cfg.field_name, cfg.field_name),
'label': cfg.translated_label_override(language_code) or labels.get(cfg.field_name, cfg.field_name),
'label_de': cfg.label_override or labels.get(cfg.field_name, cfg.field_name),
'label_en': cfg.label_override_en,
'is_visible': cfg.is_visible,
'is_required': cfg.is_required,
'locked': cfg.field_name in locked,
@@ -690,7 +730,9 @@ def form_builder_page(request):
'items': [
{
'field_name': cfg.field_name,
'label': labels.get(cfg.field_name, cfg.field_name),
'label': cfg.translated_label_override(language_code) or labels.get(cfg.field_name, cfg.field_name),
'label_de': cfg.label_override or labels.get(cfg.field_name, cfg.field_name),
'label_en': cfg.label_override_en,
'is_visible': cfg.is_visible,
'is_required': cfg.is_required,
'locked': cfg.field_name in locked,
@@ -707,9 +749,10 @@ def form_builder_page(request):
'form_type': form_type,
'columns': columns,
'form_types': [('onboarding', 'Onboarding'), ('offboarding', 'Offboarding')],
'option_categories': FormOption.CATEGORY_CHOICES,
'option_categories': _translate_choice_list(FormOption.CATEGORY_CHOICES),
'selected_option_category': option_category,
'option_items': FormOption.objects.filter(category=option_category).order_by('sort_order', 'label'),
'field_text_items': configs,
},
)
@@ -732,6 +775,7 @@ def intro_builder_page(request):
if action == 'add_item':
section = (request.POST.get('section') or '').strip()
label = (request.POST.get('label') or '').strip()
label_en = (request.POST.get('label_en') or '').strip()
if section not in {k for k, _ in IntroChecklistItem.SECTION_CHOICES}:
messages.error(request, 'Ungültiger Abschnitt.')
return redirect('intro_builder_page')
@@ -744,6 +788,7 @@ def intro_builder_page(request):
IntroChecklistItem.objects.create(
section=section,
label=label,
label_en=label_en,
sort_order=(next_sort + 1) if next_sort is not None else 0,
is_active=True,
condition_operator='always',
@@ -767,6 +812,7 @@ def intro_builder_page(request):
operator = 'always'
item.section = section
item.label = (request.POST.get(f'label_{item.id}') or item.label).strip() or item.label
item.label_en = (request.POST.get(f'label_en_{item.id}') or '').strip()
item.is_active = request.POST.get(f'active_{item.id}') == 'on'
item.condition_field = (request.POST.get(f'field_{item.id}') or '').strip()
item.condition_operator = operator
@@ -776,6 +822,7 @@ def intro_builder_page(request):
update_fields=[
'section',
'label',
'label_en',
'is_active',
'condition_field',
'condition_operator',
@@ -809,8 +856,8 @@ def intro_builder_page(request):
'workflows/intro_builder.html',
{
'items': items,
'section_choices': IntroChecklistItem.SECTION_CHOICES,
'operator_choices': IntroChecklistItem.OPERATOR_CHOICES,
'section_choices': _translate_choice_list(IntroChecklistItem.SECTION_CHOICES),
'operator_choices': _translate_choice_list(IntroChecklistItem.OPERATOR_CHOICES),
'condition_field_choices': condition_field_choices,
},
)