[TASK] Add missing delete button for Documentation 45/54845/2
authorŁukasz Uznański <l.uznanski@macopedia.pl>
Tue, 28 Nov 2017 09:22:28 +0000 (10:22 +0100)
committerSusanne Moog <susanne.moog@typo3.org>
Tue, 28 Nov 2017 22:38:05 +0000 (23:38 +0100)
Add a  missing delete button within the Documentation module. Right now,
a user can't delete previously downloaded documentation.

Resolves: #80575
Releases: master, 8.7
Change-Id: I9077270c66ec225f1eb7a26e505da0d98d5f7f0e
Reviewed-on: https://review.typo3.org/54845
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Susanne Moog <susanne.moog@typo3.org>
Tested-by: Susanne Moog <susanne.moog@typo3.org>
typo3/sysext/documentation/Classes/Controller/DocumentController.php
typo3/sysext/documentation/Configuration/Backend/AjaxRoutes.php [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Language/locallang.xlf
typo3/sysext/documentation/Resources/Private/Templates/Document/List.html
typo3/sysext/documentation/Resources/Public/JavaScript/Main.js

index e1492c7..23e261c 100644 (file)
@@ -14,8 +14,11 @@ namespace TYPO3\CMS\Documentation\Controller;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Backend\View\BackendTemplateView;
 use TYPO3\CMS\Core\Messaging\FlashMessage;
+use TYPO3\CMS\Core\Page\PageRenderer;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Documentation\Domain\Repository\DocumentRepository;
 use TYPO3\CMS\Documentation\Service\DocumentationService;
@@ -164,10 +167,34 @@ class DocumentController extends ActionController
             $documents = array_intersect_key($documents, array_flip($showDocuments));
         }
 
+        $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
+        $pageRenderer->addInlineLanguageLabelFile('EXT:documentation/Resources/Private/Language/locallang.xlf');
+        $pageRenderer->loadRequireJsModule('TYPO3/CMS/Documentation/Main');
+
         $this->view->assign('documents', $documents);
     }
 
     /**
+     * Delete documentation with given packageKey
+     *
+     * @param ServerRequestInterface $request
+     * @param ResponseInterface $response
+     * @return ResponseInterface
+     */
+    public function deleteAction(ServerRequestInterface $request, ResponseInterface $response)
+    {
+        $basePath = 'typo3conf/Documentation/';
+        $packageKey = $request->getParsedBody();
+        $isDirDeleted = GeneralUtility::rmdir(PATH_site . $basePath . $packageKey['documentationKey'], true);
+        if (!$isDirDeleted) {
+            $this->addFlashMessage(LocalizationUtility::translate('deleteFailed', 'Documentation'), '', FlashMessage::ERROR);
+        }
+
+        $response->getBody()->write(json_encode($isDirDeleted));
+        return $response;
+    }
+
+    /**
      * Returns available documents.
      *
      * @return \TYPO3\CMS\Documentation\Domain\Model\Document[]
diff --git a/typo3/sysext/documentation/Configuration/Backend/AjaxRoutes.php b/typo3/sysext/documentation/Configuration/Backend/AjaxRoutes.php
new file mode 100644 (file)
index 0000000..47f2ab9
--- /dev/null
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * Definitions for routes provided by EXT:documentation
+ */
+return [
+    'documentation_remove' => [
+        'path' => '/documentation/remove',
+        'target' => \TYPO3\CMS\Documentation\Controller\DocumentController::class . '::deleteAction'
+    ],
+];
index a6b0ba9..7782c14 100644 (file)
                        <trans-unit id="downloadFailedDetails">
                                <source>The documentation for "%s" could not be downloaded, because of the following error: %s (%d).</source>
                        </trans-unit>
-
+                       <trans-unit id="deleteModalDescription">
+                               <source>Are you sure you want to delete this record?</source>
+                       </trans-unit>
+                       <trans-unit id="cancel">
+                               <source>Cancel</source>
+                       </trans-unit>
+                       <trans-unit id="delete">
+                               <source>Delete</source>
+                       </trans-unit>
+                       <trans-unit id="deleteFailed">
+                               <source>Deletion of documentation failed.</source>
+                       </trans-unit>
                        <trans-unit id="documentationList.search">
                                <source>Search</source>
                        </trans-unit>
