[TASK] Use ModuleTemplate in ext:lang 51/43351/9
authorAnja Leichsenring <aleichsenring@ab-softlab.de>
Fri, 9 Oct 2015 20:15:18 +0000 (22:15 +0200)
committerStefan Neufeind <typo3.neufeind@speedpartner.de>
Fri, 16 Oct 2015 11:19:35 +0000 (13:19 +0200)
Ext:lang uses ModuleTemplate API and BackendTemplateView for
its Backend Module.

Change-Id: I1497d9bdd326114cff70fd723d0bbbdefc16fdf9
Resolves: #69844
Relates: #69841
Relates: #69842
Releases: master
Reviewed-on: http://review.typo3.org/43351
Reviewed-by: Daniel Goerz <ervaude@gmail.com>
Tested-by: Daniel Goerz <ervaude@gmail.com>
Reviewed-by: Frank Nägler <frank.naegler@typo3.org>
Tested-by: Frank Nägler <frank.naegler@typo3.org>
Reviewed-by: Morton Jonuschat <m.jonuschat@mojocode.de>
Tested-by: Morton Jonuschat <m.jonuschat@mojocode.de>
Reviewed-by: Stefan Neufeind <typo3.neufeind@speedpartner.de>
Tested-by: Stefan Neufeind <typo3.neufeind@speedpartner.de>
Build/Resources/Public/Less/TYPO3/_element_buttons.less
typo3/sysext/lang/Classes/Controller/LanguageController.php
typo3/sysext/lang/Resources/Private/Layouts/Default.html
typo3/sysext/lang/Resources/Private/Templates/Language/ListLanguages.html
typo3/sysext/lang/Resources/Private/Templates/Language/ListTranslations.html
typo3/sysext/lang/Resources/Public/JavaScript/LanguageModule.js
typo3/sysext/t3skin/Resources/Public/Css/backend.css

index 20eea7d..936e7e3 100644 (file)
@@ -13,6 +13,9 @@
        .collapse + .btn.collapsed:last-child {
                border-radius: @border-radius-base;
        }
+       .btn-default.disabled {
+               color: #999;
+       }
 }
 
 //
index d3e1f42..7d588bb 100644 (file)
@@ -13,13 +13,32 @@ namespace TYPO3\CMS\Lang\Controller;
  *
  * The TYPO3 project - inspiring people to share!
  */
+use TYPO3\CMS\Backend\Template\Components\ButtonBar;
+use TYPO3\CMS\Backend\Template\Components\Menu\Menu;
+use TYPO3\CMS\Backend\Template\Components\Menu\MenuItem;
+use TYPO3\CMS\Backend\View\BackendTemplateView;
+use TYPO3\CMS\Core\Imaging\Icon;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
+use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
+use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
 
 /**
  * Language controller
  */
-class LanguageController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
+class LanguageController extends ActionController
 {
     /**
+     * @var string
+     */
+    protected $defaultViewObjectName = BackendTemplateView::class;
+
+    /**
+     * @var BackendTemplateView
+     */
+    protected $view;
+
+    /**
      * @var \TYPO3\CMS\Lang\Domain\Repository\LanguageRepository
      */
     protected $languageRepository;
@@ -78,6 +97,9 @@ class LanguageController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControl
      */
     public function listLanguagesAction()
     {
+        $this->prepareDocHeaderMenu();
+        $this->prepareDocHeaderButtons();
+
         $languages = $this->languageRepository->findAll();
         $this->view->assign('languages', $languages);
     }
@@ -89,6 +111,8 @@ class LanguageController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControl
      */
     public function listTranslationsAction()
     {
+        $this->prepareDocHeaderMenu();
+
         $languages = $this->languageRepository->findSelected();
         $this->view->assign('languages', $languages);
     }
@@ -114,7 +138,7 @@ class LanguageController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControl
     {
         $numberOfExtensionsToUpdate = 10;
         $response = array(
-            'success'  => false,
+            'success' => false,
             'progress' => 0,
         );
         if (!empty($data['locale'])) {
@@ -164,7 +188,7 @@ class LanguageController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControl
             if (empty($result[$data['extension']][$data['locale']]['error'])) {
                 $response = array(
                     'success' => true,
-                    'result'  => $result,
+                    'result' => $result,
                 );
             }
         }
@@ -200,4 +224,103 @@ class LanguageController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControl
         }
         $this->view->assign('response', $response);
     }
