[FEATURE] Add AJAX logic for delete records in ListModule 03/35203/11
authorFrank Nägler <typo3@naegler.net>
Tue, 9 Dec 2014 19:45:56 +0000 (20:45 +0100)
committerBenjamin Mack <benni@typo3.org>
Sun, 4 Jan 2015 20:20:08 +0000 (21:20 +0100)
This patch introduce an AJAX call for delete records
in ListModule. The confirm message is build with a
bootstrap modal. instead of JavaScript confirm function.

Resolves: #63715
Releases: master
Change-Id: I7ed26e78029d61198d686aa5c21a07734ac6cea6
Reviewed-on: http://review.typo3.org/35203
Tested-by: Stefan Froemken <froemken@gmail.com>
Tested-by: Benjamin Mack <benni@typo3.org>
Reviewed-by: Benjamin Kott <info@bk2k.info>
Tested-by: Benjamin Kott <info@bk2k.info>
Reviewed-by: Benjamin Mack <benni@typo3.org>
typo3/sysext/backend/Classes/Controller/SimpleDataHandlerController.php
typo3/sysext/backend/Resources/Public/JavaScript/AjaxDataHandler.js
typo3/sysext/core/Classes/DataHandling/DataHandler.php
typo3/sysext/lang/locallang_mod_web_list.xlf
typo3/sysext/recordlist/Classes/RecordList.php
typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php

index 087de77..b24cbd5 100644 (file)
@@ -14,6 +14,7 @@ namespace TYPO3\CMS\Backend\Controller;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Messaging\AbstractMessage;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -272,6 +273,9 @@ class SimpleDataHandlerController {
                                        'message'  => $message->getMessage(),
                                        'severity' => $message->getSeverity()
                                );
+                               if ($message->getSeverity() === AbstractMessage::ERROR) {
+                                       $content['hasErrors'] = TRUE;
+                               }
                        }
                }
                $ajaxRequestHandler->setContentFormat('json');
index dcd61ae..e3e0beb 100644 (file)
 /**
  * AjaxDataHandler - Javascript functions to work with AJAX and interacting with tce_db.php
  */
