diff --git a/client/src/includes/chooserModal.js b/client/src/includes/chooserModal.js index 9f427a21bb..e9d58d51ad 100644 --- a/client/src/includes/chooserModal.js +++ b/client/src/includes/chooserModal.js @@ -280,6 +280,8 @@ class ChooserModalOnloadHandlerFactory { this.initSearchController(modal); this.ajaxifyLinks(modal, modal.body); this.ajaxifyCreationForm(modal); + // Set up submissions of the "choose multiple items" form to open in the modal. + modal.ajaxifyForm($('form[data-multiple-choice-form]', modal.body)); } onLoadChosenStep(modal, jsonData) { diff --git a/wagtail/admin/templates/wagtailadmin/generic/chooser/checkbox_select_cell.html b/wagtail/admin/templates/wagtailadmin/generic/chooser/checkbox_select_cell.html new file mode 100644 index 0000000000..79340071c0 --- /dev/null +++ b/wagtail/admin/templates/wagtailadmin/generic/chooser/checkbox_select_cell.html @@ -0,0 +1,4 @@ +{% load i18n %} + + + diff --git a/wagtail/admin/templates/wagtailadmin/generic/chooser/chooser.html b/wagtail/admin/templates/wagtailadmin/generic/chooser/chooser.html index 8f566c9b17..5b1027319d 100644 --- a/wagtail/admin/templates/wagtailadmin/generic/chooser/chooser.html +++ b/wagtail/admin/templates/wagtailadmin/generic/chooser/chooser.html @@ -44,9 +44,18 @@ {% endif %} {% endblock %} + {% if is_multiple_choice %} +
+ {% endif %} +
{% include view.results_template_name %}
+ + {% if is_multiple_choice %} + +
+ {% endif %} {% if creation_form %} diff --git a/wagtail/admin/views/generic/chooser.py b/wagtail/admin/views/generic/chooser.py index 66ff35d5af..c87ac01905 100644 --- a/wagtail/admin/views/generic/chooser.py +++ b/wagtail/admin/views/generic/chooser.py @@ -27,7 +27,7 @@ from wagtail.admin.forms.choosers import ( SearchFilterMixin, ) from wagtail.admin.modal_workflow import render_modal_workflow -from wagtail.admin.ui.tables import Table, TitleColumn +from wagtail.admin.ui.tables import Column, Table, TitleColumn from wagtail.coreutils import resolve_model_string from wagtail.models import CollectionMember, TranslatableMixin from wagtail.permission_policies import BlanketPermissionPolicy, ModelPermissionPolicy @@ -102,6 +102,10 @@ class PreserveURLParametersMixin: return url +class CheckboxSelectColumn(Column): + cell_template_name = "wagtailadmin/generic/chooser/checkbox_select_cell.html" + + class BaseChooseView( ModalPageFurnitureMixin, ModelLookupMixin, @@ -117,6 +121,7 @@ class BaseChooseView( per_page = 10 ordering = None chosen_url_name = None + chosen_multiple_url_name = None results_url_name = None icon = "snippet" page_title = _("Choose") @@ -180,6 +185,11 @@ class BaseChooseView( def get_results_url(self): return self.append_preserved_url_parameters(reverse(self.results_url_name)) + def get_chosen_multiple_url(self): + return self.append_preserved_url_parameters( + reverse(self.chosen_multiple_url_name) + ) + @property def columns(self): return [ @@ -196,6 +206,12 @@ class BaseChooseView( ), ] + @property + def checkbox_column(self): + return CheckboxSelectColumn( + "select", label=_("Select"), width="1%", accessor="pk" + ) + def get_results_page(self, request): objects = self.get_object_list() objects = self.apply_object_list_ordering(objects) @@ -207,7 +223,12 @@ class BaseChooseView( def get(self, request): self.filter_form = self.get_filter_form() self.results = self.get_results_page(request) - self.table = Table(self.columns, self.results) + self.is_multiple_choice = request.GET.get("multiple") + + columns = self.columns + if self.is_multiple_choice: + columns.insert(0, self.checkbox_column) + self.table = Table(columns, self.results) return self.render_to_response() @@ -228,10 +249,13 @@ class BaseChooseView( "results_pagination_url": results_pagination_url, "is_searching": self.filter_form.is_searching, "is_filtering_by_collection": self.filter_form.is_filtering_by_collection, + "is_multiple_choice": self.is_multiple_choice, "search_query": self.filter_form.search_query, "can_create": self.can_create(), } ) + if self.is_multiple_choice: + context["chosen_multiple_url"] = self.get_chosen_multiple_url() return context def render_to_response(self): diff --git a/wagtail/admin/viewsets/chooser.py b/wagtail/admin/viewsets/chooser.py index ebdc79cb2e..6f04db948d 100644 --- a/wagtail/admin/viewsets/chooser.py +++ b/wagtail/admin/viewsets/chooser.py @@ -92,6 +92,7 @@ class ChooserViewSet(ViewSet): return self.choose_view_class.as_view( model=self.model, chosen_url_name=self.get_url_name("chosen"), + chosen_multiple_url_name=self.get_url_name("chosen_multiple"), results_url_name=self.get_url_name("choose_results"), create_url_name=self.get_url_name("create"), icon=self.icon, @@ -113,6 +114,7 @@ class ChooserViewSet(ViewSet): return self.choose_results_view_class.as_view( model=self.model, chosen_url_name=self.get_url_name("chosen"), + chosen_multiple_url_name=self.get_url_name("chosen_multiple"), results_url_name=self.get_url_name("choose_results"), per_page=self.per_page, creation_form_class=self.creation_form_class,