[FEATURE] Allow page title edit by double-click 67/38367/10
authorAndreas Fernandez <a.fernandez@scripting-base.de>
Tue, 31 Mar 2015 08:39:08 +0000 (10:39 +0200)
committerAnja Leichsenring <aleichsenring@ab-softlab.de>
Fri, 1 May 2015 14:13:14 +0000 (16:13 +0200)
If a user has proper permissions, the page title can
be edited in "Page" and "List" module by double-clicking on the header.
The header will transform into a form which sends an ajax request
after saving.

Resolves: #66173
Releases: master
Change-Id: I93f03f8e86ae708cdc973cc0a3a8c6399b122428
Reviewed-on: http://review.typo3.org/38367
Reviewed-by: Nicole Cordes <typo3@cordes.co>
Tested-by: Nicole Cordes <typo3@cordes.co>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
typo3/sysext/backend/Classes/View/PageLayoutView.php
typo3/sysext/backend/Resources/Public/JavaScript/PageActions.js [new file with mode: 0644]
typo3/sysext/core/Documentation/Changelog/master/Feature-66173-AllowPageTitleEditByDoubleclick.rst [new file with mode: 0644]
typo3/sysext/recordlist/Classes/RecordList.php

index 271eaaf..fe5b4d1 100644 (file)
@@ -396,6 +396,16 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                /** @var $pageRenderer \TYPO3\CMS\Core\Page\PageRenderer */
                $pageRenderer = $this->getPageLayoutController()->doc->getPageRenderer();
                $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/LayoutModule/DragDrop');
