From 403cd5eb290e005de5093826ff296943ae563765 Mon Sep 17 00:00:00 2001 From: Shohan Date: Fri, 2 Jul 2021 01:42:59 +0530 Subject: [PATCH] [feat] Add 'Select all pages in listing' support --- client/scss/components/_listing.scss | 8 +- client/src/entrypoints/admin/bulk-actions.js | 74 ++++++++++++------- wagtail/admin/localization.py | 5 ++ .../pages/listing/_table_headers_explore.html | 9 +-- wagtail/admin/views/bulk_action.py | 1 - wagtail/admin/views/pages/listing.py | 11 ++- 6 files changed, 70 insertions(+), 38 deletions(-) diff --git a/client/scss/components/_listing.scss b/client/scss/components/_listing.scss index b6dc072ec1..bf7cc00204 100644 --- a/client/scss/components/_listing.scss +++ b/client/scss/components/_listing.scss @@ -64,6 +64,12 @@ ul.listing { opacity: 0.5; right: 0; } + + &.num-pages-in-listing { + color: $color-teal; + text-transform: none; + padding: 0 1em; + } } } @@ -95,7 +101,7 @@ ul.listing { } .bulk-actions-choices, - .bulk-actions-choices ul { + .bulk-actions-choices > ul { display: flex; align-items: center; } diff --git a/client/src/entrypoints/admin/bulk-actions.js b/client/src/entrypoints/admin/bulk-actions.js index 822848e5c0..e60cf08efa 100644 --- a/client/src/entrypoints/admin/bulk-actions.js +++ b/client/src/entrypoints/admin/bulk-actions.js @@ -1,15 +1,19 @@ +/* global wagtailConfig */ +/* global $ */ + const BULK_ACTION_PAGE_CHECKBOX_INPUT = 'bulk-action-checkbox'; const BULK_ACTION_SELECT_ALL_CHECKBOX_TH = 'bulk-actions-filter-checkbox'; const BULK_ACTION_FILTERS_CLASS = `${BULK_ACTION_SELECT_ALL_CHECKBOX_TH} .c-dropdown__item a`; const BULK_ACTION_CHOICES_DIV = 'bulk-actions-choices'; const BULK_ACTION_NUM_PAGES_SPAN = 'num-pages'; -const BULK_ACTION_NUM_PAGES_IN_LISTING_SPAN = 'num-pages-in-listing'; +const BULK_ACTION_NUM_PAGES_IN_LISTING = 'num-pages-in-listing'; const TABLE_HEADERS_TR = 'table-headers'; -let parentPageId; const checkedState = { checkedPages: new Set(), numPages: 0, + listingPageIds: [], + selectAllInListing: false }; /* Event listener for the `Select All` checkbox */ @@ -25,6 +29,7 @@ function SelectBulkActionsFilter(e) { /* Event listener for individual page checkbox */ function SelectBulkActionsCheckboxes(e) { + if (checkedState.selectAllInListing) checkedState.selectAllInListing = false; const prevLength = checkedState.checkedPages.size; if (e.target.checked) checkedState.checkedPages.add(+e.target.dataset.pageId); else { @@ -58,36 +63,48 @@ function SelectBulkActionsCheckboxes(e) { if (checkedState.checkedPages.size > 0) { /* Update text on number of pages */ - document.querySelector(`.${BULK_ACTION_NUM_PAGES_SPAN}`).textContent = - `${checkedState.checkedPages.size === checkedState.numPages ? 'All ' : ''} ${checkedState.checkedPages.size}`; + let numPagesSelected = ''; + if (checkedState.checkedPages.size === checkedState.numPages) { + document.querySelector(`.${BULK_ACTION_NUM_PAGES_IN_LISTING}`).classList.remove('u-hidden'); + if (checkedState.numPages === 1) { + numPagesSelected = wagtailConfig.STRINGS.NUM_PAGES_SELECTED_SINGULAR; + } else { + numPagesSelected = wagtailConfig.STRINGS.NUM_PAGES_SELECTED_ALL.replace('{0}', checkedState.checkedPages.size); + } + } else { + document.querySelector(`.${BULK_ACTION_NUM_PAGES_IN_LISTING}`).classList.add('u-hidden'); + if (checkedState.checkedPages.size === 1) { + numPagesSelected = wagtailConfig.STRINGS.NUM_PAGES_SELECTED_SINGULAR; + } else { + numPagesSelected = wagtailConfig.STRINGS.NUM_PAGES_SELECTED_PLURAL.replace( + '{0}', checkedState.checkedPages.size + ); + } + } + document.querySelector(`.${BULK_ACTION_NUM_PAGES_SPAN}`).textContent = numPagesSelected; } } - -/* Gets the value of given name from the query string in url */ -function getParameterByName(name) { - var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search); - return match && decodeURIComponent(match[1].replace(/\+/g, ' ')); -} - - -/* Updates the content of BULK_ACTION_NUM_PAGES_IN_LISTING_SPAN with the new count of pages */ -function updateNumPagesInListing(filterQueryString) { - // eslint-disable-next-line no-undef - $.ajax({ - url: parentPageId ? `/admin/pages/${parentPageId}/filter-count/` : '/admin/pages/filter-count/', - data: { filters: filterQueryString }, - success: (response) => { - document.querySelector(`.${BULK_ACTION_NUM_PAGES_IN_LISTING_SPAN}`).textContent = response.count; - }, - }); +function fetchAllPageIdsInListing(e) { + if (checkedState.listingPageIds.length === 0) { + e.preventDefault(); + $.ajax({ + url: '?fetchPageIds=1', + success: (response) => { + checkedState.listingPageIds = response.page_ids; + }, + }); + } + checkedState.selectAllInListing = true; + document.querySelector(`.${BULK_ACTION_NUM_PAGES_SPAN}`). + textContent = wagtailConfig.STRINGS.NUM_PAGES_SELECTED_ALL_IN_LISTING; + document.querySelector(`.${BULK_ACTION_NUM_PAGES_IN_LISTING}`).classList.add('u-hidden'); } /* Event listener for filter dropdown options */ function FilterEventListener(e) { e.preventDefault(); const filter = e.target.dataset.filter || ''; - updateNumPagesInListing(filter); const changeEvent = new Event('change'); if (filter.length) { /* split the filter string into [key,value] pairs and check for the values in the @@ -121,7 +138,7 @@ function BulkActionEventListeners(e) { e.preventDefault(); const url = e.target.getAttribute('href'); let queryString = ''; - checkedState.checkedPages.forEach(pageId => { + (checkedState.selectAllInListing ? checkedState.listingPageIds : checkedState.checkedPages).forEach(pageId => { queryString += `&id=${pageId}`; }); window.location.href = url + queryString; @@ -129,7 +146,7 @@ function BulkActionEventListeners(e) { /* Adds all event listeners */ -(function AddBulkActionEventListeners() { +function addBulkActionListeners() { document.querySelectorAll(`.${BULK_ACTION_PAGE_CHECKBOX_INPUT}`) .forEach(el => { checkedState.numPages++; @@ -142,6 +159,7 @@ function BulkActionEventListeners(e) { document.querySelectorAll(`.${BULK_ACTION_CHOICES_DIV} > ul > li > a`).forEach( elem => elem.addEventListener('click', BulkActionEventListeners) ); - parentPageId = document.querySelector(`.${BULK_ACTION_SELECT_ALL_CHECKBOX_TH}`).dataset.parentId; - updateNumPagesInListing(getParameterByName('filters')); -})() + document.querySelector(`.${BULK_ACTION_NUM_PAGES_IN_LISTING}`).addEventListener('click', fetchAllPageIdsInListing); +} + +addBulkActionListeners(); diff --git a/wagtail/admin/localization.py b/wagtail/admin/localization.py index c227db4a9c..7999d93463 100644 --- a/wagtail/admin/localization.py +++ b/wagtail/admin/localization.py @@ -107,6 +107,11 @@ def get_js_translation_strings(): # counting from -1 and use modulo 7 to get an array index 'WEEKDAYS': [str(WEEKDAYS[d % 7]) for d in range(-1, 6)], 'WEEKDAYS_SHORT': [str(WEEKDAYS_ABBR[d % 7]) for d in range(-1, 6)], + + 'NUM_PAGES_SELECTED_SINGULAR': _('1 page selected'), + 'NUM_PAGES_SELECTED_PLURAL': _("{0} pages selected"), + 'NUM_PAGES_SELECTED_ALL': _("All {0} pages on this screen selected"), + 'NUM_PAGES_SELECTED_ALL_IN_LISTING': _("All pages in listing selected"), } diff --git a/wagtail/admin/templates/wagtailadmin/pages/listing/_table_headers_explore.html b/wagtail/admin/templates/wagtailadmin/pages/listing/_table_headers_explore.html index 83d7019b38..4ec330acd8 100644 --- a/wagtail/admin/templates/wagtailadmin/pages/listing/_table_headers_explore.html +++ b/wagtail/admin/templates/wagtailadmin/pages/listing/_table_headers_explore.html @@ -37,13 +37,8 @@ ordering: the current sort parameter {% bulk_action_filters %}
- - {% blocktrans count counter=pages|length %} - 1 page on this page selected. Select all 0 in listing | - {% plural %} - All {{counter}} pages on this page selected. Select all 0 in listing | - {% endblocktrans %} - + + {{ select_all_page_text }}
diff --git a/wagtail/admin/views/bulk_action.py b/wagtail/admin/views/bulk_action.py index 17c621f6ce..a79d44c0b7 100644 --- a/wagtail/admin/views/bulk_action.py +++ b/wagtail/admin/views/bulk_action.py @@ -2,7 +2,6 @@ from abc import ABC, abstractproperty from django.db import transaction from django.shortcuts import get_list_or_404, redirect -from django.urls import reverse from django.views.generic.base import TemplateView from wagtail.admin import messages diff --git a/wagtail/admin/views/pages/listing.py b/wagtail/admin/views/pages/listing.py index 4f0cfdc8e8..e147d58d90 100644 --- a/wagtail/admin/views/pages/listing.py +++ b/wagtail/admin/views/pages/listing.py @@ -1,9 +1,11 @@ from django.conf import settings from django.core.paginator import Paginator from django.db.models import Count +from django.http.response import JsonResponse from django.shortcuts import get_object_or_404, redirect from django.template.response import TemplateResponse from django.urls import reverse +from django.utils.translation import gettext_lazy as _ from wagtail.admin.auth import user_has_any_page_permission, user_passes_test from wagtail.admin.navigation import get_explorable_root_page @@ -39,6 +41,12 @@ def index(request, parent_page_id=None): & user_perms.explorable_pages() ) + fetch_page_ids = request.GET.get('fetchPageIds', '0') + if fetch_page_ids == '1': + return JsonResponse({ + 'page_ids': list(pages.values_list('id', flat=True)) + }) + # Get page ordering ordering = request.GET.get('ordering', '-latest_revision_created_at') if ordering not in [ @@ -103,7 +111,8 @@ def index(request, parent_page_id=None): 'do_paginate': do_paginate, 'locale': None, 'translations': [], - 'show_ordering_column': 'ordering' in request.GET.dict() + 'show_ordering_column': 'ordering' in request.GET.dict(), + 'select_all_page_text': _("Select all pages in listing") } if getattr(settings, 'WAGTAIL_I18N_ENABLED', False) and not parent_page.is_root():