-
                </body>
        </file>
 </xliff>
index 6d09fee..fbdeed5 100644 (file)
@@ -3,47 +3,54 @@
 <f:layout name="Default" />
 
 <f:section name="module-headline">
-       <h1><f:translate key="showDocumentation">Show Documentation</f:translate></h1>
+  <h1><f:translate key="showDocumentation">Show Documentation</f:translate></h1>
 </f:section>
 
 <f:section name="Content">
-       <form class="form-inline">
-               <div class="form-group">
-                       <f:form.textfield name="typo3-documentation-searchfield" placeholder="{f:translate(key:'documentationList.search')}" id="typo3-documentation-searchfield" value="{search}" class="form-control t3js-documentation-searchfield" />
-               </div>
-       </form>
-       <table id="typo3-documentation-list" class="table table-striped table-hover typo3-documentation-list t3js-documentation-list">
-               <thead>
-                       <tr>
-                               <th><f:translate key="tx_documentation_domain_model_document.title" /></th>
-                               <th><f:translate key="tx_documentation_domain_model_documenttranslation.description" /></th>
-                               <th><f:translate key="tx_documentation_domain_model_documenttranslation.actions" /></th>
-                       </tr>
-               </thead>
-               <tbody>
-                       <f:for each="{documents}" as="document">
-                               <f:for each="{document.translations}" as="translation">
-                                       <tr id="{document.packageKey}" >
-                                               <td class="col-nowrap">
-                                                       <span class="typo3-app-icon">
-                                                               <span>
-                                                                       <span>
-                                                                               <img src="../{document.icon}" title="{translation.title}" alt="{translation.title}" />
-                                                                       </span>
-                                                               </span>
-                                                       </span>
-                                                       {translation.title}
-                                                       <f:if condition="{document.extensionKey}">({document.extensionKey})</f:if>
-                                               </td>
-                                               <td>{translation.description}</td>
-                                               <td class="col-nowrap">
-                                                       <div class="btn-group">
-                                                               <doc:formats documentTranslation="{translation}" />
-                                                       </div>
-                                               </td>
-                                       </tr>
-                               </f:for>
-                       </f:for>
-               </tbody>
-       </table>
+  <form class="form-inline">
+    <div class="form-group">
+      <f:form.textfield name="typo3-documentation-searchfield" placeholder="{f:translate(key:'documentationList.search')}" id="typo3-documentation-searchfield" value="{search}" class="form-control t3js-documentation-searchfield" />
+    </div>
+  </form>
+  <table id="typo3-documentation-list" class="table table-striped table-hover typo3-documentation-list t3js-documentation-list">
+    <thead>
+      <tr>
+        <th><f:translate key="tx_documentation_domain_model_document.title" /></th>
+        <th><f:translate key="tx_documentation_domain_model_documenttranslation.description" /></th>
+        <th><f:translate key="tx_documentation_domain_model_documenttranslation.actions" /></th>
+      </tr>
+    </thead>
+    <tbody>
+      <f:for each="{documents}" as="document">
+        <f:for each="{document.translations}" as="translation">
+          <tr id="{document.packageKey}" >
+            <td class="col-nowrap">
+              <span class="typo3-app-icon">
+                <span>
+                  <span>
+                    <img src="../{document.icon}" title="{translation.title}" alt="{translation.title}" />
+                  </span>
+                </span>
+              </span>
+              {translation.title}
+              <f:if condition="{document.extensionKey}">({document.extensionKey})</f:if>
+            </td>
+            <td>{translation.description}</td>
+            <td class="col-nowrap">
+              <div class="btn-group">
+                <doc:formats documentTranslation="{translation}" />
+                <f:for each="{document.translations}" as="documentation">
+                  <f:alias map="{documentation-delete-description: '{f:translate(key: \'deleteModalDescription\', extensionName: \'Documentation\')}'}">
+                  <f:link.action action="delete" class="btn btn-default t3js-documentation-delete" additionalAttributes="{data: {documentation-key: '{document.packageKey}', documentation-name: '{documentation.title}', documentation-delete-description: '{documentation-delete-description}'}}" arguments="{packageKey: '{document.packageKey}'}">
+                    <core:icon identifier="actions-edit-delete"/>
+                  </f:link.action>
+                  </f:alias>
+                </f:for>
+              </div>
+            </td>
+          </tr>
+        </f:for>
+      </f:for>
+    </tbody>
+  </table>
 </f:section>
