aboutsummaryrefslogtreecommitdiffstats
path: root/alphabetlearning/resources/forms.py
diff options
context:
space:
mode:
Diffstat (limited to 'alphabetlearning/resources/forms.py')
-rw-r--r--alphabetlearning/resources/forms.py274
1 files changed, 274 insertions, 0 deletions
diff --git a/alphabetlearning/resources/forms.py b/alphabetlearning/resources/forms.py
new file mode 100644
index 0000000..35632bd
--- /dev/null
+++ b/alphabetlearning/resources/forms.py
@@ -0,0 +1,274 @@
+import logging
+
+import magic
+from crispy_forms.bootstrap import FormActions
+from crispy_forms.helper import FormHelper
+from crispy_forms.layout import Button
+from crispy_forms.layout import Field
+from crispy_forms.layout import Layout
+from crispy_forms.layout import Submit
+from django import forms
+
+from alphabetlearning.resources.models import Resource
+from alphabetlearning.resources.models import ResourceCategory
+from alphabetlearning.resources.models import ResourceSubcategory
+from alphabetlearning.resources.models import ResourceType
+
+from .models import AGE_RANGE_CHOICES
+from .models import CURRICULUM_CHOICES
+
+logger = logging.getLogger(__name__)
+
+ALLOWED_THUMBNAILS = 5
+ALLOWED_PDFS = 20
+
+
+def _create_choices_tuple() -> list[tuple[str, str]]:
+ """Returns a list of tuples containing resource subcategory names."""
+ vals = sorted(ResourceSubcategory.objects.values_list("name", flat=True), key=str)
+ out = tuple((x, x) for x in vals)
+ return out
+
+
+class ResourceCreateForm(forms.Form):
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.helper = FormHelper(self)
+ self.helper.add_input(Submit("submit", "Submit"))
+ self.fields["subcategories"].choices = _create_choices_tuple()
+ pass
+
+ error_css_class = "error"
+ required_css_class = "required"
+
+ name = forms.CharField(
+ max_length=255,
+ help_text="Concisely describe what the resource is, aiming for"
+ " in 35-45 characters. "
+ "eg: 'Fractions KS2 Worksheet and Answers.'",
+ )
+ description = forms.CharField(
+ max_length=5000,
+ widget=forms.Textarea,
+ help_text=" You can (and should) use <strong>Markdown</strong> here. "
+ "This is your opportunity to clearly explain what your resource "
+ "is all "
+ "about! It’s worth remembering that you are using the space to "
+ "communicate to two "
+ "different audiences. Firstly, think about what fellow teachers "
+ "would like "
+ "to know, such as exactly what the resource contains and how it "
+ "could be used in the classroom. Secondly, the words you include "
+ "on this page are also talking to internal and external search "
+ "engines."
+ " External search engines, like Google, show the first 155 characters "
+ "of the resource description, so make sure you take advantage "
+ "of these "
+ "characters by using lots of relevant keywords as part of an "
+ "enticing pitch.",
+ )
+ card_description = forms.CharField(
+ max_length=1000,
+ widget=forms.Textarea,
+ help_text=(
+ "If you enter text here, it will be used in the 'card' description "
+ "box on the home page. Max 1000 characters."
+ ),
+ )
+ resource_type = forms.ModelChoiceField(queryset=ResourceType.objects.all())
+ age_range = forms.ChoiceField(
+ choices=AGE_RANGE_CHOICES,
+ help_text="Try to be accurate in your choice of age range so that your resource "
+ "shows up in the correct searches. (Although we don't have searches yet!)",
+ )
+ curriculum = forms.ChoiceField(
+ choices=CURRICULUM_CHOICES,
+ required=False,
+ )
+ main_resource_category = forms.ModelChoiceField(
+ queryset=ResourceCategory.objects.all(),
+ help_text="Categorise your resource by subject so it shows up in the correct "
+ "searches. It's a good idea to limit the number of subjects you select "
+ "to one or two to make your resource easier to find.",
+ )
+ subcategories = forms.MultipleChoiceField(
+ required=False,
+ )
+
+ pdf_files = forms.FileField(
+ widget=forms.TextInput(
+ attrs={
+ "multiple": True,
+ "type": "File",
+ "required": True,
+ },
+ ),
+ required=False,
+ help_text="You can multi-select up to 20 .pdf files here.",
+ label="PDF files",
+ )
+ thumbnail_files = forms.FileField(
+ widget=forms.TextInput(
+ attrs={
+ "multiple": True,
+ "type": "File",
+ "required": True,
+ },
+ ),
+ required=False,
+ label="Cover images",
+ help_text="Your cover image will be displayed in the search results and as "
+ "the first image on your resource page in the preview function. "
+ "It is important to add an eye catching cover image that gives "
+ "other teachers an idea about what your resource contains. "
+ "You can multi-select up to 5 .png or .jpg files here.",
+ )
+ pdf_files.widget.attrs.update({"class": "file_upload", "accept": ".pdf"})
+ thumbnail_files.widget.attrs.update({"class": "file_upload", "accept": ".png,.jpg"})
+ feature_slot = forms.IntegerField(
+ min_value=1,
+ max_value=3,
+ required=False,
+ help_text=(
+ "Please enter either 1, 2 or 3 here. This will dictate where on the page "
+ "this resource will feature on the main list page."
+ ),
+ )
+
+ def clean_thumbnail_files(self):
+ thumbnail_files = self.files.getlist("thumbnail_files")
+ if not thumbnail_files:
+ raise forms.ValidationError("Please select at least one thumbnail file.")
+ acceptable = ["image/png", "image/jpeg"]
+ for f in thumbnail_files:
+ content_type = magic.from_buffer(f.file.read(), mime=True)
+ f.file.seek(0)
+ if content_type not in acceptable:
+ raise forms.ValidationError("Please select only PNG or JPG files.")
+ if len(thumbnail_files) > ALLOWED_THUMBNAILS:
+ raise forms.ValidationError("Please select up to 5 files.")
+ return thumbnail_files
+
+ def clean_pdf_files(self):
+ pdf_files = self.files.getlist("pdf_files")
+ if not pdf_files:
+ raise forms.ValidationError("Please select at least one PDF file.")
+ acceptable = ["application/pdf"]
+ for f in pdf_files:
+ content_type = magic.from_buffer(f.file.read(), mime=True)
+ f.file.seek(0)
+ if content_type not in acceptable:
+ raise forms.ValidationError("Please select only PDF files.")
+ if len(pdf_files) > ALLOWED_PDFS:
+ raise forms.ValidationError("Please select up to 20 PDF files.")
+ return pdf_files
+
+
+class ResourceUpdateMetadataForm(forms.ModelForm):
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.helper = FormHelper(self)
+ self.helper.add_input(Submit("submit", "Submit"))
+ self.fields["subcategories"].queryset = ResourceSubcategory.objects.all().order_by("name")
+
+ error_css_class = "error"
+ required_css_class = "required"
+
+ class Meta:
+ model = Resource
+ fields = [
+ "name",
+ "description",
+ "card_description",
+ "resource_type",
+ "age_range",
+ "curriculum",
+ "main_resource_category",
+ "subcategories",
+ "feature_slot",
+ ]
+
+
+class ResourceUpdatePDFsForm(forms.Form):
+ def __init__(self, cancel_url: str, *args, **kwargs):
+ try:
+ self.resource = kwargs.pop("resource")
+ except KeyError:
+ pass
+ super().__init__(*args, **kwargs)
+ self.helper = FormHelper(self)
+ self.helper.layout = Layout(
+ Field("pdf_files"),
+ FormActions(
+ Submit("submit", "Submit", css_class="btn btn-primary"),
+ Button("cancel", "Cancel", css_class="btn btn-danger", onclick="location.href=''"),
+ ),
+ )
+
+ pdf_files = forms.FileField(
+ widget=forms.TextInput(
+ attrs={
+ "multiple": True,
+ "type": "File",
+ "required": True,
+ },
+ ),
+ required=False,
+ help_text="You can multi-select up to 20 .pdf files here.",
+ label="PDF files",
+ )
+
+ pdf_files.widget.attrs.update({"class": "file_upload", "accept": ".pdf"})
+
+ def clean_pdf_files(self):
+ pdf_files = self.files.getlist("pdf_files")
+ if not pdf_files:
+ raise forms.ValidationError("Please select at least one PDF file.")
+ acceptable = ["application/pdf"]
+ for f in pdf_files:
+ content_type = magic.from_buffer(f.file.read(), mime=True)
+ f.file.seek(0)
+ if content_type not in acceptable:
+ raise forms.ValidationError("Please select only PDF files.")
+ if len(pdf_files) > ALLOWED_PDFS:
+ raise forms.ValidationError("Please select up to 20 PDF files.")
+ return pdf_files
+
+
+class ResourceUpdateThumbnailsForm(forms.Form):
+ def __init__(self, *args, **kwargs):
+ try:
+ self.resource = kwargs.pop("resource")
+ except KeyError:
+ pass
+ super().__init__(*args, **kwargs)
+ self.helper = FormHelper(self)
+ self.helper.add_input(Submit("submit", "Submit"))
+
+ thumbnail_files = forms.FileField(
+ widget=forms.TextInput(
+ attrs={
+ "multiple": True,
+ "type": "File",
+ "required": True,
+ },
+ ),
+ required=False,
+ label="Thumbnail files",
+ help_text="You can upload 5 files.",
+ )
+ thumbnail_files.widget.attrs.update({"class": "file_upload", "accept": ".png,.jpg"})
+
+ def clean_thumbnail_files(self):
+ thumbnail_files = self.files.getlist("thumbnail_files")
+ if not thumbnail_files:
+ raise forms.ValidationError("Please select at least one thumbnail file.")
+ acceptable = ["image/png", "image/jpeg"]
+ for f in thumbnail_files:
+ content_type = magic.from_buffer(f.file.read(), mime=True)
+ f.file.seek(0)
+ if content_type not in acceptable:
+ raise forms.ValidationError("Please select only PNG or JPG files.")
+ if len(thumbnail_files) > ALLOWED_THUMBNAILS:
+ raise forms.ValidationError("Please select up to 5 files.")
+ return thumbnail_files