From b1413c7d03713dfd7fd7e9f316849732547ee9c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Uzna=C5=84ski?= <l.uznanski@macopedia.pl> Date: Tue, 28 Nov 2017 10:22:28 +0100 Subject: [PATCH] [TASK] Add missing delete button for Documentation 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/54817 Reviewed-by: Benni Mack <benni@typo3.org> Tested-by: Benni Mack <benni@typo3.org> Tested-by: TYPO3com <no-reply@typo3.com> Reviewed-by: Susanne Moog <susanne.moog@typo3.org> Tested-by: Susanne Moog <susanne.moog@typo3.org> --- .../Classes/Controller/DocumentController.php | 27 ++++++ .../Configuration/Backend/AjaxRoutes.php | 11 +++ .../Resources/Private/Language/locallang.xlf | 14 ++- .../Private/Templates/Document/List.html | 87 ++++++++++--------- .../Resources/Public/JavaScript/Main.js | 64 +++++++++++++- 5 files changed, 158 insertions(+), 45 deletions(-) create mode 100644 typo3/sysext/documentation/Configuration/Backend/AjaxRoutes.php diff --git a/typo3/sysext/documentation/Classes/Controller/DocumentController.php b/typo3/sysext/documentation/Classes/Controller/DocumentController.php index c3085390dd2e..147bf05edf0c 100644 --- a/typo3/sysext/documentation/Classes/Controller/DocumentController.php +++ b/typo3/sysext/documentation/Classes/Controller/DocumentController.php @@ -14,9 +14,12 @@ 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\Localization\LanguageService; 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,9 +167,33 @@ 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. * diff --git a/typo3/sysext/documentation/Configuration/Backend/AjaxRoutes.php b/typo3/sysext/documentation/Configuration/Backend/AjaxRoutes.php new file mode 100644 index 000000000000..47f2ab914685 --- /dev/null +++ b/typo3/sysext/documentation/Configuration/Backend/AjaxRoutes.php @@ -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' + ], +]; diff --git a/typo3/sysext/documentation/Resources/Private/Language/locallang.xlf b/typo3/sysext/documentation/Resources/Private/Language/locallang.xlf index a6b0ba968eeb..7782c14c0ad7 100644 --- a/typo3/sysext/documentation/Resources/Private/Language/locallang.xlf +++ b/typo3/sysext/documentation/Resources/Private/Language/locallang.xlf @@ -93,11 +93,21 @@ <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> diff --git a/typo3/sysext/documentation/Resources/Private/Templates/Document/List.html b/typo3/sysext/documentation/Resources/Private/Templates/Document/List.html index 6d09fee4608c..fbdeed5b29e3 100644 --- a/typo3/sysext/documentation/Resources/Private/Templates/Document/List.html +++ b/typo3/sysext/documentation/Resources/Private/Templates/Document/List.html @@ -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> diff --git a/typo3/sysext/documentation/Resources/Public/JavaScript/Main.js b/typo3/sysext/documentation/Resources/Public/JavaScript/Main.js index eb72d3224730..43a0292d4ae4 100644 --- a/typo3/sysext/documentation/Resources/Public/JavaScript/Main.js +++ b/typo3/sysext/documentation/Resources/Public/JavaScript/Main.js @@ -15,12 +15,12 @@ * 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; -- GitLab