+               $userCanEditPage = $this->ext_CALC_PERMS & Permission::PAGE_EDIT && !empty($this->id);
+               if ($this->tt_contentConfig['languageColsPointer'] > 0) {
+                       $userCanEditPage = $this->getBackendUser()->check('tables_modify', 'pages_language_overlay');
+               }
+               $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/PageActions', 'function(PageActions) {
+                       PageActions.setPageId(' . (int)$this->id . ');
+                       PageActions.setCanEditPage(' . ($userCanEditPage ? 'true' : 'false') . ');
+                       PageActions.setLanguageOverlayId(' . $this->tt_contentConfig['languageColsPointer'] . ');
+                       PageActions.initializePageTitleRenaming();
+               }');
                // Get labels for CTypes and tt_content element fields in general:
                $this->CType_labels = array();
                foreach ($GLOBALS['TCA']['tt_content']['columns']['CType']['config']['items'] as $val) {
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/PageActions.js b/typo3/sysext/backend/Resources/Public/JavaScript/PageActions.js
new file mode 100644 (file)
index 0000000..c0f9dd9
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * JavaScript implementations for page actions
+ */
+define('TYPO3/CMS/Backend/PageActions', ['jquery'], function($) {
+       var PageActions = {
+               settings: {
+                       pageId: 0,
+                       canEditPage: false,
+                       language: {
+                               pageOverlayId: 0
+                       }
+               },
+               identifier: {
+                       $pageTitle: $('h1')
+               }
+       };
+
+       /**
+        * Initialize page title renaming
+        */
+       PageActions.initializePageTitleRenaming = function() {
+               if (!(PageActions.settings.pageId > 0 && PageActions.settings.canEditPage)) {
+                       return;
+               }
+               var $inputFieldWrap = $(
+                               '<form class="row">' +
+                                       '<div class="col-lg-4 col-md-6 col-sm-12">' +
+                                               '<div class="input-group">' +
+                                                       '<input class="form-control">' +
+                                                       '<span class="input-group-btn">' +
+                                                               '<button class="btn btn-default" type="button" data-action="submit"><span class="t3-icon fa fa-floppy-o"></span></button>' +
+                                                       '</span>' +
+                                                       '<span class="input-group-btn">' +
+                                                               '<button class="btn btn-danger" type="button" data-action="cancel"><span class="t3-icon fa fa-times"></span></button>' +
+                                                       '</span>' +
+                                               '</div>' +
+                                       '</div>' +
+                               '</form>'
+                       ),
+                       $inputField = $inputFieldWrap.find('input');
+
+               $inputFieldWrap.find('[data-action=cancel]').on('click', function() {
+                       $inputFieldWrap.replaceWith(PageActions.identifier.$pageTitle);
+                       PageActions.initializePageTitleRenaming();
+               });
+
+               $inputFieldWrap.find('[data-action=submit]').on('click', function() {
+                       var newPageTitle = $.trim($inputField.val());
+                       if (newPageTitle !== '' && PageActions.identifier.$pageTitle.text() !== newPageTitle) {
+                               PageActions.saveChanges($inputField);
+                       } else {
+                               $inputFieldWrap.find('[data-action=cancel]').trigger('click');
+                       }
+               });
+
+               // the form stuff is a wacky workaround to prevent the submission of the docheader form
+               $inputField.parents('form').on('submit', function(e) {
+                       e.preventDefault();
+                       return false;
+               });
+
+               PageActions.identifier.$pageTitle.on('dblclick', function() {
+                       var $h1 = $(this);
+                       $h1.replaceWith($inputFieldWrap);
+                       $inputField.val($h1.text()).focus();
+
+                       $inputField.on('keyup', function(e) {
+                               switch (e.which) {
+                                       case 13: // enter
+                                               $inputFieldWrap.find('[data-action=submit]').trigger('click');
+                                               break;
+                                       case 27: // escape
+                                               $inputFieldWrap.find('[data-action=cancel]').trigger('click');
+                                               break;
+                               }
+                       });
+               });
+       };
+
+       /**
+        * Set the page id (used in the RequireJS callback)
+        */
+       PageActions.setPageId = function(pageId) {
+               PageActions.settings.pageId = pageId;
+       };
+
+       /**
+        * Set if user can edit the page properties
+        */
+       PageActions.setCanEditPage = function(allowed) {
+               PageActions.settings.canEditPage = allowed;
+       };
+
+       /**
+        * Set the overlay id
+        */
+       PageActions.setLanguageOverlayId = function(overlayId) {
+               PageActions.settings.language.pageOverlayId = overlayId;
+       };
+
+       /**
+        * Save the changes and reload the page tree
+        */
+       PageActions.saveChanges = function($field) {
+               var $inputFieldWrap = $field.parents('form');
+               $inputFieldWrap.find('button').addClass('disabled');
+               $field.attr('disabled', 'disabled');
+
+               var parameters = {},
+                       pagesTable,
+                       recordUid;
+
+               if (PageActions.settings.language.pageOverlayId === 0) {
+                       pagesTable = 'pages';
+                       recordUid = PageActions.settings.pageId;
+               } else {
+                       pagesTable = 'pages_language_overlay';
+                       recordUid = PageActions.settings.language.pageOverlayId;
+               }
+
+               parameters['data'] = {};
+               parameters['data'][pagesTable] = {};
+               parameters['data'][pagesTable][recordUid] = {title: $field.val()};
+               require(['TYPO3/CMS/Backend/AjaxDataHandler'], function(DataHandler) {
+                       DataHandler.process(parameters).done(function(result) {
+                               $inputFieldWrap.find('[data-action=cancel]').trigger('click');
+                               PageActions.identifier.$pageTitle.text($field.val());
+                               top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
+                       }).fail(function() {
+                               $inputFieldWrap.find('[data-action=cancel]').trigger('click');
+                       });
+               });
+       };
+
+       return function() {
+               TYPO3.PageActions = PageActions;
+               return PageActions;
+       }();
+});
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-66173-AllowPageTitleEditByDoubleclick.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-66173-AllowPageTitleEditByDoubleclick.rst
new file mode 100644 (file)
index 0000000..03e7ab9
--- /dev/null
@@ -0,0 +1,15 @@
+======================================================
+Feature - #66173: Allow page title edit by doubleclick
+======================================================
+
+Description
+===========
+
+A user can edit the page title in the "Page" and the "List" module by double-clicking the page header.
+
+
+Impact
+======
+
+If a user has sufficient permissions, the page title will become a text field after double-clicking on it.
+Pressing the "escape" key aborts the edit, pressing "enter" submits the changes.
\ No newline at end of file
index c067ab6..fe8a363 100644 (file)
@@ -20,6 +20,7 @@ use TYPO3\CMS\Backend\Utility\IconUtility;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\DataHandling\DataHandler;
 use TYPO3\CMS\Core\Messaging\FlashMessage;
+use TYPO3\CMS\Core\Type\Bitmask\Permission;
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
@@ -263,16 +264,21 @@ class RecordList {
        public function main() {
                $backendUser = $this->getBackendUserAuthentication();
                $lang = $this->getLanguageService();
+               // Loading current page record and checking access:
+               $this->pageinfo = BackendUtility::readPageAccess($this->id, $this->perms_clause);
+               $access = is_array($this->pageinfo) ? 1 : 0;
                // Start document template object:
                $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
                $this->doc->backPath = $GLOBALS['BACK_PATH'];
                $this->doc->setModuleTemplate('EXT:recordlist/Resources/Private/Templates/db_list.html');
                $this->doc->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/AjaxDataHandler');
+               $calcPerms = $backendUser->calcPerms($this->pageinfo);
+               $this->doc->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/PageActions', 'function(PageActions) {
+                       PageActions.setPageId(' . (int)$this->id . ');
+                       PageActions.setCanEditPage(' . ($calcPerms & Permission::PAGE_EDIT && !empty($this->id) ? 'true' : 'false') . ');
+                       PageActions.initializePageTitleRenaming();
+               }');
                $this->doc->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Recordlist/Tooltip');
-               // Loading current page record and checking access:
-               $this->pageinfo = BackendUtility::readPageAccess($this->id, $this->perms_clause);
-               $access = is_array($this->pageinfo) ? 1 : 0;
-
                // Apply predefined values for hidden checkboxes
                // Set predefined value for DisplayBigControlPanel:
                if ($this->modTSconfig['properties']['enableDisplayBigControlPanel'] === 'activated') {
@@ -302,7 +308,7 @@ class RecordList {
                $dblist = GeneralUtility::makeInstance(RecordList\DatabaseRecordList::class);
                $dblist->backPath = $GLOBALS['BACK_PATH'];
                $dblist->script = BackendUtility::getModuleUrl('web_list');
-               $dblist->calcPerms = $backendUser->calcPerms($this->pageinfo);
+               $dblist->calcPerms = $calcPerms;
                $dblist->thumbs = $backendUser->uc['thumbnailsByDefault'];
                $dblist->returnUrl = $this->returnUrl;
                $dblist->allFields = $this->MOD_SETTINGS['bigControlPanel'] || $this->table ? 1 : 0;