+
+    /**
+     * DocHeaderMenu
+     */
+    protected function prepareDocHeaderMenu()
+    {
+        $this->view->getModuleTemplate()->setModuleName('typo3-module-lang');
+        $this->view->getModuleTemplate()->setModuleId('typo3-module-lang');
+
+        $this->view->getModuleTemplate()->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Lang/LanguageModule');
+
+        $extensionKey = 'lang';
+        $addJsInlineLabels = [
+            'flashmessage.error',
+            'flashmessage.information',
+            'flashmessage.success',
+            'flashmessage.multipleErrors',
+            'flashmessage.updateComplete',
+            'flashmessage.canceled',
+            'flashmessage.languageActivated',
+            'flashmessage.languageDeactivated',
+            'flashmessage.errorOccurred',
+            'table.processing',
+            'table.search',
+            'table.loadingRecords',
+            'table.zeroRecords',
+            'table.emptyTable',
+            'table.dateFormat',
+        ];
+        foreach ($addJsInlineLabels as $key) {
+            $label = LocalizationUtility::translate($key, $extensionKey);
+            $this->view->getModuleTemplate()->getPageRenderer()->addInlineLanguageLabel($key, $label);
+        }
+
+        $uriBuilder = $this->objectManager->get(UriBuilder::class);
+        $uriBuilder->setRequest($this->request);
+
+        /** @var Menu $menu */
+        $menu = GeneralUtility::makeInstance(Menu::class);
+        $menu->setIdentifier('_languageMenu');
+        $menu->setLabel($this->getLanguageService()->sL('LLL:EXT:lang/locallang_general.xlf:LGL.language', TRUE));
+
+        /** @var MenuItem $languageListMenuItem */
+        $languageListMenuItem = GeneralUtility::makeInstance(MenuItem::class);
+        $action = 'listLanguages';
+        $isActive = $this->request->getControllerActionName() === $action ? TRUE : FALSE;
+        $languageListMenuItem->setTitle($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang.xlf:header.languages'));
+        $uri = $uriBuilder->reset()->uriFor('listLanguages', array(), 'Language');
+        $languageListMenuItem->setHref($uri)->setActive($isActive);
+
+        /** @var MenuItem $translationMenuItem */
+        $translationMenuItem = GeneralUtility::makeInstance(MenuItem::class);
+        $action = 'listTranslations';
+        $isActive = $this->request->getControllerActionName() === $action ? TRUE : FALSE;
+        $translationMenuItem->setTitle($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang.xlf:header.translations'));
+        $uri = $uriBuilder->reset()->uriFor('listTranslations', array(), 'Language');
+        $translationMenuItem->setHref($uri)->setActive($isActive);
+
+        $menu->addMenuItem($languageListMenuItem);
+        $menu->addMenuItem($translationMenuItem);
+        $this->view->getModuleTemplate()->getDocHeaderComponent()->getMenuRegistry()->addMenu($menu);
+
+    }
+
+    /**
+     * Returns LanguageService
+     *
+     * @return \TYPO3\CMS\Lang\LanguageService
+     */
+    protected function getLanguageService()
+    {
+        return $GLOBALS['LANG'];
+    }
+
+    /**
+     * DocHeaderButtons
+     */
+    protected function prepareDocHeaderButtons()
+    {
+        // @todo: the html structure needed to operate the buttons correctly is broken now.
+        // @todo: LanguageModule.js and backend.css -> div.typo3-module-lang div.menuItems
+
+        $downloadAllButton = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar()->makeLinkButton()
+            ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon('actions-system-extension-download', Icon::SIZE_SMALL))
+            ->setTitle($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang.xlf:button.downloadAll'))
+            ->setClasses('menuItem updateItem t3js-button-update')
+            ->setDataAttributes(['action' => 'updateActiveLanguages'])
+            ->setHref('#');
+        $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar()->addButton($downloadAllButton, ButtonBar::BUTTON_POSITION_LEFT);
+
+        $cancelButton = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar()->makeLinkButton()
+            ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon('actions-document-close', Icon::SIZE_SMALL))
+            ->setTitle($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang.xlf:button.cancel'))
+            ->setClasses('menuItem cancelItem disabled t3js-button-cancel')
+            ->setDataAttributes(['action' => 'cancelLanguageUpdate'])
+            ->setHref('#');
+
+        $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar()->addButton($cancelButton, ButtonBar::BUTTON_POSITION_LEFT);
+    }
 }
index b594a67..24bb192 100644 (file)
@@ -1,53 +1,13 @@
-<f:be.container
-       enableClickMenu="0"
-       loadExtJs="0"
-       loadJQuery="true"
-       includeRequireJsModules="{
-               0: 'TYPO3/CMS/Lang/LanguageModule'
-       }"
-       addJsInlineLabels="{
-               0: 'flashmessage.error',
-               1: 'flashmessage.information',
-               2: 'flashmessage.success',
-               3: 'flashmessage.multipleErrors',
-               4: 'flashmessage.updateComplete',
-               5: 'flashmessage.canceled',
-               6: 'flashmessage.languageActivated',
-               7: 'flashmessage.languageDeactivated',
-               8: 'flashmessage.errorOccurred',
-               9: 'table.processing',
-               10: 'table.search',
-               11: 'table.loadingRecords',
-               12: 'table.zeroRecords',
-               13: 'table.emptyTable',
-               14: 'table.dateFormat'
-       }"
+<div
+       class="typo3-fullDoc typo3-module-lang"
+       data-list-translations-uri="{f:uri.action(action:'getTranslations',format:'json')}"
+       data-update-language-uri="{f:uri.action(action:'updateLanguage',format:'json')}"
+       data-update-translation-uri="{f:uri.action(action:'updateTranslation',format:'json')}"
+       data-activate-language-uri="{f:uri.action(action:'activateLanguage',format:'json')}"
+       data-deactivate-language-uri="{f:uri.action(action:'deactivateLanguage',format:'json')}"
+       data-prefix="tx_lang_tools_langlanguage"
 >
-       <div
-               class="typo3-fullDoc typo3-module-lang"
-               data-list-translations-uri="{f:uri.action(action:'getTranslations',format:'json')}"
-               data-update-language-uri="{f:uri.action(action:'updateLanguage',format:'json')}"
-               data-update-translation-uri="{f:uri.action(action:'updateTranslation',format:'json')}"
-               data-activate-language-uri="{f:uri.action(action:'activateLanguage',format:'json')}"
-               data-deactivate-language-uri="{f:uri.action(action:'deactivateLanguage',format:'json')}"
-               data-prefix="tx_lang_tools_langlanguage"
-       >
-               <div id="typo3-docheader">
-                       <div class="typo3-docheader-functions">
-                               <f:be.menus.actionMenu>
-                                       <f:be.menus.actionMenuItem label="{f:translate(key: 'header.languages')}" controller="Language" action="listLanguages" />
-                                       <f:be.menus.actionMenuItem label="{f:translate(key: 'header.translations')}" controller="Language" action="listTranslations" />
-                               </f:be.menus.actionMenu>
-                       </div>
-                       <div class="typo3-docheader-buttons">
-                               <f:render section="iconButtons" />
-                       </div>
-               </div>
-               <div id="typo3-docbody">
-                       <div id="typo3-inner-docbody">
-                               <f:render section="content" />
-                               <f:render partial="Icons" />
-                       </div>
-               </div>
-       </div>
-</f:be.container>
+
+       <f:render section="content"/>
+       <f:render partial="Icons"/>
+</div>
index 890b06b..d25cd9c 100644 (file)
@@ -5,20 +5,6 @@
       xmlns:f="http://xsd.helmut-hummel.de/ns/TYPO3/CMS/Fluid/ViewHelpers">
 <f:layout name="Default"/>
 
-<f:section name="iconButtons">
-       <div class="menuItems">
-               <span class="menuItem updateItem" data-action="updateActiveLanguages" title="{f:translate(key:'button.downloadAll')}">
-                       <core:icon identifier="actions-system-extension-download" />
-               </span>
-               <span class="menuItem loadingItem">
-                       <span title="" class="t3-icon fa fa-spin fa-circle-o-notch">&nbsp;</span>
-               </span>
-               <span class="menuItem cancelItem" data-action="cancelLanguageUpdate" title="{f:translate(key:'button.cancel')}">
-                       &nbsp;<core:icon identifier="actions-document-close" />
-               </span>
-       </div>
-</f:section>
-
 <f:section name="content">
        <h1>
                <f:translate key="header.languages"/>
index 11405c8..1f7eea7 100644 (file)
@@ -1,9 +1,5 @@
 <f:layout name="Default"/>
 
-<f:section name="iconButtons">
-
-</f:section>
-
 <f:section name="content">
        <h1><f:translate key="header.translations" /></h1>
        <f:flashMessages />
index d6fb97a..4842af3 100644 (file)
@@ -14,7 +14,7 @@
 /**
  * Language module class
  */
-define(['jquery', 'moment', 'datatables', 'TYPO3/CMS/Backend/jquery.clearable'], function($, moment) {
+define(['jquery', 'moment', 'TYPO3/CMS/Backend/Icons', 'datatables', 'TYPO3/CMS/Backend/jquery.clearable'], function($, moment, Icons) {
        'use strict';
 
        var LanguageModule = {
@@ -23,12 +23,17 @@ define(['jquery', 'moment', 'datatables', 'TYPO3/CMS/Backend/jquery.clearable'],
                table: null,
                topMenu: null,
                currentRequest: null,
+               userAbortRequest: false,
                settings: {},
                icons: {},
                labels: {},
+               buttons: {
+                       update: null,
+                       cancel: null
+               },
                identifiers: {
                        searchField: '.t3js-language-searchfield',
-                       topMenu: 'div.menuItems',
+                       topMenu: 'div.t3js-module-docheader',
                        activateIcon: 'span.activateIcon',
                        deactivateIcon: 'span.deactivateIcon',
                        downloadIcon: 'span.downloadIcon',
@@ -66,6 +71,7 @@ define(['jquery', 'moment', 'datatables', 'TYPO3/CMS/Backend/jquery.clearable'],
                LanguageModule.table = LanguageModule.buildLanguageTable(tableElement);
                LanguageModule.initializeSearchField();
                LanguageModule.initializeEventHandler();
+               LanguageModule.initializeButtons();
        };
 
        /**
@@ -151,7 +157,7 @@ define(['jquery', 'moment', 'datatables', 'TYPO3/CMS/Backend/jquery.clearable'],
         */
        LanguageModule.updateActiveLanguagesAction = function(triggerElement, parameters) {
                var $activeRows = $('tr.' + LanguageModule.classes.enabled, LanguageModule.table.table().container());
-
+               LanguageModule.updateButtonStatus('update');
                LanguageModule.topMenu.addClass(LanguageModule.classes.processing);
                $activeRows.addClass(LanguageModule.classes.processing);
                LanguageModule.loadTranslationsByRows($activeRows, function(row, status, data, response) {
@@ -178,7 +184,7 @@ define(['jquery', 'moment', 'datatables', 'TYPO3/CMS/Backend/jquery.clearable'],
         */
        LanguageModule.cancelLanguageUpdateAction = function(triggerElement, parameters) {
                var $activeRows = $('tr.' + LanguageModule.classes.enabled, LanguageModule.table.table().container());
-
+               LanguageModule.updateButtonStatus('cancel');
                LanguageModule.topMenu.removeClass(LanguageModule.classes.processing);
                $activeRows.removeClass(LanguageModule.classes.processing);
                LanguageModule.abortAjaxRequest();
@@ -235,7 +241,8 @@ define(['jquery', 'moment', 'datatables', 'TYPO3/CMS/Backend/jquery.clearable'],
                        languageActivated: TYPO3.lang['flashmessage.languageActivated'],
                        errorOccurred: TYPO3.lang['flashmessage.errorOccurred'],
                        languageDeactivated: TYPO3.lang['flashmessage.languageDeactivated'],
-                       updateComplete: TYPO3.lang['flashmessage.updateComplete']
+                       updateComplete: TYPO3.lang['flashmessage.updateComplete'],
+                       canceled: TYPO3.lang['flashmessage.canceled']
                }
        };
 
@@ -340,20 +347,49 @@ define(['jquery', 'moment', 'datatables', 'TYPO3/CMS/Backend/jquery.clearable'],
        LanguageModule.initializeEventHandler = function() {
                $(document).on('click', function(event) {
                        var $element = $(event.target);
+                       var $parent = $element.closest('[data-action]');
 
                        if ($element.data('action') !== undefined) {
                                LanguageModule.handleActionEvent($element, event);
-                       } else if ($element.parent().data('action') !== undefined) {
-                               LanguageModule.handleActionEvent($element.parent(), event);
-                       } else if ($element.parent().parent().data('action') !== undefined) {
-                               LanguageModule.handleActionEvent($element.parent().parent(), event);
-                       } else if ($element.parent().parent().parent().parent().data('action') !== undefined) {
-                               LanguageModule.handleActionEvent($element.parent().parent().parent().parent(), event);
+                       } else if ($parent.data('action') !== undefined) {
+                               LanguageModule.handleActionEvent($parent, event);
                        }
                });
        };
 
        /**
+        * Initialize buttons
+        */
+       LanguageModule.initializeButtons = function() {
+               LanguageModule.buttons.update = LanguageModule.topMenu.find('.t3js-button-update');
+               LanguageModule.buttons.cancel = LanguageModule.topMenu.find('.t3js-button-cancel');
+       };
+
+       /**
+        * Update buttons in top menu
+        *
+        * @param {string} action
+        */
+       LanguageModule.updateButtonStatus = function(action) {
+               switch (action) {
+                       case 'update':
+                               LanguageModule.buttons.update.data('action', 'cancelLanguageUpdate');
+                               LanguageModule.buttons.cancel.removeClass('disabled');
+                               Icons.getIcon('spinner-circle-dark', Icons.sizes.small).done(function(icons) {
+                                       LanguageModule.buttons.update.find('span.icon').replaceWith(icons['spinner-circle-dark']);
+                               });
+                               break;
+                       case 'cancel':
+                               LanguageModule.buttons.update.data('action', 'updateActiveLanguages');
+                               LanguageModule.buttons.cancel.addClass('disabled');
+                               Icons.getIcon('actions-system-extension-download', Icons.sizes.small).done(function(icons) {
+                                       LanguageModule.buttons.update.find('span.icon').replaceWith(icons['actions-system-extension-download']);
+                               });
+                               break;
+               }
+       };
+
+       /**
         * Handler for "action" events
         */
        LanguageModule.handleActionEvent = function(element, event) {
@@ -454,6 +490,7 @@ define(['jquery', 'moment', 'datatables', 'TYPO3/CMS/Backend/jquery.clearable'],
         */
        LanguageModule.abortAjaxRequest = function() {
                if (LanguageModule.currentRequest) {
+                       LanguageModule.userAbortRequest = true;
                        LanguageModule.currentRequest.abort();
                }
        };
@@ -462,7 +499,9 @@ define(['jquery', 'moment', 'datatables', 'TYPO3/CMS/Backend/jquery.clearable'],
         * Display error flash message
         */
        LanguageModule.displayError = function(label) {
-               if (typeof label === 'string' && label !== '') {
+               if (LanguageModule.userAbortRequest) {
+                       LanguageModule.displaySuccess(LanguageModule.labels.canceled);
+               } else if (typeof label === 'string' && label !== '') {
                        top.TYPO3.Notification.error(LanguageModule.labels.errorHeader, label);
                }
        };
index 5e71bf1..cace3ef 100644 (file)
@@ -11573,6 +11573,9 @@ a.badge-danger:focus {
 .btn-group .collapse + .btn.collapsed:last-child {
   border-radius: 2px;
 }
+.btn-group .btn-default.disabled {
+  color: #999;
+}
 .btn-radio input[type="radio"],
 .btn-checkbox input[type="radio"],
 .btn-radio input[type="checkbox"],