From 6bd6d0c29ad89b2776323136e948f47fc8ff5c9a Mon Sep 17 00:00:00 2001 From: Christoph Lehmann Date: Sun, 17 Mar 2024 19:45:13 +0100 Subject: [PATCH] Feature: Share URL with filter Resolves: #17 --- .../Hooks/PageRendererRenderPreProcess.php | 2 + Resources/Private/Language/de.locallang.xlf | 8 +++ Resources/Private/Language/locallang.xlf | 6 ++ .../Public/Css/Backend/pagetreefilter.css | 4 -- Resources/Public/JavaScript/PageTreeFilter.js | 61 +++++++++++++++++-- 5 files changed, 73 insertions(+), 8 deletions(-) diff --git a/Classes/Hooks/PageRendererRenderPreProcess.php b/Classes/Hooks/PageRendererRenderPreProcess.php index f5962f9..991d179 100644 --- a/Classes/Hooks/PageRendererRenderPreProcess.php +++ b/Classes/Hooks/PageRendererRenderPreProcess.php @@ -25,6 +25,8 @@ public function addRequireJsModule(array $params, PageRenderer $pageRenderer): v 'pagetreefilter_wizard_title' => $this->getLanguageService()->sL($labelPrefix . 'wizard_title'), 'pagetreefilter_button_title' => $this->getLanguageService()->sL($labelPrefix . 'filter_button_title'), 'pagetreefilter_button_text_show_unused' => $this->getLanguageService()->sL($labelPrefix . 'wizard_show_unused_elements'), + 'pagetreefilter_share' => $this->getLanguageService()->sL($labelPrefix . 'share'), + 'pagetreefilter_copy_to_clipboard' => $this->getLanguageService()->sL($labelPrefix . 'copy_to_clipboard'), ]); } } diff --git a/Resources/Private/Language/de.locallang.xlf b/Resources/Private/Language/de.locallang.xlf index 7ddd88e..1b8f49c 100644 --- a/Resources/Private/Language/de.locallang.xlf +++ b/Resources/Private/Language/de.locallang.xlf @@ -35,6 +35,14 @@ Filter tree for content elements and records Baum nach Inhaltselementen und Datensätzen filtern + + Share active filter + Aktiven Filter teilen + + + Copy URL to Clipboard + URL in Zwischenablage kopieren + diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf index 04cb37d..966e93f 100644 --- a/Resources/Private/Language/locallang.xlf +++ b/Resources/Private/Language/locallang.xlf @@ -27,6 +27,12 @@ Filter tree for content elements and records + + Share active filter + + + Copy URL to Clipboard + diff --git a/Resources/Public/Css/Backend/pagetreefilter.css b/Resources/Public/Css/Backend/pagetreefilter.css index 5228a35..8bb64bf 100644 --- a/Resources/Public/Css/Backend/pagetreefilter.css +++ b/Resources/Public/Css/Backend/pagetreefilter.css @@ -15,10 +15,6 @@ padding: 0; } -.pagetreefilter-wizard .modal-title { - color: #ffffff; -} - .pagetreefilter-wizard .nav-tabs { padding: 0.75rem 0.75rem 0; background: 0 0; diff --git a/Resources/Public/JavaScript/PageTreeFilter.js b/Resources/Public/JavaScript/PageTreeFilter.js index 299261b..2e9e38f 100644 --- a/Resources/Public/JavaScript/PageTreeFilter.js +++ b/Resources/Public/JavaScript/PageTreeFilter.js @@ -1,8 +1,14 @@ class PageTreeFilter { + selectorSearchInput = '#typo3-pagetree .search-input'; + selectorPagetreeComponent = '#typo3-pagetree-tree'; + selectorPagetreeReady = '#typo3-pagetree-tree .node'; + selectorToolbarReady = '#typo3-pagetree .svg-toolbar__menu'; + urlParameter = 'tx_pagetreefilter[filter]'; + constructor() { - this.waitForElement('#typo3-pagetree .svg-toolbar__menu').then((element) => { + this.waitForElement(this.selectorToolbarReady).then((element) => { if (!element.dataset.pageTreeFilterLoaded) { element.dataset.pageTreeFilterLoaded = true; TYPO3.Icons.getIcon('actions-rocket', 'small').then((icon) => { @@ -17,6 +23,13 @@ class PageTreeFilter this.openWizard(); } }); + + const urlParams = new URLSearchParams(window.location.search) + if (urlParams.has(this.urlParameter)) { + this.waitForElement(this.selectorPagetreeReady).then(() => { + this.applyFilter(urlParams.get(this.urlParameter)); + }); + } } }) } @@ -43,7 +56,8 @@ class PageTreeFilter } openWizard = () => { - TYPO3.Modal.advanced({ + const currentFilter = document.querySelector(this.selectorSearchInput).value; + const wizard = TYPO3.Modal.advanced({ size: 'medium', type: 'ajax', title: TYPO3.lang.pagetreefilter_wizard_title, @@ -61,6 +75,18 @@ class PageTreeFilter content: TYPO3.settings.ajaxUrls.pagetreefilter_fetch_filter, additionalCssClasses: ['pagetreefilter-wizard'], buttons: [ + { + text: TYPO3.lang.pagetreefilter_share, + name: 'pagetreefilter-wizard-share', + icon: 'actions-share-alt', + active: false, + btnClass: 'btn-default' + (currentFilter ? '' : ' disabled'), + trigger: (event, modal) => { + const shareUrl = this.prepareShareUrl(); + TYPO3.Modal.dismiss(); + this.openShareModal(); + } + }, { text: TYPO3.lang.pagetreefilter_button_text_show_unused, name: 'pagetreefilter-wizard-show-unused', @@ -75,6 +101,33 @@ class PageTreeFilter }); } + openShareModal = () => { + TYPO3.Modal.confirm( + TYPO3.lang.pagetreefilter_share, + this.prepareShareUrl(), + 'info', + [ + { + text: TYPO3.lang.pagetreefilter_copy_to_clipboard, + name: 'pagetreefilter-ok', + icon: 'actions-link', + active: true, + btnClass: 'btn-primary' + (navigator.clipboard ? '' : ' disabled'), + trigger: (event, modal) => { + navigator.clipboard.writeText(this.prepareShareUrl()); + TYPO3.Modal.dismiss(); + } + } + ] + ); + } + + prepareShareUrl = () => { + const url = new URL(window.location.origin + "/typo3/module/web/layout"); + url.searchParams.set(this.urlParameter, document.querySelector(this.selectorSearchInput).value); + return url.toString(); + } + toggleHideUnusedElements = (modal) => { const items = modal.querySelectorAll('.pagetreefilter-wizard-item'); const buttonIcon = modal.querySelector('button[name="pagetreefilter-wizard-show-unused"] typo3-backend-icon'); @@ -130,8 +183,8 @@ class PageTreeFilter } applyFilter = (filter) => { - document.querySelector('#typo3-pagetree .search-input').value = filter; - document.querySelector('#typo3-pagetree-tree').filter(filter) + document.querySelector(this.selectorSearchInput).value = filter; + document.querySelector(this.selectorPagetreeComponent).filter(filter) } }