diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8acb93ca0..a81258e7e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,13 @@ jobs: django-4.0.txt, django-4.1.txt, django-4.2.txt, + django-5.0.txt, ] + exclude: + - requirements-file: django-5.0.txt + python-version: 3.8 + - requirements-file: django-5.0.txt + python-version: 3.9 os: [ ubuntu-20.04, ] diff --git a/filer/admin/clipboardadmin.py b/filer/admin/clipboardadmin.py index d9e64f21c..b09beb4be 100644 --- a/filer/admin/clipboardadmin.py +++ b/filer/admin/clipboardadmin.py @@ -31,7 +31,6 @@ class ClipboardItemInline(admin.TabularInline): class ClipboardAdmin(admin.ModelAdmin): model = Clipboard inlines = [ClipboardItemInline] - filter_horizontal = ('files',) raw_id_fields = ('user',) verbose_name = "DEBUG Clipboard" verbose_name_plural = "DEBUG Clipboards" diff --git a/filer/admin/folderadmin.py b/filer/admin/folderadmin.py index e132a9bec..203674b55 100644 --- a/filer/admin/folderadmin.py +++ b/filer/admin/folderadmin.py @@ -1288,7 +1288,6 @@ def resize_images(self, request, files_queryset, folders_queryset): "breadcrumbs_action": _("Resize images"), "to_resize": to_resize, "resize_form": form, - "cmsplugin_enabled": 'cmsplugin_filer_image' in django_settings.INSTALLED_APPS, "files_queryset": files_queryset, "folders_queryset": folders_queryset, "perms_lacking": perms_needed, diff --git a/filer/admin/forms.py b/filer/admin/forms.py index 02f6ae417..1a35e4125 100644 --- a/filer/admin/forms.py +++ b/filer/admin/forms.py @@ -1,6 +1,6 @@ from django import forms -from django.conf import settings from django.contrib.admin import widgets +from django.contrib.admin.helpers import AdminForm from django.core.exceptions import ValidationError from django.db import models from django.utils.translation import gettext as _ @@ -9,18 +9,18 @@ from ..utils.files import get_valid_filename -class AsPWithHelpMixin: - def as_p_with_help(self): - "Returns this form rendered as HTML
s with help text formated for admin." - return self._html_output( - normal_row='
%(label)s %(field)s
%(help_text)s', - error_row='%s', - row_ender='', - help_text_html='%s
', - errors_on_separate_row=True) +class WithFieldsetMixin: + def get_fieldsets(self): + return getattr(self, "fieldsets", [ + (None, {"fields": [field for field in self.fields]}) + ]) + def admin_form(self): + "Returns a class contains the Admin fieldset to show form as admin form" + return AdminForm(self, self.get_fieldsets(), {}) -class CopyFilesAndFoldersForm(forms.Form, AsPWithHelpMixin): + +class CopyFilesAndFoldersForm(forms.Form): suffix = forms.CharField(required=False, help_text=_("Suffix which will be appended to filenames of copied files.")) # TODO: We have to find a way to overwrite files with different storage backends first. # overwrite_files = forms.BooleanField(required=False, help_text=_("Overwrite a file if there already exists a file with the same filename?")) @@ -32,7 +32,7 @@ def clean_suffix(self): return self.cleaned_data['suffix'] -class RenameFilesForm(forms.Form, AsPWithHelpMixin): +class RenameFilesForm(WithFieldsetMixin, forms.Form): rename_format = forms.CharField(required=True) def clean_rename_format(self): @@ -55,15 +55,20 @@ def clean_rename_format(self): return self.cleaned_data['rename_format'] -class ResizeImagesForm(forms.Form, AsPWithHelpMixin): - if 'cmsplugin_filer_image' in settings.INSTALLED_APPS: - thumbnail_option = models.ForeignKey( - ThumbnailOption, - null=True, - blank=True, - verbose_name=_("thumbnail option"), - on_delete=models.CASCADE, - ).formfield() +class ResizeImagesForm(WithFieldsetMixin, forms.Form): + fieldsets = ((None, {"fields": ( + "thumbnail_option", + ("width", "height"), + ("crop", "upscale"))}),) + + thumbnail_option = models.ForeignKey( + ThumbnailOption, + null=True, + blank=True, + verbose_name=_("thumbnail option"), + on_delete=models.CASCADE, + ).formfield() + width = models.PositiveIntegerField(_("width"), null=True, blank=True).formfield(widget=widgets.AdminIntegerFieldWidget) height = models.PositiveIntegerField(_("height"), null=True, blank=True).formfield(widget=widgets.AdminIntegerFieldWidget) crop = models.BooleanField(_("crop"), default=True).formfield() @@ -71,8 +76,5 @@ class ResizeImagesForm(forms.Form, AsPWithHelpMixin): def clean(self): if not (self.cleaned_data.get('thumbnail_option') or ((self.cleaned_data.get('width') or 0) + (self.cleaned_data.get('height') or 0))): - if 'cmsplugin_filer_image' in settings.INSTALLED_APPS: - raise ValidationError(_('Thumbnail option or resize parameters must be choosen.')) - else: - raise ValidationError(_('Resize parameters must be choosen.')) + raise ValidationError(_('Thumbnail option or resize parameters must be choosen.')) return self.cleaned_data diff --git a/filer/locale/ar/LC_MESSAGES/django.po b/filer/locale/ar/LC_MESSAGES/django.po index 3b72f6a6c..b34041683 100644 --- a/filer/locale/ar/LC_MESSAGES/django.po +++ b/filer/locale/ar/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # Translators: # Translators: @@ -9,19 +9,19 @@ msgid "" msgstr "" "Project-Id-Version: django Filer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-31 22:21+0200\n" +"POT-Creation-Date: 2023-09-20 10:11+0200\n" "PO-Revision-Date: 2012-07-13 15:50+0000\n" "Last-Translator: Angelo Dini{% blocktrans %}Choose an existing thumbnail option or enter resize parameters:{% endblocktrans %}
- {% else %} -{% blocktrans %}Choose resize parameters:{% endblocktrans %}
- {% endif %} - {{ resize_form.as_p_with_help }} +{% blocktrans %}Choose an existing thumbnail option or enter resize parameters:{% endblocktrans %}
+ {% for fieldset in resize_form.admin_form %} + {% include "admin/includes/fieldset.html" %} + {% endfor %}{% blocktrans %}Warning: Images will be resized in-place and originals will be lost. Maybe first make a copy of them to retain the originals.{% endblocktrans %}
Rename format is in Python % operator format using dictionary of possible values:
There are no destination folders available.
') + + folder = Folder.objects.create(name="My Image Folder") + response = self.client.post(self.url, {"action": ["copy_files_and_folders"], **self.payload}) + self.assertContains(response, ' ') + + folder.delete() + + def test_move_form(self): + response = self.client.post(self.url, {"action": ["move_files_and_folders"], **self.payload}) + self.assertContains(response, 'There are no destination folders available.
') + + folder = Folder.objects.create(name="My Image Folder") + response = self.client.post(self.url, {"action": ["copy_files_and_folders"], **self.payload}) + self.assertContains(response, ' ') + + folder.delete() + + def test_resize_form(self): + response = self.client.post(self.url, {"action": ["resize_images"], **self.payload}) + self.assertContains(response, 'Warning: Images will be resized in-place and originals will be lost.') + self.assertContains(response, '