-define('TYPO3/CMS/Backend/AjaxDataHandler', ['jquery', 'TYPO3/CMS/Backend/FlashMessages'], function ($) {
+define('TYPO3/CMS/Backend/AjaxDataHandler', ['jquery', 'TYPO3/CMS/Backend/FlashMessages', 'TYPO3/CMS/Backend/Modal'], function ($) {
        var AjaxDataHandler = {};
 
        AjaxDataHandler.initialize = function() {
 
-               // click events for all action icons to hide/unhide
+               // HIDE/UNHIDE: click events for all action icons to hide/unhide
                $(document).on('click', '.t3js-record-hide', function(evt) {
                        evt.preventDefault();
                        var $anchorElement = $(this);
@@ -43,9 +43,7 @@ define('TYPO3/CMS/Backend/AjaxDataHandler', ['jquery', 'TYPO3/CMS/Backend/FlashM
                                AjaxDataHandler._hideSpinnerIcon($iconElement);
                                // print messages on errors
                                if (result.hasErrors) {
-                                       $.each(result.messages, function(position, message) {
-                                               top.TYPO3.Flashmessage.display(message.severity, message.title, message.message);
-                                       });
+                                       AjaxDataHandler.handleErrors(result);
                                        // revert to the old class
                                        $iconElement.addClass(removeClass);
                                } else {
@@ -62,13 +60,111 @@ define('TYPO3/CMS/Backend/AjaxDataHandler', ['jquery', 'TYPO3/CMS/Backend/FlashM
                                                $rowElement.fadeTo('fast', 1);
                                        });
 
-                                       if (table === 'pages' && top.TYPO3 && top.TYPO3.Backend && top.TYPO3.Backend.NavigationContainer && top.TYPO3.Backend.NavigationContainer.PageTree) {
-                                               top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
+                                       if (table === 'pages') {
+                                               AjaxDataHandler.refreshPageTree();
                                        }
                                }
-
                        });
                });
+
+               // DELETE: click events for all action icons to delete
+               $(document).on('click', '.t3js-record-delete', function(evt) {
+                       evt.preventDefault();
+                       var $anchorElement = $(this);
+                       TYPO3.Modal.confirm($anchorElement.data('title'), $anchorElement.data('message'), TYPO3.Severity.error, [
+                               {
+                                       text: TYPO3.lang['button.cancel'],
+                                       active: true,
+                                       trigger: function() {
+                                               TYPO3.Modal.dismiss();
+                                       }
+                               },
+                               {
+                                       text: TYPO3.lang['button.delete'],
+                                       btnClass: 'btn-danger',
+                                       trigger: function() {
+                                               TYPO3.Modal.dismiss();
+                                               AjaxDataHandler.deleteRecord($anchorElement);
+                                       }
+                               }
+                       ]);
+               });
+       };
+
+       /**
+        * delete record by given element (icon in table)
+        * don't call it directly!
+        *
+        * @param element
+        */
+       AjaxDataHandler.deleteRecord = function(element) {
+               var $anchorElement = $(element);
+               var elementClass = 'fa-trash';
+               var params = $anchorElement.data('params');
+               var $iconElement = $anchorElement.find('span');
+
+               // add a spinner
+               $iconElement.removeClass(elementClass);
+               AjaxDataHandler._showSpinnerIcon($iconElement);
+
+               // make the AJAX call to toggle the visibility
+               AjaxDataHandler._call(params).done(function(result) {
+                       AjaxDataHandler._hideSpinnerIcon($iconElement);
+                       // revert to the old class
+                       $iconElement.addClass(elementClass);
+                       // print messages on errors
+                       if (result.hasErrors) {
+                               AjaxDataHandler.handleErrors(result);
+                       } else {
+                               var $table = $anchorElement.closest('table[data-table]');
+                               var $panel = $anchorElement.closest('.panel');
+                               var $panelHeading = $panel.find('.panel-heading');
+                               var table = $table.data('table');
+                               var $rowElements = $anchorElement.closest('tr[data-uid]');
+                               var uid = $rowElements.data('uid');
+                               var $translatedRowElements = $table.find('[data-l10parent=' + uid + ']').closest('tr[data-uid]');
+                               $rowElements = $rowElements.add($translatedRowElements);
+
+                               $rowElements.fadeTo('slow', 0.4, function() {
+                                       $rowElements.slideUp('slow', 0, function() {
+                                               $rowElements.remove();
+                                               if ($table.find('tbody tr').length === 0) {
+                                                       $panel.slideUp('slow');
+                                               }
+                                       });
+                               });
+                               if ($anchorElement.data('l10parent') === '0' || $anchorElement.data('l10parent') === '') {
+                                       var count = Number($panelHeading.find('.t3js-table-total-items').html());
+                                       $panelHeading.find('.t3js-table-total-items').html(count-1);
+                               }
+
+                               if (table === 'pages') {
+                                       AjaxDataHandler.refreshPageTree();
+                               }
+                       }
+               });
+       };
+
+       /**
+        * handle the errors from result object
+        *
+        * @param result
+        * @private
+        */
+       AjaxDataHandler.handleErrors = function(result) {
+               $.each(result.messages, function(position, message) {
+                       top.TYPO3.Flashmessage.display(message.severity, message.title, message.message);
+               });
+       };
+
+       /**
+        * refresh the page tree
+        * @private
+        */
+       AjaxDataHandler.refreshPageTree = function() {
+               if (top.TYPO3 && top.TYPO3.Backend && top.TYPO3.Backend.NavigationContainer && top.TYPO3.Backend.NavigationContainer.PageTree) {
+                       top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
+               }
        };
 
        /**
index 39972d2..faced70 100644 (file)
@@ -4406,6 +4406,12 @@ class DataHandler {
                                $this->deleteSpecificPage($deleteId, $forceHardDelete);
                        }
                } else {
+                       $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, htmlspecialchars($res), '', FlashMessage::ERROR, TRUE);
+                       /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */
+                       $flashMessageService = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessageService::class);
+                       /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */
+                       $flashMessageService->getMessageQueueByIdentifier()->addMessage($flashMessage);
+
                        $this->newlog($res, 1);
                }
        }
index 8305f87..447c22e 100644 (file)
                        <trans-unit id="noRecordsOnThisPage" xml:space="preserve">
                                <source>There are no records on this page.</source>
                        </trans-unit>
+                       <trans-unit id="button.cancel" xml:space="preserve">
+                               <source>Cancel</source>
+                       </trans-unit>
+                       <trans-unit id="button.delete" xml:space="preserve">
+                               <source>Delete</source>
+                       </trans-unit>
+
                </body>
        </file>
 </xliff>
index bb57897..bbb3ad4 100644 (file)
@@ -206,6 +206,7 @@ class RecordList {
                $this->menuConfig();
                // Store session data
                $GLOBALS['BE_USER']->setAndSaveSessionData(\TYPO3\CMS\Recordlist\RecordList::class, $sessionData);
+               $GLOBALS['TBE_TEMPLATE']->getPageRenderer()->addInlineLanguageLabelFile('EXT:lang/locallang_mod_web_list.xlf');
        }
 
        /**
index a598ace..7e762b6 100644 (file)
@@ -489,12 +489,12 @@ class DatabaseRecordList extends AbstractDatabaseRecordList {
                        $theData = array();
                        if ($this->disableSingleTableView) {
                                $theData[$titleCol] = '<span class="c-table">' . BackendUtility::wrapInHelp($table, '', $tableTitle)
-                                       . '</span> (' . $this->totalItems . ')';
+                                       . '</span> (<span class="t3js-table-total-items">' . $this->totalItems . '</span>)';
                        } else {
                                $icon = $this->table
                                        ? IconUtility::getSpriteIcon('actions-view-table-collapse', array('title' => $GLOBALS['LANG']->getLL('contractView', TRUE)))
                                        : IconUtility::getSpriteIcon('actions-view-table-expand', array('title' => $GLOBALS['LANG']->getLL('expandView', TRUE)));
-                               $theData[$titleCol] = $this->linkWrapTable($table, $tableTitle . ' (' . $this->totalItems . ') ' . $icon);
+                               $theData[$titleCol] = $this->linkWrapTable($table, $tableTitle . ' (<span class="t3js-table-total-items">' . $this->totalItems . '</span>) ' . $icon);
                        }
                        if ($listOnlyInSingleTableMode) {
                                $tableHeader .= BackendUtility::wrapInHelp($table, '', $theData[$titleCol]);
@@ -1307,18 +1307,17 @@ class DatabaseRecordList extends AbstractDatabaseRecordList {
                                        }
 
                                        $titleOrig = BackendUtility::getRecordTitle($table, $row, FALSE, TRUE);
-                                       $title = GeneralUtility::slashJS(GeneralUtility::fixed_lgd_cs($titleOrig, $this->fixedL), 1);
-                                       $warningText = GeneralUtility::quoteJSvalue(
-                                               $GLOBALS['LANG']->getLL($actionName . 'Warning') . ' "' . $title . '" ' . $refCountMsg
-                                       );
-
-                                       $params = '&cmd[' . $table . '][' . $row['uid'] . '][delete]=1';
-                                       $onClick = 'if (confirm(' . $warningText . ')) {jumpToUrl(\''
-                                               . $GLOBALS['SOBE']->doc->issueCommand($params, -1) . '\');} return false;';
+                                       $title = GeneralUtility::fixed_lgd_cs($titleOrig, $this->fixedL);
+                                       $warningText = $GLOBALS['LANG']->getLL($actionName . 'Warning') . ' "' . $title . '" ' . '[' . $table . ':' . $row['uid'] . ']' . $refCountMsg;
 
+                                       $params = 'cmd[' . $table . '][' . $row['uid'] . '][delete]=1';
                                        $icon = IconUtility::getSpriteIcon('actions-edit-' . $actionName);
                                        $linkTitle = $GLOBALS['LANG']->getLL($actionName, TRUE);
-                                       $cells['delete'] = '<a class="btn" href="#" onclick="' . htmlspecialchars($onClick) . '" title="' . $linkTitle . '">' . $icon . '</a>';
+                                       $cells['delete'] = '<a class="btn t3js-record-delete" href="#" '
+                                               . ' data-l10parent="' . htmlspecialchars($row['l10n_parent']) . '"'
+                                               . ' data-params="' . htmlspecialchars($params) . '" data-title="' . htmlspecialchars($titleOrig) . '"'
+                                               . ' data-message="' . htmlspecialchars($warningText) . '" title="' . $linkTitle . '"'
+                                               . '>' . $icon . '</a>';
                                }
                                // "Levels" links: Moving pages into new levels...
                                if ($permsEdit && $table == 'pages' && !$this->searchLevels) {