From 6e655cb0e0fdf0d52681d12ee96e14d11d21fcc8 Mon Sep 17 00:00:00 2001 From: Jason Kelly Date: Sun, 23 May 2021 14:12:00 +0800 Subject: [PATCH] Added new widget to alert if a file is set at larger than 10 MB. - Updated default widget to use template that adds a notification box. - Added JS to add onchange & load events to look at the value in the input and trigger the notification & disable the form submits. --- bookwyrm/models/fields.py | 15 ++++++++ bookwyrm/static/js/bookwyrm.js | 35 +++++++++++++++++++ .../clearable_file_input_with_warning.html | 3 ++ 3 files changed, 53 insertions(+) create mode 100644 bookwyrm/templates/widgets/clearable_file_input_with_warning.html diff --git a/bookwyrm/models/fields.py b/bookwyrm/models/fields.py index 123b3efa..d4d94aa2 100644 --- a/bookwyrm/models/fields.py +++ b/bookwyrm/models/fields.py @@ -9,6 +9,7 @@ from django.contrib.postgres.fields import ArrayField as DjangoArrayField from django.core.exceptions import ValidationError from django.core.files.base import ContentFile from django.db import models +from django.forms import ClearableFileInput, ImageField from django.utils import timezone from django.utils.translation import gettext_lazy as _ from bookwyrm import activitypub @@ -332,6 +333,14 @@ class TagField(ManyToManyField): return items +class ClearableFileInputWithWarning(ClearableFileInput): + template_name = 'widgets/clearable_file_input_with_warning.html' + + +class CustomImageField(ImageField): + widget = ClearableFileInputWithWarning + + def image_serializer(value, alt): """helper for serializing images""" if value and hasattr(value, "url"): @@ -395,6 +404,12 @@ class ImageField(ActivitypubFieldMixin, models.ImageField): image_content = ContentFile(response.content) return [image_name, image_content] + def formfield(self, **kwargs): + return super().formfield(**{ + 'form_class': CustomImageField, + **kwargs, + }) + class DateTimeField(ActivitypubFieldMixin, models.DateTimeField): """activitypub-aware datetime field""" diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index 3659a20e..2c43d738 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -3,6 +3,7 @@ let BookWyrm = new class { constructor() { + this.MAX_FILE_SIZE = 10000000 this.initOnDOMLoaded(); this.initReccuringTasks(); this.initEventListeners(); @@ -32,15 +33,26 @@ let BookWyrm = new class { 'click', this.back) ); + + document.querySelectorAll('input[type="file"]') + .forEach(node => node.addEventListener( + 'change', + this.disableIfTooLarge.bind(this) + )); } /** * Execute code once the DOM is loaded. */ initOnDOMLoaded() { + const bookwyrm = this + window.addEventListener('DOMContentLoaded', function() { document.querySelectorAll('.tab-group') .forEach(tabs => new TabGroup(tabs)); + document.querySelectorAll('input[type="file"]').forEach( + bookwyrm.disableIfTooLarge.bind(bookwyrm) + ) }); } @@ -284,4 +296,27 @@ let BookWyrm = new class { node.classList.remove(classname); } } + + disableIfTooLarge(eventOrElement) { + const { addRemoveClass, MAX_FILE_SIZE } = this + const element = eventOrElement.currentTarget || eventOrElement + + const submits = element.form.querySelectorAll('[type="submit"]') + const warns = element.parentElement.querySelectorAll('.file-too-big') + const isTooBig = element.files && + element.files[0] && + element.files[0].size > MAX_FILE_SIZE + + if (isTooBig) { + submits.forEach(submitter => submitter.disabled = true) + warns.forEach( + sib => addRemoveClass(sib, 'is-hidden', false) + ) + } else { + submits.forEach(submitter => submitter.disabled = false) + warns.forEach( + sib => addRemoveClass(sib, 'is-hidden', true) + ) + } + } } diff --git a/bookwyrm/templates/widgets/clearable_file_input_with_warning.html b/bookwyrm/templates/widgets/clearable_file_input_with_warning.html new file mode 100644 index 00000000..700e22f9 --- /dev/null +++ b/bookwyrm/templates/widgets/clearable_file_input_with_warning.html @@ -0,0 +1,3 @@ +{% load i18n %} +{% include "django/forms/widgets/clearable_file_input.html" %} +