kopia lustrzana https://github.com/wagtail/wagtail
[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
rodzic
a32d390b83
commit
64a1d7299f
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -56,6 +56,7 @@ module.exports = function exports() {
|
|||
'wagtailadmin',
|
||||
'workflow-action',
|
||||
'workflow-status',
|
||||
'bulk-actions'
|
||||
],
|
||||
'images': [
|
||||
'image-chooser',
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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():
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue