[feat] Add bulk actions in page listing

Added following
- Add bulk action checkboxes (non functional), actions, filters in page listing (non functional)
- Add search bar in page listing (non functional)
pull/7618/head
Shohan 2021-03-23 18:28:35 +05:30 zatwierdzone przez Matt Westcott
rodzic a32d390b83
commit 64a1d7299f
7 zmienionych plików z 222 dodań i 28 usunięć

Wyświetl plik

@ -82,6 +82,50 @@ ul.listing {
.table-headers {
border-bottom: 1px solid $color-grey-4;
.bulk-actions-filter-checkbox {
> div {
display: flex;
align-items: center;
}
.c-dropdown__button {
border: 0;
padding-left: 0.3rem;
}
.bulk-actions-choices,
.bulk-actions-choices ul {
display: flex;
align-items: center;
}
.bulk-actions-choices li {
margin: 0 0.5em;
}
.bulk-actions-choices span {
text-transform: none;
}
}
.search {
padding-left: 0;
.nav-search {
padding: 0;
width: max(50%, 250px);
}
input {
background-color: #fff;
border: 0;
}
button {
color: $color-header-bg;
}
}
}
tbody {
@ -661,6 +705,15 @@ table.listing {
visibility: visible;
}
.bulk-action-checkbox {
opacity: 0;
&.show,
&:checked {
opacity: 1;
}
}
.no-children {
border-color: transparent;
@ -669,8 +722,12 @@ table.listing {
}
}
tr:hover .no-children a {
opacity: 1;
tr:hover {
.no-children a,
.bulk-action-checkbox {
opacity: 1;
}
}
tr:hover .children {

Wyświetl plik

@ -0,0 +1,56 @@
const BULK_ACTION_CHECKBOX_CLASS = 'bulk-action-checkbox';
const BULK_ACTION_CHECKBOX_FILTER_CLASS = 'bulk-actions-filter-checkbox';
const BULK_ACTION_CHOICES_CLASS = 'bulk-actions-choices';
const TABLE_HEADERS_CLASS = 'table-headers';
const checkedState = {
checkedPages: new Set(),
};
function SelectBulkActionsFilter(e) {
const changeEvent = new Event('change');
for (const el of document.querySelectorAll(`.${BULK_ACTION_CHECKBOX_CLASS}`)) {
if (el.checked === e.target.checked) continue;
el.checked = e.target.checked;
el.dispatchEvent(changeEvent);
}
}
function SelectBulkActionsCheckboxes(e) {
const prevLength = checkedState.checkedPages.size;
if (e.target.checked) checkedState.checkedPages.add(+e.target.dataset.pageId);
else {
// unchecks `select all` checkbox as soon as one page is unchecked
document.querySelector(`.${BULK_ACTION_CHECKBOX_FILTER_CLASS} input`).checked = false;
checkedState.checkedPages.delete(+e.target.dataset.pageId);
}
if (checkedState.checkedPages.size === 0) {
// all checboxes are unchecked
document.querySelectorAll(`.${TABLE_HEADERS_CLASS} > th`).forEach(el => el.classList.remove('u-hidden'));
document.querySelector(`.${BULK_ACTION_CHOICES_CLASS}`).classList.add('u-hidden');
document.querySelectorAll(`.${BULK_ACTION_CHECKBOX_CLASS}`).forEach(el => el.classList.remove('show'));
document.querySelector(`.${BULK_ACTION_CHECKBOX_FILTER_CLASS}`).setAttribute('colspan', '1');
} else if (checkedState.checkedPages.size === document.querySelectorAll(`.${BULK_ACTION_CHECKBOX_CLASS}`).length) {
// all checkboxes are checked
document.querySelector(`.${BULK_ACTION_CHECKBOX_FILTER_CLASS} input`).checked = true;
} else if (checkedState.checkedPages.size === 1 && prevLength === 0) {
// 1 checkbox is checked for the first time
document.querySelectorAll(`.${BULK_ACTION_CHECKBOX_CLASS}`).forEach(el => {
el.classList.remove('show');
el.classList.add('show');
});
document.querySelectorAll(`.${TABLE_HEADERS_CLASS} > th`).forEach(el => el.classList.add('u-hidden'));
document.querySelector(`.${BULK_ACTION_CHECKBOX_FILTER_CLASS}`).classList.remove('u-hidden');
document.querySelector(`.${BULK_ACTION_CHOICES_CLASS}`).classList.remove('u-hidden');
document.querySelector(`.${BULK_ACTION_CHECKBOX_FILTER_CLASS}`).setAttribute('colspan', '6');
}
}
function AddBulkActionCheckboxEventListeners() {
document.querySelectorAll(`.${BULK_ACTION_CHECKBOX_CLASS}`)
.forEach(el => el.addEventListener('change', SelectBulkActionsCheckboxes));
document.querySelector(`.${BULK_ACTION_CHECKBOX_FILTER_CLASS}`).addEventListener('change', SelectBulkActionsFilter);
}
window.AddBulkActionCheckboxEventListeners = AddBulkActionCheckboxEventListeners;

Wyświetl plik

@ -56,6 +56,7 @@ module.exports = function exports() {
'wagtailadmin',
'workflow-action',
'workflow-status',
'bulk-actions'
],
'images': [
'image-chooser',

Wyświetl plik

@ -2,9 +2,7 @@
{% load l10n %}
{% load wagtailadmin_tags %}
<table class="listing {% if full_width %}full-width{% endif %} {% block table_classname %}{% endblock %}">
{% if show_ordering_column %}
<col width="65px" />
{% endif %}
<col width="10px" />
<col />
{% if show_parent %}
<col />
@ -47,9 +45,9 @@
{% for page in pages %}
{% page_permissions page as page_perms %}
<tr {% if ordering == "ord" %}id="page_{{ page.id|unlocalize }}" data-page-title="{{ page.get_admin_display_title }}"{% endif %} class="{% if not page.live %}unpublished{% endif %} {% block page_row_classname %}{% endblock %}">
{% if show_ordering_column %}
<td class="ord">{% if orderable and ordering == "ord" %}<div class="handle icon icon-grip text-replace">{% trans 'Drag' %}</div>{% endif %}</td>
{% endif %}
<td>
<input data-page-id="{{page.id}}" class="bulk-action-checkbox" aria-label="Page select checkbox" type="checkbox" />
</td>
<td class="title" valign="top" data-listing-page-title>
{% block page_title %}
{% endblock %}
@ -79,3 +77,8 @@
{% endif %}
</tbody>
</table>
<script src="{% versioned_static 'wagtailadmin/js/bulk-actions.js' %}"></script>
<script>
window.AddBulkActionCheckboxEventListeners()
</script>

Wyświetl plik

@ -17,24 +17,22 @@ ordering: the current sort parameter
{% endcomment %}
<tr class="table-headers">
{% if show_ordering_column %}
<th class="ord{% if orderable and ordering == 'ord' %} ord--active{% endif %}">
{% if orderable %}
{% if ordering == "ord" %}
<a href="{% url 'wagtailadmin_explore' parent_page.id %}" title="{% trans 'Disable ordering of child pages' %}">
{% icon name="order" %}{% trans 'Sort' %}
</a>
{% else %}
<a href="{% url 'wagtailadmin_explore' parent_page.id %}?ordering=ord" title="{% trans 'Enable ordering of child pages' %}">
{% icon name="order" %}{% trans 'Sort' %}
</a>
{% endif %}
{% endif %}
</th>
{% endif %}
<th class="title">
{% trans 'Title' as title_label %}
{% page_table_header_label label=title_label sortable=sortable sort_field='title' parent_page_title=parent_page.title %}
<th class="bulk-actions-filter-checkbox">
<div>
<input type="checkbox" aria-label="Bulk action checkbox" />
{% bulk_action_filters %}
<div class="bulk-actions-choices u-hidden">
<span>All 8 on this page selected. Select all 43 in listing |</span>
<ul>{% bulk_action_choices %}</ul>
</div>
</div>
</th>
<th class="search">
<div class="nav-search">
<button class="button" type="submit">Search</button>
<label for="page-search-q">Search</label>
<input aria-label="Search text" type="text" id="page-search" name="q" placeholder="Search">
</div>
</th>
{% if show_parent %}
<th class="parent">
@ -55,9 +53,8 @@ ordering: the current sort parameter
{% page_table_header_label label=type_label sortable=0 parent_page_title=parent_page.title %}
{% endif %}
</th>
<th class="status">
<th class="status" colspan="2">
{% trans 'Status' as status_label %}
{% page_table_header_label label=status_label sortable=sortable sort_field='live' parent_page_title=parent_page.title %}
</th>
<th></th>
</tr>

Wyświetl plik

@ -486,6 +486,34 @@ def page_listing_buttons(context, page, page_perms, is_parent=False):
return {'page': page, 'buttons': buttons}
@register.inclusion_tag("wagtailadmin/pages/listing/_button_with_dropdown.html",
takes_context=True)
def bulk_action_filters(context):
button_hooks = hooks.get_hooks('register_bulk_action_filters')
buttons = []
for hook in button_hooks:
buttons.extend(hook())
buttons.sort()
return {'buttons': buttons}
@register.inclusion_tag("wagtailadmin/pages/listing/_buttons.html",
takes_context=True)
def bulk_action_choices(context):
button_hooks = hooks.get_hooks('register_bulk_action_choices')
buttons = []
for hook in button_hooks:
buttons.extend(hook())
buttons.sort()
return {'buttons': buttons}
@register.simple_tag
def message_tags(message):
level_tag = MESSAGE_TAGS.get(message.level)

Wyświetl plik

@ -160,6 +160,58 @@ def register_workflow_tasks_menu_item():
return WorkflowTasksMenuItem(_('Workflow tasks'), reverse('wagtailadmin_workflows:task_index'), icon_name='thumbtack', order=150)
@hooks.register('register_bulk_action_filters')
def bulk_action_filters():
yield Button(
_('All'),
'',
attrs={'aria-label': _("All pages")},
priority=10
)
yield Button(
_('Status: Draft'),
'',
attrs={'aria-label': _("Draft pages")},
priority=10
)
yield Button(
_('Status: Live'),
'',
attrs={'aria-label': _("Live pages")},
priority=10
)
@hooks.register('register_bulk_action_choices')
def bulk_action_choices(is_parent=False, next_url=None):
yield PageListingButton(
_('Move'),
'',
attrs={'aria-label': _("Move pages")},
priority=10
)
yield PageListingButton(
_('Publish'),
'',
attrs={'aria-label': _("Publish pages")},
priority=20
)
yield PageListingButton(
_('Unpublish'),
'',
attrs={'aria-label': _("Unpublish pages")},
priority=30
)
yield PageListingButton(
_('Delete'),
'',
attrs={'aria-label': _("Delete pages")},
priority=40
)
@hooks.register('register_page_listing_buttons')
def page_listing_buttons(page, page_perms, is_parent=False, next_url=None):
if page_perms.can_edit():