index eb72d32..43a0292 100644 (file)
  * Module: TYPO3/CMS/Documentation/Main
  * JavaScript module for ext:documentation
  */
-define(['jquery', 'datatables', 'TYPO3/CMS/Backend/jquery.clearable'], function($) {
+define(['jquery', 'datatables', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Notification', 'TYPO3/CMS/Backend/Severity', 'TYPO3/CMS/Backend/jquery.clearable'], function($, DataTable, Modal, Notification, Severity) {
        'use strict';
 
        /**
         *
-        * @type {{dataTable: null, searchField: null, identifier: {documentationList: string, searchField: string}}}
+        * @type {{dataTable: null, searchField: null, identifier: {documentationList: string, searchField: string, deleteButtons: string}}}
         * @exports TYPO3/CMS/Documentation/Main
         */
        var Documentation = {
@@ -28,7 +28,8 @@ define(['jquery', 'datatables', 'TYPO3/CMS/Backend/jquery.clearable'], function(
                searchField: null,
                identifier: {
                        documentationList: '.t3js-documentation-list',
-                       searchField: '.t3js-documentation-searchfield'
+                       searchField: '.t3js-documentation-searchfield',
+                       deleteButtons: '.t3js-documentation-delete'
                }
        };
 
@@ -76,6 +77,58 @@ define(['jquery', 'datatables', 'TYPO3/CMS/Backend/jquery.clearable'], function(
                return vars;
        };
 
+       /**
+        * Delete documentation
+        *
+        * @param {Object} $documentationRecord
+        */
+       Documentation.deleteDocumentation = function($documentationRecord) {
+
+               Modal.confirm($documentationRecord.data('documentationName'), $documentationRecord.data('documentationDeleteDescription'), Severity.warning, [
+                       {
+                               text: TYPO3.lang['cancel'],
+                               active: true,
+                               btnClass: 'btn-default',
+                               trigger: function() {
+                                       Modal.dismiss();
+                               }
+                       }, {
+                               text: TYPO3.lang['delete'],
+                               btnClass: 'btn-info',
+                               trigger: function() {
+                                       $.ajax({
+                                               url: TYPO3.settings.ajaxUrls['documentation_remove'],
+                                               data: {
+                                                       documentationKey: $documentationRecord.data('documentationKey')
+                                               },
+                                               type: 'post',
+                                               cache: false
+                                       }).done(function(data) {
+                                               if(data) {
+                                                       $documentationRecord.closest('tr').fadeOut();
+                                               } else {
+                                                       Documentation.handleErrors(data);
+                                               }
+                                       });
+                                       Modal.dismiss();
+                               }
+                       }
+               ]);
+
+       };
+
+       /**
+        * handle the errors from result object
+        *
+        * @param {Object} result
+        * @private
+        */
+       Documentation.handleErrors = function(result) {
+               $.each(result.messages, function(position, message) {
+                       Notification.error(message.title, message.message);
+               });
+       };
+
        $(function() {
                // Initialize the view
                Documentation.initializeView();
@@ -86,6 +139,11 @@ define(['jquery', 'datatables', 'TYPO3/CMS/Backend/jquery.clearable'], function(
                                Documentation.dataTable.search('').draw();
                        }
                });
+               $(Documentation.identifier.deleteButtons).on('click', function(e) {
+                       e.preventDefault();
+                       e.stopPropagation();
+                       Documentation.deleteDocumentation($(this));
+               })
        });
 
        return Documentation;