import json from django import forms from claims.models import Category, Claim, ClaimDraft class AssistantInputForm(forms.Form): article_url = forms.URLField( label='Artikel-Link', required=False, widget=forms.URLInput(attrs={ 'class': 'form-control', 'placeholder': 'https://beispiel.de/artikel', }), ) user_notes = forms.CharField( label='Beschreibung / Behauptung', required=False, widget=forms.Textarea(attrs={ 'class': 'form-control', 'rows': 4, 'placeholder': 'Welche Aussage soll überprüft werden? Kontext, Stichpunkte …', }), ) uploaded_file = forms.FileField( label='Bild oder PDF', required=False, widget=forms.ClearableFileInput(attrs={'class': 'form-control', 'accept': '.jpg,.jpeg,.png,.gif,.webp,.svg,.pdf'}), ) def clean(self): cleaned = super().clean() url = cleaned.get('article_url') notes = (cleaned.get('user_notes') or '').strip() uploaded = cleaned.get('uploaded_file') if not url and not notes and not uploaded: raise forms.ValidationError( 'Bitte mindestens einen Artikel-Link, eine Beschreibung oder eine Datei angeben.' ) return cleaned class ReviewDraftForm(forms.ModelForm): tags_text = forms.CharField( label='Schlagwörter', required=False, help_text='Kommagetrennt', widget=forms.TextInput(attrs={'class': 'form-control'}), ) sources_json = forms.CharField( label='Quellen (JSON)', required=False, widget=forms.Textarea(attrs={'class': 'form-control font-monospace', 'rows': 6}), ) counter_arguments_json = forms.CharField( label='Gegenargumente (JSON)', required=False, widget=forms.Textarea(attrs={'class': 'form-control font-monospace', 'rows': 6}), ) category_choice = forms.ModelChoiceField( label='Bestehende Kategorie', queryset=Category.objects.all(), required=False, empty_label='— Neue Kategorie verwenden —', widget=forms.Select(attrs={'class': 'form-select'}), ) class Meta: model = ClaimDraft fields = [ 'title', 'claim_status', 'short_answer', 'detailed_explanation', 'evidence_level', 'new_category_name', 'new_category_description', 'new_category_icon', ] widgets = { 'title': forms.TextInput(attrs={'class': 'form-control'}), 'claim_status': forms.Select(attrs={'class': 'form-select'}), 'short_answer': forms.Textarea(attrs={'class': 'form-control', 'rows': 4}), 'detailed_explanation': forms.Textarea(attrs={'class': 'form-control', 'rows': 6}), 'evidence_level': forms.Select(attrs={'class': 'form-select'}), 'new_category_name': forms.TextInput(attrs={'class': 'form-control'}), 'new_category_description': forms.Textarea(attrs={'class': 'form-control', 'rows': 2}), 'new_category_icon': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'bi-book'}), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) instance = kwargs.get('instance') or getattr(self, 'instance', None) if instance and instance.pk: self.fields['tags_text'].initial = ', '.join(instance.tags or []) self.fields['sources_json'].initial = json.dumps( instance.sources or [], ensure_ascii=False, indent=2 ) self.fields['counter_arguments_json'].initial = json.dumps( instance.counter_arguments or [], ensure_ascii=False, indent=2 ) if instance.category_slug: category = Category.objects.filter(slug=instance.category_slug).first() if category: self.fields['category_choice'].initial = category def clean_tags_text(self): raw = self.cleaned_data.get('tags_text', '') return [part.strip() for part in raw.split(',') if part.strip()] def clean_sources_json(self): raw = (self.cleaned_data.get('sources_json') or '').strip() if not raw: return [] try: data = json.loads(raw) except json.JSONDecodeError as exc: raise forms.ValidationError('Ungültiges JSON für Quellen.') from exc if not isinstance(data, list): raise forms.ValidationError('Quellen müssen eine JSON-Liste sein.') return data def clean_counter_arguments_json(self): raw = (self.cleaned_data.get('counter_arguments_json') or '').strip() if not raw: return [] try: data = json.loads(raw) except json.JSONDecodeError as exc: raise forms.ValidationError('Ungültiges JSON für Gegenargumente.') from exc if not isinstance(data, list): raise forms.ValidationError('Gegenargumente müssen eine JSON-Liste sein.') return data def save(self, commit=True): draft = super().save(commit=False) draft.tags = self.cleaned_data['tags_text'] draft.sources = self.cleaned_data['sources_json'] draft.counter_arguments = self.cleaned_data['counter_arguments_json'] category = self.cleaned_data.get('category_choice') if category: draft.category_slug = category.slug else: draft.category_slug = '' if commit: draft.save() return draft class RefineDraftForm(forms.Form): refinement = forms.CharField( label='Überarbeitungswunsch', widget=forms.Textarea(attrs={ 'class': 'form-control', 'rows': 3, 'placeholder': 'z. B. „Kurzantwort kürzer formulieren“ oder „mehr Quellen hinzufügen“', }), )