HH/apps/references/forms.py

257 lines
8.3 KiB
Python

"""
References forms - Forms for Reference Section
"""
from django import forms
from django.utils.translation import gettext_lazy as _
from apps.references.models import ReferenceFolder, ReferenceDocument
class ReferenceFolderForm(forms.ModelForm):
"""Form for creating and editing reference folders"""
class Meta:
model = ReferenceFolder
fields = [
'name', 'name_ar',
'description', 'description_ar',
'parent', 'icon', 'color', 'order',
'access_roles', 'is_active'
]
widgets = {
'name': forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('Enter folder name (English)')
}),
'name_ar': forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('Enter folder name (Arabic)')
}),
'description': forms.Textarea(attrs={
'class': 'form-control',
'rows': 3,
'placeholder': _('Enter folder description (English)')
}),
'description_ar': forms.Textarea(attrs={
'class': 'form-control',
'rows': 3,
'placeholder': _('Enter folder description (Arabic)')
}),
'parent': forms.Select(attrs={
'class': 'form-select'
}),
'icon': forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('e.g., fa-folder, fa-file-pdf')
}),
'color': forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('e.g., #007bff')
}),
'order': forms.NumberInput(attrs={
'class': 'form-control',
'min': 0
}),
'access_roles': forms.CheckboxSelectMultiple(),
'is_active': forms.CheckboxInput(attrs={
'class': 'form-check-input'
})
}
def __init__(self, *args, **kwargs):
hospital = kwargs.pop('hospital', None)
super().__init__(*args, **kwargs)
# Filter parent folders by hospital
if hospital:
self.fields['parent'].queryset = ReferenceFolder.objects.filter(
hospital=hospital,
is_deleted=False
)
# Filter access roles
if hospital:
from django.contrib.auth.models import Group
self.fields['access_roles'].queryset = Group.objects.all()
def clean_name(self):
"""Ensure name is provided in at least one language"""
name = self.cleaned_data.get('name', '')
name_ar = self.cleaned_data.get('name_ar', '')
if not name and not name_ar:
raise forms.ValidationError(_('Please provide a name in English or Arabic.'))
return name
class ReferenceDocumentForm(forms.ModelForm):
"""Form for uploading and editing reference documents"""
new_version = forms.BooleanField(
required=False,
label=_('Upload as new version'),
help_text=_('Check this to create a new version of an existing document')
)
class Meta:
model = ReferenceDocument
fields = [
'folder', 'title', 'title_ar',
'file', 'description', 'description_ar',
'access_roles', 'is_published',
'tags'
]
widgets = {
'folder': forms.Select(attrs={
'class': 'form-select'
}),
'title': forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('Enter document title (English)')
}),
'title_ar': forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('Enter document title (Arabic)')
}),
'file': forms.FileInput(attrs={
'class': 'form-control'
}),
'description': forms.Textarea(attrs={
'class': 'form-control',
'rows': 4,
'placeholder': _('Enter document description (English)')
}),
'description_ar': forms.Textarea(attrs={
'class': 'form-control',
'rows': 4,
'placeholder': _('Enter document description (Arabic)')
}),
'access_roles': forms.CheckboxSelectMultiple(),
'is_published': forms.CheckboxInput(attrs={
'class': 'form-check-input'
}),
'tags': forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('e.g., policy, procedure, handbook (comma-separated)')
})
}
def __init__(self, *args, **kwargs):
hospital = kwargs.pop('hospital', None)
folder = kwargs.pop('folder', None)
super().__init__(*args, **kwargs)
# Filter folders by hospital
if hospital:
self.fields['folder'].queryset = ReferenceFolder.objects.filter(
hospital=hospital,
is_active=True,
is_deleted=False
)
# Filter access roles
if hospital:
from django.contrib.auth.models import Group
self.fields['access_roles'].queryset = Group.objects.all()
# Make file required for new documents, optional for updates
if self.instance and self.instance.pk:
self.fields['file'].required = False
else:
self.fields['file'].required = True
# Make folder optional when uploading from within a folder
if folder:
self.fields['folder'].required = False
self.fields['folder'].initial = folder
def clean_title(self):
"""Ensure title is provided in at least one language"""
title = self.cleaned_data.get('title', '')
title_ar = self.cleaned_data.get('title_ar', '')
if not title and not title_ar:
raise forms.ValidationError(_('Please provide a title in English or Arabic.'))
return title
def clean(self):
"""Custom validation for new version creation"""
cleaned_data = super().clean()
new_version = cleaned_data.get('new_version')
file = cleaned_data.get('file')
# If uploading as new version, file is required
if new_version and not file and not (self.instance and self.instance.pk and self.instance.file):
raise forms.ValidationError({
'file': _('File is required when uploading a new version.')
})
return cleaned_data
class ReferenceDocumentSearchForm(forms.Form):
"""Form for searching and filtering documents"""
search = forms.CharField(
required=False,
label=_('Search'),
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('Search by title, description, or tags...')
})
)
folder = forms.ModelChoiceField(
required=False,
label=_('Folder'),
queryset=ReferenceFolder.objects.none(),
widget=forms.Select(attrs={
'class': 'form-select'
})
)
file_type = forms.ChoiceField(
required=False,
label=_('File Type'),
choices=[
('', _('All Types')),
('pdf', 'PDF'),
('doc', 'Word'),
('docx', 'Word'),
('xls', 'Excel'),
('xlsx', 'Excel'),
('ppt', 'PowerPoint'),
('pptx', 'PowerPoint'),
('jpg', 'Image'),
('jpeg', 'Image'),
('png', 'Image'),
('gif', 'Image'),
],
widget=forms.Select(attrs={
'class': 'form-select'
})
)
tags = forms.CharField(
required=False,
label=_('Tags'),
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('Filter by tags...')
})
)
def __init__(self, *args, **kwargs):
hospital = kwargs.pop('hospital', None)
super().__init__(*args, **kwargs)
# Filter folders by hospital
if hospital:
self.fields['folder'].queryset = ReferenceFolder.objects.filter(
hospital=hospital,
is_active=True,
is_deleted=False
)