Skip to content

Commit

Permalink
Merge pull request #14051 from craftcms/feature/vue-admintable-pagina…
Browse files Browse the repository at this point in the history
…ted-reordering

Admin table - move to page and paginated reordering
  • Loading branch information
brandonkelly authored Dec 29, 2023
2 parents ecdf19e + 598786a commit a615785
Show file tree
Hide file tree
Showing 15 changed files with 532 additions and 75 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG-WIP.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
- Added the `disabledUtilities` config setting. ([#14044](https://github.com/craftcms/cms/discussions/14044))
- `resave` commands now pass an empty string (`''`) to fields’ `normalizeValue()` methods when `--to` is set to `:empty:`. ([#13951](https://github.com/craftcms/cms/issues/13951))
- The `index-assets/one` and `index-assets/all` commands now accept a `--delete-empty-folders` option. ([#13947](https://github.com/craftcms/cms/discussions/13947))
- Added `craft\helpers\AdminTable::moveToPage()`. ([#14051](https://github.com/craftcms/cms/pull/14051))
- Added `craft\helpers\ElementHelper::searchableAttributes()`.
- Added `craft\services\Elements::setElementUri()`.
- Added `craft\services\Elements::EVENT_SET_ELEMENT_URI`. ([#13930](https://github.com/craftcms/cms/discussions/13930))
- Added `craft\services\Search::createDbQuery()`.
- Admin tables now have `footerActions`, `moveToPageAction`, `onCellClicked`, `onCellDoubleClicked`, `onRowClicked`, `onRowDoubleClicked`, and `paginatedReorderAction` settings. ([#14051](https://github.com/craftcms/cms/pull/14051))
226 changes: 212 additions & 14 deletions packages/craftcms-vue/admintable/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
:error="action.error"
:ajax="action.ajax"
v-on:reload="reload"
v-on:click="handleActionClick"
>
</admin-table-action-button>
</div>
Expand Down Expand Up @@ -81,11 +82,16 @@
:per-page="perPage"
:no-data-template="noDataTemplate"
:query-params="queryParams"
:row-class="rowClass"
pagination-path="pagination"
@vuetable:loaded="init"
@vuetable:loading="loading"
@vuetable:pagination-data="onPaginationData"
@vuetable:load-success="onLoadSuccess"
@vuetable:cell-clicked="handleCellClicked"
@vuetable:cell-dblclicked="handleCellDoubleClicked"
@vuetable:row-clicked="handleRowClicked"
@vuetable:row-dblclicked="handleRowDoubleClicked"
>
<template slot="checkbox" slot-scope="props">
<admin-table-checkbox
Expand Down Expand Up @@ -124,9 +130,15 @@
<template slot="menu" slot-scope="props">
<template v-if="props.rowData.menu.showItems">
<a :href="props.rowData.menu.url"
>{{ props.rowData.menu.label }} ({{
props.rowData.menu.items.length
}})</a
>{{ props.rowData.menu.label
}}<template
v-if="
props.rowData.menu.showCount ||
props.rowData.menu.showCount === undefined
"
>
({{ props.rowData.menu.items.length }})</template
></a
>
<a class="menubtn" :title="props.rowData.menu.label"></a>
<div class="menu">
Expand Down Expand Up @@ -197,13 +209,50 @@
</template>
</vuetable>
</div>
<admin-table-pagination
ref="pagination"
:itemLabels="itemLabels"
@vuetable-pagination:change-page="onChangePage"
></admin-table-pagination>
<div class="flex flex-justify vue-admin-table-footer" v-if="showFooter">
<admin-table-pagination
ref="pagination"
:itemLabels="itemLabels"
@vuetable-pagination:change-page="onChangePage"
></admin-table-pagination>
<div
v-if="checkboxes && itemActions.length"
:class="{hidden: !checks.length}"
>
<admin-table-action-button
label=""
class="vue-admin-table-footer-actions"
:icon="'settings'"
:actions="itemActions"
:allow-multiple="true"
menu-btn-class="secondary"
:ids="checks"
:enabled="checks.length ? true : false"
v-on:reload="reload"
v-on:click="handleActionClick"
>
</admin-table-action-button>
</div>
</div>
</div>
</div>

<div class="hidden" v-if="moveToPageAction && lastPage !== 1">
<admin-table-move-to-page-hud
ref="move-to-page-hud"
trigger=".vue-admin-table-footer-actions"
:action="moveToPageAction"
:current-page="currentPage"
:per-page="perPage"
:pages="lastPage"
:move-to-page-action="moveToPageAction"
:reorder-success-message="reorderSuccessMessage"
:ids="checks"
v-on:reload="reload"
v-on:submit="loading()"
v-on:error="loading(false)"
></admin-table-move-to-page-hud>
</div>
</div>
</template>
<script>
Expand All @@ -216,11 +265,13 @@
import AdminTableDetailRow from './components/AdminTableDetailRow';
import AdminTableButton from './components/AdminTableButton';
import AdminTableCopyTextButton from './components/AdminTableCopyTextButton';
import AdminTableMoveToPageHud from './components/AdminTableMoveToPageHud.vue';
import Sortable from 'sortablejs';
import {debounce, map} from 'lodash';
export default {
components: {
AdminTableMoveToPageHud,
AdminTableCopyTextButton,
AdminTableActionButton,
AdminTableCheckbox,
Expand All @@ -240,6 +291,12 @@
return [];
},
},
footerActions: {
type: Array,
default: () => {
return [];
},
},
allowMultipleSelections: {
type: Boolean,
default: true,
Expand Down Expand Up @@ -272,6 +329,10 @@
return [];
},
},
allowMultipleDeletions: {
type: Boolean,
default: false,
},
deleteAction: {
type: String,
default: null,
Expand Down Expand Up @@ -323,6 +384,12 @@
reorderAction: {
type: String,
},
moveToPageAction: {
type: String,
},
paginatedReorderAction: {
type: String,
},
reorderSuccessMessage: {
type: String,
default: Craft.t('app', 'Items reordered.'),
Expand Down Expand Up @@ -359,6 +426,18 @@
onData: {
default: function () {},
},
onCellClicked: {
default: function () {},
},
onCellDoubleClicked: {
default: function () {},
},
onRowClicked: {
default: function () {},
},
onRowDoubleClicked: {
default: function () {},
},
onPagination: {
default: function () {},
},
Expand All @@ -374,6 +453,7 @@
return {
checks: [],
currentPage: 1,
lastPage: 1,
detailRow: AdminTableDetailRow,
dragging: false,
isEmpty: false,
Expand Down Expand Up @@ -454,7 +534,37 @@
this.dragging = false;
},
rowClass(data, index) {
if (!data) {
return '';
}
if (!this.checks.length) {
return '';
}
if (this.checks.indexOf(data.id) >= 0) {
return 'sel';
}
return '';
},
handleActionClick(param, value, action, ajax) {
if (param === 'moveToPage' && value === true) {
this.$refs['move-to-page-hud'].show();
} else if (ajax) {
this.loading();
}
},
handleReorder(ev) {
// Paginated reordering must be used when supplying table data from an endpoint
const isPaginatedReorder = this.tableDataEndpoint ? true : false;
const reorderAction = isPaginatedReorder
? this.paginatedReorderAction
: this.reorderAction;
let elements = [
...ev.target.querySelectorAll('.vue-table-move-handle'),
];
Expand All @@ -472,7 +582,7 @@
: 0) + 1,
};
Craft.sendActionRequest('POST', this.reorderAction, {data}).then(
Craft.sendActionRequest('POST', reorderAction, {data}).then(
(response) => {
Craft.cp.displayNotice(
Craft.escapeHtml(this.reorderSuccessMessage)
Expand Down Expand Up @@ -540,7 +650,11 @@
reload() {
if (this.$refs.vuetable) {
this.$refs.vuetable.gotoPage(1);
const reloadToPage =
this.$refs.vuetable.currentPage > 1
? this.$refs.vuetable.currentPage
: 1;
this.$refs.vuetable.gotoPage(reloadToPage);
}
this.isLoading = true;
Expand Down Expand Up @@ -581,8 +695,37 @@
}
},
handleCellClicked(data, field, event) {
this.$emit('onCellClicked', data, field, event);
if (this.onCellClicked instanceof Function) {
this.onCellClicked(data, field, event);
}
},
handleCellDoubleClicked(data, field, event) {
this.$emit('onCellDoubleClicked', data, field, event);
if (this.onCellDoubleClicked instanceof Function) {
this.onCellDoubleClicked(data, field, event);
}
},
handleRowClicked(data, event) {
this.$emit('onRowClicked', data, event);
if (this.onRowClicked instanceof Function) {
this.onRowClicked(data, event);
}
},
handleRowDoubleClicked(data, event) {
this.$emit('onRowDoubleClicked', data, event);
if (this.onRowDoubleClicked instanceof Function) {
this.onRowDoubleClicked(data, event);
}
},
onPaginationData(paginationData) {
this.currentPage = paginationData.current_page;
this.lastPage = paginationData.last_page;
this.$refs.pagination.setPaginationData(paginationData);
this.deselectAll();
if (this.onPagination instanceof Function) {
Expand Down Expand Up @@ -653,12 +796,52 @@
);
},
itemActions() {
let itemActions = [];
if (this.paginatedReorderAction && this.moveToPageAction) {
itemActions.push({
label: Craft.t('app', 'Move to'),
action: this.moveToPageAction,
allowMultiple: false,
ajax: true,
handleClick: false,
param: 'moveToPage',
value: true,
class: {'footer-actions': true},
});
}
itemActions = [...itemActions, ...this.footerActions];
if (this.deleteAction) {
itemActions.push({
label: Craft.t('app', 'Delete'),
action: this.deleteAction,
error: true,
ajax: true,
allowMultiple: this.allowMultipleDeletions,
separator: itemActions.length ? true : false,
});
}
return itemActions;
},
canReorder() {
if (
this.$refs.vuetable == undefined ||
this.$refs.vuetable.tableData == undefined
) {
return false;
}
return (
this.$refs.vuetable.tableData.length > 1 &&
this.reorderAction &&
this.$el.querySelector(this.tableBodySelector) &&
!this.$refs.vuetable.tablePagination
((this.reorderAction && !this.$refs.vuetable.tablePagination) ||
(this.paginatedReorderAction &&
this.$refs.vuetable.tablePagination))
);
},
Expand Down Expand Up @@ -717,7 +900,10 @@
let customColumns = map(this.columns, (item) => {
// Do not allow sorting for if you can manually reorder items
if (this.reorderAction && item.hasOwnProperty('sortField')) {
if (
(this.reorderAction || this.paginatedReorderAction) &&
item.hasOwnProperty('sortField')
) {
delete item.sortField;
}
Expand All @@ -729,7 +915,7 @@
columns = [...columns, ...customColumns];
if (this.reorderAction) {
if (this.reorderAction || this.paginatedReorderAction) {
columns.push({
name: '__slot:reorder',
title: '',
Expand All @@ -755,6 +941,12 @@
return this.actions.length || (this.search && !this.tableData.length);
},
showFooter() {
return (
(this.checkboxes && this.itemActions.length) || this.tableDataEndpoint
);
},
tableCss() {
var tableClass = this.tableClass;
if (this.dragging) {
Expand Down Expand Up @@ -867,6 +1059,12 @@
margin-bottom: 0;
}
.vue-admin-table-footer {
border-top: 1px solid #f3f7fc;
margin-top: 14px;
padding-top: 14px;
}
.detail-cursor-pointer {
cursor: pointer;
}
Expand Down
Loading

0 comments on commit a615785

Please sign in to comment.