diff options
-rw-r--r-- | pyblackbird_cc/resources/forms.py | 28 | ||||
-rw-r--r-- | pyblackbird_cc/resources/views.py | 30 | ||||
-rw-r--r-- | pyblackbird_cc/templates/resources/resource_card.html | 2 | ||||
-rw-r--r-- | pyblackbird_cc/templates/resources/resource_detail.html | 3 | ||||
-rw-r--r-- | pyblackbird_cc/templates/resources/update_thumbnails.html | 29 |
5 files changed, 82 insertions, 10 deletions
diff --git a/pyblackbird_cc/resources/forms.py b/pyblackbird_cc/resources/forms.py index 1a5b51a..4b7df38 100644 --- a/pyblackbird_cc/resources/forms.py +++ b/pyblackbird_cc/resources/forms.py @@ -183,7 +183,10 @@ class ResourceUpdateMetadataForm(forms.ModelForm): class ResourceUpdateThumbnailsForm(forms.Form): def __init__(self, *args, **kwargs): - self.resource = kwargs.pop("resource") + try: + self.resource = kwargs.pop("resource") + except KeyError: + pass super().__init__(*args, **kwargs) self.helper = FormHelper(self) self.helper.add_input(Submit("submit", "Submit")) @@ -197,11 +200,22 @@ class ResourceUpdateThumbnailsForm(forms.Form): }, ), 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.", + label="Thumbnail files", + help_text="You can provide X number of files here." ) + 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 diff --git a/pyblackbird_cc/resources/views.py b/pyblackbird_cc/resources/views.py index 2feb655..4ce2472 100644 --- a/pyblackbird_cc/resources/views.py +++ b/pyblackbird_cc/resources/views.py @@ -210,6 +210,29 @@ def upload_to_s3(pdf_files, thumbnail_files, snapshotted_pages) -> bool: return False +def upload_thumbnails_to_s3(thumbnail_files) -> bool: + session = boto3.Session() + client = session.client( + "s3", + endpoint_url=settings.AWS_S3_ENDPOINT_URL, + aws_access_key_id=settings.AWS_ACCESS_KEY_ID, + aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY, + region_name=settings.AWS_S3_REGION_NAME, + ) + try: + for f in thumbnail_files: + logger.info(f"Uploading {f.name} to S3") + client.upload_fileobj( + f, + settings.AWS_STORAGE_BUCKET_NAME, + f"thumbnails/{f.name}", + ) + return True + except Exception as e: # Any exceptions generated by boto3 client will be caught here + logger.error(f"Error uploading thumbnail files to S3: {e}") + return False + + def _write_pdf_to_tempdir(f) -> str: temp_dir = tempfile.mkdtemp() file_path = os.path.join(temp_dir, f.name) @@ -376,6 +399,13 @@ def update_resource_thumbnails(request, pk): resource = get_object_or_404(Resource, pk=pk) if request.method == "POST": form = ResourceUpdateThumbnailsForm(request.POST, request.FILES) + if form.is_valid(): + thumbnail_files = form.cleaned_data["thumbnail_files"] + resource.thumbnail_filenames = [f.name for f in thumbnail_files] + if not upload_thumbnails_to_s3(thumbnail_files): + raise Exception("Error uploading files to S3") + resource.save() + return redirect("resources:resource_detail", resource_id=resource.id) else: form = ResourceUpdateThumbnailsForm(resource=pk) diff --git a/pyblackbird_cc/templates/resources/resource_card.html b/pyblackbird_cc/templates/resources/resource_card.html index 67807cc..687438c 100644 --- a/pyblackbird_cc/templates/resources/resource_card.html +++ b/pyblackbird_cc/templates/resources/resource_card.html @@ -37,6 +37,8 @@ <div class="card-footer"> <a href="{% url 'resources:resource_update_metadata' resource.id %}" class="btn btn-outline-primary btn-sm">Edit</a> + <a href="{% url 'resources:resource_update_thumbnails' resource.id %}" + class="btn btn-outline-primary btn-sm">Edit Feature Images</a> </div> {% endif %} </div>
\ No newline at end of file diff --git a/pyblackbird_cc/templates/resources/resource_detail.html b/pyblackbird_cc/templates/resources/resource_detail.html index f520340..4a513af 100644 --- a/pyblackbird_cc/templates/resources/resource_detail.html +++ b/pyblackbird_cc/templates/resources/resource_detail.html @@ -34,9 +34,6 @@ <div> {% if request.user.is_authenticated %}<a href="#" class="text-danger">Replace the PDFs</a>{% endif %} </div> - <div> - {% if request.user.is_authenticated %}<a href="{% url "resources:resource_update_thumbnails" resource.id %}" class="text-danger">Replace the preview images</a>{% endif %} - </div> </div> </div> </div> diff --git a/pyblackbird_cc/templates/resources/update_thumbnails.html b/pyblackbird_cc/templates/resources/update_thumbnails.html new file mode 100644 index 0000000..e473a00 --- /dev/null +++ b/pyblackbird_cc/templates/resources/update_thumbnails.html @@ -0,0 +1,29 @@ +{% extends "base.html" %} +{% load static %} +{% load crispy_forms_tags %} + +{% block content %} + <div class="row d-flex justify-content-center"> + <div class="col bg-light mt-lg-4 p-4 border border-success border-opacity-25 rounded"> + <h1>Update feature images for <strong>{{ resource.name }}</strong> resource</h1> + + <p>The current thumbnails for this resource are:</p> + + <ul> + {% for t in resource.thumbnail_filenames %} + <li><em>{{ t }}</em></li> + {% endfor %} + </ul> + + <form action="{% url "resources:resource_update_thumbnails" resource.id %}" + method="post" enctype="multipart/form-data"> + {% csrf_token %} + {% crispy form form.helper %} + </form> + + <button class="btn btn-danger" onclick="location.href='{{ resource.get_absolute_url }}';">Cancel</button> + </div> + </div> + + +{% endblock %} |