diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Element/ImmediateActionElement.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Element/ImmediateActionElement.ts index e5bdafbd6c00fc6f283b7c0561b911341f8745af..72be32e20f84b86252b7829e875e05a2f60f2286 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Element/ImmediateActionElement.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Element/ImmediateActionElement.ts @@ -12,6 +12,7 @@ */ import Utility = require('TYPO3/CMS/Backend/Utility'); +import {EventDispatcher} from 'TYPO3/CMS/Backend/Event/EventDispatcher'; /** * Module: TYPO3/CMS/Backend/Element/ImmediateActionElement @@ -41,6 +42,8 @@ export class ImmediateActionElement extends HTMLElement { return (await import('TYPO3/CMS/Backend/Storage/ModuleStateStorage')).ModuleStateStorage.update; case 'TYPO3.Backend.Storage.ModuleStateStorage.updateWithCurrentMount': return (await import('TYPO3/CMS/Backend/Storage/ModuleStateStorage')).ModuleStateStorage.updateWithCurrentMount; + case 'TYPO3.Backend.Event.EventDispatcher.dispatchCustomEvent': + return EventDispatcher.dispatchCustomEvent; default: throw Error('Unknown action "' + action + '"'); } diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Event/EventDispatcher.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Event/EventDispatcher.ts new file mode 100644 index 0000000000000000000000000000000000000000..4eb69a5635f9a7a15c3c72ee896ff12231b14428 --- /dev/null +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Event/EventDispatcher.ts @@ -0,0 +1,26 @@ +/* + * 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! + */ + +/** + * Module: TYPO3/CMS/Backend/Event/EventDispatcher + */ +export class EventDispatcher { + static dispatchCustomEvent(name: string, detail: any = null, useTop: boolean = false): void { + const event = new CustomEvent(name, {detail: detail}); + if (!useTop) { + document.dispatchEvent(event); + } else if (typeof top !== 'undefined') { + top.document.dispatchEvent(event); + } + } +} diff --git a/Build/Sources/TypeScript/opendocs/Resources/Public/TypeScript/Toolbar/OpendocsMenu.ts b/Build/Sources/TypeScript/opendocs/Resources/Public/TypeScript/Toolbar/OpendocsMenu.ts index 2b5708379f877348c41d9b14aaf9fdc35808d748..f9625c88c3fcec68e81ccddf037635e7959cb980 100644 --- a/Build/Sources/TypeScript/opendocs/Resources/Public/TypeScript/Toolbar/OpendocsMenu.ts +++ b/Build/Sources/TypeScript/opendocs/Resources/Public/TypeScript/Toolbar/OpendocsMenu.ts @@ -47,6 +47,10 @@ class OpendocsMenu { } constructor() { + document.addEventListener( + 'typo3:opendocs:updateRequested', + (evt: CustomEvent) => this.updateMenu(), + ); Viewport.Topbar.Toolbar.registerEvent((): void => { this.initializeEvents(); this.updateMenu(); diff --git a/typo3/sysext/backend/Classes/Domain/Model/Element/ImmediateActionElement.php b/typo3/sysext/backend/Classes/Domain/Model/Element/ImmediateActionElement.php index 16f2a4c7f2461edf116eed65ad4e078332a17efe..ffa7727ab806b271b67c2c843f22316101448810 100644 --- a/typo3/sysext/backend/Classes/Domain/Model/Element/ImmediateActionElement.php +++ b/typo3/sysext/backend/Classes/Domain/Model/Element/ImmediateActionElement.php @@ -31,6 +31,11 @@ class ImmediateActionElement protected string $action; protected ?array $args = null; + public static function forAction(string $action): self + { + return new self($action, null); + } + public static function moduleStateUpdate(string $module, $identifier, bool $select = null): self { return new self( @@ -47,6 +52,14 @@ class ImmediateActionElement ); } + public static function dispatchCustomEvent(string $name, array $details = null, bool $useTop = false): self + { + return new self( + 'TYPO3.Backend.Event.EventDispatcher.dispatchCustomEvent', + [$name, $details, $useTop] + ); + } + private function __construct(string $action, ?array $args) { $this->action = $action; diff --git a/typo3/sysext/backend/Classes/Template/ModuleTemplate.php b/typo3/sysext/backend/Classes/Template/ModuleTemplate.php index 02dac7b752ca91c0af1e91938c609b6c3988cab7..809ebf494b24af35ddb4dcdf5bab9b1aca683fec 100644 --- a/typo3/sysext/backend/Classes/Template/ModuleTemplate.php +++ b/typo3/sysext/backend/Classes/Template/ModuleTemplate.php @@ -410,7 +410,20 @@ class ModuleTemplate $this->view->assign('uiBlock', $this->uiBlock); $this->view->assign('flashMessageQueueIdentifier', $this->flashMessageQueue->getIdentifier()); $this->pageRenderer->addBodyContent($this->bodyTag . $this->view->render()); - $this->pageRenderer->addJsFooterInlineCode('updateSignals', BackendUtility::getUpdateSignalCode()); + + $updateSignalDetails = BackendUtility::getUpdateSignalDetails(); + if (!empty($updateSignalDetails['html'])) { + $this->pageRenderer->addHeaderData( + implode("\n", $updateSignalDetails['html']) + ); + } + // @todo deprecate inline JavaScript in TYPO3 v12.0 + if (!empty($updateSignalDetails['script'])) { + $this->pageRenderer->addJsFooterInlineCode( + 'updateSignals', + implode("\n", $updateSignalDetails['script']) + ); + } return $this->pageRenderer->render(); } diff --git a/typo3/sysext/backend/Classes/Utility/BackendUtility.php b/typo3/sysext/backend/Classes/Utility/BackendUtility.php index 259f383d41f393a15b145e1e83d1118bed44e911..cb557e230f97c20b4fa0319dbf752e7223fe5f6d 100644 --- a/typo3/sysext/backend/Classes/Utility/BackendUtility.php +++ b/typo3/sysext/backend/Classes/Utility/BackendUtility.php @@ -19,6 +19,7 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Log\LoggerInterface; use TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider; use TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching\ConditionMatcher; +use TYPO3\CMS\Backend\Domain\Model\Element\ImmediateActionElement; use TYPO3\CMS\Backend\Routing\Route; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; @@ -2488,13 +2489,13 @@ class BackendUtility * * @param string $set Key to set the update signal. When setting, this value contains strings telling WHAT to set. At this point it seems that the value "updatePageTree" is the only one it makes sense to set. If empty, all update signals will be removed. * @param mixed $params Additional information for the update signal, used to only refresh a branch of the tree - * @see BackendUtility::getUpdateSignalCode() + * @see BackendUtility::getUpdateSignalDetails() */ public static function setUpdateSignal($set = '', $params = '') { $beUser = static::getBackendUserAuthentication(); $modData = $beUser->getModuleData( - \TYPO3\CMS\Backend\Utility\BackendUtility::class . '::getUpdateSignal', + BackendUtility::class . '::getUpdateSignal', 'ses' ); if ($set) { @@ -2506,7 +2507,7 @@ class BackendUtility // clear the module data $modData = []; } - $beUser->pushModuleData(\TYPO3\CMS\Backend\Utility\BackendUtility::class . '::getUpdateSignal', $modData); + $beUser->pushModuleData(BackendUtility::class . '::getUpdateSignal', $modData); } /** @@ -2515,12 +2516,13 @@ class BackendUtility * * @return string HTML javascript code * @see BackendUtility::setUpdateSignal() + * @internal use getUpdateSignalDetails() instead, will be deprecated in TYPO3 v12.0 */ public static function getUpdateSignalCode() { $signals = []; $modData = static::getBackendUserAuthentication()->getModuleData( - \TYPO3\CMS\Backend\Utility\BackendUtility::class . '::getUpdateSignal', + BackendUtility::class . '::getUpdateSignal', 'ses' ); if (empty($modData)) { @@ -2570,6 +2572,76 @@ class BackendUtility return $content; } + /** + * Gets instructions for update signals (e.g. page tree shall be refreshed, + * since some page title has been modified during the current HTTP request). + * + * @return array{html: list<string>, script: list<string>} + * @see BackendUtility::setUpdateSignal() + */ + public static function getUpdateSignalDetails(): array + { + $details = [ + 'html' => [], + // @todo deprecate inline JavaScript in TYPO3 v12.0 + 'script' => [], + ]; + $modData = static::getBackendUserAuthentication()->getModuleData( + BackendUtility::class . '::getUpdateSignal', + 'ses' + ); + if (empty($modData)) { + return $details; + } + // Hook: Allows to let TYPO3 execute your JS code + $updateSignals = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['updateSignalHook'] ?? []; + // Loop through all setUpdateSignals and get the JS code + foreach ($modData as $set => $val) { + if (isset($updateSignals[$set])) { + $params = ['set' => $set, 'parameter' => $val['parameter'], 'JScode' => '', 'html' => '']; + $ref = null; + GeneralUtility::callUserFunction($updateSignals[$set], $params, $ref); + // @todo verify and adjust documentation + if (!empty($params['html'])) { + $details['html'][] = $params['html']; + } elseif (!empty($params['JScode'])) { + // @todo deprecate in TYPO3 v12.0, avoid inline JavaScript + $details['script'][] = $params['JScode']; + } + } else { + switch ($set) { + case 'updatePageTree': + $details['html'][] = ImmediateActionElement::dispatchCustomEvent( + 'typo3:pagetree:refresh', + null, + true + ); + break; + case 'updateFolderTree': + $details['html'][] = ImmediateActionElement::dispatchCustomEvent( + 'typo3:filestoragetree:refresh', + null, + true + ); + break; + case 'updateModuleMenu': + $details['html'][] = ImmediateActionElement::forAction( + 'TYPO3.ModuleMenu.App.refreshMenu', + ); + break; + case 'updateTopbar': + $details['html'][] = ImmediateActionElement::forAction( + 'TYPO3.Backend.Topbar.refresh' + ); + break; + } + } + } + // reset update signals + self::setUpdateSignal(); + return $details; + } + /** * Returns an array which is most backend modules becomes MOD_SETTINGS containing values from function menus etc. determining the function of the module. * This is kind of session variable management framework for the backend users. diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Element/ImmediateActionElement.js b/typo3/sysext/backend/Resources/Public/JavaScript/Element/ImmediateActionElement.js index 07f6c190b952c88e6f4555654e22335c8b062923..fe3ea96fd8a94861006d5f03bc01dde66e33e2a9 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Element/ImmediateActionElement.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Element/ImmediateActionElement.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,a,r){void 0===r&&(r=a),Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[a]}})}:function(e,t,a,r){void 0===r&&(r=a),e[r]=t[a]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var a in e)"default"!==a&&Object.prototype.hasOwnProperty.call(e,a)&&__createBinding(t,e,a);return __setModuleDefault(t,e),t};define(["require","exports","TYPO3/CMS/Backend/Utility"],(function(e,t,a){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ImmediateActionElement=void 0;class r extends HTMLElement{constructor(){super(...arguments),this.args=[]}static async getDelegate(t){switch(t){case"TYPO3.ModuleMenu.App.refreshMenu":const a=await new Promise((t,a)=>{e(["TYPO3/CMS/Backend/ModuleMenu"],t,a)}).then(__importStar);return a.App.refreshMenu.bind(a.App);case"TYPO3.Backend.Topbar.refresh":const r=await new Promise((t,a)=>{e(["TYPO3/CMS/Backend/Viewport"],t,a)}).then(__importStar);return r.Topbar.refresh.bind(r.Topbar);case"TYPO3.WindowManager.localOpen":const n=await new Promise((t,a)=>{e(["TYPO3/CMS/Backend/WindowManager"],t,a)}).then(__importStar);return n.localOpen.bind(n);case"TYPO3.Backend.Storage.ModuleStateStorage.update":return(await new Promise((t,a)=>{e(["TYPO3/CMS/Backend/Storage/ModuleStateStorage"],t,a)}).then(__importStar)).ModuleStateStorage.update;case"TYPO3.Backend.Storage.ModuleStateStorage.updateWithCurrentMount":return(await new Promise((t,a)=>{e(["TYPO3/CMS/Backend/Storage/ModuleStateStorage"],t,a)}).then(__importStar)).ModuleStateStorage.updateWithCurrentMount;default:throw Error('Unknown action "'+t+'"')}}static get observedAttributes(){return["action","args","args-list"]}attributeChangedCallback(e,t,r){if("action"===e)this.action=r;else if("args"===e){const e=r.replace(/"/g,'"'),t=JSON.parse(e);this.args=t instanceof Array?a.trimItems(t):[]}else if("args-list"===e){const e=r.split(",");this.args=a.trimItems(e)}}connectedCallback(){if(!this.action)throw new Error("Missing mandatory action attribute");r.getDelegate(this.action).then(e=>e.apply(null,this.args))}}t.ImmediateActionElement=r,window.customElements.define("typo3-immediate-action",r)})); \ No newline at end of file +var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,a,r){void 0===r&&(r=a),Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[a]}})}:function(e,t,a,r){void 0===r&&(r=a),e[r]=t[a]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var a in e)"default"!==a&&Object.prototype.hasOwnProperty.call(e,a)&&__createBinding(t,e,a);return __setModuleDefault(t,e),t};define(["require","exports","TYPO3/CMS/Backend/Utility","TYPO3/CMS/Backend/Event/EventDispatcher"],(function(e,t,a,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ImmediateActionElement=void 0;class n extends HTMLElement{constructor(){super(...arguments),this.args=[]}static async getDelegate(t){switch(t){case"TYPO3.ModuleMenu.App.refreshMenu":const a=await new Promise((t,a)=>{e(["TYPO3/CMS/Backend/ModuleMenu"],t,a)}).then(__importStar);return a.App.refreshMenu.bind(a.App);case"TYPO3.Backend.Topbar.refresh":const n=await new Promise((t,a)=>{e(["TYPO3/CMS/Backend/Viewport"],t,a)}).then(__importStar);return n.Topbar.refresh.bind(n.Topbar);case"TYPO3.WindowManager.localOpen":const i=await new Promise((t,a)=>{e(["TYPO3/CMS/Backend/WindowManager"],t,a)}).then(__importStar);return i.localOpen.bind(i);case"TYPO3.Backend.Storage.ModuleStateStorage.update":return(await new Promise((t,a)=>{e(["TYPO3/CMS/Backend/Storage/ModuleStateStorage"],t,a)}).then(__importStar)).ModuleStateStorage.update;case"TYPO3.Backend.Storage.ModuleStateStorage.updateWithCurrentMount":return(await new Promise((t,a)=>{e(["TYPO3/CMS/Backend/Storage/ModuleStateStorage"],t,a)}).then(__importStar)).ModuleStateStorage.updateWithCurrentMount;case"TYPO3.Backend.Event.EventDispatcher.dispatchCustomEvent":return r.EventDispatcher.dispatchCustomEvent;default:throw Error('Unknown action "'+t+'"')}}static get observedAttributes(){return["action","args","args-list"]}attributeChangedCallback(e,t,r){if("action"===e)this.action=r;else if("args"===e){const e=r.replace(/"/g,'"'),t=JSON.parse(e);this.args=t instanceof Array?a.trimItems(t):[]}else if("args-list"===e){const e=r.split(",");this.args=a.trimItems(e)}}connectedCallback(){if(!this.action)throw new Error("Missing mandatory action attribute");n.getDelegate(this.action).then(e=>e.apply(null,this.args))}}t.ImmediateActionElement=n,window.customElements.define("typo3-immediate-action",n)})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Event/EventDispatcher.js b/typo3/sysext/backend/Resources/Public/JavaScript/Event/EventDispatcher.js new file mode 100644 index 0000000000000000000000000000000000000000..e65dd56134b23fb36b2add50af946349591cf446 --- /dev/null +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Event/EventDispatcher.js @@ -0,0 +1,13 @@ +/* + * 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! + */ +define(["require","exports"],(function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.EventDispatcher=void 0;t.EventDispatcher=class{static dispatchCustomEvent(e,t=null,n=!1){const s=new CustomEvent(e,{detail:t});n?"undefined"!=typeof top&&top.document.dispatchEvent(s):document.dispatchEvent(s)}}})); \ No newline at end of file diff --git a/typo3/sysext/opendocs/Classes/Backend/ToolbarItems/OpendocsToolbarItem.php b/typo3/sysext/opendocs/Classes/Backend/ToolbarItems/OpendocsToolbarItem.php index 66d76bfceb7f1807ec5bfdc3c2672c152b84f045..c0cd8e06c61e15b7811b8065a3f9711de12f2ba8 100644 --- a/typo3/sysext/opendocs/Classes/Backend/ToolbarItems/OpendocsToolbarItem.php +++ b/typo3/sysext/opendocs/Classes/Backend/ToolbarItems/OpendocsToolbarItem.php @@ -17,6 +17,7 @@ declare(strict_types=1); namespace TYPO3\CMS\Opendocs\Backend\ToolbarItems; +use TYPO3\CMS\Backend\Domain\Model\Element\ImmediateActionElement; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface; use TYPO3\CMS\Backend\Utility\BackendUtility; @@ -121,13 +122,13 @@ class OpendocsToolbarItem implements ToolbarItemInterface * * @param array $params */ - public function updateNumberOfOpenDocsHook(&$params) + public function updateNumberOfOpenDocsHook(array &$params) { - $params['JScode'] = ' - if (top && top.TYPO3.OpendocsMenu) { - top.TYPO3.OpendocsMenu.updateMenu(); - } - '; + $params['html'] = ImmediateActionElement::dispatchCustomEvent( + 'typo3:opendocs:updateRequested', + null, + true + ); } /** diff --git a/typo3/sysext/opendocs/Resources/Public/JavaScript/Toolbar/OpendocsMenu.js b/typo3/sysext/opendocs/Resources/Public/JavaScript/Toolbar/OpendocsMenu.js index 7c2ba3695618e0a198f8664be11d6ed0caafdb41..9c8b18a22f338aab45ccda64ecbe507c3061ff7f 100644 --- a/typo3/sysext/opendocs/Resources/Public/JavaScript/Toolbar/OpendocsMenu.js +++ b/typo3/sysext/opendocs/Resources/Public/JavaScript/Toolbar/OpendocsMenu.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery","TYPO3/CMS/Core/Ajax/AjaxRequest","TYPO3/CMS/Backend/Icons","TYPO3/CMS/Backend/Viewport","TYPO3/CMS/Backend/Storage/ModuleStateStorage"],(function(e,t,o,n,r,c,a){"use strict";var l;o=__importDefault(o),function(e){e.containerSelector="#typo3-cms-opendocs-backend-toolbaritems-opendocstoolbaritem",e.closeSelector=".t3js-topbar-opendocs-close",e.menuContainerSelector=".dropdown-menu",e.toolbarIconSelector=".toolbar-item-icon .t3js-icon",e.openDocumentsItemsSelector=".t3js-topbar-opendocs-item",e.counterSelector="#tx-opendocs-counter",e.entrySelector=".t3js-open-doc"}(l||(l={}));class s{constructor(){this.hashDataAttributeName="opendocsidentifier",this.toggleMenu=()=>{o.default(".scaffold").removeClass("scaffold-toolbar-expanded"),o.default(l.containerSelector).toggleClass("open")},c.Topbar.Toolbar.registerEvent(()=>{this.initializeEvents(),this.updateMenu()})}static updateNumberOfDocs(){const e=o.default(l.containerSelector).find(l.openDocumentsItemsSelector).length;o.default(l.counterSelector).text(e).toggle(e>0)}updateMenu(){let e=o.default(l.toolbarIconSelector,l.containerSelector),t=e.clone();r.getIcon("spinner-circle-light",r.sizes.small).done(t=>{e.replaceWith(t)}),new n(TYPO3.settings.ajaxUrls.opendocs_menu).get().then(async e=>{o.default(l.containerSelector).find(l.menuContainerSelector).html(await e.resolve()),s.updateNumberOfDocs()}).finally(()=>{o.default(l.toolbarIconSelector,l.containerSelector).replaceWith(t)})}initializeEvents(){o.default(l.containerSelector).on("click",l.closeSelector,e=>{e.preventDefault();const t=o.default(e.currentTarget).data(this.hashDataAttributeName);this.closeDocument(t)}).on("click",l.entrySelector,e=>{e.preventDefault();const t=o.default(e.currentTarget);this.toggleMenu(),a.ModuleStateStorage.updateWithCurrentMount("web",t.data("pid"),!0);document.querySelector("typo3-backend-module-router").setAttribute("endpoint",t.attr("href"))})}closeDocument(e){const t={};e&&(t.md5sum=e),new n(TYPO3.settings.ajaxUrls.opendocs_closedoc).post(t).then(async e=>{o.default(l.menuContainerSelector,l.containerSelector).html(await e.resolve()),s.updateNumberOfDocs(),o.default(l.containerSelector).toggleClass("open")})}}let i;return i=new s,"undefined"!=typeof TYPO3&&(TYPO3.OpendocsMenu=i),i})); \ No newline at end of file +var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery","TYPO3/CMS/Core/Ajax/AjaxRequest","TYPO3/CMS/Backend/Icons","TYPO3/CMS/Backend/Viewport","TYPO3/CMS/Backend/Storage/ModuleStateStorage"],(function(e,t,o,n,r,a,c){"use strict";var l;o=__importDefault(o),function(e){e.containerSelector="#typo3-cms-opendocs-backend-toolbaritems-opendocstoolbaritem",e.closeSelector=".t3js-topbar-opendocs-close",e.menuContainerSelector=".dropdown-menu",e.toolbarIconSelector=".toolbar-item-icon .t3js-icon",e.openDocumentsItemsSelector=".t3js-topbar-opendocs-item",e.counterSelector="#tx-opendocs-counter",e.entrySelector=".t3js-open-doc"}(l||(l={}));class s{constructor(){this.hashDataAttributeName="opendocsidentifier",this.toggleMenu=()=>{o.default(".scaffold").removeClass("scaffold-toolbar-expanded"),o.default(l.containerSelector).toggleClass("open")},document.addEventListener("typo3:opendocs:updateRequested",e=>this.updateMenu()),a.Topbar.Toolbar.registerEvent(()=>{this.initializeEvents(),this.updateMenu()})}static updateNumberOfDocs(){const e=o.default(l.containerSelector).find(l.openDocumentsItemsSelector).length;o.default(l.counterSelector).text(e).toggle(e>0)}updateMenu(){let e=o.default(l.toolbarIconSelector,l.containerSelector),t=e.clone();r.getIcon("spinner-circle-light",r.sizes.small).done(t=>{e.replaceWith(t)}),new n(TYPO3.settings.ajaxUrls.opendocs_menu).get().then(async e=>{o.default(l.containerSelector).find(l.menuContainerSelector).html(await e.resolve()),s.updateNumberOfDocs()}).finally(()=>{o.default(l.toolbarIconSelector,l.containerSelector).replaceWith(t)})}initializeEvents(){o.default(l.containerSelector).on("click",l.closeSelector,e=>{e.preventDefault();const t=o.default(e.currentTarget).data(this.hashDataAttributeName);this.closeDocument(t)}).on("click",l.entrySelector,e=>{e.preventDefault();const t=o.default(e.currentTarget);this.toggleMenu(),c.ModuleStateStorage.updateWithCurrentMount("web",t.data("pid"),!0);document.querySelector("typo3-backend-module-router").setAttribute("endpoint",t.attr("href"))})}closeDocument(e){const t={};e&&(t.md5sum=e),new n(TYPO3.settings.ajaxUrls.opendocs_closedoc).post(t).then(async e=>{o.default(l.menuContainerSelector,l.containerSelector).html(await e.resolve()),s.updateNumberOfDocs(),o.default(l.containerSelector).toggleClass("open")})}}let u;return u=new s,"undefined"!=typeof TYPO3&&(TYPO3.OpendocsMenu=u),u})); \ No newline at end of file diff --git a/typo3/sysext/redirects/Classes/Hooks/DispatchNotificationHook.php b/typo3/sysext/redirects/Classes/Hooks/DispatchNotificationHook.php index 0b02c44fc834411f9d09e0797b1f2a2f18809c44..9c32c73db60e4316151a7ab73ad8016687db328f 100644 --- a/typo3/sysext/redirects/Classes/Hooks/DispatchNotificationHook.php +++ b/typo3/sysext/redirects/Classes/Hooks/DispatchNotificationHook.php @@ -30,6 +30,7 @@ final class DispatchNotificationHook */ public function dispatchNotification(&$params) { + // @todo https://forge.typo3.org/issues/96003 $code = ' // Ensure the event handler is ready and listening to events top.window.require(["TYPO3/CMS/Redirects/EventHandler"], function() {