From fa39b4d5d4f60ad4789a05e379b29b49c9278976 Mon Sep 17 00:00:00 2001 From: Oliver Bartsch <bo@cedev.de> Date: Wed, 18 Aug 2021 15:55:43 +0200 Subject: [PATCH] [TASK] Use multi record selection in recycler module The multi record selection component is now also used in the recycler module. This increases consistency, as custom checkbox logic could be removed. Also the recyclers' JavaScript implementation of the selection actions is simplified. To interact with the multi record selection component, some events are used. This also means, the functionality stays the same, while most of it is now handled by the Multi record selection component. Resolves: #94926 Releases: master Change-Id: I57d91d070bfa75c01d4cb87dfd0c5576d111dcfa Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/70678 Tested-by: core-ci <typo3@b13.com> Tested-by: Jochen <rothjochen@gmail.com> Tested-by: Simon Schaufelberger <simonschaufi+typo3@gmail.com> Tested-by: Benni Mack <benni@typo3.org> Reviewed-by: Jochen <rothjochen@gmail.com> Reviewed-by: Simon Schaufelberger <simonschaufi+typo3@gmail.com> Reviewed-by: Benni Mack <benni@typo3.org> --- .../Resources/Public/TypeScript/Recycler.ts | 64 ++++++---------- .../Controller/RecyclerModuleController.php | 1 + .../Partials/RecordsTable/DeletedRecord.html | 7 +- .../Templates/RecyclerModule/Index.html | 74 +++++++++++++------ .../Resources/Public/JavaScript/Recycler.js | 2 +- 5 files changed, 81 insertions(+), 67 deletions(-) diff --git a/Build/Sources/TypeScript/recycler/Resources/Public/TypeScript/Recycler.ts b/Build/Sources/TypeScript/recycler/Resources/Public/TypeScript/Recycler.ts index bd6e104fcf4a..570bb1d782a9 100644 --- a/Build/Sources/TypeScript/recycler/Resources/Public/TypeScript/Recycler.ts +++ b/Build/Sources/TypeScript/recycler/Resources/Public/TypeScript/Recycler.ts @@ -18,6 +18,7 @@ import DeferredAction = require('TYPO3/CMS/Backend/ActionButton/DeferredAction') import Modal = require('TYPO3/CMS/Backend/Modal'); import Notification = require('TYPO3/CMS/Backend/Notification'); import Severity = require('TYPO3/CMS/Backend/Severity'); +import RegularEvent from 'TYPO3/CMS/Core/Event/RegularEvent'; enum RecyclerIdentifiers { searchForm = '#recycler-form', @@ -28,9 +29,10 @@ enum RecyclerIdentifiers { recyclerTable = '#itemsInRecycler', paginator = '#recycler-index nav', reloadAction = 'a[data-action=reload]', - massUndo = 'button[data-action=massundo]', - massDelete = 'button[data-action=massdelete]', - toggleAll = '.t3js-toggle-all', + undo = 'a[data-action=undo]', + delete = 'a[data-action=delete]', + massUndo = 'button[data-multi-record-selection-action=massundo]', + massDelete = 'button[data-multi-record-selection-action=massdelete]', } /** @@ -46,7 +48,6 @@ class Recycler { itemsPerPage: TYPO3.settings.Recycler.pagingSize, }; public markedRecordsForMassAction: Array<string> = []; - public allToggled: boolean = false; /** * Reloads the page tree @@ -77,7 +78,6 @@ class Recycler { $reloadAction: $(RecyclerIdentifiers.reloadAction), $massUndo: $(RecyclerIdentifiers.massUndo), $massDelete: $(RecyclerIdentifiers.massDelete), - $toggleAll: $(RecyclerIdentifiers.toggleAll), }; } @@ -127,10 +127,10 @@ class Recycler { }); // clicking "recover" in single row - this.elements.$recyclerTable.on('click', '[data-action=undo]', this.undoRecord); + new RegularEvent('click', this.undoRecord).delegateTo(document, RecyclerIdentifiers.undo); // clicking "delete" in single row - this.elements.$recyclerTable.on('click', '[data-action=delete]', this.deleteRecord); + new RegularEvent('click', this.deleteRecord).delegateTo(document, RecyclerIdentifiers.delete); this.elements.$reloadAction.on('click', (e: JQueryEventObject): void => { e.preventDefault(); @@ -199,14 +199,9 @@ class Recycler { }); // checkboxes in the table - this.elements.$toggleAll.on('click', (): void => { - this.allToggled = !this.allToggled; - $('input[type="checkbox"]').prop('checked', this.allToggled).trigger('change'); - }); - this.elements.$recyclerTable.on('change', 'tr input[type=checkbox]', this.handleCheckboxSelects); - - this.elements.$massUndo.on('click', this.undoRecord); - this.elements.$massDelete.on('click', this.deleteRecord); + new RegularEvent('checkbox:state:changed', this.handleCheckboxStateChanged).bindTo(document); + new RegularEvent('multiRecordSelection:action:massundo', this.undoRecord).bindTo(document); + new RegularEvent('multiRecordSelection:action:massdelete', this.deleteRecord).bindTo(document); } /** @@ -230,8 +225,8 @@ class Recycler { /** * Handles the clicks on checkboxes in the records table */ - private handleCheckboxSelects = (e: JQueryEventObject): void => { - const $checkbox = $(e.currentTarget); + private handleCheckboxStateChanged = (e: Event): void => { + const $checkbox = $(e.target); const $tr = $checkbox.parents('tr'); const table = $tr.data('table'); const uid = $tr.data('uid'); @@ -239,29 +234,20 @@ class Recycler { if ($checkbox.prop('checked')) { this.markedRecordsForMassAction.push(record); - $tr.addClass('warning'); } else { const index = this.markedRecordsForMassAction.indexOf(record); if (index > -1) { this.markedRecordsForMassAction.splice(index, 1); } - $tr.removeClass('warning'); } if (this.markedRecordsForMassAction.length > 0) { - if (this.elements.$massUndo.hasClass('disabled')) { - this.elements.$massUndo.removeClass('disabled').removeAttr('disabled'); - } - if (this.elements.$massDelete.hasClass('disabled')) { - this.elements.$massDelete.removeClass('disabled').removeAttr('disabled'); - } - - const btnTextUndo = this.createMessage(TYPO3.lang['button.undoselected'], [this.markedRecordsForMassAction.length]); - const btnTextDelete = this.createMessage(TYPO3.lang['button.deleteselected'], [this.markedRecordsForMassAction.length]); - - this.elements.$massUndo.find('span.text').text(btnTextUndo); - this.elements.$massDelete.find('span.text').text(btnTextDelete); - + this.elements.$massUndo.find('span.text').text( + this.createMessage(TYPO3.lang['button.undoselected'], [this.markedRecordsForMassAction.length]) + ); + this.elements.$massDelete.find('span.text').text( + this.createMessage(TYPO3.lang['button.deleteselected'], [this.markedRecordsForMassAction.length]) + ); } else { this.resetMassActionButtons(); } @@ -272,10 +258,9 @@ class Recycler { */ private resetMassActionButtons(): void { this.markedRecordsForMassAction = []; - this.elements.$massUndo.addClass('disabled').attr('disabled', true); this.elements.$massUndo.find('span.text').text(TYPO3.lang['button.undo']); - this.elements.$massDelete.addClass('disabled').attr('disabled', true); this.elements.$massDelete.find('span.text').text(TYPO3.lang['button.delete']); + document.dispatchEvent(new Event('multiRecordSelection:actions:hide')); } /** @@ -350,12 +335,12 @@ class Recycler { }); } - private deleteRecord = (e: JQueryEventObject): void => { + private deleteRecord = (e: Event): void => { if (TYPO3.settings.Recycler.deleteDisable) { return; } - const $tr = $(e.currentTarget).parents('tr'); + const $tr = $(e.target).parents('tr'); const isMassDelete = $tr.parent().prop('tagName') !== 'TBODY'; // deleteRecord() was invoked by the mass delete button let records: Array<string>; let message: string; @@ -389,8 +374,8 @@ class Recycler { ]); } - private undoRecord = (e: JQueryEventObject): void => { - const $tr = $(e.currentTarget).parents('tr'); + private undoRecord = (e: Event): void => { + const $tr = $(e.target).parents('tr'); const isMassUndo = $tr.parent().prop('tagName') !== 'TBODY'; // undoRecord() was invoked by the mass delete button let records: Array<string>; @@ -501,9 +486,6 @@ class Recycler { if (reloadPageTree) { Recycler.refreshPageTree(); } - - // Reset toggle state - this.allToggled = false; }); }, complete: () => { diff --git a/typo3/sysext/recycler/Classes/Controller/RecyclerModuleController.php b/typo3/sysext/recycler/Classes/Controller/RecyclerModuleController.php index 288b4c5f1051..7a552df5cb05 100644 --- a/typo3/sysext/recycler/Classes/Controller/RecyclerModuleController.php +++ b/typo3/sysext/recycler/Classes/Controller/RecyclerModuleController.php @@ -156,6 +156,7 @@ class RecyclerModuleController { $this->pageRenderer->addInlineSettingArray('Recycler', $this->getJavaScriptConfiguration($request->getAttribute('normalizedParams'))); $this->pageRenderer->addInlineLanguageLabelFile('EXT:recycler/Resources/Private/Language/locallang.xlf'); + $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/MultiRecordSelection'); if ($this->isAccessibleForCurrentUser) { $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($this->pageRecord); } diff --git a/typo3/sysext/recycler/Resources/Private/Partials/RecordsTable/DeletedRecord.html b/typo3/sysext/recycler/Resources/Private/Partials/RecordsTable/DeletedRecord.html index 8cf321924519..e3cfee9adb66 100644 --- a/typo3/sysext/recycler/Resources/Private/Partials/RecordsTable/DeletedRecord.html +++ b/typo3/sysext/recycler/Resources/Private/Partials/RecordsTable/DeletedRecord.html @@ -1,10 +1,9 @@ <html xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers" data-namespace-typo3-fluid="true"> <tr data-uid="{record.uid}" data-table="{record.table}" data-recordtitle="{record.title}" data-parent-deleted="{record.isParentDeleted}"> <td class="nowrap"> - <label class="btn btn-default btn-checkbox"> - <input type="checkbox"> - <span class="t3-icon fa"></span> - </label> + <span class="form-check form-toggle"> + <input class="form-check-input t3js-multi-record-selection-check" type="checkbox"> + </span> </td> <td class="nowrap">{record.tableTitle}</td> <td class="nowrap"><f:format.raw>{record.icon}</f:format.raw> {record.title}</td> diff --git a/typo3/sysext/recycler/Resources/Private/Templates/RecyclerModule/Index.html b/typo3/sysext/recycler/Resources/Private/Templates/RecyclerModule/Index.html index 1f2dd5513ec2..1b52c3d81d48 100644 --- a/typo3/sysext/recycler/Resources/Private/Templates/RecyclerModule/Index.html +++ b/typo3/sysext/recycler/Resources/Private/Templates/RecyclerModule/Index.html @@ -27,14 +27,12 @@ </div> </div> </form> - <f:render section="buttons" arguments="{allowDelete: allowDelete}"/> - <div class="table-fit"> + <f:render section="multiRecordSelectionActions" arguments="{allowDelete: allowDelete}"/> + <div class="table-fit mb-0"> <table class="table table-hover" id="itemsInRecycler"> <thead> <tr> - <th> - <button type="button" class="btn btn-default t3js-toggle-all"><core:icon identifier="actions-document-select" /></button> - </th> + <th><f:render section="multiRecordSelectionCheckboxActions" /></th> <th><f:translate key="table.header.recordtype" /></th> <th><f:translate key="table.header.record" /></th> <th><f:translate key="table.header.tstamp" /></th> @@ -47,27 +45,61 @@ </tbody> </table> </div> - <f:render section="buttons" arguments="{allowDelete: allowDelete}"/> + <f:render section="multiRecordSelectionActions" arguments="{allowDelete: allowDelete}"/> <nav> </nav> </div> </f:section> -<f:section name="buttons"> - <div class="form-group"> - <button class="btn btn-default disabled" data-action="massundo" disabled> - <core:icon identifier="actions-edit-undo" /> - <span class="text"> - <f:translate key="button.undo" /> - </span> +<f:section name="multiRecordSelectionCheckboxActions"> + <div class="btn-group dropdown position-static"> + <button type="button" class="btn btn-borderless dropdown-toggle" data-bs-target="multi-record-selection-check-actions" data-bs-toggle="dropdown" data-bs-boundary="window" aria-expanded="false"> + <core:icon identifier="content-special-div" size="small" /> </button> - <f:if condition="{allowDelete}"> - <button class="btn btn-default disabled" data-action="massdelete" disabled> - <core:icon identifier="actions-edit-delete" /> - <span class="text"> - <f:translate key="button.delete" /> - </span> - </button> - </f:if> + <ul id="multi-record-selection-check-actions" class="dropdown-menu"> + <li> + <button type="button" class="btn btn-link dropdown-item disabled" data-multi-record-selection-check-action="check-all" title="{f:translate(key: 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.checkAll')}"> + <core:icon identifier="actions-check-square" size="small" /> <f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.checkAll" /> + </button> + </li> + <li> + <button type="button" class="btn btn-link dropdown-item disabled" data-multi-record-selection-check-action="check-none" title="{f:translate(key: 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.uncheckAll')}"> + <core:icon identifier="actions-square" size="small" /> <f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.uncheckAll" /> + </button> + </li> + <li> + <button type="button" class="btn btn-link dropdown-item" data-multi-record-selection-check-action="toggle" title="{f:translate(key: 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.toggleSelection')}"> + <core:icon identifier="actions-document-select" size="small" /> <f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.toggleSelection" /> + </button> + </li> + </ul> + </div> +</f:section> + +<f:section name="multiRecordSelectionActions"> + <div class="multi-record-selection-actions-wrapper"> + <div class="row row-cols-auto align-items-center g-2 t3js-multi-record-selection-actions hidden"> + <div class="col"> + <strong><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.selection"/></strong> + </div> + <div class="col"> + <button class="btn btn-default btn-sm" data-multi-record-selection-action="massundo" data-multi-record-selection-action-config='{"idField": "uid"}'> + <core:icon identifier="actions-edit-undo" /> + <span class="text"> + <f:translate key="button.undo" /> + </span> + </button> + </div> + <f:if condition="{allowDelete}"> + <div class="col"> + <button class="btn btn-default btn-sm" data-multi-record-selection-action="massdelete" data-multi-record-selection-action-config='{"idField": "uid"}'> + <core:icon identifier="actions-edit-delete" /> + <span class="text"> + <f:translate key="button.delete" /> + </span> + </button> + </div> + </f:if> + </div> </div> </f:section> diff --git a/typo3/sysext/recycler/Resources/Public/JavaScript/Recycler.js b/typo3/sysext/recycler/Resources/Public/JavaScript/Recycler.js index 87e1e3838bf7..3b20fa40e4fd 100644 --- a/typo3/sysext/recycler/Resources/Public/JavaScript/Recycler.js +++ b/typo3/sysext/recycler/Resources/Public/JavaScript/Recycler.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery","nprogress","TYPO3/CMS/Backend/ActionButton/DeferredAction","TYPO3/CMS/Backend/Modal","TYPO3/CMS/Backend/Notification","TYPO3/CMS/Backend/Severity","TYPO3/CMS/Backend/Input/Clearable"],(function(e,t,a,s,l,n,i,r){"use strict";var d;a=__importDefault(a),s=__importDefault(s),function(e){e.searchForm="#recycler-form",e.searchText="#recycler-form [name=search-text]",e.searchSubmitBtn="#recycler-form button[type=submit]",e.depthSelector="#recycler-form [name=depth]",e.tableSelector="#recycler-form [name=pages]",e.recyclerTable="#itemsInRecycler",e.paginator="#recycler-index nav",e.reloadAction="a[data-action=reload]",e.massUndo="button[data-action=massundo]",e.massDelete="button[data-action=massdelete]",e.toggleAll=".t3js-toggle-all"}(d||(d={}));class o{constructor(){this.elements={},this.paging={currentPage:1,totalPages:1,totalItems:0,itemsPerPage:TYPO3.settings.Recycler.pagingSize},this.markedRecordsForMassAction=[],this.allToggled=!1,this.handleCheckboxSelects=e=>{const t=a.default(e.currentTarget),s=t.parents("tr"),l=s.data("table")+":"+s.data("uid");if(t.prop("checked"))this.markedRecordsForMassAction.push(l),s.addClass("warning");else{const e=this.markedRecordsForMassAction.indexOf(l);e>-1&&this.markedRecordsForMassAction.splice(e,1),s.removeClass("warning")}if(this.markedRecordsForMassAction.length>0){this.elements.$massUndo.hasClass("disabled")&&this.elements.$massUndo.removeClass("disabled").removeAttr("disabled"),this.elements.$massDelete.hasClass("disabled")&&this.elements.$massDelete.removeClass("disabled").removeAttr("disabled");const e=this.createMessage(TYPO3.lang["button.undoselected"],[this.markedRecordsForMassAction.length]),t=this.createMessage(TYPO3.lang["button.deleteselected"],[this.markedRecordsForMassAction.length]);this.elements.$massUndo.find("span.text").text(e),this.elements.$massDelete.find("span.text").text(t)}else this.resetMassActionButtons()},this.deleteRecord=e=>{if(TYPO3.settings.Recycler.deleteDisable)return;const t=a.default(e.currentTarget).parents("tr"),s="TBODY"!==t.parent().prop("tagName");let i,d;if(s)i=this.markedRecordsForMassAction,d=TYPO3.lang["modal.massdelete.text"];else{const e=t.data("uid"),a=t.data("table"),s=t.data("recordtitle");i=[a+":"+e],d="pages"===a?TYPO3.lang["modal.deletepage.text"]:TYPO3.lang["modal.deletecontent.text"],d=this.createMessage(d,[s,"["+i[0]+"]"])}n.confirm(TYPO3.lang["modal.delete.header"],d,r.error,[{text:TYPO3.lang["button.cancel"],btnClass:"btn-default",trigger:function(){n.dismiss()}},{text:TYPO3.lang["button.delete"],btnClass:"btn-danger",action:new l(()=>Promise.resolve(this.callAjaxAction("delete",i,s)))}])},this.undoRecord=e=>{const t=a.default(e.currentTarget).parents("tr"),s="TBODY"!==t.parent().prop("tagName");let i,d,o;if(s)i=this.markedRecordsForMassAction,d=TYPO3.lang["modal.massundo.text"],o=!0;else{const e=t.data("uid"),a=t.data("table"),s=t.data("recordtitle");i=[a+":"+e],o="pages"===a,d=o?TYPO3.lang["modal.undopage.text"]:TYPO3.lang["modal.undocontent.text"],d=this.createMessage(d,[s,"["+i[0]+"]"]),o&&t.data("parentDeleted")&&(d+=TYPO3.lang["modal.undo.parentpages"])}let c=null;c=o?a.default("<div />").append(a.default("<p />").text(d),a.default("<div />",{class:"checkbox"}).append(a.default("<label />").append(TYPO3.lang["modal.undo.recursive"]).prepend(a.default("<input />",{id:"undo-recursive",type:"checkbox"})))):a.default("<p />").text(d),n.confirm(TYPO3.lang["modal.undo.header"],c,r.ok,[{text:TYPO3.lang["button.cancel"],btnClass:"btn-default",trigger:function(){n.dismiss()}},{text:TYPO3.lang["button.undo"],btnClass:"btn-success",action:new l(()=>Promise.resolve(this.callAjaxAction("undo","object"==typeof i?i:[i],s,c.find("#undo-recursive").prop("checked"))))}])},a.default(()=>{this.initialize()})}static refreshPageTree(){top.document.dispatchEvent(new CustomEvent("typo3:pagetree:refresh"))}getElements(){this.elements={$searchForm:a.default(d.searchForm),$searchTextField:a.default(d.searchText),$searchSubmitBtn:a.default(d.searchSubmitBtn),$depthSelector:a.default(d.depthSelector),$tableSelector:a.default(d.tableSelector),$recyclerTable:a.default(d.recyclerTable),$tableBody:a.default(d.recyclerTable).find("tbody"),$paginator:a.default(d.paginator),$reloadAction:a.default(d.reloadAction),$massUndo:a.default(d.massUndo),$massDelete:a.default(d.massDelete),$toggleAll:a.default(d.toggleAll)}}registerEvents(){this.elements.$searchForm.on("submit",e=>{e.preventDefault(),""!==this.elements.$searchTextField.val()&&this.loadDeletedElements()}),this.elements.$searchTextField.on("keyup",e=>{""!==a.default(e.currentTarget).val()?this.elements.$searchSubmitBtn.removeClass("disabled"):(this.elements.$searchSubmitBtn.addClass("disabled"),this.loadDeletedElements())}),this.elements.$searchTextField.get(0).clearable({onClear:()=>{this.elements.$searchSubmitBtn.addClass("disabled"),this.loadDeletedElements()}}),this.elements.$depthSelector.on("change",()=>{a.default.when(this.loadAvailableTables()).done(()=>{this.loadDeletedElements()})}),this.elements.$tableSelector.on("change",()=>{this.paging.currentPage=1,this.loadDeletedElements()}),this.elements.$recyclerTable.on("click","[data-action=undo]",this.undoRecord),this.elements.$recyclerTable.on("click","[data-action=delete]",this.deleteRecord),this.elements.$reloadAction.on("click",e=>{e.preventDefault(),a.default.when(this.loadAvailableTables()).done(()=>{this.loadDeletedElements()})}),this.elements.$paginator.on("click","a[data-action]",e=>{e.preventDefault();const t=a.default(e.currentTarget);let s=!1;switch(t.data("action")){case"previous":this.paging.currentPage>1&&(this.paging.currentPage--,s=!0);break;case"next":this.paging.currentPage<this.paging.totalPages&&(this.paging.currentPage++,s=!0);break;case"page":this.paging.currentPage=parseInt(t.find("span").text(),10),s=!0}s&&this.loadDeletedElements()}),TYPO3.settings.Recycler.deleteDisable?this.elements.$massDelete.remove():this.elements.$massDelete.show(),this.elements.$recyclerTable.on("show.bs.collapse hide.bs.collapse","tr.collapse",e=>{let t,s,l=a.default(e.currentTarget).prev("tr").find("[data-action=expand]").find(".t3-icon");switch(e.type){case"show":t="t3-icon-pagetree-collapse",s="t3-icon-pagetree-expand";break;case"hide":t="t3-icon-pagetree-expand",s="t3-icon-pagetree-collapse"}l.removeClass(t).addClass(s)}),this.elements.$toggleAll.on("click",()=>{this.allToggled=!this.allToggled,a.default('input[type="checkbox"]').prop("checked",this.allToggled).trigger("change")}),this.elements.$recyclerTable.on("change","tr input[type=checkbox]",this.handleCheckboxSelects),this.elements.$massUndo.on("click",this.undoRecord),this.elements.$massDelete.on("click",this.deleteRecord)}initialize(){s.default.configure({parent:".module-loading-indicator",showSpinner:!1}),this.getElements(),this.registerEvents(),TYPO3.settings.Recycler.depthSelection>0?this.elements.$depthSelector.val(TYPO3.settings.Recycler.depthSelection).trigger("change"):a.default.when(this.loadAvailableTables()).done(()=>{this.loadDeletedElements()})}resetMassActionButtons(){this.markedRecordsForMassAction=[],this.elements.$massUndo.addClass("disabled").attr("disabled",!0),this.elements.$massUndo.find("span.text").text(TYPO3.lang["button.undo"]),this.elements.$massDelete.addClass("disabled").attr("disabled",!0),this.elements.$massDelete.find("span.text").text(TYPO3.lang["button.delete"])}loadAvailableTables(){return a.default.ajax({url:TYPO3.settings.ajaxUrls.recycler,dataType:"json",data:{action:"getTables",startUid:TYPO3.settings.Recycler.startUid,depth:this.elements.$depthSelector.find("option:selected").val()},beforeSend:()=>{s.default.start(),this.elements.$tableSelector.val(""),this.paging.currentPage=1},success:e=>{const t=[];this.elements.$tableSelector.children().remove(),a.default.each(e,(e,s)=>{const l=s[0],n=s[1],i=(s[2]?s[2]:TYPO3.lang.label_allrecordtypes)+" ("+n+")";t.push(a.default("<option />").val(l).text(i))}),t.length>0&&(this.elements.$tableSelector.append(t),""!==TYPO3.settings.Recycler.tableSelection&&this.elements.$tableSelector.val(TYPO3.settings.Recycler.tableSelection))},complete:()=>{s.default.done()}})}loadDeletedElements(){return a.default.ajax({url:TYPO3.settings.ajaxUrls.recycler,dataType:"json",data:{action:"getDeletedRecords",depth:this.elements.$depthSelector.find("option:selected").val(),startUid:TYPO3.settings.Recycler.startUid,table:this.elements.$tableSelector.find("option:selected").val(),filterTxt:this.elements.$searchTextField.val(),start:(this.paging.currentPage-1)*this.paging.itemsPerPage,limit:this.paging.itemsPerPage},beforeSend:()=>{s.default.start(),this.resetMassActionButtons()},success:e=>{this.elements.$tableBody.html(e.rows),this.buildPaginator(e.totalItems)},complete:()=>{s.default.done()}})}callAjaxAction(e,t,l,n=!1){let r={records:t,action:""},d=!1;if("undo"===e)r.action="undoRecords",r.recursive=n?1:0,d=!0;else{if("delete"!==e)return;r.action="deleteRecords"}return a.default.ajax({url:TYPO3.settings.ajaxUrls.recycler,type:"POST",dataType:"json",data:r,beforeSend:()=>{s.default.start()},success:e=>{e.success?i.success("",e.message):i.error("",e.message),this.paging.currentPage=1,a.default.when(this.loadAvailableTables()).done(()=>{this.loadDeletedElements(),l&&this.resetMassActionButtons(),d&&o.refreshPageTree(),this.allToggled=!1})},complete:()=>{s.default.done()}})}createMessage(e,t){return void 0===e?"":e.replace(/\{([0-9]+)\}/g,(function(e,a){return t[a]}))}buildPaginator(e){if(0===e)return void this.elements.$paginator.contents().remove();if(this.paging.totalItems=e,this.paging.totalPages=Math.ceil(e/this.paging.itemsPerPage),1===this.paging.totalPages)return void this.elements.$paginator.contents().remove();const t=a.default("<ul />",{class:"pagination"}),s=[],l=a.default("<li />",{class:"page-item"}).append(a.default("<a />",{class:"page-link","data-action":"previous"}).append(a.default("<span />",{class:"t3-icon fa fa-arrow-left"}))),n=a.default("<li />",{class:"page-item"}).append(a.default("<a />",{class:"page-link","data-action":"next"}).append(a.default("<span />",{class:"t3-icon fa fa-arrow-right"})));1===this.paging.currentPage&&l.disablePagingAction(),this.paging.currentPage===this.paging.totalPages&&n.disablePagingAction();for(let e=1;e<=this.paging.totalPages;e++){const t=a.default("<li />",{class:"page-item"+(this.paging.currentPage===e?" active":"")});t.append(a.default("<a />",{class:"page-link","data-action":"page"}).append(a.default("<span />").text(e))),s.push(t)}t.append(l,s,n),this.elements.$paginator.html(t)}}return a.default.fn.disablePagingAction=function(){a.default(this).addClass("disabled").find(".t3-icon").unwrap().wrap(a.default("<span />",{class:"page-link"}))},new o})); \ No newline at end of file +var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery","nprogress","TYPO3/CMS/Backend/ActionButton/DeferredAction","TYPO3/CMS/Backend/Modal","TYPO3/CMS/Backend/Notification","TYPO3/CMS/Backend/Severity","TYPO3/CMS/Core/Event/RegularEvent","TYPO3/CMS/Backend/Input/Clearable"],(function(e,t,a,s,n,l,i,r,d){"use strict";var o;a=__importDefault(a),s=__importDefault(s),d=__importDefault(d),function(e){e.searchForm="#recycler-form",e.searchText="#recycler-form [name=search-text]",e.searchSubmitBtn="#recycler-form button[type=submit]",e.depthSelector="#recycler-form [name=depth]",e.tableSelector="#recycler-form [name=pages]",e.recyclerTable="#itemsInRecycler",e.paginator="#recycler-index nav",e.reloadAction="a[data-action=reload]",e.undo="a[data-action=undo]",e.delete="a[data-action=delete]",e.massUndo="button[data-multi-record-selection-action=massundo]",e.massDelete="button[data-multi-record-selection-action=massdelete]"}(o||(o={}));class c{constructor(){this.elements={},this.paging={currentPage:1,totalPages:1,totalItems:0,itemsPerPage:TYPO3.settings.Recycler.pagingSize},this.markedRecordsForMassAction=[],this.handleCheckboxStateChanged=e=>{const t=a.default(e.target),s=t.parents("tr"),n=s.data("table")+":"+s.data("uid");if(t.prop("checked"))this.markedRecordsForMassAction.push(n);else{const e=this.markedRecordsForMassAction.indexOf(n);e>-1&&this.markedRecordsForMassAction.splice(e,1)}this.markedRecordsForMassAction.length>0?(this.elements.$massUndo.find("span.text").text(this.createMessage(TYPO3.lang["button.undoselected"],[this.markedRecordsForMassAction.length])),this.elements.$massDelete.find("span.text").text(this.createMessage(TYPO3.lang["button.deleteselected"],[this.markedRecordsForMassAction.length]))):this.resetMassActionButtons()},this.deleteRecord=e=>{if(TYPO3.settings.Recycler.deleteDisable)return;const t=a.default(e.target).parents("tr"),s="TBODY"!==t.parent().prop("tagName");let i,d;if(s)i=this.markedRecordsForMassAction,d=TYPO3.lang["modal.massdelete.text"];else{const e=t.data("uid"),a=t.data("table"),s=t.data("recordtitle");i=[a+":"+e],d="pages"===a?TYPO3.lang["modal.deletepage.text"]:TYPO3.lang["modal.deletecontent.text"],d=this.createMessage(d,[s,"["+i[0]+"]"])}l.confirm(TYPO3.lang["modal.delete.header"],d,r.error,[{text:TYPO3.lang["button.cancel"],btnClass:"btn-default",trigger:function(){l.dismiss()}},{text:TYPO3.lang["button.delete"],btnClass:"btn-danger",action:new n(()=>Promise.resolve(this.callAjaxAction("delete",i,s)))}])},this.undoRecord=e=>{const t=a.default(e.target).parents("tr"),s="TBODY"!==t.parent().prop("tagName");let i,d,o;if(s)i=this.markedRecordsForMassAction,d=TYPO3.lang["modal.massundo.text"],o=!0;else{const e=t.data("uid"),a=t.data("table"),s=t.data("recordtitle");i=[a+":"+e],o="pages"===a,d=o?TYPO3.lang["modal.undopage.text"]:TYPO3.lang["modal.undocontent.text"],d=this.createMessage(d,[s,"["+i[0]+"]"]),o&&t.data("parentDeleted")&&(d+=TYPO3.lang["modal.undo.parentpages"])}let c=null;c=o?a.default("<div />").append(a.default("<p />").text(d),a.default("<div />",{class:"checkbox"}).append(a.default("<label />").append(TYPO3.lang["modal.undo.recursive"]).prepend(a.default("<input />",{id:"undo-recursive",type:"checkbox"})))):a.default("<p />").text(d),l.confirm(TYPO3.lang["modal.undo.header"],c,r.ok,[{text:TYPO3.lang["button.cancel"],btnClass:"btn-default",trigger:function(){l.dismiss()}},{text:TYPO3.lang["button.undo"],btnClass:"btn-success",action:new n(()=>Promise.resolve(this.callAjaxAction("undo","object"==typeof i?i:[i],s,c.find("#undo-recursive").prop("checked"))))}])},a.default(()=>{this.initialize()})}static refreshPageTree(){top.document.dispatchEvent(new CustomEvent("typo3:pagetree:refresh"))}getElements(){this.elements={$searchForm:a.default(o.searchForm),$searchTextField:a.default(o.searchText),$searchSubmitBtn:a.default(o.searchSubmitBtn),$depthSelector:a.default(o.depthSelector),$tableSelector:a.default(o.tableSelector),$recyclerTable:a.default(o.recyclerTable),$tableBody:a.default(o.recyclerTable).find("tbody"),$paginator:a.default(o.paginator),$reloadAction:a.default(o.reloadAction),$massUndo:a.default(o.massUndo),$massDelete:a.default(o.massDelete)}}registerEvents(){this.elements.$searchForm.on("submit",e=>{e.preventDefault(),""!==this.elements.$searchTextField.val()&&this.loadDeletedElements()}),this.elements.$searchTextField.on("keyup",e=>{""!==a.default(e.currentTarget).val()?this.elements.$searchSubmitBtn.removeClass("disabled"):(this.elements.$searchSubmitBtn.addClass("disabled"),this.loadDeletedElements())}),this.elements.$searchTextField.get(0).clearable({onClear:()=>{this.elements.$searchSubmitBtn.addClass("disabled"),this.loadDeletedElements()}}),this.elements.$depthSelector.on("change",()=>{a.default.when(this.loadAvailableTables()).done(()=>{this.loadDeletedElements()})}),this.elements.$tableSelector.on("change",()=>{this.paging.currentPage=1,this.loadDeletedElements()}),new d.default("click",this.undoRecord).delegateTo(document,o.undo),new d.default("click",this.deleteRecord).delegateTo(document,o.delete),this.elements.$reloadAction.on("click",e=>{e.preventDefault(),a.default.when(this.loadAvailableTables()).done(()=>{this.loadDeletedElements()})}),this.elements.$paginator.on("click","a[data-action]",e=>{e.preventDefault();const t=a.default(e.currentTarget);let s=!1;switch(t.data("action")){case"previous":this.paging.currentPage>1&&(this.paging.currentPage--,s=!0);break;case"next":this.paging.currentPage<this.paging.totalPages&&(this.paging.currentPage++,s=!0);break;case"page":this.paging.currentPage=parseInt(t.find("span").text(),10),s=!0}s&&this.loadDeletedElements()}),TYPO3.settings.Recycler.deleteDisable?this.elements.$massDelete.remove():this.elements.$massDelete.show(),this.elements.$recyclerTable.on("show.bs.collapse hide.bs.collapse","tr.collapse",e=>{let t,s,n=a.default(e.currentTarget).prev("tr").find("[data-action=expand]").find(".t3-icon");switch(e.type){case"show":t="t3-icon-pagetree-collapse",s="t3-icon-pagetree-expand";break;case"hide":t="t3-icon-pagetree-expand",s="t3-icon-pagetree-collapse"}n.removeClass(t).addClass(s)}),new d.default("checkbox:state:changed",this.handleCheckboxStateChanged).bindTo(document),new d.default("multiRecordSelection:action:massundo",this.undoRecord).bindTo(document),new d.default("multiRecordSelection:action:massdelete",this.deleteRecord).bindTo(document)}initialize(){s.default.configure({parent:".module-loading-indicator",showSpinner:!1}),this.getElements(),this.registerEvents(),TYPO3.settings.Recycler.depthSelection>0?this.elements.$depthSelector.val(TYPO3.settings.Recycler.depthSelection).trigger("change"):a.default.when(this.loadAvailableTables()).done(()=>{this.loadDeletedElements()})}resetMassActionButtons(){this.markedRecordsForMassAction=[],this.elements.$massUndo.find("span.text").text(TYPO3.lang["button.undo"]),this.elements.$massDelete.find("span.text").text(TYPO3.lang["button.delete"]),document.dispatchEvent(new Event("multiRecordSelection:actions:hide"))}loadAvailableTables(){return a.default.ajax({url:TYPO3.settings.ajaxUrls.recycler,dataType:"json",data:{action:"getTables",startUid:TYPO3.settings.Recycler.startUid,depth:this.elements.$depthSelector.find("option:selected").val()},beforeSend:()=>{s.default.start(),this.elements.$tableSelector.val(""),this.paging.currentPage=1},success:e=>{const t=[];this.elements.$tableSelector.children().remove(),a.default.each(e,(e,s)=>{const n=s[0],l=s[1],i=(s[2]?s[2]:TYPO3.lang.label_allrecordtypes)+" ("+l+")";t.push(a.default("<option />").val(n).text(i))}),t.length>0&&(this.elements.$tableSelector.append(t),""!==TYPO3.settings.Recycler.tableSelection&&this.elements.$tableSelector.val(TYPO3.settings.Recycler.tableSelection))},complete:()=>{s.default.done()}})}loadDeletedElements(){return a.default.ajax({url:TYPO3.settings.ajaxUrls.recycler,dataType:"json",data:{action:"getDeletedRecords",depth:this.elements.$depthSelector.find("option:selected").val(),startUid:TYPO3.settings.Recycler.startUid,table:this.elements.$tableSelector.find("option:selected").val(),filterTxt:this.elements.$searchTextField.val(),start:(this.paging.currentPage-1)*this.paging.itemsPerPage,limit:this.paging.itemsPerPage},beforeSend:()=>{s.default.start(),this.resetMassActionButtons()},success:e=>{this.elements.$tableBody.html(e.rows),this.buildPaginator(e.totalItems)},complete:()=>{s.default.done()}})}callAjaxAction(e,t,n,l=!1){let r={records:t,action:""},d=!1;if("undo"===e)r.action="undoRecords",r.recursive=l?1:0,d=!0;else{if("delete"!==e)return;r.action="deleteRecords"}return a.default.ajax({url:TYPO3.settings.ajaxUrls.recycler,type:"POST",dataType:"json",data:r,beforeSend:()=>{s.default.start()},success:e=>{e.success?i.success("",e.message):i.error("",e.message),this.paging.currentPage=1,a.default.when(this.loadAvailableTables()).done(()=>{this.loadDeletedElements(),n&&this.resetMassActionButtons(),d&&c.refreshPageTree()})},complete:()=>{s.default.done()}})}createMessage(e,t){return void 0===e?"":e.replace(/\{([0-9]+)\}/g,(function(e,a){return t[a]}))}buildPaginator(e){if(0===e)return void this.elements.$paginator.contents().remove();if(this.paging.totalItems=e,this.paging.totalPages=Math.ceil(e/this.paging.itemsPerPage),1===this.paging.totalPages)return void this.elements.$paginator.contents().remove();const t=a.default("<ul />",{class:"pagination"}),s=[],n=a.default("<li />",{class:"page-item"}).append(a.default("<a />",{class:"page-link","data-action":"previous"}).append(a.default("<span />",{class:"t3-icon fa fa-arrow-left"}))),l=a.default("<li />",{class:"page-item"}).append(a.default("<a />",{class:"page-link","data-action":"next"}).append(a.default("<span />",{class:"t3-icon fa fa-arrow-right"})));1===this.paging.currentPage&&n.disablePagingAction(),this.paging.currentPage===this.paging.totalPages&&l.disablePagingAction();for(let e=1;e<=this.paging.totalPages;e++){const t=a.default("<li />",{class:"page-item"+(this.paging.currentPage===e?" active":"")});t.append(a.default("<a />",{class:"page-link","data-action":"page"}).append(a.default("<span />").text(e))),s.push(t)}t.append(n,s,l),this.elements.$paginator.html(t)}}return a.default.fn.disablePagingAction=function(){a.default(this).addClass("disabled").find(".t3-icon").unwrap().wrap(a.default("<span />",{class:"page-link"}))},new c})); \ No newline at end of file -- GitLab